Initial commit

This commit is contained in:
alexpete
2021-03-05 11:26:34 -08:00
commit a10351f38d
27091 changed files with 5521199 additions and 0 deletions
+3
View File
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:83c2964eb91c4ae15c733bd6db6b5781b1dc42a02906808acefa76c3a2fda127
size 51262
+24
View File
@@ -0,0 +1,24 @@
<RCC>
<qresource prefix="/GridHub">
<file>Resources/Connected.png</file>
<file>Resources/Disconnected.png</file>
<file>Resources/style_dark.qss</file>
<file>Resources/StyleSheetImages/arrow_up_V2.png</file>
<file>Resources/StyleSheetImages/arrow_down_V2.png</file>
<file>Resources/StyleSheetImages/arrow_left_V2.png</file>
<file>Resources/StyleSheetImages/arrow_right_V2.png</file>
<file>Resources/StyleSheetImages/checkbox_checked.png</file>
<file>Resources/StyleSheetImages/checkbox_checked_disabled.png</file>
<file>Resources/StyleSheetImages/checkbox_unchecked.png</file>
<file>Resources/StyleSheetImages/checkbox_unchecked_disabled.png</file>
<file>Resources/StyleSheetImages/dropdown_arrow.png</file>
<file>Resources/StyleSheetImages/radiobutton_checked.png</file>
<file>Resources/StyleSheetImages/radiobutton_checked_disabled.png</file>
<file>Resources/StyleSheetImages/radiobutton_unchecked.png</file>
<file>Resources/StyleSheetImages/radiobutton_unchecked_disabled.png</file>
<file>Resources/StyleSheetImages/spinbox_down.png</file>
<file>Resources/StyleSheetImages/spinbox_up.png</file>
<file>Resources/StyleSheetImages/treeview_arrow_down.png</file>
<file>Resources/StyleSheetImages/treeview_arrow_right.png</file>
</qresource>
</RCC>
+2
View File
@@ -0,0 +1,2 @@
IDI_ICON1 ICON DISCARDABLE "GridHub.ico"
+882
View File
@@ -0,0 +1,882 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>GridHubClass</class>
<widget class="QWidget" name="GridHubClass">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>610</width>
<height>738</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="contextMenuPolicy">
<enum>Qt::DefaultContextMenu</enum>
</property>
<property name="windowTitle">
<string>GridHub</string>
</property>
<property name="windowIcon">
<iconset resource="gridhub.qrc">
<normaloff>:/GridHub/Resources/Connected.png</normaloff>:/GridHub/Resources/Connected.png</iconset>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<layout class="QVBoxLayout" name="verticalLayout_7">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item>
<widget class="QFrame" name="frame">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_5">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<layout class="QGridLayout" name="gridLayout">
<property name="bottomMargin">
<number>0</number>
</property>
<property name="spacing">
<number>0</number>
</property>
<item row="4" column="0" colspan="4">
<widget class="QFrame" name="frame_8">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<property name="spacing">
<number>5</number>
</property>
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QCheckBox" name="isAddToStartup">
<property name="text">
<string>Add to windows startup folder</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>10</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QCheckBox" name="isLogToFile">
<property name="text">
<string>Log activity</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item row="1" column="2">
<widget class="QFrame" name="frame_7">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item>
<widget class="QLabel" name="label_3">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>140</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Connection slots</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="numSlots">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="buttonSymbols">
<enum>QAbstractSpinBox::UpDownArrows</enum>
</property>
<property name="specialValueText">
<string/>
</property>
<property name="suffix">
<string/>
</property>
<property name="prefix">
<string/>
</property>
<property name="minimum">
<number>0</number>
</property>
<property name="maximum">
<number>32</number>
</property>
<property name="value">
<number>10</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="0" column="3" rowspan="3">
<widget class="QFrame" name="frame_6">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>5</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="startStopService">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>75</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>66</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Start</string>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>5</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item row="2" column="0">
<widget class="QFrame" name="frame_4">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="leftMargin">
<number>5</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item>
<widget class="QCheckBox" name="isDisconnectDetect">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Enable Disconnection Detection</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="0">
<widget class="QFrame" name="frame_3">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>2</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item>
<widget class="QLabel" name="sessionPortLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>65</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Session port</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="sessionPort">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<property name="frame">
<bool>false</bool>
</property>
<property name="buttonSymbols">
<enum>QAbstractSpinBox::UpDownArrows</enum>
</property>
<property name="specialValueText">
<string/>
</property>
<property name="suffix">
<string/>
</property>
<property name="prefix">
<string/>
</property>
<property name="minimum">
<number>1024</number>
</property>
<property name="maximum">
<number>65535</number>
</property>
<property name="value">
<number>5172</number>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
<item row="0" column="0" colspan="3">
<widget class="QFrame" name="frame_2">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item>
<widget class="QLabel" name="label_4">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>65</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Hub name</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="hubName">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>394</width>
<height>0</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="2">
<widget class="QFrame" name="frame_5">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item>
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>140</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>Disconnection Timeout (ms)</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="disconnectionTimeout">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="maximum">
<number>60000</number>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="1">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="1">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="0" colspan="4">
<widget class="Line" name="line">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>10</height>
</size>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="5" column="0" colspan="4">
<widget class="Line" name="line_2">
<property name="minimumSize">
<size>
<width>0</width>
<height>10</height>
</size>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QFrame" name="frame_10">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_6">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QSplitter" name="splitter">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="handleWidth">
<number>3</number>
</property>
<property name="childrenCollapsible">
<bool>false</bool>
</property>
<widget class="QFrame" name="frame_9">
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Connections</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="leftMargin">
<number>4</number>
</property>
<property name="topMargin">
<number>4</number>
</property>
<property name="rightMargin">
<number>4</number>
</property>
<property name="bottomMargin">
<number>4</number>
</property>
<item>
<widget class="QTableWidget" name="members">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::SingleSelection</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="horizontalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
</property>
<property name="rowCount">
<number>0</number>
</property>
<property name="columnCount">
<number>6</number>
</property>
<attribute name="horizontalHeaderDefaultSectionSize">
<number>90</number>
</attribute>
<column>
<property name="text">
<string>ID</string>
</property>
</column>
<column>
<property name="text">
<string>Name</string>
</property>
</column>
<column>
<property name="text">
<string>Connection ID</string>
</property>
</column>
<column>
<property name="text">
<string>IsHost</string>
</property>
</column>
<column>
<property name="text">
<string>IsLocal</string>
</property>
</column>
<column>
<property name="text">
<string>IsReady</string>
</property>
</column>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<widget class="QFrame" name="frame_11">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="frameShape">
<enum>QFrame::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Raised</enum>
</property>
<layout class="QVBoxLayout" name="verticalLayout_8">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Output</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="leftMargin">
<number>4</number>
</property>
<property name="topMargin">
<number>4</number>
</property>
<property name="rightMargin">
<number>4</number>
</property>
<property name="bottomMargin">
<number>4</number>
</property>
<item>
<widget class="QTextBrowser" name="output"/>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources>
<include location="gridhub.qrc"/>
</resources>
<connections/>
</ui>
@@ -0,0 +1,14 @@
{
"images" : [
{
"size" : "128x128",
"idiom" : "mac",
"filename" : "icon_128.png",
"scale" : "1x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:99b71f725e6899cedb12714b7d96fd5651762a4f976f9a1583f1fdffb9ea46bc
size 27913
@@ -0,0 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:90f3962e0421305cb69cf60d6d849455126cb3f570d8b3ee100e28afee446552
size 59062
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6404b8a7842eb79d8a4d025469c78cba535c78b1dee614beeb5c5af0dcab9088
size 49321
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:febc3883ac09ea579877deb49a41441f618a1558f63a838ca3e216c65c638b1c
size 448
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7e89ed1a88e4b7488a34f9d5ecc3cf231d1c3b2b225fe956e009431ae0cd02d3
size 438
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:b7226b603a86d0f49f1fcc0159389555c02814af5382ba7b52374cac7e38f3b8
size 446
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:63ed841be1103f4892ee5a6e9d7a8b0cdb0985a8267d445299aafc62b645c2fd
size 546
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:638cf180bfacf7438c9ac457d61a55df341ce5b8edd818be9c71c99b747684ef
size 503
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:47e1305d8ad0fa10377b3001fa213a7f16463339e9a15478605217a3412c9eee
size 491
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6c62d00483d3a82337900af814e1ac1c5d460681deddc98c3a120da5c8a8b72f
size 203
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3295d0d4cf26b6962f29c7fe7c2cee9abbbda06e7b0fe32cbe702ba1f8953a59
size 202
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:3d623ad9cecbb6c3fee912eb39689fe5442f805cd41d32fd6d5a49f5c7b049f7
size 372
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6686a111a1d0f0e02d544d24135b9b94599fb332cd43912675c6840eb318bc00
size 3293
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d49c822d8f43f0f05dc8e2fa1ccee86ef3731cca074a586eb5b943caddaa6e52
size 3306
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7c8bf7b3f70d5f2683a8e495ddf80ecea1a437d63d259730becfd546286a8be2
size 3191
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:1b4c23e60d84cfa16a310638ffc30d14c7821dbb852e96c5cbfb814aa0af3b1d
size 3244
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:beb00c64d91c8e9035414fba270f2b9477a1d15debb2d4acad0481256948b58d
size 298
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9b15e390624dc61ad6ae48faedb2f901f016615548747b6ed66296a8dd6ce5d7
size 296
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:b85878ce2422dba963334dfc04648d893b7f17f9f4e4a395d6fea92c3dc5998e
size 198
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:47df1e68051bd26a470e5d9d8af45c26e33c56d06cc379f861d8300963b606de
size 188
@@ -0,0 +1,988 @@
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
:disabled{
color: rgb(130,130, 130);
}
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
QWidget {
background-color: rgb(80, 80, 80);
}
QMainWindow{
background-color: rgb(80, 80, 80);
}
QMainWindow::separator {
border: 0px solid red;
}
QMainWindow::separator:hover {
background-color: rgb(255, 170, 0);
}
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
QPushButton{
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(90, 90, 90), stop:1 rgb(60, 60, 60));
border: 1px solid black;
color:rgb(220,220,220);
padding: 1ex 2ex;
}
QPushButton::hover{
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(150, 150, 150), stop:1 rgb(120, 120, 120));
color:rgb(255,255,255);
}
QPushButton:pressed{
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(120, 120, 120), stop:1 rgb(90, 90, 90));
}
QDialogButtonBox > QPushButton, QDialog > QPushButton, QWizard > QWidget > QPushButton{
min-width: 5em;
min-height: 1.4em;
}
QPushButton#m_pbFolderTpl, QPushButton#m_pbFilenameTpl, QPushButton#m_pbInfo, QPushButton#m_pbSoundPlay
{
background-color:transparent;
border: 0px solid red;
}
QPushButton[text="..."]{
min-width: 1em;
}
QPushButton#m_pbAdvancedSetting{
background-color:transparent;
border:0px solid red;
padding: 0ex 0ex;
}
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
QDockWidget
{
background-color: rgb(90, 90, 90);
border-top: 1px solid orange;
color:rgb(220, 220, 220);
}
QDockWidget::title
{
background-color: rgb(90, 90, 90);
border: 0px solid black;
padding: 0.4em;
}
QDockWidget .QWidget{
background-color: rgb(40, 40, 40);
color: rgb(200,200,200);
border: 0px solid red;
}
QDockWidget QScrollArea{
border: 0px solid rgb(90, 90, 90);
}
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
QHeaderView::section{
color: rgb(220,220,220);
}
QHeaderView::section{
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(90, 90, 90), stop:1 rgb(60, 60, 60));
padding: 1ex;
}
QHeaderView::section:first{
border-top: 0px solid black;
border-right: 0px solid black;
border-bottom: 1px solid black;
border-left: 0px solid black;
}
QHeaderView::section:middle{
border-top: 0px solid black;
border-right: 0px solid black;
border-bottom: 1px solid black;
border-left: 1px solid black;
}
QHeaderView::section:last{
border-top: 0px solid black;
border-right: 0px solid black;
border-bottom: 1px solid black;
border-left: 1px solid black;
}
QHeaderView::section:hover{
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(150, 150, 150), stop:1 rgb(120, 120, 120));
}
QHeaderView::section:pressed{
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(150, 150, 150), stop:1 rgb(120, 120, 120));
}
/* style the sort indicator */
QHeaderView::down-arrow {
image: url(UI:arrow_down_V2.png);
width: 10px;
height: 10px;
padding-right: 1ex;
}
QHeaderView::up-arrow {
image: url(UI:arrow_up_V2.png);
width: 10px;
height: 10px;
padding-right: 1ex;
}
QTreeView#UIGroup_TreeView QHeaderView::section:first{
border-left: 1px solid black;
}
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
QScrollBar{
background-color: rgb(55, 55, 55);
}
QScrollBar::add-page, QScrollBar::sub-page {
background: none;
}
QScrollBar::horizontal{
border:0px solid rgb(90, 90, 90);
border-left: 0px solid red;
border-right: 0px solid red;
margin: 0px 16px 0px 16px;
}
QScrollBar::vertical {
border: 0px solid rgb(90, 90, 90);
border-top: 0px solid red;
border-bottom: 0px solid red;
margin: 16px 0px 16px 0px;
}
QScrollBar::handle{
background-color: rgb(110, 110, 110);
border: 1px solid rgb(65, 65, 65);
}
QScrollBar::handle:horizontal{
min-width: 20px;
}
QScrollBar::handle:vertical{
min-height: 20px;
}
QScrollBar::handle:hover {
background-color: rgb(130, 130, 130);
}
QScrollBar::handle:pressed {
background-color: rgb(180, 180, 180);
}
QScrollBar::add-line:horizontal {
background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 rgb(60, 60, 60), stop:1 rgb(90, 90, 90));
border: 1px solid rgb(90, 90, 90);
border-left:0px;
width: 15px;
subcontrol-position: right;
subcontrol-origin: margin;
}
QScrollBar::sub-line:horizontal{
background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 rgb(90, 90, 90), stop:1 rgb(60, 60, 60));
border: 1px solid rgb(90, 90, 90);
border-right:0px;
width: 15px;
subcontrol-position: left;
subcontrol-origin: margin;
}
QScrollBar::add-line:horizontal:hover{
background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 rgb(100, 100, 100), stop:1 rgb(150, 150, 150));
}
QScrollBar::sub-line:horizontal:hover{
background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 rgb(150, 150, 150), stop:1 rgb(100, 100, 100));
}
QScrollBar::add-line:horizontal:pressed{
background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 rgb(130, 130, 130), stop:1 rgb(180, 180, 180));
}
QScrollBar::sub-line:horizontal:pressed{
background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 rgb(180, 180, 180), stop:1 rgb(130, 130, 130));
}
QScrollBar::add-line:vertical {
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(60, 60, 60), stop:1 rgb(90, 90, 90));
border: 1px solid rgb(90, 90, 90);
border-top:0px;
height: 15px;
subcontrol-position: bottom;
subcontrol-origin: margin;
}
QScrollBar::sub-line:vertical{
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(90, 90, 90), stop:1 rgb(60, 60, 60));
border: 1px solid rgb(90, 90, 90);
border-bottom:0px;
height: 15px;
subcontrol-position: top;
subcontrol-origin: margin;
}
QScrollBar::add-line:vertical:hover{
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(100, 100, 100), stop:1 rgb(150, 150, 150));
}
QScrollBar::sub-line:vertical:hover{
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(150, 150, 150), stop:1 rgb(100, 100, 100));
}
QScrollBar::add-line:vertical:pressed{
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(130, 130, 130), stop:1 rgb(180, 180, 180));
}
QScrollBar::sub-line:vertical:pressed{
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(180, 180, 180), stop:1 rgb(130, 130, 130));
}
QScrollBar::left-arrow:horizontal{
background-image: url(UI:arrow_left_V2.png);
background-position: center;
}
QScrollBar::right-arrow{
background-image: url(UI:arrow_right_V2.png);
background-position: center;
}
QScrollBar::up-arrow:vertical{
background-image: url(UI:arrow_up_V2.png);
background-position: center;
}
QScrollBar::down-arrow:vertical{
background-image: url(UI:arrow_down_V2.png);
background-position: center;
}
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
QSplitter{
background-color: transparent;
border: 0px solid red;
}
QSplitter::handle{
background-color: rgb(40,40,40);
border: 0px solid green;
}
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
QScrollArea {
background-color: transparent;
border: 0px solid red;
}
/*----------------------------------------------------------------------------*/
/* FOLDER TREE */
/*----------------------------------------------------------------------------*/
QTreeView{
background-color: rgb(100, 100, 100);
alternate-background-color: rgb(90, 90, 90);
border: 0px solid black;
}
QTreeView:active{
selection-background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(80, 80, 80), stop:1 rgb(60, 60, 60));
}
QTreeView:!active{
selection-background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(80, 80, 80), stop:1 rgb(70, 70, 70));
}
QTreeView::item{
color: rgb(220,220,220);
border: 0px solid green;
}
QTreeView::item:alternate{
}
QTreeView::item:selected:!active{
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(70, 70, 70), stop:1 rgb(50, 50, 50));
}
QTreeView::item:selected:active{
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(80, 80, 80), stop:1 rgb(60, 60, 60));
}
QTreeView::item:hover{
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(80, 80, 80), stop:1 rgb(60, 60, 60));
}
QTreeView::branch:closed:has-children:!has-siblings, QTreeView::branch:closed:has-children:has-siblings{
border-image: none;
image: url(UI:treeview_arrow_right.png);
}
QTreeView::branch:open:has-children:!has-siblings, QTreeView::branch:open:has-children:has-siblings{
border-image: none;
image: url(UI:treeview_arrow_down.png);
}
QTreeView::indicator{
border: 0px solid red;
width: 14px;
height: 16px;
}
QTreeView::indicator:unchecked{
image: url(UI:checkbox_unchecked.png);
}
QTreeView::indicator:unchecked:disabled{
image: url(UI:checkbox_unchecked_disabled.png);
}
QTreeView::indicator:checked{
image: url(UI:checkbox_checked.png);
}
QTreeView::indicator:checked:disabled{
image: url(UI:checkbox_checked_disabled.png);
}
QTreeView#UIGroup_TreeView{
background-color: rgb(40, 40, 40);
alternate-background-color: rgb(50, 50, 50);
border: 0px solid black;
}
QTreeView#UIGroup_TreeView:active{
selection-background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(110, 110, 110), stop:1 rgb(100, 100, 100));
}
QTreeView#UIGroup_TreeView:!active{
selection-background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(80,80, 80), stop:1 rgb(70, 70, 70));
}
QTreeView#UIGroup_TreeView::item:selected:!active{
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(80,80, 80), stop:1 rgb(70, 70, 70));
}
QTreeView#UIGroup_TreeView::item:selected:active{
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(110, 110, 110), stop:1 rgb(100, 100, 100));
}
QTreeView#UIGroup_TreeView::item:hover{
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(110, 110, 110), stop:1 rgb(100, 100, 100));
}
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
MyThumbListView{
background-color: black;
}
QListView{
background-color: rgb(65, 65, 65);
border: 0px solid black;
}
QListView::item{
color: rgb(20,20,20);
}
QListView::item:alternate{
}
QListView::item:selected{
color: rgb(220,220,220);
}
QListView::item:selected:!active{
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(60, 60, 60), stop:1 rgb(60, 60, 60));
}
QListView::item:selected:active{
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(90, 90, 90), stop:1 rgb(60, 60, 60));
}
QListView::item:hover{
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(90, 90, 90), stop:1 rgb(60, 60, 60));
}
QListView#UIGroup_ListView{
background-color: rgb(40, 40, 40);
border: 0px solid black;
selection-background-color: rgb(60, 60, 60);
}
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
QTableView{
background-color: rgb(180, 180, 180);
}
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
QMenuBar{
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(120, 120, 120), stop:1 rgb(100, 100, 100));
}
QMenuBar::item{
background-color: transparent;
color: rgb(220, 220, 220);
}
QMenuBar::item:selected{
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(180, 180, 180), stop:1 rgb(130, 130, 130));
color: rgb(220, 220, 220);
}
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
QMenu{
background-color: rgb(60, 60, 60);
color: rgb(220, 220, 220);
border: 0px solid red;
padding: 5px;
}
QMenu::item{
background-color: transparent;
border: 1px solid transparent;
padding: 2px 25px 2px 20px;
}
QMenu::item:selected{
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(150, 150, 150), stop:1 rgb(100, 100, 100));
border: 1px solid transparent;
color:rgb(220, 220, 220);
}
QMenu::separator{
height: 1px;
background-color: rgb(220, 220, 220);
margin: 5px 25px 5px 20px;
}
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
QDialog{
background-color: rgb(95, 95, 95);
border: 0px solid black;
}
QDialog QWidget#qt_scrollarea_viewport > QWidget {
border: 0px solid black;
}
QDialog WScrollArea{
background-color: rgb(40, 40, 40);
}
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
QTabWidget::pane { /* The tab widget frame */
border: 0px solid black;
margin-top:-1px;
}
/*----------------------------------------------------------------------------*/
/* TOP TAB BAR */
/*----------------------------------------------------------------------------*/
QTabBar{
background-color: transparent;
border:0px solid red;
border-right-color: rgb(30, 144, 255);
}
QTabBar::tab{
background-color: rgb(40, 40, 40);
color: rgb(200, 200, 200);
}
QTabBar[shape="0"]::tab{
min-width:3em;
padding: 1ex 3ex;
}
MyTabBar[shape="0"]::tab:selected{
border-bottom-color: rgb(120, 120, 120);
}
QTabBar[shape="0"]::tab:selected{
background-color: rgb(120, 120, 120);
border-bottom-color: rgb(40, 40, 40);
}
MyTabWidget::tab-bar {
left: 1px;
}
MyTabBar::tab:selected{
color: white;
background-color: rgb(120, 120, 120);
border-top-left-radius: 4px;
border-top-right-radius: 4px;
border-top:3px solid rgb(30, 144, 255);
}
MyTabBar[shape="0"]::tab:selected{
border-bottom-color: rgb(120, 120, 120);
}
MyTabWidget::pane{
padding: 1px 0px;
}
/*----------------------------------------------------------------------------*/
/* FOLDER TREE AND CATEGORY TABS*/
/*----------------------------------------------------------------------------*/
QTabBar[shape="2"]::tab{
min-height:3em;
padding: 3ex 1ex;
}
QTabBar[shape="2"]::tab:selected{
background-color: rgb(100, 100, 100);
border-left:3px solid rgb(30, 144, 255);
}
/*
QTabBar::tab:first:selected{
margin-left: 0px;
margin-right: -2px;
}
QTabBar::tab:middle:selected{
margin-left: 0px;
margin-right: -2px;
}
QTabBar::tab:last:selected{
margin-left: 0px;
margin-right: 0px;
}
*/
QTabBar[shape="0"]::tab:!selected{
margin-top: 2px;
}
QTabBar::tab:last:!selected{
border-left:0px solid red;
border-right:0px solid black;
}
QTabBar::tab:!selected:hover{
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(90, 90, 90), stop:1 rgb(60, 60, 60));
}
QTabBar[shape="1"]::tab:selected{
border-top-color: rgb(40, 40, 40);
margin-left: 0px;
margin-right: -2px;
}
QTabBar[shape="1"]::tab:!selected{
margin-bottom: 2px;
}
QTabBar[shape="0"]::tab:selected{
border-top-color: rgb(30, 144, 255);
}
QTabBar[shape="1"]::tab:selected{
border-bottom-color: rgb(30, 144, 255);
}
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
QProgressBar{
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(90, 90, 90), stop:1 rgb(60, 60, 60));
border: 1px solid black;
}
QProgressBar::chunk{
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgba(180, 180, 0, 100), stop:1 rgba(60, 60, 60, 60));
border: 1px solid rgba(180, 180, 180, 200);
}
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
QToolBar{
border: 0px;
}
QToolBar:horizontal{
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(100, 100, 100), stop:1 rgb(80, 80, 80));
}
QToolBar:vertical{
background-color: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 rgb(90, 90, 90), stop:1 rgb(60, 60, 60));
}
QToolBar:separator{
background-color:qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 rgb(180, 180, 180), stop:1 rgb(90, 90, 90));;
border-right: 0px solid black;
border-bottom: 0px solid black;
width:1px;
height:1px;
margin:5px;
}
QToolBar#UIPanosView_ToolBar{
border-top: 1px solid black;
border-bottom: 0px solid red;
}
QToolBar#UIGroupsView_ToolBar{
border-top: 1px solid black;
border-bottom: 0px solid red;
}
QToolBar#UIGroup_ToolBar{
border-bottom: 1px solid black;
}
QToolBar#UIPano_ToolBar{
border-bottom: 1px solid black;
}
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
QSlider::groove:horizontal {
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(180, 180, 180), stop:1 rgb(140, 140, 140));
border: 0px solid rgb(60, 60, 60);
height: 8px; /* the groove expands to the size of the slider by default. by giving it a height, it has a fixed size */
}
QSlider::handle:horizontal {
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(180, 180, 180), stop:1 rgb(140, 140, 140));
border: 1px solid rgb(60, 60, 60);
width: 8px;
margin: -2px 0; /* handle is placed by default on the contents rect of the groove. Expand outside the groove */
border-radius: 2px;
}
QSlider::handle:horizontal:hover {
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(220, 220, 220), stop:1 rgb(180, 180, 180));
}
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
QStatusBar{
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(90, 90, 90), stop:1 rgb(60, 60, 60));
color: rgb(220, 220, 220);
border: 0px solid red;
}
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
DlgSettings QToolButton {
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(60, 60, 60), stop:1 rgb(90, 90, 90));
color:rgb(220,220,220);
}
DlgSettings QTabWidget::pane {
background-color: rgb(60, 60, 60);
}
DlgSettings QTabBar[shape="0"]::tab:selected {
background-color: rgb(60, 60, 60);
color: white;
border-top:3px solid rgb(30, 144, 255);
}
QToolButton {
background-color: transparent;
border: 0px solid red;
color:rgb(220, 220, 220);
}
QToolButton#m_tbClose{
background-color: transparent;
}
QToolButton::hover{
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(150, 150, 150), stop:1 rgb(120, 120, 120));
}
QToolButton::checked{
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(180, 180, 180), stop:1 rgb(150, 150, 150));
}
QToolButton::pressed{
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(120, 120, 120), stop:1 rgb(90, 90, 90));
}
QToolButton[popupMode="1"]{
padding-right: 10px;
}
QToolButton::menu-button{
border: 0px solid red;
}
QToolButton::menu-button:hover{
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(180, 180, 180), stop:1 rgb(150, 150, 150));
}
QToolButton::menu-button:pressed{
}
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
QLabel, QCheckBox, QRadioButton{
color: rgb(220, 220, 220);
}
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
QSpinBox, QDoubleSpinBox {
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(180, 180, 180), stop:1 rgb(150, 150, 150));
border: 1px solid black;
padding:0px;
selection-background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(120, 120, 120), stop:1 rgb(90, 90, 90));
selection-color: rgb(25, 25, 25);
}
QSpinBox::up-button, QSpinBox::down-button, QDoubleSpinBox::up-button, QDoubleSpinBox::down-button {
subcontrol-origin: border;
width: 16px;
border-width: 0px;
}
QSpinBox::up-button, QDoubleSpinBox::up-button {
subcontrol-position: top right;
}
QSpinBox::down-button, QDoubleSpinBox::down-button {
subcontrol-position: bottom right;
}
QSpinBox::up-arrow, QDoubleSpinBox::up-arrow {
border-image: url(UI:spinbox_up.png);
height:7px;
}
QSpinBox::down-arrow, QDoubleSpinBox::down-arrow {
border-image: url(UI:spinbox_down.png);
height:7px;
}
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
QCheckBox::indicator:unchecked{
image: url(UI:checkbox_unchecked.png);
}
QCheckBox::indicator:unchecked:disabled{
image: url(UI:checkbox_unchecked_disabled.png);
}
QCheckBox::indicator:checked{
image: url(UI:checkbox_checked.png);
}
QCheckBox::indicator:checked:disabled{
image: url(UI:checkbox_checked_disabled.png);
}
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
QRadioButton::indicator:unchecked{
image: url(UI:radiobutton_unchecked.png);
}
QRadioButton::indicator:unchecked:disabled{
image: url(UI:radiobutton_unchecked_disabled.png);
}
QRadioButton::indicator:checked{
image: url(UI:radiobutton_checked.png);
}
QRadioButton::indicator:checked:disabled{
image: url(UI:radiobutton_checked_disabled.png);
}
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
QLineEdit{
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(180, 180, 180), stop:1 rgb(150, 150, 150));
border: 0px solid black;
padding:0px;
color:black;
selection-background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(120, 120, 120), stop:1 rgb(90, 90, 90));
selection-color: black;
}
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
QComboBox{
border: 0px solid black;
padding: 0px 18px 0px 3px;
}
QComboBox:!editable, QComboBox::drop-down:editable{
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(180, 180, 180), stop:1 rgb(150, 150, 150));
}
QComboBox:editable{
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(180, 180, 180), stop:1 rgb(150, 150, 150));
selection-background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(120, 120, 120), stop:1 rgb(90, 90, 90));
selection-color: rgb(25, 25, 25);
}
QComboBox:!editable:on, QComboBox::drop-down:editable:on{
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(180, 180, 180), stop:1 rgb(150, 150, 150));
}
QComboBox::drop-down{
subcontrol-origin: padding;
subcontrol-position: top right;
width: 15px;
border: 0px;
}
QComboBox::down-arrow{
image: url(UI:dropdown_arrow.png);
}
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
/* fix group box */
QGroupBox{
color: rgb(200, 200, 200);
background-color: rgb(90, 90, 90);
border: 1px solid black;
margin-top: 1.1em; /* leave space at the top for the title */
margin-bottom: 0.1em; /* leave space at the top for the title */
font-weight: bold;
}
QGroupBox::title{
border: 0px solid red;
subcontrol-origin: margin;
top: 0px;
}
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
QTextEdit{
background-color: rgb(90, 90, 90);
color: rgb(220,220,220);
border: 3px solid rgb(90, 90, 90);
selection-background-color: rgb(60, 60, 60) ;
selection-color: rgb(220, 220, 220);
}
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
QToolTip{
background-color: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 rgb(180, 180, 180), stop:1 rgb(150, 150, 150));
}
/*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/
QWizard{
}
QWizard .QWidget{
background-color: rgb(40,40,40);
color:rgb(220,220,220);
}
QWizard .QFrame{
background-color: rgb(40,40,40);
color:rgb(220,220,220);
}
QWizard > .QWidget > .QLabel{
background-color: rgb(40,40,40);
color:rgb(220,220,220);
}
QWizard QListView{
background-color: rgb(60,60,60);
color:rgb(220,220,220);
}
QWizardPage .QFrame{
background-color: transparent;
border: 1px solid black;
}
SearchLineEdit{
background-color: transparent;
border: 0px solid black;
padding: 0px;
}
SearchLineEdit>QLineEdit{
background-color: rgb(160, 160, 160);
}
+747
View File
@@ -0,0 +1,747 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <AzCore/PlatformDef.h>
AZ_PUSH_DISABLE_WARNING(4244 4251, "-Wunknown-warning-option")
#include <QtGui>
#include <QtWidgets/QMenu>
#include <QtNetwork/QHostInfo>
AZ_POP_DISABLE_WARNING
#ifdef AZ_PLATFORM_WINDOWS
// windows include must be first so we get the full version (AZCore bring the trimmed one)
#include <Windows.h>
#else
#include <signal.h>
#endif
#include "gridhub.hxx"
#include <GridHub/moc_gridhub.cpp>
#include <AzCore/Component/ComponentApplication.h>
#include <AzCore/PlatformId/PlatformId.h>
#include <AzCore/std/parallel/lock.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <GridMate/Carrier/Utils.h>
#include <GridMate/Session/LANSession.h>
#include <time.h> // for output timestamp
//////////////////////////////////////////////////////////////////////////
GridHub::GridHub(AZ::ComponentApplication* componentApp, GridHubComponent* hubComponent, QWidget *parent, Qt::WindowFlags flags)
: QWidget(parent, flags)
, m_componentApp(componentApp)
, m_hubComponent(hubComponent)
{
// create actions
//m_minimizeAction = new QAction(tr("Mi&nimize"), this);
//connect(m_minimizeAction, SIGNAL(triggered()), this, SLOT(hide()));
//m_maximizeAction = new QAction(tr("Ma&ximize"), this);
//connect(m_maximizeAction, SIGNAL(triggered()), this, SLOT(showMaximized()));
m_restoreAction = new QAction(tr("&Show"), this);
connect(m_restoreAction, SIGNAL(triggered()), this, SLOT(showNormal()));
m_quitAction = new QAction(tr("&Quit"), this);
connect(m_quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
// create menu
m_trayIconMenu = new QMenu(this);
//m_trayIconMenu->addAction(m_minimizeAction);
//m_trayIconMenu->addAction(m_maximizeAction);
m_trayIconMenu->addAction(m_restoreAction);
m_trayIconMenu->addSeparator();
m_trayIconMenu->addAction(m_quitAction);
// create tray icon
m_trayIcon = new QSystemTrayIcon(this);
m_trayIcon->setContextMenu(m_trayIconMenu);
m_trayIcon->setToolTip(QString("Amazon Debug Connection Hub - GridHub"));
m_trayIcon->setIcon(QIcon(":/GridHub/Resources/Disconnected.png"));
connect(m_trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(iconActivated(QSystemTrayIcon::ActivationReason)));
m_trayIcon->show();
setWindowFlags(Qt::Dialog);
ui.setupUi(this);
QObject::connect(ui.startStopService,SIGNAL(clicked()),this,SLOT(OnStartStopSession()));
ui.sessionPort->setValue(m_hubComponent->GetSessionPort());
QObject::connect(ui.sessionPort, SIGNAL(valueChanged(int)),this, SLOT(SetSessionPort(int)));
ui.numSlots->setValue(m_hubComponent->GetSessionSlots());
QObject::connect(ui.numSlots, SIGNAL(valueChanged(int)),this, SLOT(SetSessionSlots(int)));
ui.hubName->setText(QString(m_hubComponent->GetHubName().c_str()));
QObject::connect(ui.hubName, SIGNAL(textChanged(QString)),this, SLOT(SetHubName(QString)));
ui.isDisconnectDetect->setChecked(m_hubComponent->IsEnableDisconnectDetection());
QObject::connect(ui.isDisconnectDetect, SIGNAL(stateChanged(int)),this,SLOT(EnableDisconnectDetection(int)));
ui.isAddToStartup->setChecked(m_hubComponent->IsAddToStartupFolder());
QObject::connect(ui.isAddToStartup, SIGNAL(stateChanged(int)),this,SLOT(AddToStartupFolder(int)));
ui.isLogToFile->setChecked(m_hubComponent->IsLogToFile());
QObject::connect(ui.isLogToFile, SIGNAL(stateChanged(int)),this,SLOT(LogToFile(int)));
ui.disconnectionTimeout->setValue(m_hubComponent->GetDisconnectionTimeout());
QObject::connect(ui.disconnectionTimeout, SIGNAL(valueChanged(int)),this,SLOT(OnDisconnectTimeOutChange(int)));
SanityCheckDetectionTimeout();
// start at XX ms update interval
startTimer(30);
AZ::Debug::TraceMessageBus::Handler::BusConnect();
AZ::AllocatorInstance<GridMate::GridMateAllocatorMP>::Create();
// start the session
OnStartStopSession();
// Kicks off the tool's tick event
SystemTick();
}
GridHub::~GridHub()
{
AZ::Debug::TraceMessageBus::Handler::BusDisconnect();
if (m_hubComponent)
{
m_hubComponent->StopSession();
}
AZ::AllocatorInstance<GridMate::GridMateAllocatorMP>::Destroy();
delete m_trayIcon;
delete m_trayIconMenu;
delete m_quitAction;
delete m_restoreAction;
//delete m_maximizeAction;
//delete m_minimizeAction;
}
void GridHub::SystemTick()
{
AZ::SystemTickBus::ExecuteQueuedEvents();
AZ::SystemTickBus::Broadcast(&AZ::SystemTickEvents::OnSystemTick);
QTimer::singleShot(10, Qt::PreciseTimer, this, &GridHub::SystemTick);
}
//=========================================================================
// closeEvent
// [7/6/2012]
//=========================================================================
void GridHub::closeEvent(QCloseEvent *event)
{
if (m_trayIcon->isVisible()) {
/* QMessageBox::information(this, tr("GridHub - Amazon Debug Connection Hub"),
tr("The program will keep running in the "
"system tray. To terminate the program, "
"choose <b>Quit</b> in the context menu "
"that pops up when clicking this program's "
"entry in the system tray."));*/
hide();
event->ignore();
}
}
void GridHub::SanityCheckDetectionTimeout()
{
ui.disconnectionTimeout->setEnabled(m_hubComponent->IsEnableDisconnectDetection());
}
//=========================================================================
// timerEvent
// [7/6/2012]
//=========================================================================
void GridHub::timerEvent([[maybe_unused]] QTimerEvent *event)
{
m_componentApp->Tick();
if( !m_hubComponent->IsInSession() )
{
// if we get an address 169.X.X.X (AZCP is NOT ready) or 127.0.0.1 when network is not ready
AZStd::chrono::system_clock::time_point now = AZStd::chrono::system_clock::now();
static AZStd::chrono::system_clock::time_point lastUpdate = now;
if( AZStd::chrono::seconds(now - lastUpdate).count() >= 10 )
{
// Try to start it again...
OnStartStopSession();
lastUpdate = now;
}
}
UpdateOutput();
UpdateMembers();
}
//=========================================================================
// UpdateOutput
// [5/24/2011]
//=========================================================================
void GridHub::UpdateOutput()
{
if( m_output.empty() ) return;
m_outputMutex.lock();
QString msg(m_output.c_str());
m_output.clear();
m_outputMutex.unlock();
if(msg.endsWith('\n')) // append already inserts '\n' at the end
msg.chop(1);
ui.output->append(msg);
}
//=========================================================================
// UpdateMembers
// [7/11/2012]
//=========================================================================
void GridHub::UpdateMembers()
{
// update ~1 time a sec
AZStd::chrono::system_clock::time_point now = AZStd::chrono::system_clock::now();
static AZStd::chrono::system_clock::time_point lastUpdate = now;
if( AZStd::chrono::milliseconds(now - lastUpdate).count() < 1000 )
return;
lastUpdate = now;
const GridMate::GridSession* session = m_hubComponent->GetSession();
if( m_hubComponent == nullptr || session == nullptr || !session->IsReady() )
{
ui.members->setRowCount(0);
}
else
{
ui.members->setRowCount(session->GetNumberOfMembers());
for(unsigned int i = 0; i < session->GetNumberOfMembers(); ++i)
{
GridMate::GridMember* member = session->GetMemberByIndex(i);
ui.members->setItem(i,0,new QTableWidgetItem(member->GetId().ToString().c_str()));
ui.members->setItem(i,1,new QTableWidgetItem(member->GetName().c_str()));
ui.members->setItem(i,2,new QTableWidgetItem(member->GetConnectionId()==GridMate::InvalidConnectionID ? "--" : QString::number((size_t)member->GetConnectionId())));
ui.members->setItem(i,3,new QTableWidgetItem(member->IsHost()?"Yes":"No"));
ui.members->setItem(i,4,new QTableWidgetItem(member->IsLocal()?"Yes":"No"));
ui.members->setItem(i,5,new QTableWidgetItem(member->IsReady()?"Yes":"No"));
}
}
}
//=========================================================================
// TraceOutput
// [5/20/2011]
//=========================================================================
bool GridHub::OnOutput(const char* window, const char* message)
{
const QString time = QDateTime::currentDateTime().toString("HH:mm:ss|");
{
// This function will be called from multiple threads
const AZStd::lock_guard<AZStd::mutex> l(m_outputMutex);
m_output += time.toUtf8().data();
m_output += window;
m_output += " : ";
m_output += message;
}
return false;
}
//=========================================================================
// OnStartStopSession
// [7/6/2012]
//=========================================================================
void GridHub::OnStartStopSession()
{
if( m_hubComponent->IsInSession() )
{
m_hubComponent->StopSession();
ui.startStopService->setText("Start");
m_trayIcon->setIcon(QIcon(":/GridHub/Resources/Disconnected.png"));
}
else
{
if( m_hubComponent->StartSession() )
{
ui.startStopService->setText("Stop");
m_trayIcon->setIcon(QIcon(":/GridHub/Resources/Connected.png"));
}
}
}
//=========================================================================
// SetSessionPort
// [7/11/2012]
//=========================================================================
void GridHub::SetSessionPort(int port)
{
m_hubComponent->SetSessionPort(static_cast<unsigned short>(port));
}
//=========================================================================
// SetSessionSlots
// [7/11/2012]
//=========================================================================
void GridHub::SetSessionSlots(int numberOfSlots)
{
m_hubComponent->SetSessionSlots(static_cast<unsigned char>(numberOfSlots));
}
//=========================================================================
// EnableDisconnectDetection
// [9/14/2012]
//=========================================================================
void GridHub::EnableDisconnectDetection(int state)
{
m_hubComponent->EnableDisconnectDetection(state != 0);
SanityCheckDetectionTimeout();
}
//=========================================================================
// EnableDisconnectDetection
// [10/2/2012]
//=========================================================================
void GridHub::AddToStartupFolder(int state)
{
m_hubComponent->AddToStartupFolder(state != 0);
}
//=========================================================================
// LogToFile
// [7/2/2013]
//=========================================================================
void GridHub::LogToFile(int state)
{
m_hubComponent->LogToFile(state != 0);
}
void GridHub::OnDisconnectTimeOutChange(int value)
{
m_hubComponent->SetDisconnectionTimeOut(value);
}
//=========================================================================
// SetHubName
// [9/6/2012]
//=========================================================================
void GridHub::SetHubName(const QString & name)
{
m_hubComponent->SetHubName(AZStd::string(name.toUtf8().constData()));
}
//////////////////////////////////////////////////////////////////////////
//
//=========================================================================
// GridHubComponent
// [7/6/2012]
//=========================================================================
GridHubComponent::GridHubComponent()
: m_ui(nullptr)
, m_gridMate(nullptr)
, m_session(nullptr)
{
m_sessionPort = 5172;
m_numberOfSlots = 10;
m_isDisconnectDetection = true;
m_disconnectionTimeout = 5000;
m_isAddToStartupFolder = false;
m_isLogToFile = false;
#ifdef AZ_PLATFORM_WINDOWS
TCHAR name[MAX_COMPUTERNAME_LENGTH + 1];
DWORD dwCompNameLen = AZ_ARRAY_SIZE(name);
if ( GetComputerName(name, &dwCompNameLen) != 0 )
{
#ifdef _UNICODE
char c[MAX_COMPUTERNAME_LENGTH + 1];
wcstombs(c, name, AZ_ARRAY_SIZE(c));
m_hubName = c;
#else
m_hubName = name;
#endif
}
else
#endif
m_hubName = QHostInfo::localHostName().toUtf8().data();
}
//=========================================================================
// ~GridHubComponent
// [7/6/2012]
//=========================================================================
GridHubComponent::~GridHubComponent()
{
}
//=========================================================================
// Init
// [7/6/2012]
//=========================================================================
void GridHubComponent::Init()
{
}
//=========================================================================
// Activate
// [7/6/2012]
//=========================================================================
void GridHubComponent::Activate()
{
AZ::Debug::TraceMessageBus::Handler::BusConnect();
}
//=========================================================================
// Deactivate
// [7/6/2012]
//=========================================================================
void GridHubComponent::Deactivate()
{
if( IsInSession() )
StopSession();
AZ_Assert(m_monitored.empty(),"We should have removed all monitored members already!");
AZ::Debug::TraceMessageBus::Handler::BusDisconnect();
}
//=========================================================================
// OnSystemTick
//=========================================================================
void GridHubComponent::OnSystemTick()
{
if( m_gridMate )
{
m_gridMate->Update();
if( m_session == nullptr )
{
// It does have in certain condition that the PC was locked and we did not receive OnTick for a long time
// GridMate will detect that and delete the session in the update. If that happens we should just restart the entire gridmate.
RestartSession();
}
else
{
if (m_session->GetReplicaMgr())
{
m_session->GetReplicaMgr()->Unmarshal();
m_session->GetReplicaMgr()->UpdateFromReplicas();
m_session->GetReplicaMgr()->UpdateReplicas();
m_session->GetReplicaMgr()->Marshal();
}
if( !m_session->DebugIsEnableDisconnectDetection() )
{
AZStd::chrono::system_clock::time_point now = AZStd::chrono::system_clock::now();
static AZStd::chrono::system_clock::time_point lastUpdate = now;
if( AZStd::chrono::milliseconds(now - lastUpdate).count() >= 1000)
{
lastUpdate = now;
// when we have disconnect detection off, check if the process terminated
ExternalProcessMonitor* memberToKick = nullptr;
for(size_t i = 0; i < m_monitored.size(); ++i)
{
ExternalProcessMonitor& mi = m_monitored[i];
#ifdef AZ_PLATFORM_WINDOWS
if( mi.m_localProcess != INVALID_HANDLE_VALUE )
{
DWORD exitCode = 0;
GetExitCodeProcess(mi.m_localProcess,&exitCode);
if( exitCode != STILL_ACTIVE )
{
memberToKick = &mi;
break;
}
}
#else
if (mi.m_localProcess != 0)
{
if (kill(mi.m_localProcess, 0) != 0)
{
memberToKick = &mi;
break;
}
}
#endif
}
if( memberToKick )
{
GridMate::GridMember* member = m_session->GetMemberById(memberToKick->m_memberId);
if( member )
{
AZ_Printf("GridHub","Kicking member %s due to process inactivity!\n",member->GetId().ToString().c_str());
m_session->KickMember(member);
}
}
}
}
}
}
}
//=========================================================================
// LogToFile
// [7/2/2013]
//=========================================================================
void GridHubComponent::LogToFile(bool enable)
{
if( m_isLogToFile && !enable )
{
AZ_Printf("GridHub","Logging stopped!"); // indicate in the log that the user stopped logging.
}
m_isLogToFile = enable;
}
//=========================================================================
// OnOutput
// [7/2/2013]
//=========================================================================
bool GridHubComponent::OnOutput(const char* window, const char* message)
{
if( m_isLogToFile )
{
if( !m_logFile.IsOpen() )
{
const char* logFileName = "GridHubEvents.log"; // we can make this user configurable
if( !m_logFile.Open(logFileName,AZ::IO::SystemFile::SF_OPEN_APPEND) )
{
m_logFile.Open(logFileName,AZ::IO::SystemFile::SF_OPEN_CREATE);
}
}
if( m_logFile.IsOpen() )
{
const QByteArray time = QDateTime::currentDateTime().toString("MM:dd:yy-HH:mm:ss|").toUtf8();
m_logFile.Write(time.data(),time.size());
m_logFile.Write(window,strlen(window));
m_logFile.Write(" : ", 3);
m_logFile.Write(message,strlen(message));
}
}
return false;
}
//=========================================================================
// OnMemberJoined
// [5/25/2011]
//=========================================================================
void
GridHubComponent::OnMemberJoined([[maybe_unused]] GridMate::GridSession* session, GridMate::GridMember* member)
{
if( member->IsLocal() ) return;
// add non local member for process monitoring.
GridMate::MemberIDCompact id = member->GetId().Compact();
switch( member->GetPlatformId() )
{
case AZ::PlatformID::PLATFORM_WINDOWS_64:
case AZ::PlatformID::PLATFORM_APPLE_OSX:
{
GridMate::string localMachineName = GridMate::Utils::GetMachineAddress();
if( member->GetMachineName() == localMachineName )
{
ExternalProcessMonitor mi;
mi.m_memberId = id;
#ifdef AZ_PLATFORM_WINDOWS
mi.m_localProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION,TRUE,member->GetProcessId());
if( mi.m_localProcess != INVALID_HANDLE_VALUE )
m_monitored.push_back(mi);
#else
mi.m_localProcess = member->GetProcessId();
m_monitored.push_back(mi);
#endif
}
}break;
}
}
//=========================================================================
// OnMemberLeaving
// [5/25/2011]
//=========================================================================
void
GridHubComponent::OnMemberLeaving([[maybe_unused]] GridMate::GridSession* session, GridMate::GridMember* member)
{
GridMate::MemberIDCompact id = member->GetId().Compact();
for(size_t i = 0; i < m_monitored.size(); ++i )
{
ExternalProcessMonitor& mi = m_monitored[i];
if( mi.m_memberId == id )
{
#ifdef AZ_PLATFORM_WINDOWS
if( mi.m_localProcess != INVALID_HANDLE_VALUE )
CloseHandle(mi.m_localProcess);
#endif
m_monitored.erase(m_monitored.begin()+i);
break;
}
}
}
//=========================================================================
// OnSessionCreated
// [5/24/2011]
//=========================================================================
void
GridHubComponent::OnSessionCreated(GridMate::GridSession* session)
{
AZ_Assert(m_session==session,"Session missmatch!");
m_session = session;
}
//=========================================================================
// OnSessionDelete
// [5/24/2011]
//=========================================================================
void
GridHubComponent::OnSessionDelete([[maybe_unused]] GridMate::GridSession* session)
{
AZ_Assert(m_session==session,"Session missmatch!");
m_session = nullptr;
}
//=========================================================================
// StartSession
// [7/6/2012]
//=========================================================================
bool GridHubComponent::StartSession(bool isRestarting)
{
AZ_Assert(m_gridMate==nullptr,"Session was ALREADY started!");
m_gridMate = GridMate::GridMateCreate(GridMate::GridMateDesc());
AZ_Assert(m_gridMate,"Failed to create a gridmate instance!");
// Connect for session events
GridMate::SessionEventBus::Handler::BusConnect(m_gridMate);
if (!isRestarting)
{
AZ::SystemTickBus::Handler::BusConnect();
}
// start the multiplayer service (session mgr, extra allocator, etc.)
GridMate::StartGridMateService<GridMate::LANSessionService>(m_gridMate, GridMate::SessionServiceDesc());
AZ_Assert(GridMate::HasGridMateService<GridMate::LANSessionService>(m_gridMate), "Failed to start multiplayer service for LAN!");
// if we get an address 169.X.X.X (AZCP is NOT ready) or 127.0.0.1 when network is not ready
GridMate::string machineIP = GridMate::Utils::GetMachineAddress();
if( machineIP == "127.0.0.1" || machineIP.compare(0,4,"169.") == 0 )
{
AZ_Warning("GridHub", false, "\nCurrent IP %s might be invalid.\n",machineIP.c_str());
}
GridMate::CarrierDesc carrierDesc;
//carrierDesc.m_port = 0;
carrierDesc.m_enableDisconnectDetection = m_isDisconnectDetection;
carrierDesc.m_driverIsCrossPlatform = true;
carrierDesc.m_connectionTimeoutMS = m_disconnectionTimeout;
//carrierDesc.m_driverIsFullPackets = true;
// host session
GridMate::LANSessionParams sp;
sp.m_topology = GridMate::ST_PEER_TO_PEER;
// Until an authentication connection can be established between peers only supporting
// local connections (i.e. binding to localhost).
sp.m_address = "127.0.0.1";
carrierDesc.m_address = "127.0.0.1";
sp.m_numPublicSlots = m_numberOfSlots;
sp.m_numPrivateSlots = 1;
sp.m_port = m_sessionPort;
sp.m_flags = 0; // no host migration support
sp.m_numParams = 2;
sp.m_params[0].m_id = "GridHubVersion";
sp.m_params[0].SetValue(2);
sp.m_params[1].m_id = "HubName";
sp.m_params[1].SetValue(m_hubName);
EBUS_EVENT_ID_RESULT(m_session,m_gridMate,GridMate::LANSessionServiceBus,HostSession,sp,carrierDesc);
AZ_Assert(m_session,"Failed to host a session!");
return true;
}
//=========================================================================
// StopSession
// [7/6/2012]
//=========================================================================
void GridHubComponent::StopSession(bool isRestarting)
{
AZ_Assert(m_gridMate!=nullptr,"Session was NOT started!");
// disconnect from events
if (!isRestarting)
{
AZ::SystemTickBus::Handler::BusDisconnect();
}
GridMate::SessionEventBus::Handler::BusDisconnect();
m_monitored.clear();
m_session = nullptr;
// destroy gridmate instance
GridMate::GridMateDestroy(m_gridMate);
m_gridMate = nullptr;
}
//=========================================================================
// RestartSession
// [5/3/2013]
//=========================================================================
void GridHubComponent::RestartSession()
{
AZ_TracePrintf("GridHub","GridMate restarting...");
StopSession(true);
StartSession(true);
}
//=========================================================================
// EnableDisconnectDetection
// [9/17/2012]
//=========================================================================
void GridHubComponent::EnableDisconnectDetection(bool en)
{
m_isDisconnectDetection = en;
if (m_session)
m_session->DebugEnableDisconnectDetection(m_isDisconnectDetection);
}
//=========================================================================
// Reflect
// [7/6/2012]
//=========================================================================
void GridHubComponent::Reflect(AZ::ReflectContext* reflection)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(reflection);
if( serializeContext )
{
serializeContext->Class<GridHubComponent>()->
Version(3)->
Field("SessionPort", &GridHubComponent::m_sessionPort)->
Field("NumberOfSlots", &GridHubComponent::m_numberOfSlots)->
Field("HubName", &GridHubComponent::m_hubName)->
Field("IsDisconnectDetection", &GridHubComponent::m_isDisconnectDetection)->
Field("IsAddToStartupFolder", &GridHubComponent::m_isAddToStartupFolder)->
Field("IsLogToFile", &GridHubComponent::m_isLogToFile)->
Field("DisconnectionTimeOut", &GridHubComponent::m_disconnectionTimeout)
;
}
}
+235
View File
@@ -0,0 +1,235 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#ifndef GRIDHUB_H
#define GRIDHUB_H
#include <AzCore/PlatformDef.h>
#if !defined(Q_MOC_RUN)
AZ_PUSH_DISABLE_WARNING(4244 4251, "-Wunknown-warning-option")
#include <QWidget>
#include <QSystemTrayIcon>
#include <GridHub/ui_GridHub.h>
AZ_POP_DISABLE_WARNING
#include <AzCore/std/parallel/mutex.h>
#include <AzCore/std/string/string.h>
#include <AzCore/std/delegate/delegate.h>
#include <AzCore/Debug/TraceMessageBus.h>
#include <AzCore/IO/SystemFile.h>
#include <AzCore/Component/TickBus.h>
#if defined(AZ_PLATFORM_WINDOWS)
#include <windows.h>
#endif
#endif
namespace AZ
{
class ComponentApplication;
};
class GridHubComponent;
class GridHub
: public QWidget
, public AZ::Debug::TraceMessageBus::Handler
{
Q_OBJECT
public:
GridHub(AZ::ComponentApplication* componentApp, GridHubComponent* hubComponent, QWidget *parent = 0, Qt::WindowFlags flags = Qt::WindowFlags());
~GridHub();
public slots:
void OnStartStopSession();
void SetSessionPort(int port);
void SetSessionSlots(int numberOfSlots);
void SetHubName(const QString & name);
void EnableDisconnectDetection(int state);
void AddToStartupFolder(int state);
void LogToFile(int state);
void OnDisconnectTimeOutChange(int value);
protected:
void SanityCheckDetectionTimeout();
void timerEvent(QTimerEvent *event);
void closeEvent(QCloseEvent *event);
void SystemTick();
private:
//////////////////////////////////////////////////////////////////////////
// TraceMessagesBus
bool OnOutput(const char* window, const char* message) override;
//////////////////////////////////////////////////////////////////////////
void UpdateOutput();
void UpdateMembers();
QSystemTrayIcon* m_trayIcon;
QMenu* m_trayIconMenu;
QAction * m_restoreAction;
QAction * m_quitAction;
AZ::ComponentApplication* m_componentApp;
GridHubComponent* m_hubComponent;
AZStd::string m_output;
AZStd::mutex m_outputMutex;
Ui::GridHubClass ui;
};
//////////////////////////////////////////////////////////////////////////
// TODO MOVE TO A SEPARATE FILE
#include <AzCore/Component/Component.h>
#include <GridMate/Session/Session.h>
class GridHubComponent
: public AZ::Component
, public AZ::SystemTickBus::Handler
, public GridMate::SessionEventBus::Handler
, public AZ::Debug::TraceMessageBus::Handler
{
friend class GridHubComponentFactory;
public:
AZ_COMPONENT(GridHubComponent, "{11E4BB35-F135-4720-A890-979195A6B74E}");
GridHubComponent();
~GridHubComponent() override;
//////////////////////////////////////////////////////////////////////////
// AZ::Component
void Init() override;
void Activate() override;
void Deactivate() override;
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// AZ::SystemTickBus
void OnSystemTick() override;
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// TraceMessagesBus
bool OnOutput(const char* window, const char* message) override;
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// Session Events
/// Callback that is called when the Session service is ready to process sessions.
void OnSessionServiceReady() override {}
/// Callback that notifies the title when a game search query have completed.
void OnGridSearchComplete(GridMate::GridSearch* gridSearch) { (void)gridSearch; }
/// Callback that notifies the title when a new member joins the game session.
void OnMemberJoined(GridMate::GridSession* session, GridMate::GridMember* member) override;
/// Callback that notifies the title that a member is leaving the game session. member pointer is NOT valid after the callback returns.
void OnMemberLeaving(GridMate::GridSession* session, GridMate::GridMember* member) override;
// \todo a better way will be (after we solve migration) is to supply a reason to OnMemberLeaving... like the member was kicked.
// this will require that we actually remove the replica at the same moment.
/// Callback that host decided to kick a member. You will receive a OnMemberLeaving when the actual member leaves the session.
void OnMemberKicked(GridMate::GridSession* session, GridMate::GridMember* member, AZ::u8 reason) { (void)session;(void)member;(void)reason; }
/// After this callback it is safe to access session features. If host session is fully operational if client wait for OnSessionJoined.
void OnSessionCreated(GridMate::GridSession* session) override;
/// Called on client machines to indicate that we join successfully.
void OnSessionJoined(GridMate::GridSession* session) { (void)session; }
/// Callback that notifies the title when a session will be left. session pointer is NOT valid after the callback returns.
void OnSessionDelete(GridMate::GridSession* session) override;
/// Called when a session error occurs.
void OnSessionError(GridMate::GridSession* session, const GridMate::string& errorMsg ) { (void)session; (void)errorMsg; }
/// Called when the actual game(match) starts
void OnSessionStart(GridMate::GridSession* session) { (void)session; }
/// Called when the actual game(match) ends
void OnSessionEnd(GridMate::GridSession* session) { (void)session; }
/// Called when we start a host migration.
void OnMigrationStart(GridMate::GridSession* session) { (void)session; }
/// Called so the user can select a member that should be the new Host. Value will be ignored if NULL, current host or the member has invalid connection id.
void OnMigrationElectHost(GridMate::GridSession* session,GridMate::GridMember*& newHost) { (void)session;(void)newHost; }
/// Called when the host migration has completed.
void OnMigrationEnd(GridMate::GridSession* session,GridMate::GridMember* newHost) { (void)session;(void)newHost; }
//////////////////////////////////////////////////////////////////////////
void SetUI(GridHub* ui) { m_ui = ui; }
bool StartSession(bool isRestarting = false);
void StopSession(bool isRestarting = false);
void RestartSession();
bool IsInSession() const { return m_session != nullptr; }
GridMate::GridSession* GetSession() { return m_session; }
void SetSessionPort(unsigned short port) { m_sessionPort = port; }
int GetSessionPort() const { return m_sessionPort; }
void SetSessionSlots(unsigned char numSlots) { m_numberOfSlots = numSlots; }
int GetSessionSlots() const { return m_numberOfSlots; }
void SetHubName(const AZStd::string& hubName) { m_hubName = hubName; }
void EnableDisconnectDetection(bool en);
bool IsEnableDisconnectDetection() const { return m_isDisconnectDetection; }
void SetDisconnectionTimeOut(int timeout) { m_disconnectionTimeout = timeout; }
int GetDisconnectionTimeout() const { return m_disconnectionTimeout; }
void AddToStartupFolder(bool isAdd) { m_isAddToStartupFolder = isAdd; }
bool IsAddToStartupFolder() const { return m_isAddToStartupFolder; }
const AZStd::string& GetHubName() const { return m_hubName; }
void LogToFile(bool enable);
bool IsLogToFile() const { return m_isLogToFile; }
static void Reflect(AZ::ReflectContext* reflection);
private:
GridHub* m_ui;
GridMate::IGridMate* m_gridMate;
GridMate::GridSession* m_session;
unsigned short m_sessionPort;
unsigned char m_numberOfSlots;
AZStd::string m_hubName;
bool m_isDisconnectDetection;
int m_disconnectionTimeout;
bool m_isAddToStartupFolder;
bool m_isLogToFile;
AZ::IO::SystemFile m_logFile;
/**
* Contain information about members and titles that we monitor for exit. Only enabled if
* we have disconnection detection off.
*/
struct ExternalProcessMonitor
{
ExternalProcessMonitor()
: m_memberId(0)
#ifdef AZ_PLATFORM_WINDOWS
, m_localProcess(INVALID_HANDLE_VALUE)
#else
, m_localProcess(0)
#endif
{
}
GridMate::MemberIDCompact m_memberId; ///< Pointer to member ID in the session.
#ifdef AZ_PLATFORM_WINDOWS
HANDLE m_localProcess; ///< Local process ID used to monitor local applocations.
#else
pid_t m_localProcess;
#endif
};
AZStd::vector<ExternalProcessMonitor> m_monitored;
};
#endif // GRIDHUB_H
+18
View File
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>GridHub</string>
<key>CFBundleIdentifier</key>
<string>com.Amazon.Lumberyard.GridHub</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>NSHumanReadableCopyright</key>
<string>Portions of this file Copyright (c) Amazon.com, Inc. or its affiliates. All Rights Reserved. Original file Copyright (c) Crytek GMBH. Used under license by Amazon.com, Inc. and its affiliates.</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>
+716
View File
@@ -0,0 +1,716 @@
/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// windows include must be first so we get the full version (AZCore bring the trimmed one)
#ifdef _WIN32
#include <Windows.h>
#include <winnls.h>
#include <shobjidl.h>
#include <objbase.h>
#include <objidl.h>
#include <shlguid.h>
#include <shlobj.h>
#include <shlwapi.h>
#include <tchar.h>
#endif
#include "gridhub.hxx"
AZ_PUSH_DISABLE_WARNING(4244 4251, "-Wunknown-warning-option")
#include <QtWidgets/QApplication>
#include <QtWidgets/QMessageBox>
#include <QtCore/QFile>
#include <QtCore/QDateTime>
#include <QtCore/QDir>
#include <QtCore/QAbstractNativeEventFilter>
#include <QtCore/QSharedMemory>
#include <QtCore/QProcess>
AZ_POP_DISABLE_WARNING
#include <AzCore/EBus/EBus.h>
#include <AzCore/Memory/AllocatorManager.h>
#include <AzCore/Memory/MemoryComponent.h>
#include <AzCore/Component/ComponentApplication.h>
#include <AzCore/Component/TickBus.h>
#include <AzCore/Math/Crc.h>
#include <AzCore/IO/SystemFile.h>
#include <AzCore/std/parallel/mutex.h>
#ifdef AZ_PLATFORM_WINDOWS
#include <Shlwapi.h>
#elif defined AZ_PLATFORM_APPLE
#include <mach-o/dyld.h>
#include <errno.h>
#include <sys/param.h>
#include <libgen.h>
#else
#include <sys/param.h>
#include <errno.h>
#endif
#ifdef AZ_PLATFORM_WINDOWS
#define GRIDHUB_TSR_SUFFIX _T("_copyapp_")
#define GRIDHUB_TSR_NAME _T("GridHub_copyapp_.exe")
#define GRIDHUB_IMAGE_NAME _T("GridHub.exe")
#else
#define GRIDHUB_TSR_SUFFIX "_copyapp_"
#define GRIDHUB_TSR_NAME "GridHub_copyapp_"
#define GRIDHUB_IMAGE_NAME "GridHub"
#endif
#if AZ_TRAIT_OS_PLATFORM_APPLE
#ifdef _DEBUG
#include <assert.h>
#include <stdbool.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/sysctl.h>
static bool IsDebuggerPresent()
// Returns true if the current process is being debugged (either
// running under the debugger or has a debugger attached post facto).
{
int junk;
int mib[4];
struct kinfo_proc info;
size_t size;
// Initialize the flags so that, if sysctl fails for some bizarre
// reason, we get a predictable result.
info.kp_proc.p_flag = 0;
// Initialize mib, which tells sysctl the info we want, in this case
// we're looking for information about a specific process ID.
mib[0] = CTL_KERN;
mib[1] = KERN_PROC;
mib[2] = KERN_PROC_PID;
mib[3] = getpid();
// Call sysctl.
size = sizeof(info);
junk = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0);
assert(junk == 0);
// We're being debugged if the P_TRACED flag is set.
return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
}
#else
static bool IsDebuggerPresent()
{
return false;
}
#endif
#elif defined AZ_PLATFORM_LINUX
static bool IsDebuggerPresent()
{
//KDAB_TODO
return false;
}
#endif
/**
* Editor Application \ref ComponentApplication.
*/
class GridHubApplication : public AZ::ComponentApplication, AZ::SystemTickBus::Handler
{
public:
GridHubApplication() : m_monitorForExeChanges(false), m_needToRelaunch(false), m_timeSinceLastCheckForChanges(0.0f) {}
/// Create application, if systemEntityFileName is NULL, we will create with default settings.
AZ::Entity* Create(const Descriptor& descriptor, const StartupParameters& startupParameters = StartupParameters()) override;
void Destroy() override;
bool IsNeedToRelaunch() const { return m_needToRelaunch; }
bool IsValidModuleName() const { return m_monitorForExeChanges; }
const QString GetModuleName() const { return m_originalExeFileName; }
protected:
/**
* This is the function that will be called instantly after the memory
* manager is created. This is where we should register all core component
* factories that will participate in the loading of the bootstrap file
* or all factories in general.
* When you create your own application this is where you should FIRST call
* ComponentApplication::RegisterCoreComponents and then register the application
* specific core components.
*/
virtual void RegisterCoreComponents();
/**
AZ::SystemTickBus::Handler
*/
void OnSystemTick() override
{
// Calculate deltaTime
AZStd::chrono::system_clock::time_point now = AZStd::chrono::system_clock::now();
static AZStd::chrono::system_clock::time_point lastUpdate = now;
AZStd::chrono::duration<float> delta = now - lastUpdate;
float deltaTime = delta.count();
lastUpdate = now;
/// This is called from a 'safe' main sync point and should originate all messages that need to be synced to the 'main' thread.
// {
// if (AZ::IO::Streamer::IsReady())
// AZ::IO::StreamerAPI::v1_5::GetStreamer()->ReceiveRequests(); // activate callbacks on main thread!
// }
// check to see if we got a newer version of our executable, if so run it.
if( m_monitorForExeChanges )
{
m_timeSinceLastCheckForChanges += deltaTime;
if( m_timeSinceLastCheckForChanges > 5.0f ) // check every 5 seconds
{
m_timeSinceLastCheckForChanges -= 5.0f;
const QDateTime fileLastModified = QFileInfo(m_originalExeFileName).lastModified();
if (!fileLastModified.isNull())
{
if (fileLastModified != m_originalExeLastModified)
{
AZ_Printf("GridHub","Detected exe file change quitting...");
// we need to quit the APP and do copy and run
m_needToRelaunch = true;
qApp->quit();
}
}
}
}
}
void SetSettingsRegistrySpecializations(AZ::SettingsRegistryInterface::Specializations& specializations) override
{
ComponentApplication::SetSettingsRegistrySpecializations(specializations);
specializations.Append("tools");
specializations.Append("editor");
specializations.Append("gridhub");
}
QString m_originalExeFileName;
QDateTime m_originalExeLastModified;
bool m_monitorForExeChanges;
bool m_needToRelaunch;
float m_timeSinceLastCheckForChanges;
};
/**
* Gridhub application.
*/
class QGridHubApplication : public QApplication, public QAbstractNativeEventFilter
{
public:
QGridHubApplication(int &argc, char **argv) : QApplication(argc,argv)
{
#ifdef AZ_PLATFORM_WINDOWS
CoInitialize(NULL);
#endif
m_systemEntity = NULL;
m_gridHubComponent = NULL;
installNativeEventFilter(this);
}
~QGridHubApplication()
{
removeNativeEventFilter(this);
}
//virtual bool QGridHubApplication::winEventFilter( MSG *msg , long *result)
virtual bool nativeEventFilter(const QByteArray &eventType, void *message, [[maybe_unused]] long *result)
{
#ifdef AZ_PLATFORM_WINDOWS
if ((eventType == "windows_generic_MSG")||(eventType == "windows_dispatcher_MSG"))
{
MSG* msg = reinterpret_cast<MSG*>(message);
switch (msg->message) {
case WM_QUERYENDSESSION:
Finalize();
break;
}
}
#endif
return false;
}
void Initialize()
{
m_systemEntity = m_componentApp.Create({});
AZ_Assert(m_systemEntity, "Unable to create the system entity!");
if( !m_systemEntity->FindComponent<AZ::MemoryComponent>() )
{
m_systemEntity->CreateComponent<AZ::MemoryComponent>();
}
if( !m_systemEntity->FindComponent<GridHubComponent>() )
m_systemEntity->CreateComponent<GridHubComponent>();
m_gridHubComponent = m_systemEntity->FindComponent<GridHubComponent>();
if (m_componentApp.IsValidModuleName())
AddToStartupFolder(m_componentApp.GetModuleName(),m_gridHubComponent->IsAddToStartupFolder());
m_systemEntity->Init();
m_systemEntity->Activate();
if (styleSheet().isEmpty())
{
QDir::addSearchPath("UI", ":/GridHub/Resources/StyleSheetImages");
QFile file(":/GridHub/Resources/style_dark.qss");
file.open(QFile::ReadOnly);
QString styleSheet = QLatin1String(file.readAll());
setStyleSheet(styleSheet);
}
}
int Execute()
{
GridHub mainWnd(&m_componentApp,m_gridHubComponent);
m_gridHubComponent->SetUI(&mainWnd);
// show the window only when we debug
if( !m_componentApp.IsValidModuleName() )
mainWnd.show();
return exec();
}
void Finalize()
{
if( m_systemEntity )
{
m_systemEntity->Deactivate();
if (m_componentApp.IsValidModuleName())
AddToStartupFolder(m_componentApp.GetModuleName(),m_gridHubComponent->IsAddToStartupFolder());
m_componentApp.Destroy();
m_systemEntity = NULL;
m_gridHubComponent = NULL;
}
}
bool IsNeedToRelaunch()
{
if (m_systemEntity)
{
return m_componentApp.IsNeedToRelaunch();
}
return false;
}
static void AddToStartupFolder(const QString& moduleFilename, bool isAdd)
{
#ifdef AZ_PLATFORM_WINDOWS
HRESULT hres;
TCHAR startupFolder[MAX_PATH] = {0};
TCHAR fullLinkName[MAX_PATH] = {0};
LPITEMIDLIST pidlFolder = NULL;
hres = SHGetFolderLocation(0,/*CSIDL_COMMON_STARTUP all users required admin access*/CSIDL_STARTUP,NULL,0,&pidlFolder);
if (SUCCEEDED(hres))
{
if( SHGetPathFromIDList(pidlFolder,startupFolder) )
{
_tcscat_s(fullLinkName,startupFolder);
_tcscat_s(fullLinkName,"\\Amazon Grid Hub.lnk");
}
CoTaskMemFree(pidlFolder);
}
if( moduleFilename.isEmpty() || _tcslen(fullLinkName) == 0 )
return;
// for development, never autoadd to startup
if( moduleFilename.contains("gridmate\\development", Qt::CaseInsensitive))
isAdd = false;
if( isAdd )
{
// add to start up folder
// get my file full name
IShellLink* psl;
// Get a pointer to the IShellLink interface. It is assumed that CoInitialize
// has already been called.
hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl);
if (SUCCEEDED(hres))
{
IPersistFile* ppf;
// Set the path to the shortcut target and add the description.
psl->SetPath(moduleFilename.toUtf8().data());
psl->SetDescription("Amazon Grid Hub");
// Query IShellLink for the IPersistFile interface, used for saving the
// shortcut in persistent storage.
hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf);
if (SUCCEEDED(hres))
{
WCHAR wsz[MAX_PATH];
// Ensure that the string is Unicode.
MultiByteToWideChar(CP_ACP, 0, fullLinkName, -1, wsz, MAX_PATH);
// Add code here to check return value from MultiByteWideChar
// for success.
// Save the link by calling IPersistFile::Save.
hres = ppf->Save(wsz, TRUE);
ppf->Release();
}
psl->Release();
}
}
else
{
// remove from start up folder
DeleteFile(fullLinkName);
}
#endif
#if AZ_TRAIT_OS_PLATFORM_APPLE
if (isAdd)
{
const QString command = "tell application \"System Events\" to make login item at end with properties {path:\"%1\"}";
QString path = moduleFilename;
QDir dir(QFileInfo(path).absoluteDir());
dir.cdUp();
dir.cdUp();
if (dir.dirName() == GRIDHUB_IMAGE_NAME".app")
{
path = dir.path();
}
QProcess::startDetached("/usr/bin/osascript", {"-e", command.arg(path)});
}
else
{
const QString command = "tell application \"System Events\" to delete login item \"%1\"";
QProcess::startDetached("/usr/bin/osascript", {"-e", command.arg(GRIDHUB_IMAGE_NAME)});
}
#endif
}
AZ::Entity* m_systemEntity;
GridHubComponent* m_gridHubComponent;
GridHubApplication m_componentApp;
};
//=========================================================================
// Create
// [6/18/2012]
//=========================================================================
AZ::Entity*
GridHubApplication::Create(const Descriptor& descriptor, const StartupParameters& startupParameters /* = StartupParameters() */)
{
m_monitorForExeChanges = IsDebuggerPresent() ? false : true;
if (m_monitorForExeChanges)
{
bool isError = false;
#ifdef AZ_PLATFORM_WINDOWS
TCHAR originalExeFileName[MAX_PATH];
if (GetModuleFileName(NULL, originalExeFileName, AZ_ARRAY_SIZE(originalExeFileName)))
{
PathRemoveFileSpec(originalExeFileName);
PathAppend(originalExeFileName, GRIDHUB_IMAGE_NAME);
m_originalExeFileName = originalExeFileName;
m_originalExeLastModified = QFileInfo(m_originalExeFileName).lastModified();
}
#elif defined AZ_PLATFORM_LINUX
// KDAB_TODO
if (0) //Avoid compile error
{
}
#else
char path[MAXPATHLEN];
unsigned int pathSize = MAXPATHLEN;
if (_NSGetExecutablePath(path, &pathSize) == 0)
{
m_originalExeFileName = QDir(dirname(path)).absoluteFilePath(GRIDHUB_IMAGE_NAME);
m_originalExeLastModified = QFileInfo(m_originalExeFileName).lastModified();
}
#endif
else
{
isError = true;
}
if (isError)
{
#ifdef AZ_PLATFORM_WINDOWS
AZ_Printf("GridHub", "Failed to get module file name %d\n", GetLastError());
#else
AZ_Printf("GridHub", "Failed to get module file name %d\n", strerror(errno));
#endif
m_monitorForExeChanges = false;
}
}
AZ::Entity* sysEntity = ComponentApplication::Create(descriptor, startupParameters);
if (sysEntity)
{
AZ::SystemTickBus::Handler::BusConnect();
}
return sysEntity;
}
//=========================================================================
// Destroy
// [7/6/2012]
//=========================================================================
void GridHubApplication::Destroy()
{
AZ::SystemTickBus::Handler::BusDisconnect();
AZ::ComponentApplication::Destroy();
}
//=========================================================================
// RegisterCoreComponents
// [6/18/2012]
//=========================================================================
void GridHubApplication::RegisterCoreComponents()
{
ComponentApplication::RegisterCoreComponents();
// GridHub components
GridHubComponent::CreateDescriptor();
}
//=========================================================================
// CopyAndRun
// [10/24/2012]
//=========================================================================
void CopyAndRun(bool failSilently)
{
#ifdef AZ_PLATFORM_WINDOWS
TCHAR myFileName[MAX_PATH] = { _T(0) };
if (GetModuleFileName(NULL, myFileName, MAX_PATH ))
{
TCHAR sourceProcPath[MAX_PATH] = { _T(0) };
TCHAR targetProcPath[MAX_PATH] = { _T(0) };
TCHAR procDrive[MAX_PATH] = { _T(0) };
TCHAR procDir[MAX_PATH] = { _T(0) };
TCHAR procFname[MAX_PATH] = { _T(0) };
TCHAR procExt[MAX_PATH] = { _T(0) };
_tsplitpath_s(myFileName, procDrive, procDir, procFname, procExt);
_tmakepath_s(sourceProcPath, procDrive, procDir, GRIDHUB_IMAGE_NAME, NULL);
_tmakepath_s(targetProcPath, procDrive, procDir, GRIDHUB_TSR_NAME, NULL);
if (CopyFileEx(sourceProcPath, targetProcPath, NULL, NULL, NULL, 0))
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOWNORMAL;
CreateProcess(
NULL, // No module name (use command line).
targetProcPath, // Command line.
NULL, // Process handle not inheritable.
NULL, // Thread handle not inheritable.
FALSE, // Set handle inheritance to FALSE.
CREATE_NEW_PROCESS_GROUP, // Don't use the same process group as the current process!
NULL, // Use parent's environment block.
NULL, // Startup in the same directory as the executable
&si, // Pointer to STARTUPINFO structure.
&pi); // Pointer to PROCESS_INFORMATION structure.
}
else
{
if (!failSilently)
{
TCHAR errorMsg[1024] = { _T(0) };
_stprintf_s(errorMsg, _T("Failed to copy GridHub. Make sure that %s%s is writable!"), procFname, procExt);
MessageBox(NULL, errorMsg, NULL, MB_ICONSTOP|MB_OK);
}
}
}
#elif defined AZ_PLATFORM_LINUX
// KDAB_TODO
#else
char path[MAXPATHLEN];
unsigned int pathSize = MAXPATHLEN;
if (_NSGetExecutablePath(path, &pathSize) == 0)
{
QString sourceProcPath = path;
QString targetProcPath = QFileInfo(path).dir().absoluteFilePath(GRIDHUB_TSR_NAME);
QFile::remove(targetProcPath);
if (QFile::copy(sourceProcPath, targetProcPath))
{
QProcess::startDetached(targetProcPath, QStringList());
}
else
{
if (!failSilently)
{
QMessageBox::critical(nullptr, QString(), QGridHubApplication::tr("Failed to copy GridHub. Make sure that %1 is writable!"));
}
}
}
#endif
}
//=========================================================================
// RelaunchImage
// [10/19/2016]
//=========================================================================
void RelaunchImage()
{
#ifdef AZ_PLATFORM_WINDOWS
TCHAR myFileName[MAX_PATH] = { _T(0) };
if (GetModuleFileName(NULL, myFileName, MAX_PATH))
{
TCHAR targetProcPath[MAX_PATH] = { _T(0) };
TCHAR procDrive[MAX_PATH] = { _T(0) };
TCHAR procDir[MAX_PATH] = { _T(0) };
TCHAR procFname[MAX_PATH] = { _T(0) };
TCHAR procExt[MAX_PATH] = { _T(0) };
_tsplitpath_s(myFileName, procDrive, procDir, procFname, procExt);
_tmakepath_s(targetProcPath, procDrive, procDir, GRIDHUB_IMAGE_NAME, NULL);
STARTUPINFO si;
PROCESS_INFORMATION pi;
memset(&si, 0, sizeof(si));
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOWNORMAL;
CreateProcess(
NULL, // No module name (use command line).
targetProcPath, // Command line.
NULL, // Process handle not inheritable.
NULL, // Thread handle not inheritable.
FALSE, // Set handle inheritance to FALSE.
CREATE_NEW_PROCESS_GROUP, // Don't use the same process group as the current process!
NULL, // Use parent's environment block.
NULL, // Startup in the same directory as the executable
&si, // Pointer to STARTUPINFO structure.
&pi); // Pointer to PROCESS_INFORMATION structure.
}
#elif defined AZ_PLATFORM_LINUX
// KDAB_TODO
#else
char path[MAXPATHLEN];
unsigned int pathSize = MAXPATHLEN;
if (_NSGetExecutablePath(path, &pathSize) == 0)
{
QProcess::startDetached(path, QStringList());
}
#endif
}
//=========================================================================
// main
// [10/24/2012]
//=========================================================================
int main(int argc, char *argv[])
{
bool failSilently = false;
// We are laucnhing this from Woodpecker all the time.
// When launching from Woodpecker, we don't want to show
// any of our error messages, which might be useful at other times.
// So, it passes along this fail_silently flag which lets us suppress
// our messages without disrupting any other flow.
for (int i=0; i < argc; ++i)
{
if (strcmp(argv[i],"-fail_silently") == 0)
{
failSilently = true;
}
}
bool isCopyAndRunOnExit = false;
if( IsDebuggerPresent() == false )
{
#ifdef AZ_PLATFORM_WINDOWS
TCHAR exeFileName[MAX_PATH];
if( GetModuleFileName(NULL,exeFileName,AZ_ARRAY_SIZE(exeFileName)) )
#elif defined AZ_PLATFORM_LINUX
//KDAB_TODO
char exeFileName[MAXPATHLEN];
#else
char exeFileName[MAXPATHLEN];
unsigned int pathSize = MAXPATHLEN;
if (_NSGetExecutablePath(exeFileName, &pathSize) == 0)
#endif
{
if (!QString(exeFileName).contains(GRIDHUB_TSR_SUFFIX))
{
// this is a first time we run we need to run copy and run tool.
isCopyAndRunOnExit = true;
}
}
}
if (isCopyAndRunOnExit == false) // if we need to exit and run copy and run, just go there
{
bool isNeedToRelaunch = false;
{
#ifdef AZ_PLATFORM_WINDOWS
// Create a OS named mutex while the OS is running
HANDLE hInstanceMutex = CreateMutex(NULL,TRUE,"Global\\GridHub-Instance");
AZ_Assert(hInstanceMutex!=NULL,"Failed to create OS mutex [GridHub-Instance]\n");
if( hInstanceMutex != NULL && GetLastError() == ERROR_ALREADY_EXISTS)
{
return 0;
}
#else
{
QSharedMemory fix("Global\\GridHub-Instance");
fix.attach();
}
// Create a OS named shared memory segment while the OS is running
QSharedMemory mem("Global\\GridHub-Instance");
bool created = mem.create(32);
AZ_Assert(created,"Failed to create OS mutex [GridHub-Instance]\n");
if( !created )
{
return 0;
}
#endif
QGridHubApplication qtApp(argc, argv);
qtApp.Initialize();
qtApp.Execute();
isNeedToRelaunch = qtApp.IsNeedToRelaunch();
qtApp.Finalize();
#ifdef AZ_PLATFORM_WINDOWS
ReleaseMutex(hInstanceMutex);
#endif
}
if (isNeedToRelaunch)
{
// Launch the original image, which will take care
// of overwriting us and relaunch us in turn.
RelaunchImage();
}
}
else
{
// We may have been launched by the TSR due to image change,
// so wait a little bit to give the TSR time to shutdown.
AZStd::this_thread::sleep_for(AZStd::chrono::milliseconds(500));
CopyAndRun(failSilently);
}
return 0;
}