mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-21 18:22:33 +01:00
Qt: implement flow layout game grid
This will allow us to properly style the grid and also remove the need to refresh the whole grid on a window resize
This commit is contained in:
parent
0b628cb50e
commit
f115032095
@ -43,20 +43,6 @@ QLabel#gamelist_icon_background_color {
|
||||
color: rgba(209,209,209,255);
|
||||
}
|
||||
|
||||
/* game grid stylesheet */
|
||||
QTableWidget#game_grid {
|
||||
font-weight:600;
|
||||
font-size:8pt;
|
||||
font-family:Lucida Grande;
|
||||
color: rgba(51,51,51,255);
|
||||
}
|
||||
QTableWidget#game_grid::item:selected:active {
|
||||
selection-background-color: #0078D7;
|
||||
}
|
||||
QTableWidget#game_grid::item:selected:!active {
|
||||
selection-background-color: #008cff;
|
||||
}
|
||||
|
||||
/* log stylesheet */
|
||||
QTextEdit#tty_frame {
|
||||
background-color:#ffffff;
|
||||
@ -131,3 +117,33 @@ QLabel#rsx_debugger_display_buffer {
|
||||
QLabel#l_controller {
|
||||
color:#434343;
|
||||
}
|
||||
|
||||
/* Game Grid */
|
||||
#game_list_grid_item[selected="true"] {
|
||||
background: #0078D7;
|
||||
}
|
||||
#game_list_grid_item:hover {
|
||||
background: #008cff;
|
||||
}
|
||||
#game_list_grid_item:focus {
|
||||
background: #0078D7;
|
||||
}
|
||||
|
||||
/* Game Grid Font */
|
||||
#game_list_grid_item #game_list_grid_item_title_label {
|
||||
font-weight: 600;
|
||||
font-size: 8pt;
|
||||
font-family: Lucida Grande;
|
||||
color: rgba(51,51,51,255);
|
||||
}
|
||||
|
||||
/* Game Grid hover and focus: we need to handle properties differently when using descendants */
|
||||
#game_list_grid_item[selected="true"] #game_list_grid_item_title_label {
|
||||
color: #fff;
|
||||
}
|
||||
#game_list_grid_item[hover="true"] #game_list_grid_item_title_label {
|
||||
color: #fff;
|
||||
}
|
||||
#game_list_grid_item[focus="true"] #game_list_grid_item_title_label {
|
||||
color: #fff;
|
||||
}
|
||||
|
@ -197,17 +197,6 @@ QLabel#l_controller {
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
/* Game Grid Font */
|
||||
QTableWidget#game_grid {
|
||||
font-weight: 600;
|
||||
font-size: 8pt;
|
||||
font-family: Lucida Grande;
|
||||
color: #FFF;
|
||||
}
|
||||
QTableWidget#game_grid::item:selected:!active {
|
||||
selection-background-color: #313f4e;
|
||||
}
|
||||
|
||||
/* Slider on toolbar */
|
||||
QWidget#sizeSliderContainer {
|
||||
background: transparent;
|
||||
@ -365,3 +354,33 @@ QTreeView::branch:open:has-children:has-siblings:hover {
|
||||
border-image: none;
|
||||
image: url("GuiConfigs/list_arrow_down_blue.png");
|
||||
}
|
||||
|
||||
/* Game Grid */
|
||||
#game_list_grid_item[selected="true"] {
|
||||
background: #313f4e;
|
||||
}
|
||||
#game_list_grid_item:hover {
|
||||
background: #313f4e;
|
||||
}
|
||||
#game_list_grid_item:focus {
|
||||
background: #0078D7;
|
||||
}
|
||||
|
||||
/* Game Grid Font */
|
||||
#game_list_grid_item #game_list_grid_item_title_label {
|
||||
font-weight: 600;
|
||||
font-size: 8pt;
|
||||
font-family: Lucida Grande;
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
/* Game Grid hover and focus: we need to handle properties differently when using descendants */
|
||||
#game_list_grid_item[selected="true"] #game_list_grid_item_title_label {
|
||||
background-color: #313f4e;
|
||||
}
|
||||
#game_list_grid_item[hover="true"] #game_list_grid_item_title_label {
|
||||
background-color: #313f4e;
|
||||
}
|
||||
#game_list_grid_item[focus="true"] #game_list_grid_item_title_label {
|
||||
background-color: #0078D7;
|
||||
}
|
||||
|
@ -662,3 +662,21 @@ QTreeView::branch:open:has-children:has-siblings:hover {
|
||||
border-image: none;
|
||||
image: url("GuiConfigs/list_arrow_down_green.png");
|
||||
}
|
||||
|
||||
/* Game Grid */
|
||||
#game_list_grid_item[selected="true"] {
|
||||
background: #2d3038;
|
||||
}
|
||||
#game_list_grid_item:focus {
|
||||
background: #2d3038;
|
||||
}
|
||||
|
||||
/* Game Grid hover and focus: we need to handle properties differently when using descendants */
|
||||
#game_list_grid_item[selected="true"] #game_list_grid_item_title_label {
|
||||
background-color: #2d3038;
|
||||
color: #8cf944;
|
||||
}
|
||||
#game_list_grid_item[focus="true"] #game_list_grid_item_title_label {
|
||||
background-color: #2d3038;
|
||||
color: #8cf944;
|
||||
}
|
||||
|
@ -249,20 +249,6 @@ QWidget#trophy_notification_frame {
|
||||
color: #e6e6e6;
|
||||
}
|
||||
|
||||
/* Game Grid Font */
|
||||
QTableWidget#game_grid {
|
||||
font-weight: 600;
|
||||
font-size: 8pt;
|
||||
font-family: Lucida Grande;
|
||||
selection-color: #e6e6e6;
|
||||
}
|
||||
QTableWidget#game_grid::item:selected:active {
|
||||
selection-background-color: #4c4b4b;
|
||||
}
|
||||
QTableWidget#game_grid::item:selected:!active {
|
||||
selection-background-color: #3d3d3d;
|
||||
}
|
||||
|
||||
/* Set Toolbar Slider Size */
|
||||
QSlider#sizeSlider::groove:horizontal {
|
||||
border: 0em solid transparent;
|
||||
@ -368,3 +354,33 @@ QTreeView::branch:open:has-children:has-siblings:hover {
|
||||
border-image: none;
|
||||
image: url("GuiConfigs/list_arrow_down_blue.png");
|
||||
}
|
||||
|
||||
/* Game Grid */
|
||||
#game_list_grid_item[selected="true"] {
|
||||
background: #3d3d3d;
|
||||
}
|
||||
#game_list_grid_item:hover {
|
||||
background: #3d3d3d;
|
||||
}
|
||||
#game_list_grid_item:focus {
|
||||
background: #4c4b4b;
|
||||
}
|
||||
|
||||
/* Game Grid Font */
|
||||
#game_list_grid_item #game_list_grid_item_title_label {
|
||||
font-weight: 600;
|
||||
font-size: 8pt;
|
||||
font-family: Lucida Grande;
|
||||
}
|
||||
|
||||
/* Game Grid hover and focus: we need to handle properties differently when using descendants */
|
||||
#game_list_grid_item[selected="true"] #game_list_grid_item_title_label {
|
||||
background-color: #3d3d3d;
|
||||
}
|
||||
#game_list_grid_item[hover="true"] #game_list_grid_item_title_label {
|
||||
background-color: #3d3d3d;
|
||||
}
|
||||
#game_list_grid_item[focus="true"] #game_list_grid_item_title_label {
|
||||
color: #e6e6e6;
|
||||
background-color: #4c4b4b;
|
||||
}
|
||||
|
@ -194,17 +194,6 @@ QLabel#l_controller {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/* Game Grid Font */
|
||||
QTableWidget#game_grid {
|
||||
font-weight: 600;
|
||||
font-size: 8pt;
|
||||
font-family: Lucida Grande;
|
||||
color: #fff;
|
||||
}
|
||||
QTableWidget#game_grid::item:selected:!active {
|
||||
selection-background-color: #354454;
|
||||
}
|
||||
|
||||
/* Slider on toolbar */
|
||||
QWidget#sizeSliderContainer {
|
||||
background: transparent;
|
||||
@ -362,3 +351,33 @@ QTreeView::branch:open:has-children:has-siblings:hover {
|
||||
border-image: none;
|
||||
image: url("GuiConfigs/list_arrow_down_blue.png");
|
||||
}
|
||||
|
||||
/* Game Grid */
|
||||
#game_list_grid_item[selected="true"] {
|
||||
background: #354454;
|
||||
}
|
||||
#game_list_grid_item:hover {
|
||||
background: #354454;
|
||||
}
|
||||
#game_list_grid_item:focus {
|
||||
background: #0078D7;
|
||||
}
|
||||
|
||||
/* Game Grid Font */
|
||||
#game_list_grid_item #game_list_grid_item_title_label {
|
||||
font-weight: 600;
|
||||
font-size: 8pt;
|
||||
font-family: Lucida Grande;
|
||||
color: #FFF;
|
||||
}
|
||||
|
||||
/* Game Grid hover and focus: we need to handle properties differently when using descendants */
|
||||
#game_list_grid_item[selected="true"] #game_list_grid_item_title_label {
|
||||
background-color: #354454;
|
||||
}
|
||||
#game_list_grid_item[hover="true"] #game_list_grid_item_title_label {
|
||||
background-color: #354454;
|
||||
}
|
||||
#game_list_grid_item[focus="true"] #game_list_grid_item_title_label {
|
||||
background-color: #0078D7;
|
||||
}
|
||||
|
@ -367,21 +367,6 @@ QLabel#l_controller {
|
||||
}
|
||||
|
||||
|
||||
/* Game Grid Font */
|
||||
QTableWidget#game_grid {
|
||||
font-weight: 600;
|
||||
color: #ffd785;
|
||||
text-transform: uppercase;
|
||||
selection-color: #ffd785;
|
||||
}
|
||||
QTableWidget#game_grid::item:selected:active {
|
||||
selection-background-color: #4d4940;
|
||||
}
|
||||
QTableWidget#game_grid::item:selected:!active {
|
||||
selection-background-color: #615c51;
|
||||
}
|
||||
|
||||
|
||||
/* Debug UI Settings buttons */
|
||||
QLabel#color_button {
|
||||
background: transparent;
|
||||
@ -489,3 +474,33 @@ QWidget#trophy_notification_frame {
|
||||
background-color: #b3ac98;
|
||||
color: #4d4940;
|
||||
}
|
||||
|
||||
/* Game Grid */
|
||||
#game_list_grid_item[selected="true"] {
|
||||
background: #615c51;
|
||||
}
|
||||
#game_list_grid_item:hover {
|
||||
background: #615c51;
|
||||
}
|
||||
#game_list_grid_item:focus {
|
||||
background: #4d4940;
|
||||
}
|
||||
|
||||
/* Game Grid Font */
|
||||
#game_list_grid_item #game_list_grid_item_title_label {
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
color: #ffd785;
|
||||
}
|
||||
|
||||
/* Game Grid hover and focus: we need to handle properties differently when using descendants */
|
||||
#game_list_grid_item[selected="true"] #game_list_grid_item_title_label {
|
||||
background-color: #615c51;
|
||||
}
|
||||
#game_list_grid_item[hover="true"] #game_list_grid_item_title_label {
|
||||
background-color: #615c51;
|
||||
}
|
||||
#game_list_grid_item[focus="true"] #game_list_grid_item_title_label {
|
||||
background-color: #4d4940;
|
||||
color: #ffd785;
|
||||
}
|
||||
|
@ -220,6 +220,17 @@ QScrollBar::up-arrow, QScrollBar::down-arrow, QScrollBar::up-button:vertical, QS
|
||||
border: none;
|
||||
}
|
||||
|
||||
#game_list_grid QScrollBar {
|
||||
width: 10px;
|
||||
height: 3px;
|
||||
}
|
||||
#game_list_grid QScrollBar::handle {
|
||||
background: #1c273d;
|
||||
}
|
||||
#game_list_grid QScrollBar::handle:hover, QScrollBar::handle:pressed {
|
||||
background: #0074e7;
|
||||
}
|
||||
|
||||
/* Radio Buttons */
|
||||
QRadioButton::indicator {
|
||||
border: 0.0625em solid #455971;
|
||||
@ -684,3 +695,28 @@ QTreeView::branch:open:has-children:has-siblings:hover {
|
||||
border-image: none;
|
||||
image: url("GuiConfigs/list_arrow_down_blue.png");
|
||||
}
|
||||
|
||||
/* Game Grid */
|
||||
#game_list_grid_item[selected="true"] {
|
||||
background: #0f1d36;
|
||||
}
|
||||
#game_list_grid_item:focus {
|
||||
background: #0f1d36;
|
||||
}
|
||||
|
||||
#game_list_grid_item #game_list_grid_item_title_label {
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
/* Game Grid hover and focus: we need to handle properties differently when using descendants */
|
||||
#game_list_grid_item[selected="true"] #game_list_grid_item_title_label {
|
||||
background-color: #0f1d36;
|
||||
color: #2397ff;
|
||||
}
|
||||
#game_list_grid_item[hover="true"] #game_list_grid_item_title_label {
|
||||
color: #2397ff;
|
||||
}
|
||||
#game_list_grid_item[focus="true"] #game_list_grid_item_title_label {
|
||||
background-color: #0f1d36;
|
||||
color: #2397ff;
|
||||
}
|
||||
|
@ -678,3 +678,24 @@ QLabel#debugger_frame_pc {
|
||||
color: #000; /* Font Color: Black */
|
||||
background-color: #00ff00; /* Green */
|
||||
}
|
||||
|
||||
/* Game Grid */
|
||||
#game_list_grid_item[selected="true"] {
|
||||
background: #4343c1;
|
||||
}
|
||||
#game_list_grid_item:focus {
|
||||
background: #4343c1;
|
||||
}
|
||||
|
||||
/* Game Grid hover and focus: we need to handle properties differently when using descendants */
|
||||
#game_list_grid_item[selected="true"] #game_list_grid_item_title_label {
|
||||
background-color: #4343c1;
|
||||
color: #FFF;
|
||||
}
|
||||
#game_list_grid_item[hover="true"] #game_list_grid_item_title_label {
|
||||
color: #4343c1;
|
||||
}
|
||||
#game_list_grid_item[focus="true"] #game_list_grid_item_title_label {
|
||||
background-color: #4343c1;
|
||||
color: #FFF;
|
||||
}
|
||||
|
@ -358,14 +358,6 @@ QLabel#l_controller {
|
||||
color: #4d4940;
|
||||
}
|
||||
|
||||
/* Game Grid Font */
|
||||
QTableWidget#game_grid {
|
||||
font-weight: 600;
|
||||
color: #4d4940;
|
||||
text-transform: uppercase;
|
||||
selection-color: #aea993;
|
||||
}
|
||||
|
||||
/* Debug UI Settings buttons */
|
||||
QLabel#color_button {
|
||||
background: transparent;
|
||||
@ -463,3 +455,26 @@ QSlider#sizeSlider::groove:horizontal {
|
||||
QLabel#validLabel {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* Game Grid */
|
||||
#game_list_grid_item[selected="true"] {
|
||||
background: #4d4940;
|
||||
}
|
||||
#game_list_grid_item:focus {
|
||||
background: #4d4940;
|
||||
}
|
||||
|
||||
/* Game Grid Font */
|
||||
#game_list_grid_item #game_list_grid_item_title_label {
|
||||
font-weight: 600;
|
||||
color: #4d4940;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
/* Game Grid hover and focus: we need to handle properties differently when using descendants */
|
||||
#game_list_grid_item[selected="true"] #game_list_grid_item_title_label {
|
||||
color: #aea993;
|
||||
}
|
||||
#game_list_grid_item[focus="true"] #game_list_grid_item_title_label {
|
||||
color: #aea993;
|
||||
}
|
||||
|
@ -234,6 +234,12 @@
|
||||
<ClCompile Include="QTGeneratedFiles\Debug\moc_find_dialog.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Debug\moc_flow_widget.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Debug\moc_flow_widget_item.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Debug\moc_game_compatibility.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
@ -246,6 +252,12 @@
|
||||
<ClCompile Include="QTGeneratedFiles\Debug\moc_game_list_grid.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Debug\moc_game_list_grid_item.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Debug\moc_game_list_table.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Debug\moc_gs_frame.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
@ -348,6 +360,9 @@
|
||||
<ClCompile Include="QTGeneratedFiles\Debug\moc_save_manager_dialog.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Debug\moc_screenshot_item.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Debug\moc_screenshot_manager_dialog.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
@ -471,6 +486,12 @@
|
||||
<ClCompile Include="QTGeneratedFiles\Release\moc_find_dialog.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release\moc_flow_widget.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release\moc_flow_widget_item.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release\moc_game_compatibility.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
@ -483,6 +504,12 @@
|
||||
<ClCompile Include="QTGeneratedFiles\Release\moc_game_list_grid.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release\moc_game_list_grid_item.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release\moc_game_list_table.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release\moc_gs_frame.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
@ -585,6 +612,9 @@
|
||||
<ClCompile Include="QTGeneratedFiles\Release\moc_save_manager_dialog.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release\moc_screenshot_item.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release\moc_screenshot_manager_dialog.cpp">
|
||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||
</ClCompile>
|
||||
@ -667,8 +697,12 @@
|
||||
<ClCompile Include="rpcs3qt\fatal_error_dialog.cpp" />
|
||||
<ClCompile Include="rpcs3qt\flow_layout.cpp" />
|
||||
<ClCompile Include="rpcs3qt\flow_widget.cpp" />
|
||||
<ClCompile Include="rpcs3qt\flow_widget_item.cpp" />
|
||||
<ClCompile Include="rpcs3qt\game_list.cpp" />
|
||||
<ClCompile Include="rpcs3qt\game_list_base.cpp" />
|
||||
<ClCompile Include="rpcs3qt\game_list_delegate.cpp" />
|
||||
<ClCompile Include="rpcs3qt\game_list_grid_item.cpp" />
|
||||
<ClCompile Include="rpcs3qt\game_list_table.cpp" />
|
||||
<ClCompile Include="rpcs3qt\gui_application.cpp" />
|
||||
<ClCompile Include="rpcs3qt\input_dialog.cpp" />
|
||||
<ClCompile Include="rpcs3qt\ipc_settings_dialog.cpp" />
|
||||
@ -676,6 +710,7 @@
|
||||
<ClCompile Include="rpcs3qt\log_viewer.cpp" />
|
||||
<ClCompile Include="rpcs3qt\microphone_creator.cpp" />
|
||||
<ClCompile Include="rpcs3qt\movie_item.cpp" />
|
||||
<ClCompile Include="rpcs3qt\movie_item_base.cpp" />
|
||||
<ClCompile Include="rpcs3qt\osk_dialog_frame.cpp" />
|
||||
<ClCompile Include="rpcs3qt\pad_led_settings_dialog.cpp" />
|
||||
<ClCompile Include="rpcs3qt\pad_motion_settings_dialog.cpp" />
|
||||
@ -691,6 +726,7 @@
|
||||
<ClCompile Include="rpcs3qt\recvmessage_dialog_frame.cpp" />
|
||||
<ClCompile Include="rpcs3qt\render_creator.cpp" />
|
||||
<ClCompile Include="rpcs3qt\rpcn_settings_dialog.cpp" />
|
||||
<ClCompile Include="rpcs3qt\screenshot_item.cpp" />
|
||||
<ClCompile Include="rpcs3qt\screenshot_manager_dialog.cpp" />
|
||||
<ClCompile Include="rpcs3qt\screenshot_preview.cpp" />
|
||||
<ClCompile Include="rpcs3qt\sendmessage_dialog_frame.cpp" />
|
||||
@ -713,7 +749,6 @@
|
||||
<ClCompile Include="rpcs3qt\find_dialog.cpp" />
|
||||
<ClCompile Include="rpcs3qt\game_compatibility.cpp" />
|
||||
<ClCompile Include="rpcs3qt\game_list_grid.cpp" />
|
||||
<ClCompile Include="rpcs3qt\game_list_grid_delegate.cpp" />
|
||||
<ClCompile Include="rpcs3qt\progress_dialog.cpp" />
|
||||
<ClCompile Include="rpcs3qt\qt_utils.cpp" />
|
||||
<ClCompile Include="rpcs3qt\syntax_highlighter.cpp" />
|
||||
@ -1148,6 +1183,16 @@
|
||||
</CustomBuild>
|
||||
<ClInclude Include="rpcs3qt\flow_layout.h" />
|
||||
<CustomBuild Include="rpcs3qt\flow_widget.h">
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Moc%27ing %(Identity)...</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWIN32_LEAN_AND_MEAN -DHAVE_VULKAN -DMINIUPNP_STATICLIB -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -DQT_MULTIMEDIA_LIB -DQT_MULTIMEDIAWIDGETS_LIB -DQT_SVG_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\SoundTouch\soundtouch\include" "-I.\..\3rdparty\cubeb\extra" "-I.\..\3rdparty\cubeb\cubeb\include" "-I.\..\3rdparty\flatbuffers\include" "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\XAudio2Redist\include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtMultimedia" "-I$(QTDIR)\include\QtMultimediaWidgets" "-I$(QTDIR)\include\QtSvg"</Command>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Moc%27ing %(Identity)...</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWIN32_LEAN_AND_MEAN -DHAVE_VULKAN -DMINIUPNP_STATICLIB -DHAVE_SDL2 -DWITH_DISCORD_RPC -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DNDEBUG -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -DQT_MULTIMEDIA_LIB -DQT_MULTIMEDIAWIDGETS_LIB -DQT_SVG_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\SoundTouch\soundtouch\include" "-I.\..\3rdparty\cubeb\extra" "-I.\..\3rdparty\cubeb\cubeb\include" "-I.\..\3rdparty\flatbuffers\include" "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\libsdl-org\SDL\include" "-I.\..\3rdparty\XAudio2Redist\include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtCore" "-I.\release" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtMultimedia" "-I$(QTDIR)\include\QtMultimediaWidgets" "-I$(QTDIR)\include\QtSvg"</Command>
|
||||
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\game_list_base.h">
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
@ -1161,7 +1206,37 @@
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
</Command>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\flow_widget_item.h">
|
||||
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Moc%27ing %(Identity)...</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWIN32_LEAN_AND_MEAN -DHAVE_VULKAN -DMINIUPNP_STATICLIB -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -DQT_MULTIMEDIA_LIB -DQT_MULTIMEDIAWIDGETS_LIB -DQT_SVG_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\SoundTouch\soundtouch\include" "-I.\..\3rdparty\cubeb\extra" "-I.\..\3rdparty\cubeb\cubeb\include" "-I.\..\3rdparty\flatbuffers\include" "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\XAudio2Redist\include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtMultimedia" "-I$(QTDIR)\include\QtMultimediaWidgets" "-I$(QTDIR)\include\QtSvg"</Command>
|
||||
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Moc%27ing %(Identity)...</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWIN32_LEAN_AND_MEAN -DHAVE_VULKAN -DMINIUPNP_STATICLIB -DHAVE_SDL2 -DWITH_DISCORD_RPC -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DNDEBUG -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -DQT_MULTIMEDIA_LIB -DQT_MULTIMEDIAWIDGETS_LIB -DQT_SVG_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\SoundTouch\soundtouch\include" "-I.\..\3rdparty\cubeb\extra" "-I.\..\3rdparty\cubeb\cubeb\include" "-I.\..\3rdparty\flatbuffers\include" "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\libsdl-org\SDL\include" "-I.\..\3rdparty\XAudio2Redist\include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtCore" "-I.\release" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtMultimedia" "-I$(QTDIR)\include\QtMultimediaWidgets" "-I$(QTDIR)\include\QtSvg"</Command>
|
||||
</CustomBuild>
|
||||
<ClInclude Include="rpcs3qt\game_list_delegate.h" />
|
||||
<CustomBuild Include="rpcs3qt\game_list_table.h">
|
||||
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Moc%27ing %(Identity)...</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWIN32_LEAN_AND_MEAN -DHAVE_VULKAN -DMINIUPNP_STATICLIB -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -DQT_MULTIMEDIA_LIB -DQT_MULTIMEDIAWIDGETS_LIB -DQT_SVG_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\SoundTouch\soundtouch\include" "-I.\..\3rdparty\cubeb\extra" "-I.\..\3rdparty\cubeb\cubeb\include" "-I.\..\3rdparty\flatbuffers\include" "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\XAudio2Redist\include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtMultimedia" "-I$(QTDIR)\include\QtMultimediaWidgets" "-I$(QTDIR)\include\QtSvg"</Command>
|
||||
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Moc%27ing %(Identity)...</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWIN32_LEAN_AND_MEAN -DHAVE_VULKAN -DMINIUPNP_STATICLIB -DHAVE_SDL2 -DWITH_DISCORD_RPC -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DNDEBUG -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -DQT_MULTIMEDIA_LIB -DQT_MULTIMEDIAWIDGETS_LIB -DQT_SVG_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\SoundTouch\soundtouch\include" "-I.\..\3rdparty\cubeb\extra" "-I.\..\3rdparty\cubeb\cubeb\include" "-I.\..\3rdparty\flatbuffers\include" "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\libsdl-org\SDL\include" "-I.\..\3rdparty\XAudio2Redist\include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtCore" "-I.\release" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtMultimedia" "-I$(QTDIR)\include\QtMultimediaWidgets" "-I$(QTDIR)\include\QtSvg"</Command>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\game_list_grid_item.h">
|
||||
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Moc%27ing %(Identity)...</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWIN32_LEAN_AND_MEAN -DHAVE_VULKAN -DMINIUPNP_STATICLIB -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -DQT_MULTIMEDIA_LIB -DQT_MULTIMEDIAWIDGETS_LIB -DQT_SVG_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\SoundTouch\soundtouch\include" "-I.\..\3rdparty\cubeb\extra" "-I.\..\3rdparty\cubeb\cubeb\include" "-I.\..\3rdparty\flatbuffers\include" "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\XAudio2Redist\include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtMultimedia" "-I$(QTDIR)\include\QtMultimediaWidgets" "-I$(QTDIR)\include\QtSvg"</Command>
|
||||
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Moc%27ing %(Identity)...</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWIN32_LEAN_AND_MEAN -DHAVE_VULKAN -DMINIUPNP_STATICLIB -DHAVE_SDL2 -DWITH_DISCORD_RPC -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DNDEBUG -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -DQT_MULTIMEDIA_LIB -DQT_MULTIMEDIAWIDGETS_LIB -DQT_SVG_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\SoundTouch\soundtouch\include" "-I.\..\3rdparty\cubeb\extra" "-I.\..\3rdparty\cubeb\cubeb\include" "-I.\..\3rdparty\flatbuffers\include" "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\libsdl-org\SDL\include" "-I.\..\3rdparty\XAudio2Redist\include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtCore" "-I.\release" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtMultimedia" "-I$(QTDIR)\include\QtMultimediaWidgets" "-I$(QTDIR)\include\QtSvg"</Command>
|
||||
</CustomBuild>
|
||||
<ClInclude Include="rpcs3qt\gui_save.h" />
|
||||
<CustomBuild Include="rpcs3qt\patch_manager_dialog.h">
|
||||
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||
@ -1214,6 +1289,7 @@
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWIN32_LEAN_AND_MEAN -DHAVE_VULKAN -DWITH_DISCORD_RPC -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DNDEBUG -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -DQT_MULTIMEDIA_LIB -DQT_MULTIMEDIAWIDGETS_LIB -DQT_SVG_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\SoundTouch\soundtouch\include" "-I.\..\3rdparty\cubeb\extra" "-I.\..\3rdparty\cubeb\cubeb\include" "-I.\..\3rdparty\flatbuffers\include" "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\XAudio2Redist\include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtCore" "-I.\release" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtMultimedia" "-I$(QTDIR)\include\QtMultimediaWidgets" "-I$(QTDIR)\include\QtSvg"</Command>
|
||||
</CustomBuild>
|
||||
<ClInclude Include="rpcs3qt\movie_item.h" />
|
||||
<ClInclude Include="rpcs3qt\movie_item_base.h" />
|
||||
<ClInclude Include="rpcs3qt\numbered_widget_item.h" />
|
||||
<CustomBuild Include="rpcs3qt\patch_creator_dialog.h">
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Moc%27ing %(Identity)...</Message>
|
||||
@ -1310,6 +1386,16 @@
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWIN32_LEAN_AND_MEAN -DHAVE_VULKAN -DWITH_DISCORD_RPC -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DNDEBUG -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -DQT_MULTIMEDIA_LIB -DQT_MULTIMEDIAWIDGETS_LIB -DQT_SVG_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\SoundTouch\soundtouch\include" "-I.\..\3rdparty\cubeb\extra" "-I.\..\3rdparty\cubeb\cubeb\include" "-I.\..\3rdparty\flatbuffers\include" "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\XAudio2Redist\include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtCore" "-I.\release" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtMultimedia" "-I$(QTDIR)\include\QtMultimediaWidgets" "-I$(QTDIR)\include\QtSvg"</Command>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\screenshot_item.h">
|
||||
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Moc%27ing %(Identity)...</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWIN32_LEAN_AND_MEAN -DHAVE_VULKAN -DMINIUPNP_STATICLIB -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -DQT_MULTIMEDIA_LIB -DQT_MULTIMEDIAWIDGETS_LIB -DQT_SVG_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\SoundTouch\soundtouch\include" "-I.\..\3rdparty\cubeb\extra" "-I.\..\3rdparty\cubeb\cubeb\include" "-I.\..\3rdparty\flatbuffers\include" "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\XAudio2Redist\include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtMultimedia" "-I$(QTDIR)\include\QtMultimediaWidgets" "-I$(QTDIR)\include\QtSvg"</Command>
|
||||
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Moc%27ing %(Identity)...</Message>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWIN32_LEAN_AND_MEAN -DHAVE_VULKAN -DMINIUPNP_STATICLIB -DHAVE_SDL2 -DWITH_DISCORD_RPC -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DNDEBUG -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -DQT_MULTIMEDIA_LIB -DQT_MULTIMEDIAWIDGETS_LIB -DQT_SVG_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\SoundTouch\soundtouch\include" "-I.\..\3rdparty\cubeb\extra" "-I.\..\3rdparty\cubeb\cubeb\include" "-I.\..\3rdparty\flatbuffers\include" "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\libsdl-org\SDL\include" "-I.\..\3rdparty\XAudio2Redist\include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtCore" "-I.\release" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtMultimedia" "-I$(QTDIR)\include\QtMultimediaWidgets" "-I$(QTDIR)\include\QtSvg"</Command>
|
||||
</CustomBuild>
|
||||
<ClInclude Include="rpcs3qt\shortcut_utils.h" />
|
||||
<ClInclude Include="rpcs3qt\stylesheets.h" />
|
||||
<CustomBuild Include="rpcs3qt\skylander_dialog.h">
|
||||
@ -1416,7 +1502,6 @@
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWIN32_LEAN_AND_MEAN -DHAVE_VULKAN -DMINIUPNP_STATICLIB -DHAVE_SDL2 -DWITH_DISCORD_RPC -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DNDEBUG -DQT_WINEXTRAS_LIB -DQT_CONCURRENT_LIB -DQT_MULTIMEDIA_LIB -DQT_MULTIMEDIAWIDGETS_LIB -DQT_SVG_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\SoundTouch\soundtouch\include" "-I.\..\3rdparty\cubeb\extra" "-I.\..\3rdparty\cubeb\cubeb\include" "-I.\..\3rdparty\flatbuffers\include" "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I.\..\3rdparty\libsdl-org\SDL\include" "-I.\..\3rdparty\XAudio2Redist\include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtCore" "-I.\release" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(QTDIR)\include\QtConcurrent" "-I$(QTDIR)\include\QtMultimedia" "-I$(QTDIR)\include\QtMultimediaWidgets" "-I$(QTDIR)\include\QtSvg"</Command>
|
||||
</CustomBuild>
|
||||
<ClInclude Include="rpcs3qt\game_list_grid_delegate.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="rpcs3qt\gl_gs_frame.h" />
|
||||
<CustomBuild Include="rpcs3qt\syntax_highlighter.h">
|
||||
@ -1752,6 +1837,17 @@
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"$(QTDIR)\bin\uic.exe" -o ".\QTGeneratedFiles\ui_%(Filename).h" "%(FullPath)"</Command>
|
||||
</CustomBuild>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\bin\GuiConfigs\Classic (Bright).qss" />
|
||||
<None Include="..\bin\GuiConfigs\Darker Style by TheMitoSan.qss" />
|
||||
<None Include="..\bin\GuiConfigs\Envy.qss" />
|
||||
<None Include="..\bin\GuiConfigs\Kuroi (Dark) by Ani.qss" />
|
||||
<None Include="..\bin\GuiConfigs\ModernBlue Theme by TheMitoSan.qss" />
|
||||
<None Include="..\bin\GuiConfigs\Nekotekina by GooseWing.qss" />
|
||||
<None Include="..\bin\GuiConfigs\Skyline (Nightfall).qss" />
|
||||
<None Include="..\bin\GuiConfigs\Skyline.qss" />
|
||||
<None Include="..\bin\GuiConfigs\YoRHa by Ani.qss" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets" />
|
||||
<ProjectExtensions>
|
||||
|
@ -154,6 +154,9 @@
|
||||
<Filter Include="Gui\flow_layout">
|
||||
<UniqueIdentifier>{9191ae51-8b80-4606-b5bc-966a9588f538}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="StyleSheets">
|
||||
<UniqueIdentifier>{b927140a-5214-4628-a648-8380ae793179}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="main.cpp">
|
||||
@ -381,9 +384,6 @@
|
||||
<ClCompile Include="rpcs3qt\game_list_grid.cpp">
|
||||
<Filter>Gui\game list</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\game_list_grid_delegate.cpp">
|
||||
<Filter>Gui\game list</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\memory_string_searcher.cpp">
|
||||
<Filter>Gui\dev tools</Filter>
|
||||
</ClCompile>
|
||||
@ -954,6 +954,54 @@
|
||||
<ClCompile Include="rpcs3qt\flow_widget.cpp">
|
||||
<Filter>Gui\flow_layout</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\game_list_table.cpp">
|
||||
<Filter>Gui\game list</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Debug\moc_game_list_table.cpp">
|
||||
<Filter>Generated Files\Debug</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release\moc_game_list_table.cpp">
|
||||
<Filter>Generated Files\Release</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\game_list_base.cpp">
|
||||
<Filter>Gui\game list</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\movie_item_base.cpp">
|
||||
<Filter>Gui\custom items</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\game_list_grid_item.cpp">
|
||||
<Filter>Gui\game list</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Debug\moc_game_list_grid_item.cpp">
|
||||
<Filter>Generated Files\Debug</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release\moc_game_list_grid_item.cpp">
|
||||
<Filter>Generated Files\Release</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\flow_widget_item.cpp">
|
||||
<Filter>Gui\flow_layout</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Debug\moc_screenshot_item.cpp">
|
||||
<Filter>Generated Files\Debug</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release\moc_screenshot_item.cpp">
|
||||
<Filter>Generated Files\Release</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rpcs3qt\screenshot_item.cpp">
|
||||
<Filter>Gui\screenshot manager</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Debug\moc_flow_widget_item.cpp">
|
||||
<Filter>Generated Files\Debug</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release\moc_flow_widget_item.cpp">
|
||||
<Filter>Generated Files\Release</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Debug\moc_flow_widget.cpp">
|
||||
<Filter>Generated Files\Debug</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QTGeneratedFiles\Release\moc_flow_widget.cpp">
|
||||
<Filter>Generated Files\Release</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Input\ds4_pad_handler.h">
|
||||
@ -992,9 +1040,6 @@
|
||||
<ClInclude Include="rpcs3qt\gl_gs_frame.h">
|
||||
<Filter>Gui\game window</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="rpcs3qt\game_list_grid_delegate.h">
|
||||
<Filter>Gui\game list</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Input\evdev_joystick_handler.h">
|
||||
<Filter>Io\evdev</Filter>
|
||||
</ClInclude>
|
||||
@ -1130,6 +1175,9 @@
|
||||
<ClInclude Include="rpcs3qt\flow_layout.h">
|
||||
<Filter>Gui\flow_layout</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="rpcs3qt\movie_item_base.h">
|
||||
<Filter>Gui\custom items</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CustomBuild Include="debug\moc_predefs.h.cbt">
|
||||
@ -1408,6 +1456,21 @@
|
||||
<CustomBuild Include="rpcs3qt\flow_widget.h">
|
||||
<Filter>Gui\flow_layout</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\game_list_table.h">
|
||||
<Filter>Gui\game list</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\game_list_base.h">
|
||||
<Filter>Gui\game list</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\game_list_grid_item.h">
|
||||
<Filter>Gui\game list</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\screenshot_item.h">
|
||||
<Filter>Gui\screenshot manager</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="rpcs3qt\flow_widget_item.h">
|
||||
<Filter>Gui\flow_layout</Filter>
|
||||
</CustomBuild>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="rpcs3.ico" />
|
||||
@ -1415,4 +1478,33 @@
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="rpcs3.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\bin\GuiConfigs\Classic (Bright).qss">
|
||||
<Filter>StyleSheets</Filter>
|
||||
</None>
|
||||
<None Include="..\bin\GuiConfigs\Darker Style by TheMitoSan.qss">
|
||||
<Filter>StyleSheets</Filter>
|
||||
</None>
|
||||
<None Include="..\bin\GuiConfigs\YoRHa by Ani.qss">
|
||||
<Filter>StyleSheets</Filter>
|
||||
</None>
|
||||
<None Include="..\bin\GuiConfigs\Skyline.qss">
|
||||
<Filter>StyleSheets</Filter>
|
||||
</None>
|
||||
<None Include="..\bin\GuiConfigs\ModernBlue Theme by TheMitoSan.qss">
|
||||
<Filter>StyleSheets</Filter>
|
||||
</None>
|
||||
<None Include="..\bin\GuiConfigs\Nekotekina by GooseWing.qss">
|
||||
<Filter>StyleSheets</Filter>
|
||||
</None>
|
||||
<None Include="..\bin\GuiConfigs\Skyline (Nightfall).qss">
|
||||
<Filter>StyleSheets</Filter>
|
||||
</None>
|
||||
<None Include="..\bin\GuiConfigs\Kuroi (Dark) by Ani.qss">
|
||||
<Filter>StyleSheets</Filter>
|
||||
</None>
|
||||
<None Include="..\bin\GuiConfigs\Envy.qss">
|
||||
<Filter>StyleSheets</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -24,12 +24,15 @@ set(SRC_FILES
|
||||
find_dialog.cpp
|
||||
flow_layout.cpp
|
||||
flow_widget.cpp
|
||||
flow_widget_item.cpp
|
||||
game_compatibility.cpp
|
||||
game_list.cpp
|
||||
game_list_base.cpp
|
||||
game_list_delegate.cpp
|
||||
game_list_frame.cpp
|
||||
game_list_grid.cpp
|
||||
game_list_grid_delegate.cpp
|
||||
game_list_grid_item.cpp
|
||||
game_list_table.cpp
|
||||
gui_application.cpp
|
||||
gl_gs_frame.cpp
|
||||
gs_frame.cpp
|
||||
@ -47,6 +50,7 @@ set(SRC_FILES
|
||||
memory_viewer_panel.cpp
|
||||
microphone_creator.cpp
|
||||
movie_item.cpp
|
||||
movie_item_base.cpp
|
||||
msg_dialog_frame.cpp
|
||||
osk_dialog_frame.cpp
|
||||
pad_led_settings_dialog.cpp
|
||||
@ -73,6 +77,7 @@ set(SRC_FILES
|
||||
save_data_info_dialog.cpp
|
||||
save_data_list_dialog.cpp
|
||||
save_manager_dialog.cpp
|
||||
screenshot_item.cpp
|
||||
screenshot_manager_dialog.cpp
|
||||
screenshot_preview.cpp
|
||||
sendmessage_dialog_frame.cpp
|
||||
|
@ -51,14 +51,23 @@
|
||||
#include <QtWidgets>
|
||||
#include "flow_layout.h"
|
||||
|
||||
flow_layout::flow_layout(QWidget* parent, int margin, int hSpacing, int vSpacing)
|
||||
: QLayout(parent), m_hSpace(hSpacing), m_vSpace(vSpacing)
|
||||
flow_layout::flow_layout(QWidget* parent, int margin, bool dynamic_spacing, int hSpacing, int vSpacing)
|
||||
: QLayout(parent)
|
||||
, m_dynamic_spacing(dynamic_spacing)
|
||||
, m_hSpaceInitial(hSpacing)
|
||||
, m_vSpaceInitial(vSpacing)
|
||||
, m_hSpace(hSpacing)
|
||||
, m_vSpace(vSpacing)
|
||||
{
|
||||
setContentsMargins(margin, margin, margin, margin);
|
||||
}
|
||||
|
||||
flow_layout::flow_layout(int margin, int hSpacing, int vSpacing)
|
||||
: m_hSpace(hSpacing), m_vSpace(vSpacing)
|
||||
flow_layout::flow_layout(int margin, bool dynamic_spacing, int hSpacing, int vSpacing)
|
||||
: m_dynamic_spacing(dynamic_spacing)
|
||||
, m_hSpaceInitial(hSpacing)
|
||||
, m_vSpaceInitial(vSpacing)
|
||||
, m_hSpace(hSpacing)
|
||||
, m_vSpace(vSpacing)
|
||||
{
|
||||
setContentsMargins(margin, margin, margin, margin);
|
||||
}
|
||||
@ -76,10 +85,12 @@ void flow_layout::clear()
|
||||
delete item;
|
||||
}
|
||||
itemList.clear();
|
||||
m_positions.clear();
|
||||
}
|
||||
|
||||
void flow_layout::addItem(QLayoutItem* item)
|
||||
{
|
||||
m_positions.append(position{ .row = -1, .col = -1 });
|
||||
itemList.append(item);
|
||||
}
|
||||
|
||||
@ -116,7 +127,10 @@ QLayoutItem* flow_layout::itemAt(int index) const
|
||||
QLayoutItem* flow_layout::takeAt(int index)
|
||||
{
|
||||
if (index >= 0 && index < itemList.size())
|
||||
{
|
||||
m_positions.takeAt(index);
|
||||
return itemList.takeAt(index);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
@ -167,13 +181,57 @@ int flow_layout::doLayout(const QRect& rect, bool testOnly) const
|
||||
{
|
||||
int left, top, right, bottom;
|
||||
getContentsMargins(&left, &top, &right, &bottom);
|
||||
QRect effectiveRect = rect.adjusted(+left, +top, -right, -bottom);
|
||||
const QRect effectiveRect = rect.adjusted(+left, +top, -right, -bottom);
|
||||
int x = effectiveRect.x();
|
||||
int y = effectiveRect.y();
|
||||
int lineHeight = 0;
|
||||
int rows = 0;
|
||||
int cols = 0;
|
||||
|
||||
for (QLayoutItem* item : qAsConst(itemList))
|
||||
if (m_dynamic_spacing)
|
||||
{
|
||||
const int available_width = effectiveRect.width();
|
||||
const int min_spacing = smartSpacing(QStyle::PM_LayoutHorizontalSpacing);
|
||||
bool fits_into_width = true;
|
||||
int width = 0;
|
||||
int index = 0;
|
||||
|
||||
for (; index < itemList.size(); index++)
|
||||
{
|
||||
if (QLayoutItem* item = itemList.at(index))
|
||||
{
|
||||
const int new_width = width + item->sizeHint().width() + (width > 0 ? min_spacing : 0);
|
||||
|
||||
if (new_width > effectiveRect.width())
|
||||
{
|
||||
fits_into_width = false;
|
||||
break;
|
||||
}
|
||||
|
||||
width = new_width;
|
||||
}
|
||||
}
|
||||
|
||||
// Try to evenly distribute the items across the width
|
||||
m_hSpace = (index == 0) ? -1 : ((available_width - width) / index);
|
||||
|
||||
if (fits_into_width)
|
||||
{
|
||||
// Make sure there aren't huge gaps between the items
|
||||
m_hSpace = smartSpacing(QStyle::PM_LayoutHorizontalSpacing);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_hSpace = m_hSpaceInitial;
|
||||
}
|
||||
|
||||
for (int i = 0, row = 0, col = 0; i < itemList.size(); i++)
|
||||
{
|
||||
QLayoutItem* item = itemList.at(i);
|
||||
if (!item)
|
||||
continue;
|
||||
|
||||
const QWidget* wid = item->widget();
|
||||
if (!wid)
|
||||
continue;
|
||||
@ -193,20 +251,33 @@ int flow_layout::doLayout(const QRect& rect, bool testOnly) const
|
||||
y = y + lineHeight + spaceY;
|
||||
nextX = x + item->sizeHint().width() + spaceX;
|
||||
lineHeight = 0;
|
||||
col = 0;
|
||||
row++;
|
||||
}
|
||||
|
||||
position& pos = m_positions[i];
|
||||
pos.row = row;
|
||||
pos.col = col++;
|
||||
|
||||
rows = std::max(rows, pos.row + 1);
|
||||
cols = std::max(cols, pos.col + 1);
|
||||
|
||||
if (!testOnly)
|
||||
item->setGeometry(QRect(QPoint(x, y), item->sizeHint()));
|
||||
|
||||
x = nextX;
|
||||
lineHeight = qMax(lineHeight, item->sizeHint().height());
|
||||
}
|
||||
|
||||
m_rows = rows;
|
||||
m_cols = cols;
|
||||
|
||||
return y + lineHeight - rect.y() + bottom;
|
||||
}
|
||||
|
||||
int flow_layout::smartSpacing(QStyle::PixelMetric pm) const
|
||||
{
|
||||
QObject* parent = this->parent();
|
||||
const QObject* parent = this->parent();
|
||||
if (!parent)
|
||||
{
|
||||
return -1;
|
||||
@ -214,9 +285,9 @@ int flow_layout::smartSpacing(QStyle::PixelMetric pm) const
|
||||
|
||||
if (parent->isWidgetType())
|
||||
{
|
||||
QWidget* pw = static_cast<QWidget*>(parent);
|
||||
const QWidget* pw = static_cast<const QWidget*>(parent);
|
||||
return pw->style()->pixelMetric(pm, nullptr, pw);
|
||||
}
|
||||
|
||||
return static_cast<QLayout*>(parent)->spacing();
|
||||
return static_cast<const QLayout*>(parent)->spacing();
|
||||
}
|
||||
|
@ -57,15 +57,23 @@
|
||||
class flow_layout : public QLayout
|
||||
{
|
||||
public:
|
||||
explicit flow_layout(QWidget* parent, int margin = -1, int hSpacing = -1, int vSpacing = -1);
|
||||
explicit flow_layout(int margin = -1, int hSpacing = -1, int vSpacing = -1);
|
||||
struct position
|
||||
{
|
||||
int row{};
|
||||
int col{};
|
||||
};
|
||||
|
||||
explicit flow_layout(QWidget* parent, int margin = -1, bool dynamic_spacing = false, int hSpacing = -1, int vSpacing = -1);
|
||||
explicit flow_layout(int margin = -1, bool dynamic_spacing = false, int hSpacing = -1, int vSpacing = -1);
|
||||
~flow_layout();
|
||||
|
||||
void clear();
|
||||
const QList<QLayoutItem*>& item_list() const { return itemList; }
|
||||
const QList<position>& positions() const { return m_positions; }
|
||||
int rows() const { return m_rows; }
|
||||
int cols() const { return m_cols; }
|
||||
|
||||
void addItem(QLayoutItem* item) override;
|
||||
int horizontalSpacing() const;
|
||||
int verticalSpacing() const;
|
||||
Qt::Orientations expandingDirections() const override;
|
||||
bool hasHeightForWidth() const override;
|
||||
int heightForWidth(int) const override;
|
||||
@ -77,10 +85,19 @@ public:
|
||||
QLayoutItem* takeAt(int index) override;
|
||||
|
||||
private:
|
||||
int horizontalSpacing() const;
|
||||
int verticalSpacing() const;
|
||||
int doLayout(const QRect& rect, bool testOnly) const;
|
||||
int smartSpacing(QStyle::PixelMetric pm) const;
|
||||
|
||||
QList<QLayoutItem*> itemList;
|
||||
int m_hSpace;
|
||||
int m_vSpace;
|
||||
bool m_dynamic_spacing{};
|
||||
int m_hSpaceInitial{-1};
|
||||
int m_vSpaceInitial{-1};
|
||||
mutable int m_hSpace{-1};
|
||||
mutable int m_vSpace{-1};
|
||||
|
||||
mutable QList<position> m_positions;
|
||||
mutable int m_rows{};
|
||||
mutable int m_cols{};
|
||||
};
|
||||
|
@ -1,8 +1,10 @@
|
||||
#include "stdafx.h"
|
||||
#include "flow_widget.h"
|
||||
#include "flow_layout.h"
|
||||
|
||||
#include <QScrollArea>
|
||||
#include <QVBoxLayout>
|
||||
#include <QStyleOption>
|
||||
#include <QPainter>
|
||||
|
||||
flow_widget::flow_widget(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
@ -11,13 +13,15 @@ flow_widget::flow_widget(QWidget* parent)
|
||||
|
||||
QWidget* widget = new QWidget(this);
|
||||
widget->setLayout(m_flow_layout);
|
||||
widget->setObjectName("flow_widget_content");
|
||||
widget->setFocusProxy(this);
|
||||
|
||||
QScrollArea* scrollArea = new QScrollArea(this);
|
||||
scrollArea->setWidget(widget);
|
||||
scrollArea->setWidgetResizable(true);
|
||||
m_scroll_area = new QScrollArea(this);
|
||||
m_scroll_area->setWidget(widget);
|
||||
m_scroll_area->setWidgetResizable(true);
|
||||
|
||||
QVBoxLayout* layout = new QVBoxLayout(this);
|
||||
layout->addWidget(scrollArea);
|
||||
layout->addWidget(m_scroll_area);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
setLayout(layout);
|
||||
}
|
||||
@ -32,6 +36,9 @@ void flow_widget::add_widget(flow_widget_item* widget)
|
||||
{
|
||||
m_widgets << widget;
|
||||
m_flow_layout->addWidget(widget);
|
||||
|
||||
connect(widget, &flow_widget_item::navigate, this, &flow_widget::on_navigate);
|
||||
connect(widget, &flow_widget_item::focused, this, &flow_widget::on_item_focus);
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,19 +53,192 @@ QList<flow_widget_item*>& flow_widget::items()
|
||||
return m_widgets;
|
||||
}
|
||||
|
||||
void flow_widget_item::paintEvent(QPaintEvent* event)
|
||||
flow_widget_item* flow_widget::selected_item() const
|
||||
{
|
||||
QWidget::paintEvent(event);
|
||||
if (m_selected_index >= 0 && m_selected_index < m_widgets.size())
|
||||
{
|
||||
return ::at32(m_widgets, m_selected_index);
|
||||
}
|
||||
|
||||
if (!got_visible && cb_on_first_visibility)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QScrollArea* flow_widget::scroll_area() const
|
||||
{
|
||||
if (QWidget* widget = static_cast<QWidget*>(parent()))
|
||||
return m_scroll_area;
|
||||
}
|
||||
|
||||
void flow_widget::paintEvent(QPaintEvent* /*event*/)
|
||||
{
|
||||
if (widget->visibleRegion().intersects(geometry()))
|
||||
// Needed for stylesheets to apply to QWidgets
|
||||
QStyleOption option;
|
||||
option.initFrom(this);
|
||||
QPainter painter(this);
|
||||
style()->drawPrimitive(QStyle::PE_Widget, &option, &painter, this);
|
||||
}
|
||||
|
||||
int flow_widget::find_item(const flow_layout::position& pos)
|
||||
{
|
||||
got_visible = true;
|
||||
cb_on_first_visibility();
|
||||
if (pos.row < 0 || pos.col < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
const auto& positions = m_flow_layout->positions();
|
||||
|
||||
for (int i = 0; i < positions.size(); i++)
|
||||
{
|
||||
if (const auto& other = ::at32(positions, i); other.row == pos.row && other.col == pos.col)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
flow_layout::position flow_widget::find_item(flow_widget_item* item)
|
||||
{
|
||||
if (item)
|
||||
{
|
||||
const auto& item_list = m_flow_layout->item_list();
|
||||
const auto& positions = m_flow_layout->positions();
|
||||
ensure(item_list.size() == positions.size());
|
||||
|
||||
for (int i = 0; i < item_list.size(); i++)
|
||||
{
|
||||
if (const auto& layout_item = ::at32(item_list, i); layout_item && layout_item->widget() == item)
|
||||
{
|
||||
return ::at32(positions, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return flow_layout::position{ .row = -1, .col = - 1};
|
||||
}
|
||||
|
||||
flow_layout::position flow_widget::find_next_item(flow_layout::position current_pos, flow_navigation value)
|
||||
{
|
||||
if (current_pos.row >= 0 && current_pos.col >= 0 && m_flow_layout->rows() > 0 && m_flow_layout->cols() > 0)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case flow_navigation::up:
|
||||
// Go up one row.
|
||||
if (current_pos.row > 0)
|
||||
{
|
||||
current_pos.row--;
|
||||
}
|
||||
break;
|
||||
case flow_navigation::down:
|
||||
// Go down one row. Beware of last row which might have less columns.
|
||||
for (const auto& pos : m_flow_layout->positions())
|
||||
{;
|
||||
if (pos.col != current_pos.col) continue;
|
||||
if (pos.row == current_pos.row + 1)
|
||||
{
|
||||
current_pos.row = pos.row;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case flow_navigation::left:
|
||||
// Go left one column.
|
||||
if (current_pos.col > 0)
|
||||
{
|
||||
current_pos.col--;
|
||||
}
|
||||
break;
|
||||
case flow_navigation::right:
|
||||
// Go right one column. Beware of last row which might have less columns.
|
||||
for (const auto& pos : m_flow_layout->positions())
|
||||
{
|
||||
if (pos.row > current_pos.row) break;
|
||||
if (pos.row < current_pos.row) continue;
|
||||
if (pos.col == current_pos.col + 1)
|
||||
{
|
||||
current_pos.col = pos.col;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case flow_navigation::home:
|
||||
// Go to leftmost column.
|
||||
current_pos.col = 0;
|
||||
break;
|
||||
case flow_navigation::end:
|
||||
// Go to last column. Beware of last row which might have less columns.
|
||||
for (const auto& pos : m_flow_layout->positions())
|
||||
{
|
||||
if (pos.row > current_pos.row) break;
|
||||
if (pos.row < current_pos.row) continue;
|
||||
current_pos.col = std::max(current_pos.col, pos.col);
|
||||
}
|
||||
break;
|
||||
case flow_navigation::page_up:
|
||||
// Go to top row.
|
||||
current_pos.row = 0;
|
||||
break;
|
||||
case flow_navigation::page_down:
|
||||
// Go to bottom row. Beware of last row which might have less columns.
|
||||
for (const auto& pos : m_flow_layout->positions())
|
||||
{
|
||||
if (pos.col != current_pos.col) continue;
|
||||
current_pos.row = std::max(current_pos.row, pos.row);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return current_pos;
|
||||
}
|
||||
|
||||
void flow_widget::select_item(flow_widget_item* item)
|
||||
{
|
||||
const flow_layout::position selected_pos = find_item(item);
|
||||
const int selected_index = find_item(selected_pos);
|
||||
|
||||
if (selected_index < 0 || selected_index >= items().size())
|
||||
{
|
||||
m_selected_index = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
m_selected_index = selected_index;
|
||||
Q_EMIT ItemSelectionChanged(m_selected_index);
|
||||
|
||||
for (int i = 0; i < items().size(); i++)
|
||||
{
|
||||
if (flow_widget_item* item = items().at(i))
|
||||
{
|
||||
// We need to polish the widgets in order to re-apply any stylesheet changes for the selected property.
|
||||
item->selected = i == m_selected_index;
|
||||
item->polish_style();
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure we see the focused widget
|
||||
m_scroll_area->ensureWidgetVisible(::at32(items(), m_selected_index));
|
||||
}
|
||||
|
||||
void flow_widget::on_item_focus()
|
||||
{
|
||||
select_item(static_cast<flow_widget_item*>(QObject::sender()));
|
||||
}
|
||||
|
||||
void flow_widget::on_navigate(flow_navigation value)
|
||||
{
|
||||
const flow_layout::position selected_pos = find_next_item(find_item(static_cast<flow_widget_item*>(QObject::sender())), value);
|
||||
const int selected_index = find_item(selected_pos);
|
||||
if (selected_index < 0 || selected_index >= items().size())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (flow_widget_item* item = items().at(selected_index))
|
||||
{
|
||||
item->setFocus();
|
||||
}
|
||||
|
||||
m_selected_index = selected_index;
|
||||
}
|
||||
|
@ -1,21 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "flow_widget_item.h"
|
||||
#include "flow_layout.h"
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
class flow_layout;
|
||||
|
||||
class flow_widget_item : public QWidget
|
||||
{
|
||||
public:
|
||||
using QWidget::QWidget;
|
||||
void paintEvent(QPaintEvent* event) override;
|
||||
|
||||
bool got_visible{};
|
||||
std::function<void()> cb_on_first_visibility{};
|
||||
};
|
||||
#include <QScrollArea>
|
||||
#include <QPaintEvent>
|
||||
|
||||
class flow_widget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
flow_widget(QWidget* parent);
|
||||
virtual ~flow_widget();
|
||||
@ -24,8 +19,28 @@ public:
|
||||
void clear();
|
||||
|
||||
QList<flow_widget_item*>& items();
|
||||
flow_widget_item* selected_item() const;
|
||||
QScrollArea* scroll_area() const;
|
||||
|
||||
void paintEvent(QPaintEvent* event) override;
|
||||
|
||||
Q_SIGNALS:
|
||||
void ItemSelectionChanged(int index);
|
||||
|
||||
private Q_SLOTS:
|
||||
void on_item_focus();
|
||||
void on_navigate(flow_navigation value);
|
||||
|
||||
protected:
|
||||
void select_item(flow_widget_item* item);
|
||||
|
||||
private:
|
||||
int find_item(const flow_layout::position& pos);
|
||||
flow_layout::position find_item(flow_widget_item* item);
|
||||
flow_layout::position find_next_item(flow_layout::position current_pos, flow_navigation value);
|
||||
|
||||
flow_layout* m_flow_layout{};
|
||||
QScrollArea* m_scroll_area{};
|
||||
QList<flow_widget_item*> m_widgets{};
|
||||
int m_selected_index = -1;
|
||||
};
|
||||
|
116
rpcs3/rpcs3qt/flow_widget_item.cpp
Normal file
116
rpcs3/rpcs3qt/flow_widget_item.cpp
Normal file
@ -0,0 +1,116 @@
|
||||
#include "flow_widget_item.h"
|
||||
|
||||
#include <QStyle>
|
||||
#include <QStyleOption>
|
||||
#include <QPainter>
|
||||
|
||||
void flow_widget_item::polish_style()
|
||||
{
|
||||
style()->unpolish(this);
|
||||
style()->polish(this);
|
||||
}
|
||||
|
||||
void flow_widget_item::paintEvent(QPaintEvent* /*event*/)
|
||||
{
|
||||
// Needed for stylesheets to apply to QWidgets
|
||||
QStyleOption option;
|
||||
option.initFrom(this);
|
||||
QPainter painter(this);
|
||||
style()->drawPrimitive(QStyle::PE_Widget, &option, &painter, this);
|
||||
|
||||
if (!got_visible && cb_on_first_visibility)
|
||||
{
|
||||
if (QWidget* widget = static_cast<QWidget*>(parent()))
|
||||
{
|
||||
if (widget->visibleRegion().intersects(geometry()))
|
||||
{
|
||||
got_visible = true;
|
||||
cb_on_first_visibility();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void flow_widget_item::focusInEvent(QFocusEvent* event)
|
||||
{
|
||||
QWidget::focusInEvent(event);
|
||||
|
||||
// We need to polish the widgets in order to re-apply any stylesheet changes for the focus property.
|
||||
polish_style();
|
||||
|
||||
Q_EMIT focused();
|
||||
}
|
||||
|
||||
void flow_widget_item::focusOutEvent(QFocusEvent* event)
|
||||
{
|
||||
QWidget::focusOutEvent(event);
|
||||
|
||||
// We need to polish the widgets in order to re-apply any stylesheet changes for the focus property.
|
||||
polish_style();
|
||||
}
|
||||
|
||||
void flow_widget_item::keyPressEvent(QKeyEvent* event)
|
||||
{
|
||||
if (!event)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event->key())
|
||||
{
|
||||
case Qt::Key_Left:
|
||||
Q_EMIT navigate(flow_navigation::left);
|
||||
return;
|
||||
case Qt::Key_Right:
|
||||
Q_EMIT navigate(flow_navigation::right);
|
||||
return;
|
||||
case Qt::Key_Up:
|
||||
Q_EMIT navigate(flow_navigation::up);
|
||||
return;
|
||||
case Qt::Key_Down:
|
||||
Q_EMIT navigate(flow_navigation::down);
|
||||
return;
|
||||
case Qt::Key_Home:
|
||||
Q_EMIT navigate(flow_navigation::home);
|
||||
return;
|
||||
case Qt::Key_End:
|
||||
Q_EMIT navigate(flow_navigation::end);
|
||||
return;
|
||||
case Qt::Key_PageUp:
|
||||
Q_EMIT navigate(flow_navigation::page_up);
|
||||
return;
|
||||
case Qt::Key_PageDown:
|
||||
Q_EMIT navigate(flow_navigation::page_down);
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
QWidget::keyPressEvent(event);
|
||||
}
|
||||
|
||||
bool flow_widget_item::event(QEvent* event)
|
||||
{
|
||||
bool hover_changed = false;
|
||||
|
||||
switch (event->type())
|
||||
{
|
||||
case QEvent::HoverEnter:
|
||||
hover_changed = setProperty("hover", "true");
|
||||
break;
|
||||
case QEvent::HoverLeave:
|
||||
hover_changed = setProperty("hover", "false");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (hover_changed)
|
||||
{
|
||||
// We need to polish the widgets in order to re-apply any stylesheet changes for the custom hover property.
|
||||
// :hover does not work if we add descendants in the qss, so we need to use a custom property.
|
||||
polish_style();
|
||||
}
|
||||
|
||||
return QWidget::event(event);
|
||||
}
|
48
rpcs3/rpcs3qt/flow_widget_item.h
Normal file
48
rpcs3/rpcs3qt/flow_widget_item.h
Normal file
@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWidget>
|
||||
#include <QKeyEvent>
|
||||
|
||||
#include <functional>
|
||||
|
||||
enum class flow_navigation
|
||||
{
|
||||
up,
|
||||
down,
|
||||
left,
|
||||
right,
|
||||
home,
|
||||
end,
|
||||
page_up,
|
||||
page_down
|
||||
};
|
||||
|
||||
class flow_widget_item : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(bool hover MEMBER m_hover) // Stylesheet workaround for descendants with parent pseudo state
|
||||
Q_PROPERTY(bool selected MEMBER selected) // Stylesheet workaround for descendants with parent pseudo state
|
||||
|
||||
public:
|
||||
using QWidget::QWidget;
|
||||
|
||||
virtual void polish_style();
|
||||
|
||||
void paintEvent(QPaintEvent* event) override;
|
||||
void focusInEvent(QFocusEvent* event) override;
|
||||
void focusOutEvent(QFocusEvent* event) override;
|
||||
void keyPressEvent(QKeyEvent* event) override;
|
||||
bool event(QEvent* event) override;
|
||||
|
||||
bool got_visible{};
|
||||
bool selected{};
|
||||
std::function<void()> cb_on_first_visibility{};
|
||||
|
||||
protected:
|
||||
bool m_hover{};
|
||||
|
||||
Q_SIGNALS:
|
||||
void navigate(flow_navigation value);
|
||||
void focused();
|
||||
};
|
@ -1,6 +1,15 @@
|
||||
#include "stdafx.h"
|
||||
#include "game_list.h"
|
||||
#include "movie_item.h"
|
||||
|
||||
game_list::game_list() : QTableWidget(), game_list_base()
|
||||
{
|
||||
m_icon_ready_callback = [this](const game_info& game)
|
||||
{
|
||||
Q_EMIT IconReady(game);
|
||||
};
|
||||
}
|
||||
|
||||
void game_list::clear_list()
|
||||
{
|
||||
m_last_hover_item = nullptr;
|
||||
|
@ -3,46 +3,31 @@
|
||||
#include <QTableWidget>
|
||||
#include <QMouseEvent>
|
||||
#include <QKeyEvent>
|
||||
#include <QPixmap>
|
||||
|
||||
#include "game_compatibility.h"
|
||||
#include "Emu/GameInfo.h"
|
||||
#include "game_list_base.h"
|
||||
#include "util/atomic.hpp"
|
||||
|
||||
class movie_item;
|
||||
|
||||
/* Having the icons associated with the game info simplifies logic internally */
|
||||
struct gui_game_info
|
||||
{
|
||||
GameInfo info{};
|
||||
QString localized_category;
|
||||
compat::status compat;
|
||||
QPixmap icon;
|
||||
QPixmap pxmap;
|
||||
bool hasCustomConfig = false;
|
||||
bool hasCustomPadConfig = false;
|
||||
bool has_hover_gif = false;
|
||||
movie_item* item = nullptr;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<gui_game_info> game_info;
|
||||
Q_DECLARE_METATYPE(game_info)
|
||||
|
||||
/*
|
||||
class used in order to get deselection and hover change
|
||||
if you know a simpler way, tell @Megamouse
|
||||
*/
|
||||
class game_list : public QTableWidget
|
||||
class game_list : public QTableWidget, public game_list_base
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
void clear_list(); // Use this instead of clearContents
|
||||
game_list();
|
||||
|
||||
void clear_list() override; // Use this instead of clearContents
|
||||
|
||||
public Q_SLOTS:
|
||||
void FocusAndSelectFirstEntryIfNoneIs();
|
||||
|
||||
Q_SIGNALS:
|
||||
void FocusToSearchBar();
|
||||
void IconReady(const game_info& game);
|
||||
|
||||
protected:
|
||||
movie_item* m_last_hover_item = nullptr;
|
||||
|
227
rpcs3/rpcs3qt/game_list_base.cpp
Normal file
227
rpcs3/rpcs3qt/game_list_base.cpp
Normal file
@ -0,0 +1,227 @@
|
||||
#include "stdafx.h"
|
||||
#include "game_list_base.h"
|
||||
#include "localized.h"
|
||||
|
||||
#include <QDir>
|
||||
|
||||
#include <cmath>
|
||||
#include <unordered_set>
|
||||
|
||||
LOG_CHANNEL(game_list_log, "GameList");
|
||||
|
||||
game_list_base::game_list_base()
|
||||
{
|
||||
}
|
||||
|
||||
void game_list_base::repaint_icons(QList<game_info>& game_data, const QColor& icon_color, const QSize& icon_size, qreal device_pixel_ratio)
|
||||
{
|
||||
m_icon_size = icon_size;
|
||||
m_icon_color = icon_color;
|
||||
|
||||
QPixmap placeholder(icon_size * device_pixel_ratio);
|
||||
placeholder.setDevicePixelRatio(device_pixel_ratio);
|
||||
placeholder.fill(Qt::transparent);
|
||||
|
||||
for (game_info& game : game_data)
|
||||
{
|
||||
game->pxmap = placeholder;
|
||||
|
||||
if (movie_item_base* item = game->item)
|
||||
{
|
||||
item->set_icon_load_func([this, game, device_pixel_ratio, cancel = item->icon_loading_aborted()](int)
|
||||
{
|
||||
IconLoadFunction(game, device_pixel_ratio, cancel);
|
||||
});
|
||||
|
||||
item->call_icon_func();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void game_list_base::IconLoadFunction(game_info game, qreal device_pixel_ratio, std::shared_ptr<atomic_t<bool>> cancel)
|
||||
{
|
||||
if (cancel && cancel->load())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
static std::unordered_set<std::string> warn_once_list;
|
||||
static shared_mutex s_mtx;
|
||||
|
||||
if (game->icon.isNull() && (game->info.icon_path.empty() || !game->icon.load(QString::fromStdString(game->info.icon_path))))
|
||||
{
|
||||
if (game_list_log.warning)
|
||||
{
|
||||
bool logged = false;
|
||||
{
|
||||
std::lock_guard lock(s_mtx);
|
||||
logged = !warn_once_list.emplace(game->info.icon_path).second;
|
||||
}
|
||||
|
||||
if (!logged)
|
||||
{
|
||||
game_list_log.warning("Could not load image from path %s", QDir(QString::fromStdString(game->info.icon_path)).absolutePath().toStdString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!game->item || (cancel && cancel->load()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const QColor color = GetGridCompatibilityColor(game->compat.color);
|
||||
{
|
||||
std::lock_guard lock(game->item->pixmap_mutex);
|
||||
game->pxmap = PaintedPixmap(game->icon, device_pixel_ratio, game->hasCustomConfig, game->hasCustomPadConfig, color);
|
||||
}
|
||||
|
||||
if (!cancel || !cancel->load())
|
||||
{
|
||||
if (m_icon_ready_callback)
|
||||
m_icon_ready_callback(game);
|
||||
}
|
||||
}
|
||||
|
||||
QPixmap game_list_base::PaintedPixmap(const QPixmap& icon, qreal device_pixel_ratio, bool paint_config_icon, bool paint_pad_config_icon, const QColor& compatibility_color) const
|
||||
{
|
||||
QSize canvas_size(320, 176);
|
||||
QSize icon_size(icon.size());
|
||||
QPoint target_pos;
|
||||
|
||||
if (!icon.isNull())
|
||||
{
|
||||
// Let's upscale the original icon to at least fit into the outer rect of the size of PS3's ICON0.PNG
|
||||
if (icon_size.width() < 320 || icon_size.height() < 176)
|
||||
{
|
||||
icon_size.scale(320, 176, Qt::KeepAspectRatio);
|
||||
}
|
||||
|
||||
canvas_size = icon_size;
|
||||
|
||||
// Calculate the centered size and position of the icon on our canvas.
|
||||
if (icon_size.width() != 320 || icon_size.height() != 176)
|
||||
{
|
||||
ensure(icon_size.height() > 0);
|
||||
constexpr double target_ratio = 320.0 / 176.0; // aspect ratio 20:11
|
||||
|
||||
if ((icon_size.width() / static_cast<double>(icon_size.height())) > target_ratio)
|
||||
{
|
||||
canvas_size.setHeight(std::ceil(icon_size.width() / target_ratio));
|
||||
}
|
||||
else
|
||||
{
|
||||
canvas_size.setWidth(std::ceil(icon_size.height() * target_ratio));
|
||||
}
|
||||
|
||||
target_pos.setX(std::max<int>(0, (canvas_size.width() - icon_size.width()) / 2.0));
|
||||
target_pos.setY(std::max<int>(0, (canvas_size.height() - icon_size.height()) / 2.0));
|
||||
}
|
||||
}
|
||||
|
||||
// Create a canvas large enough to fit our entire scaled icon
|
||||
QPixmap canvas(canvas_size * device_pixel_ratio);
|
||||
canvas.setDevicePixelRatio(device_pixel_ratio);
|
||||
canvas.fill(m_icon_color);
|
||||
|
||||
// Create a painter for our canvas
|
||||
QPainter painter(&canvas);
|
||||
painter.setRenderHint(QPainter::SmoothPixmapTransform);
|
||||
|
||||
// Draw the icon onto our canvas
|
||||
if (!icon.isNull())
|
||||
{
|
||||
painter.drawPixmap(target_pos.x(), target_pos.y(), icon_size.width(), icon_size.height(), icon);
|
||||
}
|
||||
|
||||
// Draw config icons if necessary
|
||||
if (!m_is_list_layout && (paint_config_icon || paint_pad_config_icon))
|
||||
{
|
||||
const int width = canvas_size.width() * 0.2;
|
||||
const QPoint origin = QPoint(canvas_size.width() - width, 0);
|
||||
QString icon_path;
|
||||
|
||||
if (paint_config_icon && paint_pad_config_icon)
|
||||
{
|
||||
icon_path = ":/Icons/combo_config_bordered.png";
|
||||
}
|
||||
else if (paint_config_icon)
|
||||
{
|
||||
icon_path = ":/Icons/custom_config.png";
|
||||
}
|
||||
else if (paint_pad_config_icon)
|
||||
{
|
||||
icon_path = ":/Icons/controllers.png";
|
||||
}
|
||||
|
||||
QPixmap custom_config_icon(icon_path);
|
||||
custom_config_icon.setDevicePixelRatio(device_pixel_ratio);
|
||||
painter.drawPixmap(origin, custom_config_icon.scaled(QSize(width, width) * device_pixel_ratio, Qt::KeepAspectRatio, Qt::TransformationMode::SmoothTransformation));
|
||||
}
|
||||
|
||||
// Draw game compatibility icons if necessary
|
||||
if (compatibility_color.isValid())
|
||||
{
|
||||
const int size = canvas_size.height() * 0.2;
|
||||
const int spacing = canvas_size.height() * 0.05;
|
||||
QColor copyColor = QColor(compatibility_color);
|
||||
copyColor.setAlpha(215); // ~85% opacity
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
painter.setBrush(QBrush(copyColor));
|
||||
painter.setPen(QPen(Qt::black, std::max(canvas_size.width() / 320, canvas_size.height() / 176)));
|
||||
painter.drawEllipse(spacing, spacing, size, size);
|
||||
}
|
||||
|
||||
// Finish the painting
|
||||
painter.end();
|
||||
|
||||
// Scale and return our final image
|
||||
return canvas.scaled(m_icon_size * device_pixel_ratio, Qt::KeepAspectRatio, Qt::TransformationMode::SmoothTransformation);
|
||||
}
|
||||
|
||||
QColor game_list_base::GetGridCompatibilityColor(const QString& string) const
|
||||
{
|
||||
if (m_draw_compat_status_to_grid && !m_is_list_layout)
|
||||
{
|
||||
return QColor(string);
|
||||
}
|
||||
return QColor();
|
||||
}
|
||||
|
||||
std::string game_list_base::GetGameVersion(const game_info& game)
|
||||
{
|
||||
if (game->info.app_ver == Localized().category.unknown.toStdString())
|
||||
{
|
||||
// Fall back to Disc/Pkg Revision
|
||||
return game->info.version;
|
||||
}
|
||||
|
||||
return game->info.app_ver;
|
||||
}
|
||||
|
||||
QIcon game_list_base::GetCustomConfigIcon(const game_info& game)
|
||||
{
|
||||
if (!game)
|
||||
return {};
|
||||
|
||||
static const QIcon icon_combo_config_bordered(":/Icons/combo_config_bordered.png");
|
||||
static const QIcon icon_custom_config(":/Icons/custom_config.png");
|
||||
static const QIcon icon_controllers(":/Icons/controllers.png");
|
||||
|
||||
if (game->hasCustomConfig && game->hasCustomPadConfig)
|
||||
{
|
||||
return icon_combo_config_bordered;
|
||||
}
|
||||
|
||||
if (game->hasCustomConfig)
|
||||
{
|
||||
return icon_custom_config;
|
||||
}
|
||||
|
||||
if (game->hasCustomPadConfig)
|
||||
{
|
||||
return icon_controllers;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
63
rpcs3/rpcs3qt/game_list_base.h
Normal file
63
rpcs3/rpcs3qt/game_list_base.h
Normal file
@ -0,0 +1,63 @@
|
||||
#pragma once
|
||||
|
||||
#include "movie_item_base.h"
|
||||
#include "game_compatibility.h"
|
||||
#include "Emu/GameInfo.h"
|
||||
|
||||
#include <QIcon>
|
||||
#include <QPixmap>
|
||||
#include <QWidget>
|
||||
|
||||
/* Having the icons associated with the game info simplifies logic internally */
|
||||
struct gui_game_info
|
||||
{
|
||||
GameInfo info{};
|
||||
QString localized_category;
|
||||
compat::status compat;
|
||||
QPixmap icon;
|
||||
QPixmap pxmap;
|
||||
bool hasCustomConfig = false;
|
||||
bool hasCustomPadConfig = false;
|
||||
bool has_hover_gif = false;
|
||||
movie_item_base* item = nullptr;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<gui_game_info> game_info;
|
||||
Q_DECLARE_METATYPE(game_info)
|
||||
|
||||
class game_list_base
|
||||
{
|
||||
public:
|
||||
game_list_base();
|
||||
|
||||
virtual void clear_list(){};
|
||||
virtual void populate(
|
||||
[[maybe_unused]] const std::vector<game_info>& game_data,
|
||||
[[maybe_unused]] const QMap<QString, QString>& notes_map,
|
||||
[[maybe_unused]] const QMap<QString, QString>& title_map,
|
||||
[[maybe_unused]] const std::string& selected_item_id,
|
||||
[[maybe_unused]] bool play_hover_movies){};
|
||||
|
||||
void set_icon_size(QSize size) { m_icon_size = std::move(size); }
|
||||
void set_icon_color(QColor color) { m_icon_color = std::move(color); }
|
||||
void set_draw_compat_status_to_grid(bool enabled) { m_draw_compat_status_to_grid = enabled; }
|
||||
|
||||
virtual void repaint_icons(QList<game_info>& game_data, const QColor& icon_color, const QSize& icon_size, qreal device_pixel_ratio);
|
||||
|
||||
// Returns the visible version string in the game list
|
||||
static std::string GetGameVersion(const game_info& game);
|
||||
|
||||
/** Sets the custom config icon. */
|
||||
static QIcon GetCustomConfigIcon(const game_info& game);
|
||||
|
||||
protected:
|
||||
void IconLoadFunction(game_info game, qreal device_pixel_ratio, std::shared_ptr<atomic_t<bool>> cancel);
|
||||
QPixmap PaintedPixmap(const QPixmap& icon, qreal device_pixel_ratio, bool paint_config_icon = false, bool paint_pad_config_icon = false, const QColor& compatibility_color = {}) const;
|
||||
QColor GetGridCompatibilityColor(const QString& string) const;
|
||||
|
||||
std::function<void(const game_info&)> m_icon_ready_callback{};
|
||||
bool m_draw_compat_status_to_grid{};
|
||||
bool m_is_list_layout{};
|
||||
QSize m_icon_size{};
|
||||
QColor m_icon_color{};
|
||||
};
|
File diff suppressed because it is too large
Load Diff
@ -19,6 +19,7 @@
|
||||
#include <memory>
|
||||
#include <set>
|
||||
|
||||
class game_list_table;
|
||||
class game_list_grid;
|
||||
class gui_settings;
|
||||
class emu_settings;
|
||||
@ -33,12 +34,6 @@ public:
|
||||
explicit game_list_frame(std::shared_ptr<gui_settings> gui_settings, std::shared_ptr<emu_settings> emu_settings, std::shared_ptr<persistent_settings> persistent_settings, QWidget* parent = nullptr);
|
||||
~game_list_frame();
|
||||
|
||||
/** Fix columns with width smaller than the minimal section size */
|
||||
void FixNarrowColumns() const;
|
||||
|
||||
/** Resizes the columns to their contents and adds a small spacing */
|
||||
void ResizeColumnsToContents(int spacing = 20) const;
|
||||
|
||||
/** Refresh the gamelist with/without loading game data from files. Public so that main frame can refresh after vfs or install */
|
||||
void Refresh(const bool from_drive = false, const bool scroll_after = true);
|
||||
|
||||
@ -63,11 +58,10 @@ public:
|
||||
|
||||
const QList<game_info>& GetGameInfo() const;
|
||||
|
||||
// Returns the visible version string in the game list
|
||||
static std::string GetGameVersion(const game_info& game);
|
||||
|
||||
void CreateShortcuts(const game_info& gameinfo, const std::set<gui::utils::shortcut_location>& locations);
|
||||
|
||||
bool IsEntryVisible(const game_info& game, bool search_fallback = false) const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void BatchCreatePPUCaches();
|
||||
void BatchRemovePPUCaches();
|
||||
@ -89,6 +83,7 @@ private Q_SLOTS:
|
||||
void OnColClicked(int col);
|
||||
void ShowContextMenu(const QPoint &pos);
|
||||
void doubleClickedSlot(QTableWidgetItem *item);
|
||||
void doubleClickedSlot(const game_info& game);
|
||||
void ItemSelectionChangedSlot();
|
||||
Q_SIGNALS:
|
||||
void GameListFrameClosed();
|
||||
@ -96,28 +91,15 @@ Q_SIGNALS:
|
||||
void RequestBoot(const game_info& game, cfg_mode config_mode = cfg_mode::custom, const std::string& config_path = "", const std::string& savestate = "");
|
||||
void RequestIconSizeChange(const int& val);
|
||||
void NotifyEmuSettingsChange();
|
||||
void IconReady(const game_info& game);
|
||||
void SizeOnDiskReady(const game_info& game);
|
||||
void FocusToSearchBar();
|
||||
protected:
|
||||
/** Override inherited method from Qt to allow signalling when close happened.*/
|
||||
void closeEvent(QCloseEvent* event) override;
|
||||
void resizeEvent(QResizeEvent *event) override;
|
||||
bool eventFilter(QObject *object, QEvent *event) override;
|
||||
private:
|
||||
void push_path(const std::string& path, std::vector<std::string>& legit_paths);
|
||||
|
||||
QPixmap PaintedPixmap(const QPixmap& icon, bool paint_config_icon = false, bool paint_pad_config_icon = false, const QColor& color = QColor()) const;
|
||||
QColor getGridCompatibilityColor(const QString& string) const;
|
||||
void IconLoadFunction(game_info game, std::shared_ptr<atomic_t<bool>> cancel);
|
||||
|
||||
/** Sets the custom config icon. Only call this for list title items. */
|
||||
void SetCustomConfigIcon(QTableWidgetItem* title_item, const game_info& game);
|
||||
void ShowCustomConfigIcon(const game_info& game);
|
||||
void PopulateGameList();
|
||||
void PopulateGameGrid(int maxCols, const QSize& image_size, const QColor& image_color);
|
||||
bool IsEntryVisible(const game_info& game, bool search_fallback = false);
|
||||
void SortGameList();
|
||||
bool SearchMatchesApp(const QString& name, const QString& serial, bool fallback = false) const;
|
||||
|
||||
bool RemoveCustomConfiguration(const std::string& title_id, const game_info& game = nullptr, bool is_interactive = false);
|
||||
@ -128,11 +110,9 @@ private:
|
||||
static bool CreatePPUCache(const std::string& path, const std::string& serial = {});
|
||||
static bool CreatePPUCache(const game_info& game);
|
||||
|
||||
QString GetLastPlayedBySerial(const QString& serial) const;
|
||||
static std::string GetCacheDirBySerial(const std::string& serial);
|
||||
static std::string GetDataDirBySerial(const std::string& serial);
|
||||
std::string CurrentSelectionPath();
|
||||
static std::string GetStringFromU32(const u32& key, const std::map<u32, QString>& map, bool combined = false);
|
||||
|
||||
game_info GetGameInfoByMode(const QTableWidgetItem* item) const;
|
||||
static game_info GetGameInfoFromItem(const QTableWidgetItem* item);
|
||||
@ -148,13 +128,13 @@ private:
|
||||
game_list_grid* m_game_grid = nullptr;
|
||||
|
||||
// Game List
|
||||
game_list* m_game_list = nullptr;
|
||||
game_list_table* m_game_list = nullptr;
|
||||
game_compatibility* m_game_compat = nullptr;
|
||||
progress_dialog* m_progress_dialog = nullptr;
|
||||
QTimer* m_progress_dialog_timer = nullptr;
|
||||
QList<QAction*> m_columnActs;
|
||||
Qt::SortOrder m_col_sort_order;
|
||||
int m_sort_column;
|
||||
Qt::SortOrder m_col_sort_order{};
|
||||
int m_sort_column{};
|
||||
bool m_initial_refresh_done = false;
|
||||
QMap<QString, QString> m_notes;
|
||||
QMap<QString, QString> m_titles;
|
||||
|
@ -1,125 +1,100 @@
|
||||
#include "stdafx.h"
|
||||
#include "game_list_grid.h"
|
||||
#include "game_list_grid_delegate.h"
|
||||
#include "game_list_grid_item.h"
|
||||
#include "movie_item.h"
|
||||
#include "gui_settings.h"
|
||||
#include "qt_utils.h"
|
||||
#include "Utilities/File.h"
|
||||
|
||||
#include <QHeaderView>
|
||||
#include <QScrollBar>
|
||||
#include <QApplication>
|
||||
#include <QStringBuilder>
|
||||
|
||||
game_list_grid::game_list_grid(const QSize& icon_size, QColor icon_color, const qreal& margin_factor, const qreal& text_factor, const bool& showText)
|
||||
: game_list()
|
||||
, m_icon_size(icon_size)
|
||||
, m_icon_color(std::move(icon_color))
|
||||
, m_margin_factor(margin_factor)
|
||||
, m_text_factor(text_factor)
|
||||
, m_text_enabled(showText)
|
||||
game_list_grid::game_list_grid()
|
||||
: flow_widget(nullptr), game_list_base()
|
||||
{
|
||||
setObjectName("game_grid");
|
||||
|
||||
QSize item_size;
|
||||
if (m_text_enabled)
|
||||
{
|
||||
item_size = m_icon_size + QSize(m_icon_size.width() * m_margin_factor * 2, m_icon_size.height() * m_margin_factor * (m_text_factor + 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
item_size = m_icon_size + m_icon_size * m_margin_factor * 2;
|
||||
}
|
||||
|
||||
grid_item_delegate = new game_list_grid_delegate(item_size, m_margin_factor, m_text_factor, this);
|
||||
setItemDelegate(grid_item_delegate);
|
||||
setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||
setSelectionBehavior(QAbstractItemView::SelectItems);
|
||||
setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
|
||||
setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
|
||||
verticalScrollBar()->setSingleStep(20);
|
||||
horizontalScrollBar()->setSingleStep(20);
|
||||
setObjectName("game_list_grid");
|
||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
verticalHeader()->setVisible(false);
|
||||
horizontalHeader()->setVisible(false);
|
||||
setShowGrid(false);
|
||||
setMouseTracking(true);
|
||||
|
||||
m_icon_ready_callback = [this](const game_info& game)
|
||||
{
|
||||
Q_EMIT IconReady(game);
|
||||
};
|
||||
|
||||
connect(this, &game_list_grid::IconReady, this, [this](const game_info& game)
|
||||
{
|
||||
if (!game || !game->item) return;
|
||||
game->item->call_icon_func();
|
||||
}, Qt::QueuedConnection); // The default 'AutoConnection' doesn't seem to work in this specific case...
|
||||
|
||||
connect(this, &flow_widget::ItemSelectionChanged, this, [this](int index)
|
||||
{
|
||||
if (game_list_grid_item* item = static_cast<game_list_grid_item*>(::at32(items(), index)))
|
||||
{
|
||||
Q_EMIT ItemSelectionChanged(item->game());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void game_list_grid::enableText(const bool& enabled)
|
||||
void game_list_grid::clear_list()
|
||||
{
|
||||
m_text_enabled = enabled;
|
||||
clear();
|
||||
}
|
||||
|
||||
void game_list_grid::setIconSize(const QSize& size) const
|
||||
void game_list_grid::populate(
|
||||
const std::vector<game_info>& game_data,
|
||||
const QMap<QString, QString>& notes_map,
|
||||
const QMap<QString, QString>& title_map,
|
||||
const std::string& selected_item_id,
|
||||
bool play_hover_movies)
|
||||
{
|
||||
if (m_text_enabled)
|
||||
clear_list();
|
||||
|
||||
const QString game_icon_path = play_hover_movies ? QString::fromStdString(fs::get_config_dir() + "/Icons/game_icons/") : "";
|
||||
game_list_grid_item* selected_item = nullptr;
|
||||
|
||||
blockSignals(true);
|
||||
|
||||
for (const auto& game : game_data)
|
||||
{
|
||||
grid_item_delegate->setItemSize(size + QSize(size.width() * m_margin_factor * 2, size.height() * m_margin_factor * (m_text_factor + 1)));
|
||||
const QString serial = QString::fromStdString(game->info.serial);
|
||||
const QString title = title_map.value(serial, QString::fromStdString(game->info.name)).simplified();
|
||||
const QString notes = notes_map.value(serial);
|
||||
|
||||
game_list_grid_item* item = new game_list_grid_item(this, game, title);
|
||||
item->installEventFilter(this);
|
||||
item->setFocusPolicy(Qt::StrongFocus);
|
||||
|
||||
game->item = item;
|
||||
|
||||
if (notes.isEmpty())
|
||||
{
|
||||
item->setToolTip(tr("%0 [%1]").arg(title).arg(serial));
|
||||
}
|
||||
else
|
||||
{
|
||||
grid_item_delegate->setItemSize(size + size * m_margin_factor * 2);
|
||||
}
|
||||
item->setToolTip(tr("%0 [%1]\n\nNotes:\n%2").arg(title).arg(serial).arg(notes));
|
||||
}
|
||||
|
||||
movie_item* game_list_grid::addItem(const game_info& app, const QString& name, const QString& movie_path, const int& row, const int& col)
|
||||
item->set_icon_func([this, item, game](int)
|
||||
{
|
||||
// create item with expanded image, title and position
|
||||
movie_item* item = new movie_item;
|
||||
|
||||
item->set_icon_func([this, app, item](int)
|
||||
{
|
||||
if (!item)
|
||||
if (!item || !game)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const qreal device_pixel_ratio = devicePixelRatioF();
|
||||
|
||||
// define size of expanded image, which is raw image size + margins
|
||||
QSizeF exp_size_f;
|
||||
if (m_text_enabled)
|
||||
if (std::shared_ptr<QMovie> movie = item->movie(); movie && item->get_active())
|
||||
{
|
||||
exp_size_f = m_icon_size + QSizeF(m_icon_size.width() * m_margin_factor * 2, m_icon_size.height() * m_margin_factor * (m_text_factor + 1));
|
||||
item->set_icon(gui::utils::get_centered_pixmap(movie->currentPixmap(), m_icon_size, 0, 0, 1.0, Qt::FastTransformation));
|
||||
}
|
||||
else
|
||||
{
|
||||
exp_size_f = m_icon_size + m_icon_size * m_margin_factor * 2;
|
||||
}
|
||||
std::lock_guard lock(item->pixmap_mutex);
|
||||
|
||||
std::shared_ptr<QMovie> movie = item->movie();
|
||||
const bool draw_movie_frame = movie && movie->isValid() && item->get_active();
|
||||
const QSize exp_size = (exp_size_f * device_pixel_ratio).toSize();
|
||||
item->set_icon(game->pxmap);
|
||||
|
||||
// create empty canvas for expanded image
|
||||
QImage exp_img(exp_size, QImage::Format_ARGB32);
|
||||
exp_img.setDevicePixelRatio(device_pixel_ratio);
|
||||
exp_img.fill(Qt::transparent);
|
||||
|
||||
// define offset for raw image placement
|
||||
QPoint offset(m_icon_size.width() * m_margin_factor, m_icon_size.height() * m_margin_factor);
|
||||
|
||||
// place raw image inside expanded image
|
||||
QPainter painter(&exp_img);
|
||||
painter.setRenderHint(QPainter::SmoothPixmapTransform);
|
||||
|
||||
if (draw_movie_frame)
|
||||
if (!game->has_hover_gif)
|
||||
{
|
||||
const QPixmap scaled_movie_frame = movie->currentPixmap().scaled(m_icon_size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
offset += QPoint(m_icon_size.width() / 2 - scaled_movie_frame.width() / 2,
|
||||
m_icon_size.height() / 2 - scaled_movie_frame.height() / 2);
|
||||
painter.drawPixmap(offset, scaled_movie_frame);
|
||||
}
|
||||
else
|
||||
{
|
||||
// create background for image
|
||||
QImage bg_img(app->pxmap.size(), QImage::Format_ARGB32);
|
||||
bg_img.setDevicePixelRatio(device_pixel_ratio);
|
||||
bg_img.fill(m_icon_color);
|
||||
|
||||
painter.drawImage(offset, bg_img);
|
||||
painter.drawPixmap(offset, app->pxmap);
|
||||
|
||||
if (!app->has_hover_gif)
|
||||
{
|
||||
app->pxmap = {};
|
||||
game->pxmap = {};
|
||||
}
|
||||
|
||||
if (movie)
|
||||
@ -127,28 +102,111 @@ movie_item* game_list_grid::addItem(const game_info& app, const QString& name, c
|
||||
movie->stop();
|
||||
}
|
||||
}
|
||||
|
||||
painter.end();
|
||||
|
||||
// create item with expanded image, title and position
|
||||
item->setData(Qt::ItemDataRole::DecorationRole, QPixmap::fromImage(exp_img));
|
||||
});
|
||||
|
||||
if (!movie_path.isEmpty())
|
||||
if (play_hover_movies && game->has_hover_gif)
|
||||
{
|
||||
item->init_movie(movie_path);
|
||||
item->init_movie(game_icon_path % serial % "/hover.gif");
|
||||
}
|
||||
|
||||
if (m_text_enabled)
|
||||
if (selected_item_id == game->info.path + game->info.icon_path)
|
||||
{
|
||||
item->setData(Qt::ItemDataRole::DisplayRole, name);
|
||||
selected_item = item;
|
||||
}
|
||||
|
||||
setItem(row, col, item);
|
||||
return item;
|
||||
add_widget(item);
|
||||
}
|
||||
|
||||
qreal game_list_grid::getMarginFactor() const
|
||||
{
|
||||
return m_margin_factor;
|
||||
blockSignals(false);
|
||||
|
||||
// Update layout before setting focus on the selected item
|
||||
show();
|
||||
|
||||
QApplication::processEvents();
|
||||
|
||||
select_item(selected_item);
|
||||
}
|
||||
|
||||
void game_list_grid::repaint_icons(QList<game_info>& game_data, const QColor& icon_color, const QSize& icon_size, qreal device_pixel_ratio)
|
||||
{
|
||||
m_icon_size = icon_size;
|
||||
m_icon_color = icon_color;
|
||||
|
||||
QPixmap placeholder(icon_size * device_pixel_ratio);
|
||||
placeholder.setDevicePixelRatio(device_pixel_ratio);
|
||||
placeholder.fill(Qt::transparent);
|
||||
|
||||
const bool show_title = m_icon_size.width() > (gui::gl_icon_size_medium.width() + gui::gl_icon_size_small.width()) / 2;
|
||||
|
||||
for (game_info& game : game_data)
|
||||
{
|
||||
if (game_list_grid_item* item = static_cast<game_list_grid_item*>(game->item))
|
||||
{
|
||||
if (item->icon_loading())
|
||||
{
|
||||
// We already have an icon. Simply set the icon size to let the label scale itself in a quick and dirty fashion.
|
||||
item->set_icon_size(m_icon_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
// We don't have an icon. Set a placeholder to initialize the layout.
|
||||
game->pxmap = placeholder;
|
||||
item->call_icon_func();
|
||||
}
|
||||
|
||||
item->set_icon_load_func([this, game, device_pixel_ratio, cancel = item->icon_loading_aborted()](int)
|
||||
{
|
||||
IconLoadFunction(game, device_pixel_ratio, cancel);
|
||||
});
|
||||
|
||||
item->adjust_size();
|
||||
item->show_title(show_title);
|
||||
item->got_visible = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void game_list_grid::FocusAndSelectFirstEntryIfNoneIs()
|
||||
{
|
||||
if (items().empty() == false)
|
||||
{
|
||||
items().first()->setFocus();
|
||||
}
|
||||
}
|
||||
|
||||
bool game_list_grid::eventFilter(QObject* watched, QEvent* event)
|
||||
{
|
||||
if (!event)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (event->type() == QEvent::MouseButtonDblClick && static_cast<QMouseEvent*>(event)->button() == Qt::LeftButton)
|
||||
{
|
||||
if (game_list_grid_item* item = static_cast<game_list_grid_item*>(watched))
|
||||
{
|
||||
Q_EMIT ItemDoubleClicked(item->game());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void game_list_grid::keyPressEvent(QKeyEvent* event)
|
||||
{
|
||||
if (!event)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto modifiers = event->modifiers();
|
||||
|
||||
if (modifiers == Qt::ControlModifier && event->key() == Qt::Key_F && !event->isAutoRepeat())
|
||||
{
|
||||
Q_EMIT FocusToSearchBar();
|
||||
return;
|
||||
}
|
||||
|
||||
flow_widget::keyPressEvent(event);
|
||||
}
|
||||
|
@ -1,28 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include "game_list.h"
|
||||
#include "game_list_base.h"
|
||||
#include "flow_widget.h"
|
||||
|
||||
class game_list_grid_delegate;
|
||||
#include <QKeyEvent>
|
||||
|
||||
class game_list_grid : public game_list
|
||||
class game_list_grid : public flow_widget, public game_list_base
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
QSize m_icon_size;
|
||||
QColor m_icon_color;
|
||||
qreal m_margin_factor;
|
||||
qreal m_text_factor;
|
||||
bool m_text_enabled = true;
|
||||
|
||||
public:
|
||||
explicit game_list_grid(const QSize& icon_size, QColor icon_color, const qreal& margin_factor, const qreal& text_factor, const bool& showText);
|
||||
explicit game_list_grid();
|
||||
|
||||
void enableText(const bool& enabled);
|
||||
void setIconSize(const QSize& size) const;
|
||||
movie_item* addItem(const game_info& app, const QString& name, const QString& movie_path, const int& row, const int& col);
|
||||
void clear_list() override;
|
||||
|
||||
[[nodiscard]] qreal getMarginFactor() const;
|
||||
void populate(
|
||||
const std::vector<game_info>& game_data,
|
||||
const QMap<QString, QString>& notes_map,
|
||||
const QMap<QString, QString>& title_map,
|
||||
const std::string& selected_item_id,
|
||||
bool play_hover_movies) override;
|
||||
|
||||
private:
|
||||
game_list_grid_delegate* grid_item_delegate;
|
||||
void repaint_icons(QList<game_info>& game_data, const QColor& icon_color, const QSize& icon_size, qreal device_pixel_ratio) override;
|
||||
|
||||
bool eventFilter(QObject* watched, QEvent* event) override;
|
||||
void keyPressEvent(QKeyEvent* event) override;
|
||||
|
||||
public Q_SLOTS:
|
||||
void FocusAndSelectFirstEntryIfNoneIs();
|
||||
|
||||
Q_SIGNALS:
|
||||
void FocusToSearchBar();
|
||||
void ItemDoubleClicked(const game_info& game);
|
||||
void ItemSelectionChanged(const game_info& game);
|
||||
void IconReady(const game_info& game);
|
||||
};
|
||||
|
@ -1,88 +0,0 @@
|
||||
#include "game_list_grid_delegate.h"
|
||||
#include "movie_item.h"
|
||||
|
||||
#include <QTableWidget>
|
||||
|
||||
game_list_grid_delegate::game_list_grid_delegate(const QSize& size, const qreal& margin_factor, const qreal& text_factor, QObject *parent)
|
||||
: QStyledItemDelegate(parent), m_size(size), m_margin_factor(margin_factor), m_text_factor(text_factor)
|
||||
{
|
||||
}
|
||||
|
||||
void game_list_grid_delegate::initStyleOption(QStyleOptionViewItem* option, const QModelIndex& index) const
|
||||
{
|
||||
Q_UNUSED(index)
|
||||
|
||||
// Remove the focus frame around selected items
|
||||
option->state &= ~QStyle::State_HasFocus;
|
||||
|
||||
// Call initStyleOption without a model index, since we want to paint the relevant data ourselves
|
||||
QStyledItemDelegate::initStyleOption(option, QModelIndex());
|
||||
}
|
||||
|
||||
void game_list_grid_delegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
const QRect r = option.rect;
|
||||
|
||||
painter->setRenderHints(QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
|
||||
painter->eraseRect(r);
|
||||
|
||||
// Paint from our stylesheet
|
||||
QStyledItemDelegate::paint(painter, option, index);
|
||||
|
||||
// Check if the item is visible
|
||||
if (const QTableWidget* table = static_cast<const QTableWidget*>(parent()))
|
||||
{
|
||||
if (movie_item* item = static_cast<movie_item*>(table->item(index.row(), index.column())))
|
||||
{
|
||||
if (!table->visibleRegion().intersects(table->visualItemRect(item)))
|
||||
{
|
||||
// Skip all further actions if the item is not visible
|
||||
return;
|
||||
}
|
||||
|
||||
if (!item->icon_loading())
|
||||
{
|
||||
item->call_icon_load_func(index.row());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get title and image
|
||||
const QPixmap image = qvariant_cast<QPixmap>(index.data(Qt::DecorationRole));
|
||||
const QString title = index.data(Qt::DisplayRole).toString();
|
||||
|
||||
// image
|
||||
if (image.isNull() == false)
|
||||
{
|
||||
painter->drawPixmap(option.rect, image);
|
||||
}
|
||||
|
||||
const int h = r.height() / (1 + m_margin_factor + m_margin_factor * m_text_factor);
|
||||
const int height = r.height() - h - h * m_margin_factor;
|
||||
const int top = r.bottom() - height;
|
||||
|
||||
// title
|
||||
if (option.state & QStyle::State_Selected)
|
||||
{
|
||||
painter->setPen(QPen(option.palette.color(QPalette::HighlightedText), 1, Qt::SolidLine));
|
||||
}
|
||||
else
|
||||
{
|
||||
painter->setPen(QPen(option.palette.color(QPalette::WindowText), 1, Qt::SolidLine));
|
||||
}
|
||||
|
||||
painter->setFont(option.font);
|
||||
painter->drawText(QRect(r.left(), top, r.width(), height), +Qt::TextWordWrap | +Qt::AlignCenter, title);
|
||||
}
|
||||
|
||||
QSize game_list_grid_delegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
|
||||
{
|
||||
Q_UNUSED(option)
|
||||
Q_UNUSED(index)
|
||||
return m_size;
|
||||
}
|
||||
|
||||
void game_list_grid_delegate::setItemSize(const QSize& size)
|
||||
{
|
||||
m_size = size;
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QPainter>
|
||||
#include <QStyledItemDelegate>
|
||||
|
||||
class game_list_grid_delegate : public QStyledItemDelegate
|
||||
{
|
||||
public:
|
||||
game_list_grid_delegate(const QSize& imageSize, const qreal& margin_factor, const qreal& margin_ratio, QObject *parent = nullptr);
|
||||
|
||||
void initStyleOption(QStyleOptionViewItem *option, const QModelIndex &index) const override;
|
||||
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
|
||||
QSize sizeHint(const QStyleOptionViewItem & option, const QModelIndex & index) const override;
|
||||
void setItemSize(const QSize& size);
|
||||
private:
|
||||
QSize m_size;
|
||||
qreal m_margin_factor;
|
||||
qreal m_text_factor;
|
||||
};
|
86
rpcs3/rpcs3qt/game_list_grid_item.cpp
Normal file
86
rpcs3/rpcs3qt/game_list_grid_item.cpp
Normal file
@ -0,0 +1,86 @@
|
||||
#include "game_list_grid_item.h"
|
||||
|
||||
#include <QVBoxLayout>
|
||||
#include <QStyle>
|
||||
|
||||
game_list_grid_item::game_list_grid_item(QWidget* parent, game_info game, const QString& title)
|
||||
: flow_widget_item(parent), movie_item_base(), m_game(std::move(game))
|
||||
{
|
||||
setObjectName("game_list_grid_item");
|
||||
|
||||
cb_on_first_visibility = [this]()
|
||||
{
|
||||
if (!icon_loading())
|
||||
{
|
||||
call_icon_load_func(0);
|
||||
}
|
||||
};
|
||||
|
||||
m_icon_label = new QLabel(this);
|
||||
m_icon_label->setObjectName("game_list_grid_item_icon_label");
|
||||
m_icon_label->setAttribute(Qt::WA_TranslucentBackground);
|
||||
m_icon_label->setScaledContents(true);
|
||||
|
||||
m_title_label = new QLabel(title, this);
|
||||
m_title_label->setObjectName("game_list_grid_item_title_label");
|
||||
m_title_label->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
|
||||
m_title_label->setWordWrap(true);
|
||||
m_title_label->setVisible(false);
|
||||
|
||||
QVBoxLayout* layout = new QVBoxLayout(this);
|
||||
layout->addWidget(m_icon_label, 1);
|
||||
layout->addWidget(m_title_label, 0);
|
||||
|
||||
setLayout(layout);
|
||||
}
|
||||
|
||||
void game_list_grid_item::set_icon_size(const QSize& size)
|
||||
{
|
||||
m_icon_size = size;
|
||||
}
|
||||
|
||||
void game_list_grid_item::set_icon(const QPixmap& pixmap)
|
||||
{
|
||||
m_icon_size = pixmap.size() / devicePixelRatioF();
|
||||
m_icon_label->setPixmap(pixmap);
|
||||
}
|
||||
|
||||
void game_list_grid_item::adjust_size()
|
||||
{
|
||||
m_icon_label->setMinimumSize(m_icon_size);
|
||||
m_icon_label->setMaximumSize(m_icon_size);
|
||||
m_title_label->setMaximumWidth(m_icon_size.width());
|
||||
}
|
||||
|
||||
void game_list_grid_item::show_title(bool visible)
|
||||
{
|
||||
if (m_title_label)
|
||||
{
|
||||
m_title_label->setVisible(visible);
|
||||
}
|
||||
}
|
||||
|
||||
void game_list_grid_item::polish_style()
|
||||
{
|
||||
flow_widget_item::polish_style();
|
||||
|
||||
m_title_label->style()->unpolish(m_title_label);
|
||||
m_title_label->style()->polish(m_title_label);
|
||||
}
|
||||
|
||||
bool game_list_grid_item::event(QEvent* event)
|
||||
{
|
||||
switch (event->type())
|
||||
{
|
||||
case QEvent::HoverEnter:
|
||||
set_active(true);
|
||||
break;
|
||||
case QEvent::HoverLeave:
|
||||
set_active(false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return flow_widget_item::event(event);
|
||||
}
|
36
rpcs3/rpcs3qt/game_list_grid_item.h
Normal file
36
rpcs3/rpcs3qt/game_list_grid_item.h
Normal file
@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include "flow_widget_item.h"
|
||||
#include "movie_item_base.h"
|
||||
#include "game_list_base.h"
|
||||
|
||||
#include <QLabel>
|
||||
|
||||
class game_list_grid_item : public flow_widget_item, public movie_item_base
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
game_list_grid_item(QWidget* parent, game_info game, const QString& title);
|
||||
|
||||
void set_icon_size(const QSize& size);
|
||||
void set_icon(const QPixmap& pixmap);
|
||||
void adjust_size();
|
||||
|
||||
const game_info& game() const
|
||||
{
|
||||
return m_game;
|
||||
}
|
||||
|
||||
void show_title(bool visible);
|
||||
|
||||
void polish_style() override;
|
||||
|
||||
bool event(QEvent* event) override;
|
||||
|
||||
private:
|
||||
QSize m_icon_size{};
|
||||
QLabel* m_icon_label{};
|
||||
QLabel* m_title_label{};
|
||||
game_info m_game{};
|
||||
};
|
415
rpcs3/rpcs3qt/game_list_table.cpp
Normal file
415
rpcs3/rpcs3qt/game_list_table.cpp
Normal file
@ -0,0 +1,415 @@
|
||||
#include "stdafx.h"
|
||||
#include "game_list_table.h"
|
||||
#include "game_list_delegate.h"
|
||||
#include "game_list_frame.h"
|
||||
#include "gui_settings.h"
|
||||
#include "localized.h"
|
||||
#include "custom_table_widget_item.h"
|
||||
#include "persistent_settings.h"
|
||||
#include "qt_utils.h"
|
||||
|
||||
#include "Emu/vfs_config.h"
|
||||
#include "Utilities/StrUtil.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QHeaderView>
|
||||
#include <QScrollBar>
|
||||
#include <QStringBuilder>
|
||||
|
||||
game_list_table::game_list_table(game_list_frame* frame, std::shared_ptr<persistent_settings> persistent_settings)
|
||||
: game_list(), m_game_list_frame(frame), m_persistent_settings(std::move(persistent_settings))
|
||||
{
|
||||
m_is_list_layout = true;
|
||||
|
||||
setShowGrid(false);
|
||||
setItemDelegate(new game_list_delegate(this));
|
||||
setEditTriggers(QAbstractItemView::NoEditTriggers);
|
||||
setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
|
||||
setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
|
||||
verticalScrollBar()->installEventFilter(this);
|
||||
verticalScrollBar()->setSingleStep(20);
|
||||
horizontalScrollBar()->setSingleStep(20);
|
||||
verticalHeader()->setSectionResizeMode(QHeaderView::Fixed);
|
||||
verticalHeader()->setVisible(false);
|
||||
horizontalHeader()->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
horizontalHeader()->setHighlightSections(false);
|
||||
horizontalHeader()->setSortIndicatorShown(true);
|
||||
horizontalHeader()->setStretchLastSection(true);
|
||||
horizontalHeader()->setDefaultSectionSize(150);
|
||||
horizontalHeader()->setDefaultAlignment(Qt::AlignLeft);
|
||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
setAlternatingRowColors(true);
|
||||
installEventFilter(this);
|
||||
setColumnCount(gui::column_count);
|
||||
setMouseTracking(true);
|
||||
|
||||
connect(this, &game_list_table::size_on_disk_ready, this, [this](const game_info& game)
|
||||
{
|
||||
if (!game || !game->item) return;
|
||||
if (QTableWidgetItem* size_item = item(static_cast<movie_item*>(game->item)->row(), gui::column_dir_size))
|
||||
{
|
||||
const u64& game_size = game->info.size_on_disk;
|
||||
size_item->setText(game_size != umax ? gui::utils::format_byte_size(game_size) : tr("Unknown"));
|
||||
size_item->setData(Qt::UserRole, QVariant::fromValue<qulonglong>(game_size));
|
||||
}
|
||||
});
|
||||
|
||||
connect(this, &game_list::IconReady, this, [this](const game_info& game)
|
||||
{
|
||||
if (!game || !game->item) return;
|
||||
game->item->call_icon_func();
|
||||
});
|
||||
}
|
||||
|
||||
void game_list_table::restore_layout(const QByteArray& state)
|
||||
{
|
||||
// Resize to fit and get the ideal icon column width
|
||||
resize_columns_to_contents();
|
||||
const int icon_column_width = columnWidth(gui::column_icon);
|
||||
|
||||
// Restore header layout from last session
|
||||
if (!horizontalHeader()->restoreState(state) && rowCount())
|
||||
{
|
||||
// Nothing to do
|
||||
}
|
||||
|
||||
// Make sure no columns are squished
|
||||
fix_narrow_columns();
|
||||
|
||||
// Make sure that the icon column is large enough for the actual items.
|
||||
// This is important if the list appeared as empty when closing the software before.
|
||||
horizontalHeader()->resizeSection(gui::column_icon, icon_column_width);
|
||||
|
||||
// Save new header state
|
||||
horizontalHeader()->restoreState(horizontalHeader()->saveState());
|
||||
}
|
||||
|
||||
void game_list_table::fix_narrow_columns()
|
||||
{
|
||||
QApplication::processEvents();
|
||||
|
||||
// handle columns (other than the icon column) that have zero width after showing them (stuck between others)
|
||||
for (int col = 1; col < columnCount(); ++col)
|
||||
{
|
||||
if (isColumnHidden(col))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (columnWidth(col) <= horizontalHeader()->minimumSectionSize())
|
||||
{
|
||||
setColumnWidth(col, horizontalHeader()->minimumSectionSize());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void game_list_table::resize_columns_to_contents(int spacing)
|
||||
{
|
||||
verticalHeader()->resizeSections(QHeaderView::ResizeMode::ResizeToContents);
|
||||
horizontalHeader()->resizeSections(QHeaderView::ResizeMode::ResizeToContents);
|
||||
|
||||
// Make non-icon columns slighty bigger for better visuals
|
||||
for (int i = 1; i < columnCount(); i++)
|
||||
{
|
||||
if (isColumnHidden(i))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const int size = horizontalHeader()->sectionSize(i) + spacing;
|
||||
horizontalHeader()->resizeSection(i, size);
|
||||
}
|
||||
}
|
||||
|
||||
void game_list_table::adjust_icon_column()
|
||||
{
|
||||
// Fixate vertical header and row height
|
||||
verticalHeader()->setMinimumSectionSize(m_icon_size.height());
|
||||
verticalHeader()->setMaximumSectionSize(m_icon_size.height());
|
||||
|
||||
// Resize the icon column
|
||||
resizeColumnToContents(gui::column_icon);
|
||||
|
||||
// Shorten the last section to remove horizontal scrollbar if possible
|
||||
resizeColumnToContents(gui::column_count - 1);
|
||||
}
|
||||
|
||||
void game_list_table::sort(int game_count, int sort_column, Qt::SortOrder col_sort_order)
|
||||
{
|
||||
// Back-up old header sizes to handle unwanted column resize in case of zero search results
|
||||
const int old_row_count = rowCount();
|
||||
const int old_game_count = game_count;
|
||||
|
||||
std::vector<int> column_widths(columnCount());
|
||||
for (int i = 0; i < columnCount(); i++)
|
||||
{
|
||||
column_widths[i] = columnWidth(i);
|
||||
}
|
||||
|
||||
// Sorting resizes hidden columns, so unhide them as a workaround
|
||||
std::vector<int> columns_to_hide;
|
||||
|
||||
for (int i = 0; i < columnCount(); i++)
|
||||
{
|
||||
if (isColumnHidden(i))
|
||||
{
|
||||
setColumnHidden(i, false);
|
||||
columns_to_hide.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
// Sort the list by column and sort order
|
||||
sortByColumn(sort_column, col_sort_order);
|
||||
|
||||
// Hide columns again
|
||||
for (int col : columns_to_hide)
|
||||
{
|
||||
setColumnHidden(col, true);
|
||||
}
|
||||
|
||||
// Don't resize the columns if no game is shown to preserve the header settings
|
||||
if (!rowCount())
|
||||
{
|
||||
for (int i = 0; i < columnCount(); i++)
|
||||
{
|
||||
setColumnWidth(i, column_widths[i]);
|
||||
}
|
||||
|
||||
horizontalHeader()->setSectionResizeMode(gui::column_icon, QHeaderView::Fixed);
|
||||
return;
|
||||
}
|
||||
|
||||
// Fixate vertical header and row height
|
||||
verticalHeader()->setMinimumSectionSize(m_icon_size.height());
|
||||
verticalHeader()->setMaximumSectionSize(m_icon_size.height());
|
||||
resizeRowsToContents();
|
||||
|
||||
// Resize columns if the game list was empty before
|
||||
if (!old_row_count && !old_game_count)
|
||||
{
|
||||
resize_columns_to_contents();
|
||||
}
|
||||
else
|
||||
{
|
||||
resizeColumnToContents(gui::column_icon);
|
||||
}
|
||||
|
||||
// Fixate icon column
|
||||
horizontalHeader()->setSectionResizeMode(gui::column_icon, QHeaderView::Fixed);
|
||||
|
||||
// Shorten the last section to remove horizontal scrollbar if possible
|
||||
resizeColumnToContents(gui::column_count - 1);
|
||||
}
|
||||
|
||||
void game_list_table::set_custom_config_icon(const game_info& game)
|
||||
{
|
||||
if (!game)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const QString serial = QString::fromStdString(game->info.serial);
|
||||
|
||||
for (int row = 0; row < rowCount(); ++row)
|
||||
{
|
||||
if (QTableWidgetItem* title_item = item(row, gui::column_name))
|
||||
{
|
||||
if (const QTableWidgetItem* serial_item = item(row, gui::column_serial); serial_item && serial_item->text() == serial)
|
||||
{
|
||||
title_item->setIcon(game_list_base::GetCustomConfigIcon(game));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void game_list_table::populate(
|
||||
const std::vector<game_info>& game_data,
|
||||
const QMap<QString, QString>& notes_map,
|
||||
const QMap<QString, QString>& title_map,
|
||||
const std::string& selected_item_id,
|
||||
bool play_hover_movies)
|
||||
{
|
||||
clear_list();
|
||||
|
||||
setRowCount(::narrow<int>(game_data.size()));
|
||||
|
||||
// Default locale. Uses current Qt application language.
|
||||
const QLocale locale{};
|
||||
const Localized localized;
|
||||
|
||||
const QString game_icon_path = play_hover_movies ? QString::fromStdString(fs::get_config_dir() + "/Icons/game_icons/") : "";
|
||||
const std::string dev_flash = g_cfg_vfs.get_dev_flash();
|
||||
|
||||
int row = 0;
|
||||
int index = -1;
|
||||
int selected_row = -1;
|
||||
|
||||
for (const auto& game : game_data)
|
||||
{
|
||||
index++;
|
||||
|
||||
const QString serial = QString::fromStdString(game->info.serial);
|
||||
const QString title = title_map.value(serial, QString::fromStdString(game->info.name));
|
||||
const QString notes = notes_map.value(serial);
|
||||
|
||||
// Icon
|
||||
custom_table_widget_item* icon_item = new custom_table_widget_item;
|
||||
game->item = icon_item;
|
||||
|
||||
icon_item->set_icon_func([this, icon_item, game](int)
|
||||
{
|
||||
if (!icon_item || !game)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (std::shared_ptr<QMovie> movie = icon_item->movie(); movie && icon_item->get_active())
|
||||
{
|
||||
icon_item->setData(Qt::DecorationRole, movie->currentPixmap().scaled(m_icon_size, Qt::KeepAspectRatio));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::lock_guard lock(icon_item->pixmap_mutex);
|
||||
|
||||
icon_item->setData(Qt::DecorationRole, game->pxmap);
|
||||
|
||||
if (!game->has_hover_gif)
|
||||
{
|
||||
game->pxmap = {};
|
||||
}
|
||||
|
||||
if (movie)
|
||||
{
|
||||
movie->stop();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
icon_item->set_size_calc_func([this, game, cancel = icon_item->size_on_disk_loading_aborted(), dev_flash]()
|
||||
{
|
||||
if (game && game->info.size_on_disk == umax && (!cancel || !cancel->load()))
|
||||
{
|
||||
if (game->info.path.starts_with(dev_flash))
|
||||
{
|
||||
// Do not report size of apps inside /dev_flash (it does not make sense to do so)
|
||||
game->info.size_on_disk = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
game->info.size_on_disk = fs::get_dir_size(game->info.path, 1, cancel.get());
|
||||
}
|
||||
|
||||
if (!cancel || !cancel->load())
|
||||
{
|
||||
Q_EMIT size_on_disk_ready(game);
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (play_hover_movies && game->has_hover_gif)
|
||||
{
|
||||
icon_item->init_movie(game_icon_path % serial % "/hover.gif");
|
||||
}
|
||||
|
||||
icon_item->setData(Qt::UserRole, index, true);
|
||||
icon_item->setData(gui::custom_roles::game_role, QVariant::fromValue(game));
|
||||
|
||||
// Title
|
||||
custom_table_widget_item* title_item = new custom_table_widget_item(title);
|
||||
title_item->setIcon(game_list_base::GetCustomConfigIcon(game));
|
||||
|
||||
// Serial
|
||||
custom_table_widget_item* serial_item = new custom_table_widget_item(game->info.serial);
|
||||
|
||||
if (!notes.isEmpty())
|
||||
{
|
||||
const QString tool_tip = tr("%0 [%1]\n\nNotes:\n%2").arg(title).arg(serial).arg(notes);
|
||||
title_item->setToolTip(tool_tip);
|
||||
serial_item->setToolTip(tool_tip);
|
||||
}
|
||||
|
||||
// Move Support (http://www.psdevwiki.com/ps3/PARAM.SFO#ATTRIBUTE)
|
||||
const bool supports_move = game->info.attr & 0x800000;
|
||||
|
||||
// Compatibility
|
||||
custom_table_widget_item* compat_item = new custom_table_widget_item;
|
||||
compat_item->setText(game->compat.text % (game->compat.date.isEmpty() ? QStringLiteral("") : " (" % game->compat.date % ")"));
|
||||
compat_item->setData(Qt::UserRole, game->compat.index, true);
|
||||
compat_item->setToolTip(game->compat.tooltip);
|
||||
if (!game->compat.color.isEmpty())
|
||||
{
|
||||
compat_item->setData(Qt::DecorationRole, gui::utils::circle_pixmap(game->compat.color, devicePixelRatioF() * 2));
|
||||
}
|
||||
|
||||
// Version
|
||||
QString app_version = QString::fromStdString(game_list::GetGameVersion(game));
|
||||
|
||||
if (game->info.bootable && !game->compat.latest_version.isEmpty())
|
||||
{
|
||||
f64 top_ver = 0.0, app_ver = 0.0;
|
||||
const bool unknown = app_version == localized.category.unknown;
|
||||
const bool ok_app = !unknown && try_to_float(&app_ver, app_version.toStdString(), ::std::numeric_limits<s32>::min(), ::std::numeric_limits<s32>::max());
|
||||
const bool ok_top = !unknown && try_to_float(&top_ver, game->compat.latest_version.toStdString(), ::std::numeric_limits<s32>::min(), ::std::numeric_limits<s32>::max());
|
||||
|
||||
// If the app is bootable and the compat database contains info about the latest patch version:
|
||||
// add a hint for available software updates if the app version is unknown or lower than the latest version.
|
||||
if (unknown || (ok_top && ok_app && top_ver > app_ver))
|
||||
{
|
||||
app_version = tr("%0 (Update available: %1)").arg(app_version, game->compat.latest_version);
|
||||
}
|
||||
}
|
||||
|
||||
// Playtimes
|
||||
const quint64 elapsed_ms = m_persistent_settings->GetPlaytime(serial);
|
||||
|
||||
// Last played (support outdated values)
|
||||
QDateTime last_played;
|
||||
const QString last_played_str = m_persistent_settings->GetLastPlayed(serial);
|
||||
|
||||
if (!last_played_str.isEmpty())
|
||||
{
|
||||
last_played = QDateTime::fromString(last_played_str, gui::persistent::last_played_date_format);
|
||||
|
||||
if (!last_played.isValid())
|
||||
{
|
||||
last_played = QDateTime::fromString(last_played_str, gui::persistent::last_played_date_format_old);
|
||||
}
|
||||
}
|
||||
|
||||
const u64 game_size = game->info.size_on_disk;
|
||||
|
||||
setItem(row, gui::column_icon, icon_item);
|
||||
setItem(row, gui::column_name, title_item);
|
||||
setItem(row, gui::column_serial, serial_item);
|
||||
setItem(row, gui::column_firmware, new custom_table_widget_item(game->info.fw));
|
||||
setItem(row, gui::column_version, new custom_table_widget_item(app_version));
|
||||
setItem(row, gui::column_category, new custom_table_widget_item(game->localized_category));
|
||||
setItem(row, gui::column_path, new custom_table_widget_item(game->info.path));
|
||||
setItem(row, gui::column_move, new custom_table_widget_item((supports_move ? tr("Supported") : tr("Not Supported")).toStdString(), Qt::UserRole, !supports_move));
|
||||
setItem(row, gui::column_resolution, new custom_table_widget_item(Localized::GetStringFromU32(game->info.resolution, localized.resolution.mode, true)));
|
||||
setItem(row, gui::column_sound, new custom_table_widget_item(Localized::GetStringFromU32(game->info.sound_format, localized.sound.format, true)));
|
||||
setItem(row, gui::column_parental, new custom_table_widget_item(Localized::GetStringFromU32(game->info.parental_lvl, localized.parental.level), Qt::UserRole, game->info.parental_lvl));
|
||||
setItem(row, gui::column_last_play, new custom_table_widget_item(locale.toString(last_played, last_played >= QDateTime::currentDateTime().addDays(-7) ? gui::persistent::last_played_date_with_time_of_day_format : gui::persistent::last_played_date_format_new), Qt::UserRole, last_played));
|
||||
setItem(row, gui::column_playtime, new custom_table_widget_item(elapsed_ms == 0 ? tr("Never played") : localized.GetVerboseTimeByMs(elapsed_ms), Qt::UserRole, elapsed_ms));
|
||||
setItem(row, gui::column_compat, compat_item);
|
||||
setItem(row, gui::column_dir_size, new custom_table_widget_item(game_size != umax ? gui::utils::format_byte_size(game_size) : tr("Unknown"), Qt::UserRole, QVariant::fromValue<qulonglong>(game_size)));
|
||||
|
||||
if (selected_item_id == game->info.path + game->info.icon_path)
|
||||
{
|
||||
selected_row = row;
|
||||
}
|
||||
|
||||
row++;
|
||||
}
|
||||
|
||||
selectRow(selected_row);
|
||||
}
|
||||
|
||||
void game_list_table::repaint_icons(QList<game_info>& game_data, const QColor& icon_color, const QSize& icon_size, qreal device_pixel_ratio)
|
||||
{
|
||||
game_list_base::repaint_icons(game_data, icon_color, icon_size, device_pixel_ratio);
|
||||
adjust_icon_column();
|
||||
}
|
45
rpcs3/rpcs3qt/game_list_table.h
Normal file
45
rpcs3/rpcs3qt/game_list_table.h
Normal file
@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include "game_list.h"
|
||||
|
||||
class persistent_settings;
|
||||
class game_list_frame;
|
||||
|
||||
class game_list_table : public game_list
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
game_list_table(game_list_frame* frame, std::shared_ptr<persistent_settings> persistent_settings);
|
||||
|
||||
/** Restores the initial layout of the table */
|
||||
void restore_layout(const QByteArray& state);
|
||||
|
||||
/** Fix columns with width smaller than the minimal section size */
|
||||
void fix_narrow_columns();
|
||||
|
||||
/** Resizes the columns to their contents and adds a small spacing */
|
||||
void resize_columns_to_contents(int spacing = 20);
|
||||
|
||||
void adjust_icon_column();
|
||||
|
||||
void sort(int game_count, int sort_column, Qt::SortOrder col_sort_order);
|
||||
|
||||
void set_custom_config_icon(const game_info& game);
|
||||
|
||||
void populate(
|
||||
const std::vector<game_info>& game_data,
|
||||
const QMap<QString, QString>& notes_map,
|
||||
const QMap<QString, QString>& title_map,
|
||||
const std::string& selected_item_id,
|
||||
bool play_hover_movies) override;
|
||||
|
||||
void repaint_icons(QList<game_info>& game_data, const QColor& icon_color, const QSize& icon_size, qreal device_pixel_ratio) override;
|
||||
|
||||
Q_SIGNALS:
|
||||
void size_on_disk_ready(const game_info& game);
|
||||
|
||||
private:
|
||||
game_list_frame* m_game_list_frame{};
|
||||
std::shared_ptr<persistent_settings> m_persistent_settings;
|
||||
};
|
@ -47,6 +47,36 @@ QString Localized::GetVerboseTimeByMs(quint64 elapsed_ms, bool show_days) const
|
||||
return str_seconds;
|
||||
}
|
||||
|
||||
std::string Localized::GetStringFromU32(const u32& key, const std::map<u32, QString>& map, bool combined)
|
||||
{
|
||||
QStringList string;
|
||||
|
||||
if (combined)
|
||||
{
|
||||
for (const auto& item : map)
|
||||
{
|
||||
if (key & item.first)
|
||||
{
|
||||
string << item.second;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (map.find(key) != map.end())
|
||||
{
|
||||
string << ::at32(map, key);
|
||||
}
|
||||
}
|
||||
|
||||
if (string.isEmpty())
|
||||
{
|
||||
string << tr("Unknown");
|
||||
}
|
||||
|
||||
return string.join(", ").toStdString();
|
||||
}
|
||||
|
||||
Localized::resolution::resolution()
|
||||
: mode({
|
||||
{ psf::resolution_flag::_480p, tr("480p") },
|
||||
|
@ -17,6 +17,7 @@ public:
|
||||
Localized() {}
|
||||
|
||||
QString GetVerboseTimeByMs(quint64 elapsed_ms, bool show_days = false) const;
|
||||
static std::string GetStringFromU32(const u32& key, const std::map<u32, QString>& map, bool combined = false);
|
||||
|
||||
const struct category // (see PARAM.SFO in psdevwiki.com) TODO: Disc Categories
|
||||
{
|
||||
|
@ -2430,7 +2430,7 @@ void main_window::CreateConnects()
|
||||
{
|
||||
if (game)
|
||||
{
|
||||
games[game->info.serial].insert(game_list_frame::GetGameVersion(game));
|
||||
games[game->info.serial].insert(game_list::GetGameVersion(game));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,11 +8,6 @@
|
||||
#include "Utilities/Thread.h"
|
||||
#include "Utilities/StrUtil.h"
|
||||
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QPushButton>
|
||||
#include <QHBoxLayout>
|
||||
#include <QComboBox>
|
||||
#include <QCheckBox>
|
||||
|
||||
#include <charconv>
|
||||
@ -24,8 +19,6 @@
|
||||
|
||||
LOG_CHANNEL(gui_log, "GUI");
|
||||
|
||||
constexpr auto qstr = QString::fromStdString;
|
||||
|
||||
template <>
|
||||
void fmt_class_string<search_mode>::format(std::string& out, u64 arg)
|
||||
{
|
||||
|
@ -1,152 +1,14 @@
|
||||
#include "stdafx.h"
|
||||
#include "movie_item.h"
|
||||
|
||||
movie_item::movie_item() : QTableWidgetItem()
|
||||
movie_item::movie_item() : QTableWidgetItem(), movie_item_base()
|
||||
{
|
||||
init_pointers();
|
||||
}
|
||||
|
||||
movie_item::movie_item(const QString& text, int type) : QTableWidgetItem(text, type)
|
||||
movie_item::movie_item(const QString& text, int type) : QTableWidgetItem(text, type), movie_item_base()
|
||||
{
|
||||
init_pointers();
|
||||
}
|
||||
|
||||
movie_item::movie_item(const QIcon& icon, const QString& text, int type) : QTableWidgetItem(icon, text, type)
|
||||
movie_item::movie_item(const QIcon& icon, const QString& text, int type) : QTableWidgetItem(icon, text, type), movie_item_base()
|
||||
{
|
||||
init_pointers();
|
||||
}
|
||||
|
||||
movie_item::~movie_item()
|
||||
{
|
||||
if (m_movie)
|
||||
{
|
||||
m_movie->stop();
|
||||
}
|
||||
|
||||
wait_for_icon_loading(true);
|
||||
wait_for_size_on_disk_loading(true);
|
||||
}
|
||||
|
||||
void movie_item::init_pointers()
|
||||
{
|
||||
m_icon_loading_aborted.reset(new atomic_t<bool>(false));
|
||||
m_size_on_disk_loading_aborted.reset(new atomic_t<bool>(false));
|
||||
}
|
||||
|
||||
void movie_item::set_active(bool active)
|
||||
{
|
||||
if (!std::exchange(m_active, active) && active && m_movie)
|
||||
{
|
||||
m_movie->jumpToFrame(1);
|
||||
m_movie->start();
|
||||
}
|
||||
}
|
||||
|
||||
void movie_item::init_movie(const QString& path)
|
||||
{
|
||||
if (path.isEmpty() || !m_icon_callback) return;
|
||||
|
||||
m_movie.reset(new QMovie(path));
|
||||
|
||||
if (!m_movie->isValid())
|
||||
{
|
||||
m_movie.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
QObject::connect(m_movie.get(), &QMovie::frameChanged, m_movie.get(), m_icon_callback);
|
||||
}
|
||||
|
||||
void movie_item::call_icon_func() const
|
||||
{
|
||||
if (m_icon_callback)
|
||||
{
|
||||
m_icon_callback(0);
|
||||
}
|
||||
}
|
||||
|
||||
void movie_item::set_icon_func(const icon_callback_t& func)
|
||||
{
|
||||
m_icon_callback = func;
|
||||
call_icon_func();
|
||||
}
|
||||
|
||||
void movie_item::call_icon_load_func(int index)
|
||||
{
|
||||
if (!m_icon_load_callback || m_icon_loading || m_icon_loading_aborted->load())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
wait_for_icon_loading(true);
|
||||
|
||||
*m_icon_loading_aborted = false;
|
||||
m_icon_loading = true;
|
||||
m_icon_load_thread.reset(QThread::create([this, index]()
|
||||
{
|
||||
if (m_icon_load_callback)
|
||||
{
|
||||
m_icon_load_callback(index);
|
||||
}
|
||||
}));
|
||||
m_icon_load_thread->start();
|
||||
}
|
||||
|
||||
void movie_item::set_icon_load_func(const icon_load_callback_t& func)
|
||||
{
|
||||
wait_for_icon_loading(true);
|
||||
|
||||
m_icon_loading = false;
|
||||
m_icon_load_callback = func;
|
||||
*m_icon_loading_aborted = false;
|
||||
}
|
||||
|
||||
void movie_item::call_size_calc_func()
|
||||
{
|
||||
if (!m_size_calc_callback || m_size_on_disk_loading || m_size_on_disk_loading_aborted->load())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
wait_for_size_on_disk_loading(true);
|
||||
|
||||
*m_size_on_disk_loading_aborted = false;
|
||||
m_size_on_disk_loading = true;
|
||||
m_size_calc_thread.reset(QThread::create([this]()
|
||||
{
|
||||
if (m_size_calc_callback)
|
||||
{
|
||||
m_size_calc_callback();
|
||||
}
|
||||
}));
|
||||
m_size_calc_thread->start();
|
||||
}
|
||||
|
||||
void movie_item::set_size_calc_func(const size_calc_callback_t& func)
|
||||
{
|
||||
m_size_on_disk_loading = false;
|
||||
m_size_calc_callback = func;
|
||||
*m_size_on_disk_loading_aborted = false;
|
||||
}
|
||||
|
||||
void movie_item::wait_for_icon_loading(bool abort)
|
||||
{
|
||||
*m_icon_loading_aborted = abort;
|
||||
|
||||
if (m_icon_load_thread && m_icon_load_thread->isRunning())
|
||||
{
|
||||
m_icon_load_thread->wait();
|
||||
m_icon_load_thread.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void movie_item::wait_for_size_on_disk_loading(bool abort)
|
||||
{
|
||||
*m_size_on_disk_loading_aborted = abort;
|
||||
|
||||
if (m_size_calc_thread && m_size_calc_thread->isRunning())
|
||||
{
|
||||
m_size_calc_thread->wait();
|
||||
m_size_calc_thread.reset();
|
||||
}
|
||||
}
|
||||
|
@ -1,89 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "util/atomic.hpp"
|
||||
#include "Utilities/mutex.h"
|
||||
#include "movie_item_base.h"
|
||||
|
||||
#include <QTableWidgetItem>
|
||||
#include <QMovie>
|
||||
#include <QObject>
|
||||
#include <QThread>
|
||||
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
|
||||
using icon_callback_t = std::function<void(int)>;
|
||||
using icon_load_callback_t = std::function<void(int)>;
|
||||
using size_calc_callback_t = std::function<void()>;
|
||||
|
||||
class movie_item : public QTableWidgetItem
|
||||
class movie_item : public QTableWidgetItem, public movie_item_base
|
||||
{
|
||||
public:
|
||||
movie_item();
|
||||
movie_item(const QString& text, int type = Type);
|
||||
movie_item(const QIcon& icon, const QString& text, int type = Type);
|
||||
~movie_item();
|
||||
|
||||
void init_pointers();
|
||||
|
||||
void set_active(bool active);
|
||||
|
||||
[[nodiscard]] bool get_active() const
|
||||
{
|
||||
return m_active;
|
||||
}
|
||||
|
||||
[[nodiscard]] std::shared_ptr<QMovie> movie() const
|
||||
{
|
||||
return m_movie;
|
||||
}
|
||||
|
||||
void init_movie(const QString& path);
|
||||
|
||||
void call_icon_func() const;
|
||||
void set_icon_func(const icon_callback_t& func);
|
||||
|
||||
void call_icon_load_func(int index);
|
||||
void set_icon_load_func(const icon_load_callback_t& func);
|
||||
|
||||
void call_size_calc_func();
|
||||
void set_size_calc_func(const size_calc_callback_t& func);
|
||||
|
||||
void wait_for_icon_loading(bool abort);
|
||||
void wait_for_size_on_disk_loading(bool abort);
|
||||
|
||||
bool icon_loading() const
|
||||
{
|
||||
return m_icon_loading;
|
||||
}
|
||||
|
||||
bool size_on_disk_loading() const
|
||||
{
|
||||
return m_size_on_disk_loading;
|
||||
}
|
||||
|
||||
[[nodiscard]] std::shared_ptr<atomic_t<bool>> icon_loading_aborted() const
|
||||
{
|
||||
return m_icon_loading_aborted;
|
||||
}
|
||||
|
||||
[[nodiscard]] std::shared_ptr<atomic_t<bool>> size_on_disk_loading_aborted() const
|
||||
{
|
||||
return m_size_on_disk_loading_aborted;
|
||||
}
|
||||
|
||||
shared_mutex pixmap_mutex;
|
||||
|
||||
private:
|
||||
std::shared_ptr<QMovie> m_movie;
|
||||
std::unique_ptr<QThread> m_icon_load_thread;
|
||||
std::unique_ptr<QThread> m_size_calc_thread;
|
||||
bool m_active = false;
|
||||
atomic_t<bool> m_size_on_disk_loading = false;
|
||||
atomic_t<bool> m_icon_loading = false;
|
||||
size_calc_callback_t m_size_calc_callback = nullptr;
|
||||
icon_load_callback_t m_icon_load_callback = nullptr;
|
||||
icon_callback_t m_icon_callback = nullptr;
|
||||
|
||||
std::shared_ptr<atomic_t<bool>> m_icon_loading_aborted;
|
||||
std::shared_ptr<atomic_t<bool>> m_size_on_disk_loading_aborted;
|
||||
};
|
||||
|
141
rpcs3/rpcs3qt/movie_item_base.cpp
Normal file
141
rpcs3/rpcs3qt/movie_item_base.cpp
Normal file
@ -0,0 +1,141 @@
|
||||
#include "stdafx.h"
|
||||
#include "movie_item_base.h"
|
||||
|
||||
movie_item_base::movie_item_base()
|
||||
{
|
||||
init_pointers();
|
||||
}
|
||||
|
||||
movie_item_base::~movie_item_base()
|
||||
{
|
||||
if (m_movie)
|
||||
{
|
||||
m_movie->stop();
|
||||
}
|
||||
|
||||
wait_for_icon_loading(true);
|
||||
wait_for_size_on_disk_loading(true);
|
||||
}
|
||||
|
||||
void movie_item_base::init_pointers()
|
||||
{
|
||||
m_icon_loading_aborted.reset(new atomic_t<bool>(false));
|
||||
m_size_on_disk_loading_aborted.reset(new atomic_t<bool>(false));
|
||||
}
|
||||
|
||||
void movie_item_base::set_active(bool active)
|
||||
{
|
||||
if (!std::exchange(m_active, active) && active && m_movie)
|
||||
{
|
||||
m_movie->jumpToFrame(1);
|
||||
m_movie->start();
|
||||
}
|
||||
}
|
||||
|
||||
void movie_item_base::init_movie(const QString& path)
|
||||
{
|
||||
if (path.isEmpty() || !m_icon_callback) return;
|
||||
|
||||
m_movie.reset(new QMovie(path));
|
||||
|
||||
if (!m_movie->isValid())
|
||||
{
|
||||
m_movie.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
QObject::connect(m_movie.get(), &QMovie::frameChanged, m_movie.get(), m_icon_callback);
|
||||
}
|
||||
|
||||
void movie_item_base::call_icon_func() const
|
||||
{
|
||||
if (m_icon_callback)
|
||||
{
|
||||
m_icon_callback(0);
|
||||
}
|
||||
}
|
||||
|
||||
void movie_item_base::set_icon_func(const icon_callback_t& func)
|
||||
{
|
||||
m_icon_callback = func;
|
||||
}
|
||||
|
||||
void movie_item_base::call_icon_load_func(int index)
|
||||
{
|
||||
if (!m_icon_load_callback || m_icon_loading || m_icon_loading_aborted->load())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
wait_for_icon_loading(true);
|
||||
|
||||
*m_icon_loading_aborted = false;
|
||||
m_icon_loading = true;
|
||||
m_icon_load_thread.reset(QThread::create([this, index]()
|
||||
{
|
||||
if (m_icon_load_callback)
|
||||
{
|
||||
m_icon_load_callback(index);
|
||||
}
|
||||
}));
|
||||
m_icon_load_thread->start();
|
||||
}
|
||||
|
||||
void movie_item_base::set_icon_load_func(const icon_load_callback_t& func)
|
||||
{
|
||||
wait_for_icon_loading(true);
|
||||
|
||||
m_icon_loading = false;
|
||||
m_icon_load_callback = func;
|
||||
*m_icon_loading_aborted = false;
|
||||
}
|
||||
|
||||
void movie_item_base::call_size_calc_func()
|
||||
{
|
||||
if (!m_size_calc_callback || m_size_on_disk_loading || m_size_on_disk_loading_aborted->load())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
wait_for_size_on_disk_loading(true);
|
||||
|
||||
*m_size_on_disk_loading_aborted = false;
|
||||
m_size_on_disk_loading = true;
|
||||
m_size_calc_thread.reset(QThread::create([this]()
|
||||
{
|
||||
if (m_size_calc_callback)
|
||||
{
|
||||
m_size_calc_callback();
|
||||
}
|
||||
}));
|
||||
m_size_calc_thread->start();
|
||||
}
|
||||
|
||||
void movie_item_base::set_size_calc_func(const size_calc_callback_t& func)
|
||||
{
|
||||
m_size_on_disk_loading = false;
|
||||
m_size_calc_callback = func;
|
||||
*m_size_on_disk_loading_aborted = false;
|
||||
}
|
||||
|
||||
void movie_item_base::wait_for_icon_loading(bool abort)
|
||||
{
|
||||
*m_icon_loading_aborted = abort;
|
||||
|
||||
if (m_icon_load_thread && m_icon_load_thread->isRunning())
|
||||
{
|
||||
m_icon_load_thread->wait();
|
||||
m_icon_load_thread.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void movie_item_base::wait_for_size_on_disk_loading(bool abort)
|
||||
{
|
||||
*m_size_on_disk_loading_aborted = abort;
|
||||
|
||||
if (m_size_calc_thread && m_size_calc_thread->isRunning())
|
||||
{
|
||||
m_size_calc_thread->wait();
|
||||
m_size_calc_thread.reset();
|
||||
}
|
||||
}
|
88
rpcs3/rpcs3qt/movie_item_base.h
Normal file
88
rpcs3/rpcs3qt/movie_item_base.h
Normal file
@ -0,0 +1,88 @@
|
||||
#pragma once
|
||||
|
||||
#include "movie_item_base.h"
|
||||
#include "util/atomic.hpp"
|
||||
#include "Utilities/mutex.h"
|
||||
|
||||
#include <QMovie>
|
||||
#include <QThread>
|
||||
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
|
||||
using icon_callback_t = std::function<void(int)>;
|
||||
using icon_load_callback_t = std::function<void(int)>;
|
||||
using size_calc_callback_t = std::function<void()>;
|
||||
|
||||
class movie_item_base
|
||||
{
|
||||
public:
|
||||
movie_item_base();
|
||||
virtual ~movie_item_base();
|
||||
|
||||
void init_pointers();
|
||||
|
||||
void set_active(bool active);
|
||||
|
||||
[[nodiscard]] bool get_active() const
|
||||
{
|
||||
return m_active;
|
||||
}
|
||||
|
||||
[[nodiscard]] std::shared_ptr<QMovie> movie() const
|
||||
{
|
||||
return m_movie;
|
||||
}
|
||||
|
||||
void init_movie(const QString& path);
|
||||
|
||||
void call_icon_func() const;
|
||||
void set_icon_func(const icon_callback_t& func);
|
||||
|
||||
void call_icon_load_func(int index);
|
||||
void set_icon_load_func(const icon_load_callback_t& func);
|
||||
|
||||
void call_size_calc_func();
|
||||
void set_size_calc_func(const size_calc_callback_t& func);
|
||||
|
||||
void wait_for_icon_loading(bool abort);
|
||||
void wait_for_size_on_disk_loading(bool abort);
|
||||
|
||||
bool icon_loading() const
|
||||
{
|
||||
return m_icon_loading;
|
||||
}
|
||||
|
||||
bool size_on_disk_loading() const
|
||||
{
|
||||
return m_size_on_disk_loading;
|
||||
}
|
||||
|
||||
[[nodiscard]] std::shared_ptr<atomic_t<bool>> icon_loading_aborted() const
|
||||
{
|
||||
return m_icon_loading_aborted;
|
||||
}
|
||||
|
||||
[[nodiscard]] std::shared_ptr<atomic_t<bool>> size_on_disk_loading_aborted() const
|
||||
{
|
||||
return m_size_on_disk_loading_aborted;
|
||||
}
|
||||
|
||||
shared_mutex pixmap_mutex;
|
||||
|
||||
protected:
|
||||
std::shared_ptr<QMovie> m_movie;
|
||||
|
||||
private:
|
||||
std::unique_ptr<QThread> m_icon_load_thread;
|
||||
std::unique_ptr<QThread> m_size_calc_thread;
|
||||
bool m_active = false;
|
||||
atomic_t<bool> m_size_on_disk_loading = false;
|
||||
atomic_t<bool> m_icon_loading = false;
|
||||
size_calc_callback_t m_size_calc_callback = nullptr;
|
||||
icon_load_callback_t m_icon_load_callback = nullptr;
|
||||
icon_callback_t m_icon_callback = nullptr;
|
||||
|
||||
std::shared_ptr<atomic_t<bool>> m_icon_loading_aborted;
|
||||
std::shared_ptr<atomic_t<bool>> m_size_on_disk_loading_aborted;
|
||||
};
|
@ -198,15 +198,15 @@ namespace gui
|
||||
return l.sizeHint().width();
|
||||
}
|
||||
|
||||
QImage get_centered_image(const QString& path, const QSize& icon_size, int offset_x, int offset_y, qreal device_pixel_ratio)
|
||||
QPixmap get_centered_pixmap(QPixmap pixmap, const QSize& icon_size, int offset_x, int offset_y, qreal device_pixel_ratio, Qt::TransformationMode mode)
|
||||
{
|
||||
// Create empty canvas for expanded image
|
||||
QImage exp_img(icon_size, QImage::Format_ARGB32);
|
||||
QPixmap exp_img(icon_size);
|
||||
exp_img.setDevicePixelRatio(device_pixel_ratio);
|
||||
exp_img.fill(Qt::transparent);
|
||||
|
||||
// Load scaled pixmap
|
||||
const QPixmap pixmap = QPixmap(path).scaled(icon_size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
pixmap = pixmap.scaled(icon_size, Qt::KeepAspectRatio, mode);
|
||||
|
||||
// Define offset for raw image placement
|
||||
QPoint offset(offset_x + icon_size.width() / 2 - pixmap.width() / 2,
|
||||
@ -221,9 +221,9 @@ namespace gui
|
||||
return exp_img;
|
||||
}
|
||||
|
||||
QPixmap get_centered_pixmap(const QString& path, const QSize& icon_size, int offset_x, int offset_y, qreal device_pixel_ratio)
|
||||
QPixmap get_centered_pixmap(const QString& path, const QSize& icon_size, int offset_x, int offset_y, qreal device_pixel_ratio, Qt::TransformationMode mode)
|
||||
{
|
||||
return QPixmap::fromImage(get_centered_image(path, icon_size, offset_x, offset_y, device_pixel_ratio));
|
||||
return get_centered_pixmap(QPixmap(path), icon_size, offset_x, offset_y, device_pixel_ratio, mode);
|
||||
}
|
||||
|
||||
QImage get_opaque_image_area(const QString& path)
|
||||
|
@ -82,11 +82,11 @@ namespace gui
|
||||
qobj.setFont(font);
|
||||
}
|
||||
|
||||
// Returns a scaled, centered QImage
|
||||
QImage get_centered_image(const QString& path, const QSize& icon_size, int offset_x, int offset_y, qreal device_pixel_ratio);
|
||||
// Returns a scaled, centered QPixmap
|
||||
QPixmap get_centered_pixmap(QPixmap pixmap, const QSize& icon_size, int offset_x, int offset_y, qreal device_pixel_ratio, Qt::TransformationMode mode);
|
||||
|
||||
// Returns a scaled, centered QPixmap
|
||||
QPixmap get_centered_pixmap(const QString& path, const QSize& icon_size, int offset_x, int offset_y, qreal device_pixel_ratio);
|
||||
QPixmap get_centered_pixmap(const QString& path, const QSize& icon_size, int offset_x, int offset_y, qreal device_pixel_ratio, Qt::TransformationMode mode);
|
||||
|
||||
// Returns the part of the image loaded from path that is inside the bounding box of its opaque areas
|
||||
QImage get_opaque_image_area(const QString& path);
|
||||
|
@ -16,8 +16,6 @@
|
||||
|
||||
LOG_CHANNEL(cfg_log, "CFG");
|
||||
|
||||
constexpr auto qstr = QString::fromStdString;
|
||||
|
||||
render_creator::render_creator(QObject *parent) : QObject(parent)
|
||||
{
|
||||
#if defined(HAVE_VULKAN)
|
||||
@ -50,9 +48,9 @@ render_creator::render_creator(QObject *parent) : QObject(parent)
|
||||
|
||||
if (!work_done) // The spawning thread gave up, do not attempt to modify vulkan_adapters
|
||||
{
|
||||
for (auto& gpu : gpus)
|
||||
for (const auto& gpu : gpus)
|
||||
{
|
||||
adapters->append(qstr(gpu.get_name()));
|
||||
adapters->append(QString::fromStdString(gpu.get_name()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
32
rpcs3/rpcs3qt/screenshot_item.cpp
Normal file
32
rpcs3/rpcs3qt/screenshot_item.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
#include "screenshot_item.h"
|
||||
#include "qt_utils.h"
|
||||
|
||||
#include <QVBoxLayout>
|
||||
|
||||
screenshot_item::screenshot_item(QWidget* parent)
|
||||
: flow_widget_item(parent)
|
||||
{
|
||||
cb_on_first_visibility = [this]()
|
||||
{
|
||||
m_thread.reset(QThread::create([this]()
|
||||
{
|
||||
const QPixmap pixmap = gui::utils::get_centered_pixmap(icon_path, icon_size, 0, 0, 1.0, Qt::SmoothTransformation);
|
||||
Q_EMIT signal_icon_update(pixmap);
|
||||
}));
|
||||
m_thread->start();
|
||||
};
|
||||
|
||||
label = new QLabel(this);
|
||||
QVBoxLayout* layout = new QVBoxLayout(this);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->addWidget(label);
|
||||
setLayout(layout);
|
||||
}
|
||||
|
||||
screenshot_item::~screenshot_item()
|
||||
{
|
||||
if (m_thread && m_thread->isRunning())
|
||||
{
|
||||
m_thread->wait();
|
||||
}
|
||||
}
|
24
rpcs3/rpcs3qt/screenshot_item.h
Normal file
24
rpcs3/rpcs3qt/screenshot_item.h
Normal file
@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "flow_widget_item.h"
|
||||
#include <QLabel>
|
||||
#include <QThread>
|
||||
|
||||
class screenshot_item : public flow_widget_item
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
screenshot_item(QWidget* parent);
|
||||
virtual ~screenshot_item();
|
||||
|
||||
QString icon_path;
|
||||
QSize icon_size;
|
||||
QLabel* label{};
|
||||
|
||||
private:
|
||||
std::unique_ptr<QThread> m_thread;
|
||||
|
||||
Q_SIGNALS:
|
||||
void signal_icon_update(const QPixmap& pixmap);
|
||||
};
|
@ -1,6 +1,7 @@
|
||||
#include "stdafx.h"
|
||||
#include "screenshot_manager_dialog.h"
|
||||
#include "screenshot_preview.h"
|
||||
#include "screenshot_item.h"
|
||||
#include "flow_widget.h"
|
||||
#include "qt_utils.h"
|
||||
#include "Utilities/File.h"
|
||||
@ -23,7 +24,7 @@ screenshot_manager_dialog::screenshot_manager_dialog(QWidget* parent) : QDialog(
|
||||
|
||||
m_icon_size = QSize(160, 90);
|
||||
m_flow_widget = new flow_widget(this);
|
||||
m_flow_widget->setObjectName("m_flow_widget");
|
||||
m_flow_widget->setObjectName("flow_widget");
|
||||
|
||||
m_placeholder = QPixmap(m_icon_size);
|
||||
m_placeholder.fill(Qt::gray);
|
||||
@ -137,31 +138,3 @@ bool screenshot_manager_dialog::eventFilter(QObject* watched, QEvent* event)
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
screenshot_item::screenshot_item(QWidget* parent)
|
||||
: flow_widget_item(parent)
|
||||
{
|
||||
cb_on_first_visibility = [this]()
|
||||
{
|
||||
m_thread.reset(QThread::create([this]()
|
||||
{
|
||||
const QPixmap pixmap = gui::utils::get_centered_pixmap(icon_path, icon_size, 0, 0, 1.0);
|
||||
Q_EMIT signal_icon_update(pixmap);
|
||||
}));
|
||||
m_thread->start();
|
||||
};
|
||||
|
||||
label = new QLabel(this);
|
||||
QVBoxLayout* layout = new QVBoxLayout(this);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->addWidget(label);
|
||||
setLayout(layout);
|
||||
}
|
||||
|
||||
screenshot_item::~screenshot_item()
|
||||
{
|
||||
if (m_thread && m_thread->isRunning())
|
||||
{
|
||||
m_thread->wait();
|
||||
}
|
||||
}
|
||||
|
@ -6,9 +6,7 @@
|
||||
#include <QFutureWatcher>
|
||||
#include <QPixmap>
|
||||
#include <QSize>
|
||||
#include <QLabel>
|
||||
#include <QEvent>
|
||||
#include <QThread>
|
||||
#include <array>
|
||||
|
||||
class screenshot_manager_dialog : public QDialog
|
||||
@ -46,22 +44,3 @@ private:
|
||||
QSize m_icon_size;
|
||||
QPixmap m_placeholder;
|
||||
};
|
||||
|
||||
class screenshot_item : public flow_widget_item
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
screenshot_item(QWidget* parent);
|
||||
virtual ~screenshot_item();
|
||||
|
||||
QString icon_path;
|
||||
QSize icon_size;
|
||||
QLabel* label{};
|
||||
|
||||
private:
|
||||
std::unique_ptr<QThread> m_thread;
|
||||
|
||||
Q_SIGNALS:
|
||||
void signal_icon_update(const QPixmap& pixmap);
|
||||
};
|
||||
|
@ -29,6 +29,20 @@ namespace gui
|
||||
// game list icon color
|
||||
"QLabel#gamelist_icon_background_color { color: rgba(240, 240, 240, 255); }"
|
||||
|
||||
// game grid
|
||||
"#game_list_grid #flow_widget_content { background: #fff; }"
|
||||
"#game_list_grid_item { background: #fff; }"
|
||||
"#game_list_grid_item[selected=\"true\"] { background: #148aff; }"
|
||||
"#game_list_grid_item:focus { background: #148aff; }"
|
||||
"#game_list_grid_item:hover { background: #94c9ff; }"
|
||||
"#game_list_grid_item:hover:focus { background: #007fff; }"
|
||||
"#game_list_grid_item #game_list_grid_item_title_label { color: rgba(51, 51, 51, 255); font-weight: 600; font-size: 8pt; font-family: Lucida Grande; border: 0em solid white; }"
|
||||
|
||||
// game grid hover and focus: we need to handle properties differently when using descendants
|
||||
"#game_list_grid_item[selected=\"true\"] #game_list_grid_item_title_label { color: #fff; }"
|
||||
"#game_list_grid_item[hover=\"true\"] #game_list_grid_item_title_label { color: #fff; }"
|
||||
"#game_list_grid_item[focus=\"true\"] #game_list_grid_item_title_label { color: #fff; }"
|
||||
|
||||
// save manager icon color
|
||||
"QLabel#save_manager_icon_background_color { color: rgba(240, 240, 240, 255); }"
|
||||
|
||||
@ -37,11 +51,8 @@ namespace gui
|
||||
|
||||
// tables
|
||||
"QTableWidget { alternate-background-color: #f2f2f2; background-color: #fff; border: none; }"
|
||||
"QTableWidget#game_grid { alternate-background-color: #f2f2f2; background-color: #fff; font-weight: 600; font-size: 8pt; font-family: Lucida Grande; color: rgba(51, 51, 51, 255); border: 0em solid white; }"
|
||||
"QTableView::item { border-left: 0.063em solid white; border-right: 0.063em solid white; padding-left:0.313em; }"
|
||||
"QTableView::item:selected { background-color: #148aff; color: #fff; }"
|
||||
"QTableView#game_grid::item:hover:!selected { background-color: #94c9ff; color: #fff; }"
|
||||
"QTableView#game_grid::item:hover:selected { background-color: #007fff; color: #fff; }"
|
||||
|
||||
// table headers
|
||||
"QHeaderView::section { padding-left: .5em; padding-right: .5em; padding-top: .4em; padding-bottom: -.1em; border: 0.063em solid #ffffff; }"
|
||||
|
Loading…
Reference in New Issue
Block a user