remove the stack-manager
|
@ -202,8 +202,6 @@ if (NOT ANDROID)
|
|||
set_target_properties(ice-server PROPERTIES FOLDER "Apps")
|
||||
add_subdirectory(interface)
|
||||
set_target_properties(interface PROPERTIES FOLDER "Apps")
|
||||
add_subdirectory(stack-manager)
|
||||
set_target_properties(stack-manager PROPERTIES FOLDER "Apps")
|
||||
add_subdirectory(console)
|
||||
add_subdirectory(tests)
|
||||
add_subdirectory(plugins)
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
set(TARGET_NAME "stack-manager")
|
||||
set(BUILD_BUNDLE YES)
|
||||
setup_hifi_project(Widgets Gui Svg Core Network WebKitWidgets)
|
||||
|
||||
if (WIN32)
|
||||
target_zlib()
|
||||
endif ()
|
||||
target_quazip()
|
||||
|
||||
set_target_properties(
|
||||
${TARGET_NAME} PROPERTIES
|
||||
EXCLUDE_FROM_ALL TRUE
|
||||
)
|
||||
|
||||
if (DEFINED ENV{JOB_ID})
|
||||
set(PR_BUILD "false")
|
||||
set(BUILD_SEQ $ENV{JOB_ID})
|
||||
set(BASE_URL "http://s3.amazonaws.com/hifi-public")
|
||||
else ()
|
||||
set(BUILD_SEQ "dev")
|
||||
if (DEFINED ENV{PR_NUMBER})
|
||||
set(PR_BUILD "true")
|
||||
set(BASE_URL "http://s3.amazonaws.com/hifi-public/pr-builds/$ENV{PR_NUMBER}")
|
||||
else ()
|
||||
set(PR_BUILD "false")
|
||||
set(BASE_URL "http://s3.amazonaws.com/hifi-public")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
configure_file(src/StackManagerVersion.h.in "${PROJECT_BINARY_DIR}/includes/StackManagerVersion.h")
|
||||
include_directories(
|
||||
${PROJECT_BINARY_DIR}/includes
|
||||
${PROJECT_SOURCE_DIR}/src
|
||||
${PROJECT_SOURCE_DIR}/src/ui
|
||||
${QUAZIP_INCLUDE_DIRS}
|
||||
${ZLIB_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
if (APPLE)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.8)
|
||||
set(MACOSX_BUNDLE_BUNDLE_NAME "Stack Manager")
|
||||
set(MACOSX_BUNDLE_GUI_IDENTIFIER io.highfidelity.StackManager)
|
||||
set(MACOSX_BUNDLE_ICON_FILE icon.icns)
|
||||
set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/assets/icon.icns PROPERTIES MACOSX_PACKAGE_LOCATION Resources)
|
||||
set(SM_SRCS ${SM_SRCS} "${CMAKE_CURRENT_SOURCE_DIR}/assets/icon.icns")
|
||||
endif ()
|
||||
|
||||
package_libraries_for_deployment()
|
|
@ -1,22 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 18.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 59 32" enable-background="new 0 0 59 32" xml:space="preserve">
|
||||
<g>
|
||||
<path fill="#29957E" d="M54,32H5c-2.8,0-5-2.2-5-5V5c0-2.8,2.2-5,5-5h49c2.8,0,5,2.2,5,5v22C59,29.8,56.8,32,54,32z"/>
|
||||
<g>
|
||||
<path fill="#EDEDED" d="M22.1,10.1c0.5,0.2,0.8,0.5,1.1,0.9c0.3,0.3,0.5,0.7,0.6,1c0.2,0.4,0.2,0.8,0.2,1.3c0,0.6-0.1,1.2-0.4,1.7
|
||||
c-0.3,0.6-0.8,1-1.5,1.2c0.6,0.2,1,0.5,1.2,1s0.4,1.1,0.4,1.9v0.8c0,0.6,0,0.9,0.1,1.1c0.1,0.3,0.2,0.5,0.5,0.7V22h-2.8
|
||||
c-0.1-0.3-0.1-0.5-0.2-0.7c-0.1-0.3-0.1-0.7-0.1-1.1l0-1.1c0-0.8-0.1-1.3-0.4-1.6c-0.3-0.3-0.7-0.4-1.5-0.4h-2.5V22h-2.5V9.8h5.9
|
||||
C21,9.8,21.7,9.9,22.1,10.1z M16.8,11.9v3.3h2.8c0.5,0,1-0.1,1.2-0.2c0.5-0.2,0.7-0.7,0.7-1.4c0-0.7-0.2-1.2-0.7-1.5
|
||||
c-0.3-0.1-0.7-0.2-1.2-0.2H16.8z"/>
|
||||
<path fill="#EDEDED" d="M28.7,13v5.5c0,0.5,0.1,0.9,0.2,1.2c0.2,0.5,0.6,0.7,1.3,0.7c0.8,0,1.4-0.3,1.7-1c0.2-0.4,0.2-0.8,0.2-1.4
|
||||
V13h2.4v9h-2.3v-1.3c0,0-0.1,0.1-0.2,0.2c-0.1,0.1-0.2,0.3-0.3,0.4c-0.4,0.3-0.7,0.6-1.1,0.7s-0.7,0.2-1.2,0.2
|
||||
c-1.3,0-2.2-0.5-2.7-1.4c-0.3-0.5-0.4-1.3-0.4-2.3V13H28.7z"/>
|
||||
<path fill="#EDEDED" d="M44,13.5c0.6,0.5,0.9,1.3,0.9,2.4V22h-2.4v-5.5c0-0.5-0.1-0.8-0.2-1.1c-0.2-0.5-0.7-0.7-1.3-0.7
|
||||
c-0.8,0-1.3,0.3-1.6,1c-0.2,0.4-0.2,0.8-0.2,1.4V22h-2.4v-9H39v1.3c0.3-0.5,0.6-0.8,0.9-1c0.5-0.4,1.1-0.5,1.8-0.5
|
||||
C42.7,12.7,43.4,13,44,13.5z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 1.7 KiB |
|
@ -1,27 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 18.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 59 32" enable-background="new 0 0 59 32" xml:space="preserve">
|
||||
<g>
|
||||
<path fill="#BB3850" d="M54,32H5c-2.8,0-5-2.2-5-5V5c0-2.8,2.2-5,5-5h49c2.8,0,5,2.2,5,5v22C59,29.8,56.8,32,54,32z"/>
|
||||
<g>
|
||||
<path fill="#EDEDED" d="M13.8,18.2c0.1,0.6,0.2,1,0.5,1.3c0.4,0.5,1.1,0.8,2.2,0.8c0.6,0,1.1-0.1,1.5-0.2c0.7-0.3,1.1-0.7,1.1-1.4
|
||||
c0-0.4-0.2-0.7-0.5-0.9c-0.4-0.2-0.9-0.4-1.7-0.6l-1.3-0.3c-1.3-0.3-2.2-0.6-2.7-0.9c-0.8-0.6-1.2-1.4-1.2-2.6
|
||||
c0-1.1,0.4-2,1.2-2.7s2-1.1,3.6-1.1c1.3,0,2.4,0.3,3.3,1c0.9,0.7,1.4,1.7,1.4,3h-2.5c0-0.7-0.4-1.3-1-1.6
|
||||
c-0.4-0.2-0.9-0.3-1.5-0.3c-0.7,0-1.2,0.1-1.6,0.4s-0.6,0.6-0.6,1.1c0,0.4,0.2,0.8,0.6,1c0.3,0.1,0.8,0.3,1.6,0.5l2.1,0.5
|
||||
c0.9,0.2,1.6,0.5,2.1,0.9c0.7,0.6,1.1,1.4,1.1,2.5c0,1.1-0.4,2-1.3,2.8c-0.9,0.7-2.1,1.1-3.7,1.1c-1.6,0-2.9-0.4-3.8-1.1
|
||||
s-1.4-1.7-1.4-3H13.8z"/>
|
||||
<path fill="#EDEDED" d="M22.1,14.7V13h1.3v-2.5h2.3V13h1.5v1.7h-1.5v4.8c0,0.4,0,0.6,0.1,0.7c0.1,0.1,0.4,0.1,0.9,0.1
|
||||
c0.1,0,0.1,0,0.2,0c0.1,0,0.2,0,0.2,0v1.8l-1.1,0c-1.1,0-1.9-0.2-2.3-0.6c-0.3-0.3-0.4-0.7-0.4-1.3v-5.6H22.1z"/>
|
||||
<path fill="#EDEDED" d="M36.3,20.9c-0.8,0.9-1.9,1.4-3.5,1.4s-2.7-0.5-3.5-1.4c-0.8-0.9-1.1-2.1-1.1-3.4c0-1.3,0.4-2.4,1.1-3.4
|
||||
c0.8-1,1.9-1.4,3.5-1.4s2.7,0.5,3.5,1.4c0.8,1,1.1,2.1,1.1,3.4C37.4,18.8,37,19.9,36.3,20.9z M34.4,19.6c0.4-0.5,0.6-1.2,0.6-2.1
|
||||
s-0.2-1.6-0.6-2.1s-0.9-0.7-1.6-0.7s-1.2,0.2-1.6,0.7c-0.4,0.5-0.6,1.2-0.6,2.1s0.2,1.6,0.6,2.1c0.4,0.5,0.9,0.7,1.6,0.7
|
||||
S34,20.1,34.4,19.6z"/>
|
||||
<path fill="#EDEDED" d="M46.7,13.9c0.7,0.8,1.1,1.9,1.1,3.4c0,1.6-0.4,2.8-1.1,3.6s-1.6,1.3-2.8,1.3c-0.7,0-1.3-0.2-1.8-0.5
|
||||
c-0.3-0.2-0.5-0.5-0.8-0.9v4.7H39V13h2.3v1.3c0.3-0.4,0.5-0.7,0.8-0.9c0.5-0.4,1.2-0.6,1.9-0.6C45.1,12.8,46,13.1,46.7,13.9z
|
||||
M44.9,15.6c-0.3-0.5-0.8-0.8-1.6-0.8c-0.9,0-1.5,0.4-1.8,1.2c-0.2,0.4-0.3,1-0.3,1.6c0,1.1,0.3,1.8,0.8,2.2
|
||||
c0.3,0.2,0.7,0.4,1.2,0.4c0.7,0,1.2-0.3,1.5-0.8s0.5-1.2,0.5-2C45.4,16.8,45.2,16.2,44.9,15.6z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 361 KiB |
Before Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 2.5 KiB |
|
@ -1,57 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 18.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 189 46" enable-background="new 0 0 189 46" xml:space="preserve">
|
||||
<g>
|
||||
<path fill="#29957E" d="M184,46H5c-2.8,0-5-2.2-5-5V5c0-2.8,2.2-5,5-5h179c2.8,0,5,2.2,5,5v36C189,43.8,186.8,46,184,46z"/>
|
||||
<g>
|
||||
<path fill="#EDEDED" d="M25.3,33.7c-5.7,0-10.3-4.6-10.3-10.3c0-3.3,1.5-6.3,4.1-8.2c0.8-0.6,1.8-0.4,2.4,0.3
|
||||
c0.6,0.8,0.4,1.8-0.3,2.4c-1.7,1.3-2.7,3.3-2.7,5.5c0,3.8,3.1,6.9,6.9,6.9s6.9-3.1,6.9-6.9c0-2.2-1-4.2-2.7-5.5
|
||||
c-0.8-0.6-0.9-1.6-0.3-2.4c0.6-0.8,1.6-0.9,2.4-0.3c2.6,2,4.1,5,4.1,8.2C35.6,29.1,31,33.7,25.3,33.7z M27,21.7
|
||||
c0,0.9-0.8,1.7-1.7,1.7s-1.7-0.8-1.7-1.7v-8.6c0-0.9,0.8-1.7,1.7-1.7s1.7,0.8,1.7,1.7V21.7z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#EDEDED" d="M46.4,26.7c0.1,0.8,0.3,1.4,0.7,1.8c0.6,0.7,1.6,1.1,3.1,1.1c0.9,0,1.6-0.1,2.1-0.3c1-0.4,1.5-1,1.5-2
|
||||
c0-0.6-0.3-1-0.8-1.3c-0.5-0.3-1.3-0.6-2.4-0.8l-1.9-0.4c-1.8-0.4-3.1-0.8-3.8-1.3c-1.2-0.8-1.7-2-1.7-3.7c0-1.5,0.6-2.8,1.7-3.9
|
||||
c1.1-1,2.8-1.5,5-1.5c1.8,0,3.4,0.5,4.7,1.4c1.3,1,2,2.4,2,4.2h-3.5c-0.1-1-0.5-1.8-1.4-2.2c-0.6-0.3-1.3-0.4-2.2-0.4
|
||||
c-1,0-1.7,0.2-2.3,0.6s-0.9,0.9-0.9,1.6c0,0.6,0.3,1.1,0.8,1.4c0.4,0.2,1.1,0.4,2.3,0.7l3,0.7c1.3,0.3,2.3,0.7,3,1.3
|
||||
c1,0.8,1.5,2,1.5,3.5c0,1.6-0.6,2.9-1.8,3.9c-1.2,1-2.9,1.6-5.2,1.6c-2.3,0-4.1-0.5-5.4-1.5c-1.3-1-2-2.4-2-4.2H46.4z"/>
|
||||
<path fill="#EDEDED" d="M58.3,21.7v-2.4H60v-3.6h3.3v3.6h2.1v2.4h-2.1v6.8c0,0.5,0.1,0.8,0.2,1s0.5,0.2,1.2,0.2c0.1,0,0.2,0,0.3,0
|
||||
s0.2,0,0.3,0v2.5l-1.6,0.1c-1.6,0.1-2.7-0.2-3.2-0.8c-0.4-0.4-0.6-1-0.6-1.8v-7.9H58.3z"/>
|
||||
<path fill="#EDEDED" d="M72.6,24.2c0.6-0.1,1.1-0.2,1.3-0.3c0.5-0.2,0.7-0.5,0.7-0.9c0-0.5-0.2-0.9-0.6-1.1
|
||||
c-0.4-0.2-0.9-0.3-1.6-0.3c-0.8,0-1.4,0.2-1.7,0.6c-0.2,0.3-0.4,0.7-0.5,1.2h-3.2c0.1-1.1,0.4-2,0.9-2.8c0.9-1.1,2.4-1.7,4.6-1.7
|
||||
c1.4,0,2.7,0.3,3.7,0.8c1.1,0.6,1.6,1.6,1.6,3.1v5.9c0,0.4,0,0.9,0,1.5c0,0.4,0.1,0.7,0.2,0.9s0.3,0.3,0.5,0.4V32h-3.6
|
||||
c-0.1-0.3-0.2-0.5-0.2-0.7s-0.1-0.5-0.1-0.8c-0.5,0.5-1,0.9-1.6,1.3c-0.7,0.4-1.5,0.6-2.5,0.6c-1.2,0-2.1-0.3-2.9-1
|
||||
c-0.8-0.7-1.1-1.6-1.1-2.8c0-1.6,0.6-2.7,1.8-3.4c0.7-0.4,1.7-0.7,3-0.8L72.6,24.2z M74.7,25.8c-0.2,0.1-0.4,0.2-0.6,0.3
|
||||
c-0.2,0.1-0.5,0.2-0.9,0.2l-0.8,0.1c-0.7,0.1-1.2,0.3-1.5,0.5c-0.5,0.3-0.8,0.8-0.8,1.4c0,0.6,0.2,1,0.5,1.2s0.7,0.4,1.2,0.4
|
||||
c0.7,0,1.4-0.2,2-0.6s0.9-1.2,1-2.3V25.8z"/>
|
||||
<path fill="#EDEDED" d="M88,18.9c0,0,0.1,0,0.3,0v3.4c-0.2,0-0.4,0-0.6,0s-0.3,0-0.4,0c-1.3,0-2.2,0.4-2.7,1.3
|
||||
c-0.3,0.5-0.4,1.2-0.4,2.3V32h-3.4V19.2h3.2v2.2c0.5-0.9,1-1.4,1.3-1.7c0.6-0.5,1.4-0.8,2.4-0.8C87.9,18.9,88,18.9,88,18.9z"/>
|
||||
<path fill="#EDEDED" d="M88.9,21.7v-2.4h1.8v-3.6H94v3.6h2.1v2.4H94v6.8c0,0.5,0.1,0.8,0.2,1s0.5,0.2,1.2,0.2c0.1,0,0.2,0,0.3,0
|
||||
s0.2,0,0.3,0v2.5l-1.6,0.1c-1.6,0.1-2.7-0.2-3.2-0.8c-0.4-0.4-0.6-1-0.6-1.8v-7.9H88.9z"/>
|
||||
<path fill="#EDEDED" d="M107.5,27.9c0.1,0.6,0.2,1,0.5,1.3c0.4,0.4,1.2,0.7,2.3,0.7c0.7,0,1.2-0.1,1.6-0.3
|
||||
c0.4-0.2,0.6-0.5,0.6-0.9c0-0.4-0.2-0.7-0.5-0.9s-1.5-0.5-3.5-1c-1.5-0.4-2.5-0.8-3.1-1.3c-0.6-0.5-0.9-1.3-0.9-2.3
|
||||
c0-1.2,0.5-2.2,1.4-3s2.2-1.3,3.9-1.3c1.6,0,2.9,0.3,3.9,1s1.6,1.7,1.7,3.3h-3.3c0-0.4-0.2-0.8-0.4-1c-0.4-0.5-1-0.7-1.9-0.7
|
||||
c-0.7,0-1.2,0.1-1.6,0.3c-0.3,0.2-0.5,0.5-0.5,0.8c0,0.4,0.2,0.7,0.5,0.8c0.3,0.2,1.5,0.5,3.5,0.9c1.3,0.3,2.3,0.8,3,1.4
|
||||
c0.7,0.6,1,1.4,1,2.4c0,1.3-0.5,2.3-1.4,3.1s-2.4,1.2-4.4,1.2c-2,0-3.5-0.4-4.5-1.3s-1.4-1.9-1.4-3.2H107.5z"/>
|
||||
<path fill="#EDEDED" d="M126.6,19.5c0.9,0.4,1.6,1,2.2,1.9c0.5,0.8,0.9,1.6,1,2.6c0.1,0.6,0.1,1.4,0.1,2.5h-9.3
|
||||
c0.1,1.3,0.5,2.2,1.3,2.7c0.5,0.3,1.1,0.5,1.8,0.5c0.8,0,1.4-0.2,1.9-0.6c0.3-0.2,0.5-0.5,0.7-0.9h3.4c-0.1,0.8-0.5,1.5-1.2,2.3
|
||||
c-1.1,1.2-2.7,1.9-4.8,1.9c-1.7,0-3.2-0.5-4.5-1.6c-1.3-1-1.9-2.8-1.9-5.1c0-2.2,0.6-3.9,1.8-5.1c1.2-1.2,2.7-1.8,4.6-1.8
|
||||
C124.7,18.9,125.7,19.1,126.6,19.5z M121.6,22.4c-0.5,0.5-0.8,1.1-0.9,2h5.8c-0.1-0.9-0.4-1.6-0.9-2c-0.5-0.5-1.2-0.7-2-0.7
|
||||
C122.7,21.6,122.1,21.9,121.6,22.4z"/>
|
||||
<path fill="#EDEDED" d="M138.7,18.9c0,0,0.1,0,0.3,0v3.4c-0.2,0-0.4,0-0.6,0s-0.3,0-0.4,0c-1.3,0-2.2,0.4-2.7,1.3
|
||||
c-0.3,0.5-0.4,1.2-0.4,2.3V32h-3.4V19.2h3.2v2.2c0.5-0.9,1-1.4,1.3-1.7c0.6-0.5,1.4-0.8,2.4-0.8C138.6,18.9,138.7,18.9,138.7,18.9
|
||||
z"/>
|
||||
<path fill="#EDEDED" d="M148.8,19.2h3.6L147.8,32h-3.5l-4.6-12.8h3.8l2.7,9.4L148.8,19.2z"/>
|
||||
<path fill="#EDEDED" d="M162.6,19.5c0.9,0.4,1.6,1,2.2,1.9c0.5,0.8,0.9,1.6,1,2.6c0.1,0.6,0.1,1.4,0.1,2.5h-9.3
|
||||
c0.1,1.3,0.5,2.2,1.3,2.7c0.5,0.3,1.1,0.5,1.8,0.5c0.8,0,1.4-0.2,1.9-0.6c0.3-0.2,0.5-0.5,0.7-0.9h3.4c-0.1,0.8-0.5,1.5-1.2,2.3
|
||||
c-1.1,1.2-2.7,1.9-4.8,1.9c-1.7,0-3.2-0.5-4.5-1.6c-1.3-1-1.9-2.8-1.9-5.1c0-2.2,0.6-3.9,1.8-5.1c1.2-1.2,2.7-1.8,4.6-1.8
|
||||
C160.7,18.9,161.7,19.1,162.6,19.5z M157.6,22.4c-0.5,0.5-0.8,1.1-0.9,2h5.8c-0.1-0.9-0.4-1.6-0.9-2c-0.5-0.5-1.2-0.7-2-0.7
|
||||
C158.8,21.6,158.1,21.9,157.6,22.4z"/>
|
||||
<path fill="#EDEDED" d="M174.7,18.9c0,0,0.1,0,0.3,0v3.4c-0.2,0-0.4,0-0.6,0s-0.3,0-0.4,0c-1.3,0-2.2,0.4-2.7,1.3
|
||||
c-0.3,0.5-0.4,1.2-0.4,2.3V32h-3.4V19.2h3.2v2.2c0.5-0.9,1-1.4,1.3-1.7c0.6-0.5,1.4-0.8,2.4-0.8C174.6,18.9,174.7,18.9,174.7,18.9
|
||||
z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 5.2 KiB |
|
@ -1,53 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 18.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 189 46" enable-background="new 0 0 189 46" xml:space="preserve">
|
||||
<g>
|
||||
<path fill="#BB3850" d="M184,46H5c-2.8,0-5-2.2-5-5V5c0-2.8,2.2-5,5-5h179c2.8,0,5,2.2,5,5v36C189,43.8,186.8,46,184,46z"/>
|
||||
<g>
|
||||
<path fill="#EDEDED" d="M25.3,33.7c-5.7,0-10.3-4.6-10.3-10.3c0-3.3,1.5-6.3,4.1-8.2c0.8-0.6,1.8-0.4,2.4,0.3
|
||||
c0.6,0.8,0.4,1.8-0.3,2.4c-1.7,1.3-2.7,3.3-2.7,5.5c0,3.8,3.1,6.9,6.9,6.9s6.9-3.1,6.9-6.9c0-2.2-1-4.2-2.7-5.5
|
||||
c-0.8-0.6-0.9-1.6-0.3-2.4c0.6-0.8,1.6-0.9,2.4-0.3c2.6,2,4.1,5,4.1,8.2C35.6,29.1,31,33.7,25.3,33.7z M27,21.7
|
||||
c0,0.9-0.8,1.7-1.7,1.7s-1.7-0.8-1.7-1.7v-8.6c0-0.9,0.8-1.7,1.7-1.7s1.7,0.8,1.7,1.7V21.7z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path fill="#EDEDED" d="M46.4,26.7c0.1,0.8,0.3,1.4,0.7,1.8c0.6,0.7,1.6,1.1,3.1,1.1c0.9,0,1.6-0.1,2.1-0.3c1-0.4,1.5-1,1.5-2
|
||||
c0-0.6-0.3-1-0.8-1.3c-0.5-0.3-1.3-0.6-2.4-0.8l-1.9-0.4c-1.8-0.4-3.1-0.8-3.8-1.3c-1.2-0.8-1.7-2-1.7-3.7c0-1.5,0.6-2.8,1.7-3.9
|
||||
c1.1-1,2.8-1.5,5-1.5c1.8,0,3.4,0.5,4.7,1.4c1.3,1,2,2.4,2,4.2h-3.5c-0.1-1-0.5-1.8-1.4-2.2c-0.6-0.3-1.3-0.4-2.2-0.4
|
||||
c-1,0-1.7,0.2-2.3,0.6s-0.9,0.9-0.9,1.6c0,0.6,0.3,1.1,0.8,1.4c0.4,0.2,1.1,0.4,2.3,0.7l3,0.7c1.3,0.3,2.3,0.7,3,1.3
|
||||
c1,0.8,1.5,2,1.5,3.5c0,1.6-0.6,2.9-1.8,3.9c-1.2,1-2.9,1.6-5.2,1.6c-2.3,0-4.1-0.5-5.4-1.5c-1.3-1-2-2.4-2-4.2H46.4z"/>
|
||||
<path fill="#EDEDED" d="M58.3,21.7v-2.4H60v-3.6h3.3v3.6h2.1v2.4h-2.1v6.8c0,0.5,0.1,0.8,0.2,1s0.5,0.2,1.2,0.2c0.1,0,0.2,0,0.3,0
|
||||
s0.2,0,0.3,0v2.5l-1.6,0.1c-1.6,0.1-2.7-0.2-3.2-0.8c-0.4-0.4-0.6-1-0.6-1.8v-7.9H58.3z"/>
|
||||
<path fill="#EDEDED" d="M78.2,30.4c-1.1,1.3-2.7,2-4.9,2s-3.8-0.7-4.9-2s-1.6-2.9-1.6-4.8c0-1.8,0.5-3.4,1.6-4.8
|
||||
c1.1-1.3,2.7-2,4.9-2s3.8,0.7,4.9,2c1.1,1.4,1.6,2.9,1.6,4.8C79.8,27.5,79.3,29.1,78.2,30.4z M75.5,28.6c0.5-0.7,0.8-1.7,0.8-3
|
||||
s-0.3-2.3-0.8-3c-0.5-0.7-1.3-1-2.2-1s-1.7,0.3-2.3,1c-0.5,0.7-0.8,1.7-0.8,3s0.3,2.3,0.8,3s1.3,1,2.3,1S75,29.3,75.5,28.6z"/>
|
||||
<path fill="#EDEDED" d="M93,20.6c1,1.1,1.6,2.7,1.6,4.9c0,2.2-0.5,4-1.5,5.1c-1,1.2-2.3,1.8-3.9,1.8c-1,0-1.9-0.3-2.5-0.8
|
||||
c-0.4-0.3-0.7-0.7-1.1-1.2V37h-3.3V19.2h3.2v1.9c0.4-0.6,0.7-1,1.2-1.3c0.7-0.6,1.6-0.9,2.7-0.9C90.6,18.9,91.9,19.5,93,20.6z
|
||||
M90.4,23c-0.5-0.8-1.2-1.1-2.2-1.1c-1.2,0-2.1,0.6-2.5,1.7c-0.2,0.6-0.4,1.4-0.4,2.3c0,1.5,0.4,2.5,1.2,3.1
|
||||
c0.5,0.4,1,0.5,1.7,0.5c0.9,0,1.7-0.4,2.1-1.1s0.7-1.7,0.7-2.9C91.1,24.6,90.9,23.8,90.4,23z"/>
|
||||
<path fill="#EDEDED" d="M106.1,27.9c0.1,0.6,0.2,1,0.5,1.3c0.4,0.4,1.2,0.7,2.3,0.7c0.7,0,1.2-0.1,1.6-0.3
|
||||
c0.4-0.2,0.6-0.5,0.6-0.9c0-0.4-0.2-0.7-0.5-0.9s-1.5-0.5-3.5-1c-1.5-0.4-2.5-0.8-3.1-1.3c-0.6-0.5-0.9-1.3-0.9-2.3
|
||||
c0-1.2,0.5-2.2,1.4-3s2.2-1.3,3.9-1.3c1.6,0,2.9,0.3,3.9,1s1.6,1.7,1.7,3.3h-3.3c0-0.4-0.2-0.8-0.4-1c-0.4-0.5-1-0.7-1.9-0.7
|
||||
c-0.7,0-1.2,0.1-1.6,0.3c-0.3,0.2-0.5,0.5-0.5,0.8c0,0.4,0.2,0.7,0.5,0.8c0.3,0.2,1.5,0.5,3.5,0.9c1.3,0.3,2.3,0.8,3,1.4
|
||||
c0.7,0.6,1,1.4,1,2.4c0,1.3-0.5,2.3-1.4,3.1s-2.4,1.2-4.4,1.2c-2,0-3.5-0.4-4.5-1.3s-1.4-1.9-1.4-3.2H106.1z"/>
|
||||
<path fill="#EDEDED" d="M125.2,19.5c0.9,0.4,1.6,1,2.2,1.9c0.5,0.8,0.9,1.6,1,2.6c0.1,0.6,0.1,1.4,0.1,2.5h-9.3
|
||||
c0.1,1.3,0.5,2.2,1.3,2.7c0.5,0.3,1.1,0.5,1.8,0.5c0.8,0,1.4-0.2,1.9-0.6c0.3-0.2,0.5-0.5,0.7-0.9h3.4c-0.1,0.8-0.5,1.5-1.2,2.3
|
||||
c-1.1,1.2-2.7,1.9-4.8,1.9c-1.7,0-3.2-0.5-4.5-1.6c-1.3-1-1.9-2.8-1.9-5.1c0-2.2,0.6-3.9,1.8-5.1c1.2-1.2,2.7-1.8,4.6-1.8
|
||||
C123.3,18.9,124.3,19.1,125.2,19.5z M120.2,22.4c-0.5,0.5-0.8,1.1-0.9,2h5.8c-0.1-0.9-0.4-1.6-0.9-2c-0.5-0.5-1.2-0.7-2-0.7
|
||||
C121.4,21.6,120.7,21.9,120.2,22.4z"/>
|
||||
<path fill="#EDEDED" d="M137.3,18.9c0,0,0.1,0,0.3,0v3.4c-0.2,0-0.4,0-0.6,0s-0.3,0-0.4,0c-1.3,0-2.2,0.4-2.7,1.3
|
||||
c-0.3,0.5-0.4,1.2-0.4,2.3V32h-3.4V19.2h3.2v2.2c0.5-0.9,1-1.4,1.3-1.7c0.6-0.5,1.4-0.8,2.4-0.8C137.2,18.9,137.3,18.9,137.3,18.9
|
||||
z"/>
|
||||
<path fill="#EDEDED" d="M147.5,19.2h3.6L146.4,32h-3.5l-4.6-12.8h3.8l2.7,9.4L147.5,19.2z"/>
|
||||
<path fill="#EDEDED" d="M161.3,19.5c0.9,0.4,1.6,1,2.2,1.9c0.5,0.8,0.9,1.6,1,2.6c0.1,0.6,0.1,1.4,0.1,2.5h-9.3
|
||||
c0.1,1.3,0.5,2.2,1.3,2.7c0.5,0.3,1.1,0.5,1.8,0.5c0.8,0,1.4-0.2,1.9-0.6c0.3-0.2,0.5-0.5,0.7-0.9h3.4c-0.1,0.8-0.5,1.5-1.2,2.3
|
||||
c-1.1,1.2-2.7,1.9-4.8,1.9c-1.7,0-3.2-0.5-4.5-1.6c-1.3-1-1.9-2.8-1.9-5.1c0-2.2,0.6-3.9,1.8-5.1c1.2-1.2,2.7-1.8,4.6-1.8
|
||||
C159.4,18.9,160.4,19.1,161.3,19.5z M156.3,22.4c-0.5,0.5-0.8,1.1-0.9,2h5.8c-0.1-0.9-0.4-1.6-0.9-2c-0.5-0.5-1.2-0.7-2-0.7
|
||||
C157.4,21.6,156.7,21.9,156.3,22.4z"/>
|
||||
<path fill="#EDEDED" d="M173.4,18.9c0,0,0.1,0,0.3,0v3.4c-0.2,0-0.4,0-0.6,0s-0.3,0-0.4,0c-1.3,0-2.2,0.4-2.7,1.3
|
||||
c-0.3,0.5-0.4,1.2-0.4,2.3V32h-3.4V19.2h3.2v2.2c0.5-0.9,1-1.4,1.3-1.7c0.6-0.5,1.4-0.8,2.4-0.8C173.3,18.9,173.3,18.9,173.4,18.9
|
||||
z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 4.8 KiB |
|
@ -1,64 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>High Fidelity Stack Manager Content Sets</title>
|
||||
|
||||
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
|
||||
|
||||
<!-- Latest compiled and minified CSS -->
|
||||
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
|
||||
|
||||
<!-- Latest compiled and minified JavaScript -->
|
||||
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/js/bootstrap.min.js"></script>
|
||||
|
||||
<!-- underscore.js for easy templates -->
|
||||
<script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.7.0/underscore-min.js"></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-xs-12" style="margin-top: 15px;">
|
||||
<h5>Click on the name of one of the content sets below to replace your local content with that set.</h5>
|
||||
<h5>Note that the content set you choose may change the index path ('/') in your domain-server settings.</h5>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" id="content-set-panels">
|
||||
<script type="text/template" class="template">
|
||||
<% var index = 1 %>
|
||||
<% _.each(sets, function(set, key, list){ %>
|
||||
<div class="col-xs-4" >
|
||||
<% var models_url = "http://hifi-public.s3.amazonaws.com/content-sets/" + key + "/models.svo" + (_.has(set, "path") ? "?path=" + set.path : '') %>
|
||||
<div class="panel panel-default" style="margin-top: 15px;">
|
||||
<div class="panel-heading">
|
||||
<a href="<%- models_url %>">
|
||||
<h4 class="media-heading"><%- set.name %></h4>
|
||||
</a>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<p class="text-center">
|
||||
<a href="<%- models_url %>">
|
||||
<img width="200" height="200" src="http://hifi-public.s3.amazonaws.com/content-sets/<%- key %>/thumbnail.jpg" alt="content set thumbnail">
|
||||
</a>
|
||||
</p>
|
||||
<p><%- set.description %></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% if (index % 3 == 0) { %>
|
||||
<div class="clearfix"></div>
|
||||
<% } %>
|
||||
<% index++ %>
|
||||
<% }); %>
|
||||
</script>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
<script type="text/javascript">
|
||||
var setsTemplate = _.template($('.template').html());
|
||||
$.getJSON("content-sets.json", function(json){
|
||||
$('#content-set-panels').html(setsTemplate({sets: json}));
|
||||
});
|
||||
</script>
|
||||
</html>
|
|
@ -1,27 +0,0 @@
|
|||
{
|
||||
"floating-island": {
|
||||
"name": "Floating Island",
|
||||
"description": "Start your galactic empire with this floating island and small oasis. Build it up and share it with your friends.",
|
||||
"path": "/1064.2,75.6,915.1/0.0000127922,0.71653,0.0000684642,0.697556"
|
||||
},
|
||||
"low-poly-floating-island": {
|
||||
"name": "Low-poly Floating Island",
|
||||
"description": "Impressionism with polygons. If you want your virtual island to be nothing but a beautiful painting, this is the aesthetic for you.",
|
||||
"path": "/8216.88,580.568,8264.03/-0.000192036,-0.838296,-0.000124955,0.545216"
|
||||
},
|
||||
"mid-century-modern-living-room": {
|
||||
"name": "Mid-century Modern Living Room",
|
||||
"description": "Timeless, mid-century modern beauty. Notice the classic Eames Recliner and the beautiful built-in shelving.",
|
||||
"path": "/8206.22,22.8716,8210.47/1.61213e-06,0.814919,1.44589e-06,0.579575"
|
||||
},
|
||||
"bar" : {
|
||||
"name": "The Bar",
|
||||
"description": "A sexy club scene to plan your parties and live shows.",
|
||||
"path": "/1048.52,9.5386,1005.7/-0.0000565125,-0.395713,-0.000131155,0.918374"
|
||||
},
|
||||
"space": {
|
||||
"name": "Space",
|
||||
"description": "Vast, empty, nothingness. A completely clean slate for you to start building anything you desire.",
|
||||
"path": "/1000,100,100"
|
||||
}
|
||||
}
|
|
@ -1,776 +0,0 @@
|
|||
//
|
||||
// AppDelegate.cpp
|
||||
// StackManagerQt/src
|
||||
//
|
||||
// Created by Mohammed Nafees on 06/27/14.
|
||||
// Copyright (c) 2014 High Fidelity. All rights reserved.
|
||||
//
|
||||
|
||||
#include <csignal>
|
||||
|
||||
#include "AppDelegate.h"
|
||||
#include "BackgroundProcess.h"
|
||||
#include "GlobalData.h"
|
||||
#include "DownloadManager.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
#include <QDesktopServices>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFileInfoList>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QMessageBox>
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkRequest>
|
||||
#include <QUrlQuery>
|
||||
#include <QUuid>
|
||||
#include <QCommandLineParser>
|
||||
#include <QXmlStreamReader>
|
||||
|
||||
const QString HIGH_FIDELITY_API_URL = "https://metaverse.highfidelity.com/api/v1";
|
||||
|
||||
const QString CHECK_BUILDS_URL = "https://highfidelity.com/builds.xml";
|
||||
|
||||
// Use a custom User-Agent to avoid ModSecurity filtering, e.g. by hosting providers.
|
||||
const QByteArray HIGH_FIDELITY_USER_AGENT = "Mozilla/5.0 (HighFidelity)";
|
||||
|
||||
const int VERSION_CHECK_INTERVAL_MS = 86400000; // a day
|
||||
|
||||
const int WAIT_FOR_CHILD_MSECS = 5000;
|
||||
|
||||
void signalHandler(int param) {
|
||||
AppDelegate* app = AppDelegate::getInstance();
|
||||
|
||||
app->quit();
|
||||
}
|
||||
|
||||
static QTextStream* outStream = NULL;
|
||||
|
||||
void myMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) {
|
||||
Q_UNUSED(context);
|
||||
|
||||
QString dateTime = QDateTime::currentDateTime().toString("dd/MM/yyyy hh:mm:ss");
|
||||
QString txt = QString("[%1] ").arg(dateTime);
|
||||
|
||||
//in this function, you can write the message to any stream!
|
||||
switch (type) {
|
||||
case QtDebugMsg:
|
||||
fprintf(stdout, "Debug: %s\n", qPrintable(msg));
|
||||
txt += msg;
|
||||
break;
|
||||
case QtWarningMsg:
|
||||
fprintf(stdout, "Warning: %s\n", qPrintable(msg));
|
||||
txt += msg;
|
||||
break;
|
||||
case QtCriticalMsg:
|
||||
fprintf(stdout, "Critical: %s\n", qPrintable(msg));
|
||||
txt += msg;
|
||||
break;
|
||||
case QtFatalMsg:
|
||||
fprintf(stdout, "Fatal: %s\n", qPrintable(msg));
|
||||
txt += msg;
|
||||
}
|
||||
|
||||
if (outStream) {
|
||||
*outStream << txt << endl;
|
||||
}
|
||||
}
|
||||
|
||||
AppDelegate::AppDelegate(int argc, char* argv[]) :
|
||||
QApplication(argc, argv),
|
||||
_qtReady(false),
|
||||
_dsReady(false),
|
||||
_dsResourcesReady(false),
|
||||
_acReady(false),
|
||||
_domainServerProcess(NULL),
|
||||
_acMonitorProcess(NULL),
|
||||
_domainServerName("localhost")
|
||||
{
|
||||
// be a signal handler for SIGTERM so we can stop child processes if we get it
|
||||
signal(SIGTERM, signalHandler);
|
||||
|
||||
// look for command-line options
|
||||
parseCommandLine();
|
||||
|
||||
setApplicationName("Stack Manager");
|
||||
setOrganizationName("High Fidelity");
|
||||
setOrganizationDomain("io.highfidelity.StackManager");
|
||||
|
||||
QFile* logFile = new QFile("last_run_log", this);
|
||||
if (!logFile->open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
||||
qDebug() << "Failed to open log file. Will not be able to write STDOUT/STDERR to file.";
|
||||
} else {
|
||||
outStream = new QTextStream(logFile);
|
||||
}
|
||||
|
||||
|
||||
qInstallMessageHandler(myMessageHandler);
|
||||
_domainServerProcess = new BackgroundProcess(GlobalData::getInstance().getDomainServerExecutablePath(), this);
|
||||
_acMonitorProcess = new BackgroundProcess(GlobalData::getInstance().getAssignmentClientExecutablePath(), this);
|
||||
|
||||
_manager = new QNetworkAccessManager(this);
|
||||
|
||||
_window = new MainWindow();
|
||||
|
||||
createExecutablePath();
|
||||
downloadLatestExecutablesAndRequirements();
|
||||
|
||||
_checkVersionTimer.setInterval(0);
|
||||
connect(&_checkVersionTimer, SIGNAL(timeout()), this, SLOT(checkVersion()));
|
||||
_checkVersionTimer.start();
|
||||
|
||||
connect(this, &QApplication::aboutToQuit, this, &AppDelegate::stopStack);
|
||||
}
|
||||
|
||||
AppDelegate::~AppDelegate() {
|
||||
QHash<QUuid, BackgroundProcess*>::iterator it = _scriptProcesses.begin();
|
||||
|
||||
qDebug() << "Stopping scripted assignment-client processes prior to quit.";
|
||||
while (it != _scriptProcesses.end()) {
|
||||
BackgroundProcess* backgroundProcess = it.value();
|
||||
|
||||
// remove from the script processes hash
|
||||
it = _scriptProcesses.erase(it);
|
||||
|
||||
// make sure the process is dead
|
||||
backgroundProcess->terminate();
|
||||
backgroundProcess->waitForFinished();
|
||||
backgroundProcess->deleteLater();
|
||||
}
|
||||
|
||||
qDebug() << "Stopping domain-server process prior to quit.";
|
||||
_domainServerProcess->terminate();
|
||||
_domainServerProcess->waitForFinished();
|
||||
|
||||
qDebug() << "Stopping assignment-client process prior to quit.";
|
||||
_acMonitorProcess->terminate();
|
||||
_acMonitorProcess->waitForFinished();
|
||||
|
||||
_domainServerProcess->deleteLater();
|
||||
_acMonitorProcess->deleteLater();
|
||||
|
||||
_window->deleteLater();
|
||||
|
||||
delete outStream;
|
||||
outStream = NULL;
|
||||
}
|
||||
|
||||
void AppDelegate::parseCommandLine() {
|
||||
QCommandLineParser parser;
|
||||
parser.setApplicationDescription("High Fidelity Stack Manager");
|
||||
parser.addHelpOption();
|
||||
|
||||
const QCommandLineOption helpOption = parser.addHelpOption();
|
||||
|
||||
const QCommandLineOption hifiBuildDirectoryOption("b", "Path to build of hifi", "build-directory");
|
||||
parser.addOption(hifiBuildDirectoryOption);
|
||||
|
||||
if (!parser.parse(QCoreApplication::arguments())) {
|
||||
qCritical() << parser.errorText() << endl;
|
||||
parser.showHelp();
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
|
||||
if (parser.isSet(helpOption)) {
|
||||
parser.showHelp();
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
|
||||
if (parser.isSet(hifiBuildDirectoryOption)) {
|
||||
const QString hifiBuildDirectory = parser.value(hifiBuildDirectoryOption);
|
||||
qDebug() << "hifiBuildDirectory=" << hifiBuildDirectory << "\n";
|
||||
GlobalData::getInstance().setHifiBuildDirectory(hifiBuildDirectory);
|
||||
}
|
||||
}
|
||||
|
||||
void AppDelegate::toggleStack(bool start) {
|
||||
toggleDomainServer(start);
|
||||
toggleAssignmentClientMonitor(start);
|
||||
toggleScriptedAssignmentClients(start);
|
||||
emit stackStateChanged(start);
|
||||
}
|
||||
|
||||
void AppDelegate::toggleDomainServer(bool start) {
|
||||
|
||||
if (start) {
|
||||
_domainServerProcess->start(QStringList());
|
||||
|
||||
_window->getLogsWidget()->addTab(_domainServerProcess->getLogViewer(), "Domain Server");
|
||||
|
||||
if (_domainServerID.isEmpty()) {
|
||||
// after giving the domain server some time to set up, ask for its ID
|
||||
QTimer::singleShot(1000, this, SLOT(requestDomainServerID()));
|
||||
}
|
||||
} else {
|
||||
_domainServerProcess->terminate();
|
||||
_domainServerProcess->waitForFinished(WAIT_FOR_CHILD_MSECS);
|
||||
_domainServerProcess->kill();
|
||||
}
|
||||
}
|
||||
|
||||
void AppDelegate::toggleAssignmentClientMonitor(bool start) {
|
||||
if (start) {
|
||||
_acMonitorProcess->start(QStringList() << "--min" << "5");
|
||||
_window->getLogsWidget()->addTab(_acMonitorProcess->getLogViewer(), "Assignment Clients");
|
||||
} else {
|
||||
_acMonitorProcess->terminate();
|
||||
_acMonitorProcess->waitForFinished(WAIT_FOR_CHILD_MSECS);
|
||||
_acMonitorProcess->kill();
|
||||
}
|
||||
}
|
||||
|
||||
void AppDelegate::toggleScriptedAssignmentClients(bool start) {
|
||||
foreach(BackgroundProcess* scriptProcess, _scriptProcesses) {
|
||||
if (start) {
|
||||
scriptProcess->start(scriptProcess->getLastArgList());
|
||||
} else {
|
||||
scriptProcess->terminate();
|
||||
scriptProcess->waitForFinished(WAIT_FOR_CHILD_MSECS);
|
||||
scriptProcess->kill();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int AppDelegate::startScriptedAssignment(const QUuid& scriptID, const QString& pool) {
|
||||
|
||||
BackgroundProcess* scriptProcess = _scriptProcesses.value(scriptID);
|
||||
|
||||
if (!scriptProcess) {
|
||||
QStringList argList = QStringList() << "-t" << "2";
|
||||
if (!pool.isEmpty()) {
|
||||
argList << "--pool" << pool;
|
||||
}
|
||||
|
||||
scriptProcess = new BackgroundProcess(GlobalData::getInstance().getAssignmentClientExecutablePath(),
|
||||
this);
|
||||
|
||||
scriptProcess->start(argList);
|
||||
|
||||
qint64 processID = scriptProcess->processId();
|
||||
_scriptProcesses.insert(scriptID, scriptProcess);
|
||||
|
||||
_window->getLogsWidget()->addTab(scriptProcess->getLogViewer(), "Scripted Assignment "
|
||||
+ QString::number(processID));
|
||||
} else {
|
||||
scriptProcess->QProcess::start();
|
||||
}
|
||||
|
||||
return scriptProcess->processId();
|
||||
}
|
||||
|
||||
void AppDelegate::stopScriptedAssignment(BackgroundProcess* backgroundProcess) {
|
||||
_window->getLogsWidget()->removeTab(_window->getLogsWidget()->indexOf(backgroundProcess->getLogViewer()));
|
||||
backgroundProcess->terminate();
|
||||
backgroundProcess->waitForFinished(WAIT_FOR_CHILD_MSECS);
|
||||
backgroundProcess->kill();
|
||||
}
|
||||
|
||||
void AppDelegate::stopScriptedAssignment(const QUuid& scriptID) {
|
||||
BackgroundProcess* processValue = _scriptProcesses.take(scriptID);
|
||||
if (processValue) {
|
||||
stopScriptedAssignment(processValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void AppDelegate::requestDomainServerID() {
|
||||
// ask the domain-server for its ID so we can update the accessible name
|
||||
emit domainAddressChanged();
|
||||
QUrl domainIDURL = GlobalData::getInstance().getDomainServerBaseUrl() + "/id";
|
||||
|
||||
qDebug() << "Requesting domain server ID from" << domainIDURL.toString();
|
||||
|
||||
QNetworkReply* idReply = _manager->get(QNetworkRequest(domainIDURL));
|
||||
|
||||
connect(idReply, &QNetworkReply::finished, this, &AppDelegate::handleDomainIDReply);
|
||||
}
|
||||
|
||||
const QString AppDelegate::getServerAddress() const {
|
||||
return "hifi://" + _domainServerName;
|
||||
}
|
||||
|
||||
void AppDelegate::handleDomainIDReply() {
|
||||
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
|
||||
|
||||
if (reply->error() == QNetworkReply::NoError
|
||||
&& reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() == 200) {
|
||||
_domainServerID = QString(reply->readAll());
|
||||
|
||||
if (!_domainServerID.isEmpty()) {
|
||||
|
||||
if (!QUuid(_domainServerID).isNull()) {
|
||||
qDebug() << "The domain server ID is" << _domainServerID;
|
||||
qDebug() << "Asking High Fidelity API for associated domain name.";
|
||||
|
||||
// fire off a request to high fidelity API to see if this domain exists with them
|
||||
QUrl domainGetURL = HIGH_FIDELITY_API_URL + "/domains/" + _domainServerID;
|
||||
QNetworkReply* domainGetReply = _manager->get(QNetworkRequest(domainGetURL));
|
||||
connect(domainGetReply, &QNetworkReply::finished, this, &AppDelegate::handleDomainGetReply);
|
||||
} else {
|
||||
emit domainServerIDMissing();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
qDebug() << "Error getting domain ID from domain-server - "
|
||||
<< reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt()
|
||||
<< reply->errorString();
|
||||
}
|
||||
}
|
||||
|
||||
void AppDelegate::handleDomainGetReply() {
|
||||
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
|
||||
|
||||
if (reply->error() == QNetworkReply::NoError
|
||||
&& reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() == 200) {
|
||||
QJsonDocument responseDocument = QJsonDocument::fromJson(reply->readAll());
|
||||
|
||||
QJsonObject domainObject = responseDocument.object()["domain"].toObject();
|
||||
|
||||
const QString DOMAIN_NAME_KEY = "name";
|
||||
const QString DOMAIN_OWNER_PLACES_KEY = "owner_places";
|
||||
|
||||
if (domainObject.contains(DOMAIN_NAME_KEY)) {
|
||||
_domainServerName = domainObject[DOMAIN_NAME_KEY].toString();
|
||||
} else if (domainObject.contains(DOMAIN_OWNER_PLACES_KEY)) {
|
||||
QJsonArray ownerPlaces = domainObject[DOMAIN_OWNER_PLACES_KEY].toArray();
|
||||
if (ownerPlaces.size() > 0) {
|
||||
_domainServerName = ownerPlaces[0].toObject()[DOMAIN_NAME_KEY].toString();
|
||||
}
|
||||
}
|
||||
|
||||
qDebug() << "This domain server's name is" << _domainServerName << "- updating address link.";
|
||||
|
||||
emit domainAddressChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void AppDelegate::changeDomainServerIndexPath(const QString& newPath) {
|
||||
if (!newPath.isEmpty()) {
|
||||
QString pathsJSON = "{\"paths\": { \"/\": { \"viewpoint\": \"%1\" }}}";
|
||||
|
||||
QNetworkRequest settingsRequest(GlobalData::getInstance().getDomainServerBaseUrl() + "/settings.json");
|
||||
settingsRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
|
||||
|
||||
QNetworkReply* settingsReply = _manager->post(settingsRequest, pathsJSON.arg(newPath).toLocal8Bit());
|
||||
connect(settingsReply, &QNetworkReply::finished, this, &AppDelegate::handleChangeIndexPathResponse);
|
||||
}
|
||||
}
|
||||
|
||||
void AppDelegate::handleChangeIndexPathResponse() {
|
||||
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
|
||||
|
||||
if (reply->error() == QNetworkReply::NoError
|
||||
&& reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() == 200) {
|
||||
|
||||
qDebug() << "Successfully changed index path in domain-server.";
|
||||
emit indexPathChangeResponse(true);
|
||||
} else {
|
||||
qDebug() << "Error changing domain-server index path-" << reply->errorString();
|
||||
emit indexPathChangeResponse(false);
|
||||
}
|
||||
}
|
||||
|
||||
void AppDelegate::downloadContentSet(const QUrl& contentSetURL) {
|
||||
// make sure this link was an svo
|
||||
if (contentSetURL.path().endsWith(".svo")) {
|
||||
// setup a request for this content set
|
||||
QNetworkRequest contentRequest(contentSetURL);
|
||||
QNetworkReply* contentReply = _manager->get(contentRequest);
|
||||
connect(contentReply, &QNetworkReply::finished, this, &AppDelegate::handleContentSetDownloadFinished);
|
||||
}
|
||||
}
|
||||
|
||||
void AppDelegate::handleContentSetDownloadFinished() {
|
||||
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
|
||||
|
||||
if (reply->error() == QNetworkReply::NoError
|
||||
&& reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() == 200) {
|
||||
|
||||
QString modelFilename = GlobalData::getInstance().getClientsResourcesPath() + "models.svo";
|
||||
|
||||
// write the model file
|
||||
QFile modelFile(modelFilename);
|
||||
modelFile.open(QIODevice::WriteOnly);
|
||||
|
||||
// stop the base assignment clients before we try to write the new content
|
||||
toggleAssignmentClientMonitor(false);
|
||||
|
||||
if (modelFile.write(reply->readAll()) == -1) {
|
||||
qDebug() << "Error writing content set to" << modelFilename;
|
||||
modelFile.close();
|
||||
toggleAssignmentClientMonitor(true);
|
||||
} else {
|
||||
qDebug() << "Wrote new content set to" << modelFilename;
|
||||
modelFile.close();
|
||||
|
||||
// restart the assignment-client
|
||||
toggleAssignmentClientMonitor(true);
|
||||
|
||||
emit contentSetDownloadResponse(true);
|
||||
|
||||
// did we have a path in the query?
|
||||
// if so when we need to set the DS index path to that path
|
||||
QUrlQuery svoQuery(reply->url().query());
|
||||
changeDomainServerIndexPath(svoQuery.queryItemValue("path"));
|
||||
|
||||
emit domainAddressChanged();
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// if we failed we need to emit our signal with a fail
|
||||
emit contentSetDownloadResponse(false);
|
||||
emit domainAddressChanged();
|
||||
}
|
||||
|
||||
void AppDelegate::onFileSuccessfullyInstalled(const QUrl& url) {
|
||||
if (url == GlobalData::getInstance().getRequirementsURL()) {
|
||||
_qtReady = true;
|
||||
} else if (url == GlobalData::getInstance().getAssignmentClientURL()) {
|
||||
_acReady = true;
|
||||
} else if (url == GlobalData::getInstance().getDomainServerURL()) {
|
||||
_dsReady = true;
|
||||
} else if (url == GlobalData::getInstance().getDomainServerResourcesURL()) {
|
||||
_dsResourcesReady = true;
|
||||
}
|
||||
|
||||
if (_qtReady && _acReady && _dsReady && _dsResourcesReady) {
|
||||
_window->setRequirementsLastChecked(QDateTime::currentDateTime().toString());
|
||||
_window->show();
|
||||
toggleStack(true);
|
||||
}
|
||||
}
|
||||
|
||||
void AppDelegate::createExecutablePath() {
|
||||
QDir launchDir(GlobalData::getInstance().getClientsLaunchPath());
|
||||
QDir resourcesDir(GlobalData::getInstance().getClientsResourcesPath());
|
||||
QDir logsDir(GlobalData::getInstance().getLogsPath());
|
||||
if (!launchDir.exists()) {
|
||||
if (QDir().mkpath(launchDir.absolutePath())) {
|
||||
qDebug() << "Successfully created directory: "
|
||||
<< launchDir.absolutePath();
|
||||
} else {
|
||||
qCritical() << "Failed to create directory: "
|
||||
<< launchDir.absolutePath();
|
||||
}
|
||||
}
|
||||
if (!resourcesDir.exists()) {
|
||||
if (QDir().mkpath(resourcesDir.absolutePath())) {
|
||||
qDebug() << "Successfully created directory: "
|
||||
<< resourcesDir.absolutePath();
|
||||
} else {
|
||||
qCritical() << "Failed to create directory: "
|
||||
<< resourcesDir.absolutePath();
|
||||
}
|
||||
}
|
||||
if (!logsDir.exists()) {
|
||||
if (QDir().mkpath(logsDir.absolutePath())) {
|
||||
qDebug() << "Successfully created directory: "
|
||||
<< logsDir.absolutePath();
|
||||
} else {
|
||||
qCritical() << "Failed to create directory: "
|
||||
<< logsDir.absolutePath();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AppDelegate::downloadLatestExecutablesAndRequirements() {
|
||||
// Check if Qt is already installed
|
||||
if (GlobalData::getInstance().getPlatform() == "mac") {
|
||||
if (QDir(GlobalData::getInstance().getClientsLaunchPath() + "QtCore.framework").exists()) {
|
||||
_qtReady = true;
|
||||
}
|
||||
} else if (GlobalData::getInstance().getPlatform() == "win") {
|
||||
if (QFileInfo(GlobalData::getInstance().getClientsLaunchPath() + "Qt5Core.dll").exists()) {
|
||||
_qtReady = true;
|
||||
}
|
||||
} else { // linux
|
||||
if (QFileInfo(GlobalData::getInstance().getClientsLaunchPath() + "libQt5Core.so.5").exists()) {
|
||||
_qtReady = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QFile reqZipFile(GlobalData::getInstance().getRequirementsZipPath());
|
||||
QByteArray reqZipData;
|
||||
if (reqZipFile.open(QIODevice::ReadOnly)) {
|
||||
reqZipData = reqZipFile.readAll();
|
||||
reqZipFile.close();
|
||||
}
|
||||
QFile resZipFile(GlobalData::getInstance().getDomainServerResourcesZipPath());
|
||||
QByteArray resZipData;
|
||||
if (resZipFile.open(QIODevice::ReadOnly)) {
|
||||
resZipData = resZipFile.readAll();
|
||||
resZipFile.close();
|
||||
}
|
||||
|
||||
QDir resourcesDir(GlobalData::getInstance().getClientsResourcesPath());
|
||||
if (!(resourcesDir.entryInfoList(QDir::AllEntries).size() < 3)) {
|
||||
_dsResourcesReady = true;
|
||||
}
|
||||
|
||||
// if the user has set hifiBuildDirectory, don't attempt to download the domain-server or assignement-client
|
||||
if (GlobalData::getInstance().isGetHifiBuildDirectorySet()) {
|
||||
_dsReady = true;
|
||||
_acReady = true;
|
||||
} else {
|
||||
QByteArray dsData;
|
||||
QFile dsFile(GlobalData::getInstance().getDomainServerExecutablePath());
|
||||
if (dsFile.open(QIODevice::ReadOnly)) {
|
||||
dsData = dsFile.readAll();
|
||||
dsFile.close();
|
||||
}
|
||||
QByteArray acData;
|
||||
QFile acFile(GlobalData::getInstance().getAssignmentClientExecutablePath());
|
||||
if (acFile.open(QIODevice::ReadOnly)) {
|
||||
acData = acFile.readAll();
|
||||
acFile.close();
|
||||
}
|
||||
|
||||
QNetworkRequest acReq(QUrl(GlobalData::getInstance().getAssignmentClientMD5URL()));
|
||||
QNetworkReply* acReply = _manager->get(acReq);
|
||||
QEventLoop acLoop;
|
||||
connect(acReply, SIGNAL(finished()), &acLoop, SLOT(quit()));
|
||||
acLoop.exec();
|
||||
QByteArray acMd5Data = acReply->readAll().trimmed();
|
||||
if (GlobalData::getInstance().getPlatform() == "win") {
|
||||
// fix for reading the MD5 hash from Windows-generated
|
||||
// binary data of the MD5 hash
|
||||
QTextStream stream(acMd5Data);
|
||||
stream >> acMd5Data;
|
||||
}
|
||||
|
||||
// fix for Mac and Linux network accessibility
|
||||
if (acMd5Data.size() == 0) {
|
||||
// network is not accessible
|
||||
qDebug() << "Could not connect to the internet.";
|
||||
_window->show();
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << "AC MD5: " << acMd5Data;
|
||||
if (acMd5Data.toLower() == QCryptographicHash::hash(acData, QCryptographicHash::Md5).toHex()) {
|
||||
_acReady = true;
|
||||
}
|
||||
|
||||
|
||||
QNetworkRequest dsReq(QUrl(GlobalData::getInstance().getDomainServerMD5URL()));
|
||||
QNetworkReply* dsReply = _manager->get(dsReq);
|
||||
QEventLoop dsLoop;
|
||||
connect(dsReply, SIGNAL(finished()), &dsLoop, SLOT(quit()));
|
||||
dsLoop.exec();
|
||||
QByteArray dsMd5Data = dsReply->readAll().trimmed();
|
||||
if (GlobalData::getInstance().getPlatform() == "win") {
|
||||
// fix for reading the MD5 hash from Windows generated
|
||||
// binary data of the MD5 hash
|
||||
QTextStream stream(dsMd5Data);
|
||||
stream >> dsMd5Data;
|
||||
}
|
||||
qDebug() << "DS MD5: " << dsMd5Data;
|
||||
if (dsMd5Data.toLower() == QCryptographicHash::hash(dsData, QCryptographicHash::Md5).toHex()) {
|
||||
_dsReady = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (_qtReady) {
|
||||
// check MD5 of requirements.zip only if Qt is found
|
||||
QNetworkRequest reqZipReq(QUrl(GlobalData::getInstance().getRequirementsMD5URL()));
|
||||
QNetworkReply* reqZipReply = _manager->get(reqZipReq);
|
||||
QEventLoop reqZipLoop;
|
||||
connect(reqZipReply, SIGNAL(finished()), &reqZipLoop, SLOT(quit()));
|
||||
reqZipLoop.exec();
|
||||
QByteArray reqZipMd5Data = reqZipReply->readAll().trimmed();
|
||||
if (GlobalData::getInstance().getPlatform() == "win") {
|
||||
// fix for reading the MD5 hash from Windows generated
|
||||
// binary data of the MD5 hash
|
||||
QTextStream stream(reqZipMd5Data);
|
||||
stream >> reqZipMd5Data;
|
||||
}
|
||||
qDebug() << "Requirements ZIP MD5: " << reqZipMd5Data;
|
||||
if (reqZipMd5Data.toLower() != QCryptographicHash::hash(reqZipData, QCryptographicHash::Md5).toHex()) {
|
||||
_qtReady = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (_dsResourcesReady) {
|
||||
// check MD5 of resources.zip only if Domain Server
|
||||
// resources are installed
|
||||
QNetworkRequest resZipReq(QUrl(GlobalData::getInstance().getDomainServerResourcesMD5URL()));
|
||||
QNetworkReply* resZipReply = _manager->get(resZipReq);
|
||||
QEventLoop resZipLoop;
|
||||
connect(resZipReply, SIGNAL(finished()), &resZipLoop, SLOT(quit()));
|
||||
resZipLoop.exec();
|
||||
QByteArray resZipMd5Data = resZipReply->readAll().trimmed();
|
||||
if (GlobalData::getInstance().getPlatform() == "win") {
|
||||
// fix for reading the MD5 hash from Windows generated
|
||||
// binary data of the MD5 hash
|
||||
QTextStream stream(resZipMd5Data);
|
||||
stream >> resZipMd5Data;
|
||||
}
|
||||
qDebug() << "Domain Server Resources ZIP MD5: " << resZipMd5Data;
|
||||
if (resZipMd5Data.toLower() != QCryptographicHash::hash(resZipData, QCryptographicHash::Md5).toHex()) {
|
||||
_dsResourcesReady = false;
|
||||
}
|
||||
}
|
||||
|
||||
DownloadManager* downloadManager = 0;
|
||||
if (!_qtReady || !_acReady || !_dsReady || !_dsResourcesReady) {
|
||||
// initialise DownloadManager
|
||||
downloadManager = new DownloadManager(_manager);
|
||||
downloadManager->setWindowModality(Qt::ApplicationModal);
|
||||
connect(downloadManager, SIGNAL(fileSuccessfullyInstalled(QUrl)),
|
||||
SLOT(onFileSuccessfullyInstalled(QUrl)));
|
||||
downloadManager->show();
|
||||
} else {
|
||||
_window->setRequirementsLastChecked(QDateTime::currentDateTime().toString());
|
||||
_window->show();
|
||||
toggleStack(true);
|
||||
}
|
||||
|
||||
if (!_qtReady) {
|
||||
downloadManager->downloadFile(GlobalData::getInstance().getRequirementsURL());
|
||||
}
|
||||
|
||||
if (!_acReady) {
|
||||
downloadManager->downloadFile(GlobalData::getInstance().getAssignmentClientURL());
|
||||
}
|
||||
|
||||
if (!_dsReady) {
|
||||
downloadManager->downloadFile(GlobalData::getInstance().getDomainServerURL());
|
||||
}
|
||||
|
||||
if (!_dsResourcesReady) {
|
||||
downloadManager->downloadFile(GlobalData::getInstance().getDomainServerResourcesURL());
|
||||
}
|
||||
}
|
||||
|
||||
void AppDelegate::checkVersion() {
|
||||
QNetworkRequest latestVersionRequest((QUrl(CHECK_BUILDS_URL)));
|
||||
latestVersionRequest.setHeader(QNetworkRequest::UserAgentHeader, HIGH_FIDELITY_USER_AGENT);
|
||||
latestVersionRequest.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache);
|
||||
QNetworkReply* reply = _manager->get(latestVersionRequest);
|
||||
connect(reply, &QNetworkReply::finished, this, &AppDelegate::parseVersionXml);
|
||||
|
||||
_checkVersionTimer.setInterval(VERSION_CHECK_INTERVAL_MS);
|
||||
_checkVersionTimer.start();
|
||||
}
|
||||
|
||||
struct VersionInformation {
|
||||
QString version;
|
||||
QUrl downloadUrl;
|
||||
QString timeStamp;
|
||||
QString releaseNotes;
|
||||
};
|
||||
|
||||
void AppDelegate::parseVersionXml() {
|
||||
|
||||
#ifdef Q_OS_WIN32
|
||||
QString operatingSystem("windows");
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
QString operatingSystem("mac");
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
QString operatingSystem("ubuntu");
|
||||
#endif
|
||||
|
||||
QNetworkReply* sender = qobject_cast<QNetworkReply*>(QObject::sender());
|
||||
QXmlStreamReader xml(sender);
|
||||
|
||||
QHash<QString, VersionInformation> projectVersions;
|
||||
|
||||
while (!xml.atEnd() && !xml.hasError()) {
|
||||
if (xml.tokenType() == QXmlStreamReader::StartElement && xml.name().toString() == "project") {
|
||||
QString projectName = "";
|
||||
foreach(const QXmlStreamAttribute &attr, xml.attributes()) {
|
||||
if (attr.name().toString() == "name") {
|
||||
projectName = attr.value().toString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (!(xml.tokenType() == QXmlStreamReader::EndElement && xml.name().toString() == "project")) {
|
||||
if (projectName != "") {
|
||||
if (xml.tokenType() == QXmlStreamReader::StartElement && xml.name().toString() == "platform") {
|
||||
QString platformName = "";
|
||||
foreach(const QXmlStreamAttribute &attr, xml.attributes()) {
|
||||
if (attr.name().toString() == "name") {
|
||||
platformName = attr.value().toString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
int latestVersion = 0;
|
||||
VersionInformation latestVersionInformation;
|
||||
while (!(xml.tokenType() == QXmlStreamReader::EndElement && xml.name().toString() == "platform")) {
|
||||
if (platformName == operatingSystem) {
|
||||
if (xml.tokenType() == QXmlStreamReader::StartElement && xml.name().toString() == "build") {
|
||||
VersionInformation buildVersionInformation;
|
||||
while (!(xml.tokenType() == QXmlStreamReader::EndElement && xml.name().toString() == "build")) {
|
||||
if (xml.tokenType() == QXmlStreamReader::StartElement && xml.name().toString() == "version") {
|
||||
xml.readNext();
|
||||
buildVersionInformation.version = xml.text().toString();
|
||||
}
|
||||
if (xml.tokenType() == QXmlStreamReader::StartElement && xml.name().toString() == "url") {
|
||||
xml.readNext();
|
||||
buildVersionInformation.downloadUrl = QUrl(xml.text().toString());
|
||||
}
|
||||
if (xml.tokenType() == QXmlStreamReader::StartElement && xml.name().toString() == "timestamp") {
|
||||
xml.readNext();
|
||||
buildVersionInformation.timeStamp = xml.text().toString();
|
||||
}
|
||||
if (xml.tokenType() == QXmlStreamReader::StartElement && xml.name().toString() == "note") {
|
||||
xml.readNext();
|
||||
if (buildVersionInformation.releaseNotes != "") {
|
||||
buildVersionInformation.releaseNotes += "\n";
|
||||
}
|
||||
buildVersionInformation.releaseNotes += xml.text().toString();
|
||||
}
|
||||
xml.readNext();
|
||||
}
|
||||
if (latestVersion < buildVersionInformation.version.toInt()) {
|
||||
latestVersionInformation = buildVersionInformation;
|
||||
latestVersion = buildVersionInformation.version.toInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
xml.readNext();
|
||||
}
|
||||
if (latestVersion>0) {
|
||||
projectVersions[projectName] = latestVersionInformation;
|
||||
}
|
||||
}
|
||||
}
|
||||
xml.readNext();
|
||||
}
|
||||
}
|
||||
xml.readNext();
|
||||
}
|
||||
|
||||
#ifdef WANT_DEBUG
|
||||
qDebug() << "parsed projects for OS" << operatingSystem;
|
||||
QHashIterator<QString, VersionInformation> projectVersion(projectVersions);
|
||||
while (projectVersion.hasNext()) {
|
||||
projectVersion.next();
|
||||
qDebug() << "project:" << projectVersion.key();
|
||||
qDebug() << "version:" << projectVersion.value().version;
|
||||
qDebug() << "downloadUrl:" << projectVersion.value().downloadUrl.toString();
|
||||
qDebug() << "timeStamp:" << projectVersion.value().timeStamp;
|
||||
qDebug() << "releaseNotes:" << projectVersion.value().releaseNotes;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (projectVersions.contains("stackmanager")) {
|
||||
VersionInformation latestVersion = projectVersions["stackmanager"];
|
||||
if (QCoreApplication::applicationVersion() != latestVersion.version && QCoreApplication::applicationVersion() != "dev") {
|
||||
_window->setUpdateNotification("There is an update available. Please download and install version " + latestVersion.version + ".");
|
||||
_window->update();
|
||||
}
|
||||
}
|
||||
|
||||
sender->deleteLater();
|
||||
}
|
|
@ -1,89 +0,0 @@
|
|||
//
|
||||
// AppDelegate.h
|
||||
// StackManagerQt/src
|
||||
//
|
||||
// Created by Mohammed Nafees on 06/27/14.
|
||||
// Copyright (c) 2014 High Fidelity. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef hifi_AppDelegate_h
|
||||
#define hifi_AppDelegate_h
|
||||
|
||||
|
||||
#include <QApplication>
|
||||
#include <QCoreApplication>
|
||||
#include <QList>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QUrl>
|
||||
#include <QUuid>
|
||||
#include <QHash>
|
||||
#include <QTimer>
|
||||
|
||||
#include "MainWindow.h"
|
||||
|
||||
class BackgroundProcess;
|
||||
|
||||
class AppDelegate : public QApplication
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
static AppDelegate* getInstance() { return static_cast<AppDelegate*>(QCoreApplication::instance()); }
|
||||
|
||||
AppDelegate(int argc, char* argv[]);
|
||||
~AppDelegate();
|
||||
|
||||
void toggleStack(bool start);
|
||||
void toggleDomainServer(bool start);
|
||||
void toggleAssignmentClientMonitor(bool start);
|
||||
void toggleScriptedAssignmentClients(bool start);
|
||||
|
||||
int startScriptedAssignment(const QUuid& scriptID, const QString& pool = QString());
|
||||
void stopScriptedAssignment(BackgroundProcess* backgroundProcess);
|
||||
void stopScriptedAssignment(const QUuid& scriptID);
|
||||
|
||||
void stopStack() { toggleStack(false); }
|
||||
|
||||
const QString getServerAddress() const;
|
||||
public slots:
|
||||
void downloadContentSet(const QUrl& contentSetURL);
|
||||
signals:
|
||||
void domainServerIDMissing();
|
||||
void domainAddressChanged();
|
||||
void contentSetDownloadResponse(bool wasSuccessful);
|
||||
void indexPathChangeResponse(bool wasSuccessful);
|
||||
void stackStateChanged(bool isOn);
|
||||
private slots:
|
||||
void onFileSuccessfullyInstalled(const QUrl& url);
|
||||
void requestDomainServerID();
|
||||
void handleDomainIDReply();
|
||||
void handleDomainGetReply();
|
||||
void handleChangeIndexPathResponse();
|
||||
void handleContentSetDownloadFinished();
|
||||
void checkVersion();
|
||||
void parseVersionXml();
|
||||
|
||||
private:
|
||||
void parseCommandLine();
|
||||
void createExecutablePath();
|
||||
void downloadLatestExecutablesAndRequirements();
|
||||
|
||||
void changeDomainServerIndexPath(const QString& newPath);
|
||||
|
||||
QNetworkAccessManager* _manager;
|
||||
bool _qtReady;
|
||||
bool _dsReady;
|
||||
bool _dsResourcesReady;
|
||||
bool _acReady;
|
||||
BackgroundProcess* _domainServerProcess;
|
||||
BackgroundProcess* _acMonitorProcess;
|
||||
QHash<QUuid, BackgroundProcess*> _scriptProcesses;
|
||||
|
||||
QString _domainServerID;
|
||||
QString _domainServerName;
|
||||
|
||||
QTimer _checkVersionTimer;
|
||||
|
||||
MainWindow* _window;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,125 +0,0 @@
|
|||
//
|
||||
// BackgroundProcess.cpp
|
||||
// StackManagerQt/src
|
||||
//
|
||||
// Created by Mohammed Nafees on 07/03/14.
|
||||
// Copyright (c) 2014 High Fidelity. All rights reserved.
|
||||
//
|
||||
|
||||
#include "BackgroundProcess.h"
|
||||
#include "GlobalData.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QStandardPaths>
|
||||
#include <QWidget>
|
||||
|
||||
const int LOG_CHECK_INTERVAL_MS = 500;
|
||||
|
||||
const QString DATETIME_FORMAT = "yyyy-MM-dd_hh.mm.ss";
|
||||
const QString LOGS_DIRECTORY = "/Logs/";
|
||||
|
||||
BackgroundProcess::BackgroundProcess(const QString& program, QObject *parent) :
|
||||
QProcess(parent),
|
||||
_program(program),
|
||||
_stdoutFilePos(0),
|
||||
_stderrFilePos(0)
|
||||
{
|
||||
_logViewer = new LogViewer;
|
||||
|
||||
connect(this, SIGNAL(started()), SLOT(processStarted()));
|
||||
connect(this, SIGNAL(error(QProcess::ProcessError)), SLOT(processError()));
|
||||
|
||||
_logFilePath = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
|
||||
_logFilePath.append(LOGS_DIRECTORY);
|
||||
QDir logDir(_logFilePath);
|
||||
if (!logDir.exists(_logFilePath)) {
|
||||
logDir.mkpath(_logFilePath);
|
||||
}
|
||||
|
||||
_logTimer.setInterval(LOG_CHECK_INTERVAL_MS);
|
||||
_logTimer.setSingleShot(false);
|
||||
connect(&_logTimer, SIGNAL(timeout()), this, SLOT(receivedStandardError()));
|
||||
connect(&_logTimer, SIGNAL(timeout()), this, SLOT(receivedStandardOutput()));
|
||||
connect(this, SIGNAL(started()), &_logTimer, SLOT(start()));
|
||||
|
||||
setWorkingDirectory(GlobalData::getInstance().getClientsLaunchPath());
|
||||
}
|
||||
|
||||
void BackgroundProcess::start(const QStringList& arguments) {
|
||||
QDateTime now = QDateTime::currentDateTime();
|
||||
QString nowString = now.toString(DATETIME_FORMAT);
|
||||
QFileInfo programFile(_program);
|
||||
QString baseFilename = _logFilePath + programFile.completeBaseName();
|
||||
_stdoutFilename = QString("%1_stdout_%2.txt").arg(baseFilename, nowString);
|
||||
_stderrFilename = QString("%1_stderr_%2.txt").arg(baseFilename, nowString);
|
||||
|
||||
qDebug() << "stdout for " << _program << " being written to: " << _stdoutFilename;
|
||||
qDebug() << "stderr for " << _program << " being written to: " << _stderrFilename;
|
||||
|
||||
// reset the stdout and stderr file positions
|
||||
_stdoutFilePos = 0;
|
||||
_stderrFilePos = 0;
|
||||
|
||||
// clear our LogViewer
|
||||
_logViewer->clear();
|
||||
|
||||
// reset our output and error files
|
||||
setStandardOutputFile(_stdoutFilename);
|
||||
setStandardErrorFile(_stderrFilename);
|
||||
|
||||
_lastArgList = arguments;
|
||||
|
||||
QProcess::start(_program, arguments);
|
||||
}
|
||||
|
||||
void BackgroundProcess::processStarted() {
|
||||
qDebug() << "process " << _program << " started.";
|
||||
}
|
||||
|
||||
void BackgroundProcess::processError() {
|
||||
qDebug() << "process error for" << _program << "-" << errorString();
|
||||
}
|
||||
|
||||
void BackgroundProcess::receivedStandardOutput() {
|
||||
QString output;
|
||||
|
||||
QFile file(_stdoutFilename);
|
||||
|
||||
if (!file.open(QIODevice::ReadOnly)) return;
|
||||
|
||||
if (file.size() > _stdoutFilePos) {
|
||||
file.seek(_stdoutFilePos);
|
||||
output = file.readAll();
|
||||
_stdoutFilePos = file.pos();
|
||||
}
|
||||
|
||||
file.close();
|
||||
|
||||
if (!output.isEmpty() && !output.isNull()) {
|
||||
_logViewer->appendStandardOutput(output);
|
||||
}
|
||||
}
|
||||
|
||||
void BackgroundProcess::receivedStandardError() {
|
||||
QString output;
|
||||
|
||||
QFile file(_stderrFilename);
|
||||
|
||||
if (!file.open(QIODevice::ReadOnly)) return;
|
||||
|
||||
if (file.size() > _stderrFilePos) {
|
||||
file.seek(_stderrFilePos);
|
||||
output = file.readAll();
|
||||
_stderrFilePos = file.pos();
|
||||
}
|
||||
|
||||
file.close();
|
||||
|
||||
if (!output.isEmpty() && !output.isNull()) {
|
||||
_logViewer->appendStandardError(output);
|
||||
}
|
||||
}
|
|
@ -1,48 +0,0 @@
|
|||
//
|
||||
// BackgroundProcess.h
|
||||
// StackManagerQt/src
|
||||
//
|
||||
// Created by Mohammed Nafees on 07/03/14.
|
||||
// Copyright (c) 2014 High Fidelity. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef hifi_BackgroundProcess_h
|
||||
#define hifi_BackgroundProcess_h
|
||||
|
||||
#include <LogViewer.h>
|
||||
|
||||
#include <QProcess>
|
||||
#include <QString>
|
||||
#include <QTimer>
|
||||
|
||||
class BackgroundProcess : public QProcess
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
BackgroundProcess(const QString& program, QObject* parent = 0);
|
||||
|
||||
LogViewer* getLogViewer() { return _logViewer; }
|
||||
|
||||
const QStringList& getLastArgList() const { return _lastArgList; }
|
||||
|
||||
void start(const QStringList& arguments);
|
||||
|
||||
private slots:
|
||||
void processStarted();
|
||||
void processError();
|
||||
void receivedStandardOutput();
|
||||
void receivedStandardError();
|
||||
|
||||
private:
|
||||
QString _program;
|
||||
QStringList _lastArgList;
|
||||
QString _logFilePath;
|
||||
LogViewer* _logViewer;
|
||||
QTimer _logTimer;
|
||||
QString _stdoutFilename;
|
||||
QString _stderrFilename;
|
||||
qint64 _stdoutFilePos;
|
||||
qint64 _stderrFilePos;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,164 +0,0 @@
|
|||
//
|
||||
// DownloadManager.cpp
|
||||
// StackManagerQt/src
|
||||
//
|
||||
// Created by Mohammed Nafees on 07/09/14.
|
||||
// Copyright (c) 2014 High Fidelity. All rights reserved.
|
||||
//
|
||||
|
||||
#include "DownloadManager.h"
|
||||
#include "GlobalData.h"
|
||||
|
||||
#include <QFileInfo>
|
||||
#include <QTableWidgetItem>
|
||||
#include <QHeaderView>
|
||||
#include <QDebug>
|
||||
#include <QVBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QSizePolicy>
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
#include <QProgressBar>
|
||||
#include <QMessageBox>
|
||||
#include <QApplication>
|
||||
|
||||
DownloadManager::DownloadManager(QNetworkAccessManager* manager, QWidget* parent) :
|
||||
QWidget(parent),
|
||||
_manager(manager)
|
||||
{
|
||||
setBaseSize(500, 250);
|
||||
|
||||
QVBoxLayout* layout = new QVBoxLayout;
|
||||
layout->setContentsMargins(10, 10, 10, 10);
|
||||
QLabel* label = new QLabel;
|
||||
label->setText("Download Manager");
|
||||
label->setStyleSheet("font-size: 19px;");
|
||||
label->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
|
||||
label->setAlignment(Qt::AlignCenter);
|
||||
layout->addWidget(label);
|
||||
|
||||
_table = new QTableWidget;
|
||||
_table->setEditTriggers(QTableWidget::NoEditTriggers);
|
||||
_table->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
_table->setColumnCount(3);
|
||||
_table->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
|
||||
_table->setHorizontalHeaderLabels(QStringList() << "Name" << "Progress" << "Status");
|
||||
layout->addWidget(_table);
|
||||
|
||||
setLayout(layout);
|
||||
}
|
||||
|
||||
DownloadManager::~DownloadManager() {
|
||||
_downloaderHash.clear();
|
||||
}
|
||||
|
||||
void DownloadManager::downloadFile(const QUrl& url) {
|
||||
for (int i = 0; i < _downloaderHash.size(); ++i) {
|
||||
if (_downloaderHash.keys().at(i)->getUrl() == url) {
|
||||
qDebug() << "Downloader for URL " << url << " already initialised.";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Downloader* downloader = new Downloader(url);
|
||||
connect(downloader, SIGNAL(downloadCompleted(QUrl)), SLOT(onDownloadCompleted(QUrl)));
|
||||
connect(downloader, SIGNAL(downloadStarted(Downloader*,QUrl)),
|
||||
SLOT(onDownloadStarted(Downloader*,QUrl)));
|
||||
connect(downloader, SIGNAL(downloadFailed(QUrl)), SLOT(onDownloadFailed(QUrl)));
|
||||
connect(downloader, SIGNAL(downloadProgress(QUrl,int)), SLOT(onDownloadProgress(QUrl,int)));
|
||||
connect(downloader, SIGNAL(installingFiles(QUrl)), SLOT(onInstallingFiles(QUrl)));
|
||||
connect(downloader, SIGNAL(filesSuccessfullyInstalled(QUrl)), SLOT(onFilesSuccessfullyInstalled(QUrl)));
|
||||
connect(downloader, SIGNAL(filesInstallationFailed(QUrl)), SLOT(onFilesInstallationFailed(QUrl)));
|
||||
downloader->start(_manager);
|
||||
}
|
||||
|
||||
void DownloadManager::onDownloadStarted(Downloader* downloader, const QUrl& url) {
|
||||
int rowIndex = _table->rowCount();
|
||||
_table->setRowCount(rowIndex + 1);
|
||||
QTableWidgetItem* nameItem = new QTableWidgetItem(QFileInfo(url.toString()).fileName());
|
||||
_table->setItem(rowIndex, 0, nameItem);
|
||||
QProgressBar* progressBar = new QProgressBar;
|
||||
_table->setCellWidget(rowIndex, 1, progressBar);
|
||||
QTableWidgetItem* statusItem = new QTableWidgetItem;
|
||||
if (QFile(QDir::toNativeSeparators(GlobalData::getInstance().getClientsLaunchPath() + "/" + QFileInfo(url.toString()).fileName())).exists()) {
|
||||
statusItem->setText("Updating");
|
||||
} else {
|
||||
statusItem->setText("Downloading");
|
||||
}
|
||||
_table->setItem(rowIndex, 2, statusItem);
|
||||
_downloaderHash.insert(downloader, rowIndex);
|
||||
}
|
||||
|
||||
void DownloadManager::onDownloadCompleted(const QUrl& url) {
|
||||
_table->item(downloaderRowIndexForUrl(url), 2)->setText("Download Complete");
|
||||
}
|
||||
|
||||
void DownloadManager::onDownloadProgress(const QUrl& url, int percentage) {
|
||||
qobject_cast<QProgressBar*>(_table->cellWidget(downloaderRowIndexForUrl(url), 1))->setValue(percentage);
|
||||
}
|
||||
|
||||
void DownloadManager::onDownloadFailed(const QUrl& url) {
|
||||
_table->item(downloaderRowIndexForUrl(url), 2)->setText("Download Failed");
|
||||
_downloaderHash.remove(downloaderForUrl(url));
|
||||
}
|
||||
|
||||
void DownloadManager::onInstallingFiles(const QUrl& url) {
|
||||
_table->item(downloaderRowIndexForUrl(url), 2)->setText("Installing");
|
||||
}
|
||||
|
||||
void DownloadManager::onFilesSuccessfullyInstalled(const QUrl& url) {
|
||||
_table->item(downloaderRowIndexForUrl(url), 2)->setText("Successfully Installed");
|
||||
_downloaderHash.remove(downloaderForUrl(url));
|
||||
emit fileSuccessfullyInstalled(url);
|
||||
if (_downloaderHash.size() == 0) {
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
void DownloadManager::onFilesInstallationFailed(const QUrl& url) {
|
||||
_table->item(downloaderRowIndexForUrl(url), 2)->setText("Installation Failed");
|
||||
_downloaderHash.remove(downloaderForUrl(url));
|
||||
}
|
||||
|
||||
void DownloadManager::closeEvent(QCloseEvent*) {
|
||||
if (_downloaderHash.size() > 0) {
|
||||
QMessageBox msgBox;
|
||||
msgBox.setText("There are active downloads that need to be installed for the proper functioning of Stack Manager. Do you want to stop the downloads and exit?");
|
||||
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
|
||||
int ret = msgBox.exec();
|
||||
switch (ret) {
|
||||
case QMessageBox::Yes:
|
||||
qApp->quit();
|
||||
break;
|
||||
case QMessageBox::No:
|
||||
msgBox.close();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int DownloadManager::downloaderRowIndexForUrl(const QUrl& url) {
|
||||
QHash<Downloader*, int>::const_iterator i = _downloaderHash.constBegin();
|
||||
while (i != _downloaderHash.constEnd()) {
|
||||
if (i.key()->getUrl() == url) {
|
||||
return i.value();
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
Downloader* DownloadManager::downloaderForUrl(const QUrl& url) {
|
||||
QHash<Downloader*, int>::const_iterator i = _downloaderHash.constBegin();
|
||||
while (i != _downloaderHash.constEnd()) {
|
||||
if (i.key()->getUrl() == url) {
|
||||
return i.key();
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
//
|
||||
// DownloadManager.h
|
||||
// StackManagerQt/src
|
||||
//
|
||||
// Created by Mohammed Nafees on 07/09/14.
|
||||
// Copyright (c) 2014 High Fidelity. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef hifi_DownloadManager_h
|
||||
#define hifi_DownloadManager_h
|
||||
|
||||
#include <QWidget>
|
||||
#include <QTableWidget>
|
||||
#include <QHash>
|
||||
#include <QEvent>
|
||||
#include <QNetworkAccessManager>
|
||||
|
||||
#include "Downloader.h"
|
||||
|
||||
class DownloadManager : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
DownloadManager(QNetworkAccessManager* manager, QWidget* parent = 0);
|
||||
~DownloadManager();
|
||||
|
||||
void downloadFile(const QUrl& url);
|
||||
|
||||
private slots:
|
||||
void onDownloadStarted(Downloader* downloader, const QUrl& url);
|
||||
void onDownloadCompleted(const QUrl& url);
|
||||
void onDownloadProgress(const QUrl& url, int percentage);
|
||||
void onDownloadFailed(const QUrl& url);
|
||||
void onInstallingFiles(const QUrl& url);
|
||||
void onFilesSuccessfullyInstalled(const QUrl& url);
|
||||
void onFilesInstallationFailed(const QUrl& url);
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent*);
|
||||
|
||||
signals:
|
||||
void fileSuccessfullyInstalled(const QUrl& url);
|
||||
|
||||
private:
|
||||
QTableWidget* _table;
|
||||
QNetworkAccessManager* _manager;
|
||||
QHash<Downloader*, int> _downloaderHash;
|
||||
|
||||
int downloaderRowIndexForUrl(const QUrl& url);
|
||||
Downloader* downloaderForUrl(const QUrl& url);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,133 +0,0 @@
|
|||
//
|
||||
// Downloader.cpp
|
||||
// StackManagerQt/src
|
||||
//
|
||||
// Created by Mohammed Nafees on 07/09/14.
|
||||
// Copyright (c) 2014 High Fidelity. All rights reserved.
|
||||
//
|
||||
|
||||
#include "Downloader.h"
|
||||
#include "GlobalData.h"
|
||||
|
||||
#include <quazip/quazip.h>
|
||||
#include <quazip/quazipfile.h>
|
||||
|
||||
#include <QNetworkRequest>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QDir>
|
||||
#include <QDebug>
|
||||
|
||||
Downloader::Downloader(const QUrl& url, QObject* parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
_url = url;
|
||||
}
|
||||
|
||||
void Downloader::start(QNetworkAccessManager* manager) {
|
||||
qDebug() << "Downloader::start() for URL - " << _url;
|
||||
QNetworkRequest req(_url);
|
||||
QNetworkReply* reply = manager->get(req);
|
||||
emit downloadStarted(this, _url);
|
||||
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(error(QNetworkReply::NetworkError)));
|
||||
connect(reply, SIGNAL(downloadProgress(qint64,qint64)), SLOT(downloadProgress(qint64,qint64)));
|
||||
connect(reply, SIGNAL(finished()), SLOT(downloadFinished()));
|
||||
}
|
||||
|
||||
void Downloader::error(QNetworkReply::NetworkError error) {
|
||||
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
|
||||
qDebug() << reply->errorString();
|
||||
reply->deleteLater();
|
||||
}
|
||||
|
||||
void Downloader::downloadProgress(qint64 bytesReceived, qint64 bytesTotal) {
|
||||
int percentage = bytesReceived*100/bytesTotal;
|
||||
emit downloadProgress(_url, percentage);
|
||||
}
|
||||
|
||||
void Downloader::downloadFinished() {
|
||||
qDebug() << "Downloader::downloadFinished() for URL - " << _url;
|
||||
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
|
||||
if (reply->error() != QNetworkReply::NoError) {
|
||||
qDebug() << reply->errorString();
|
||||
emit downloadFailed(_url);
|
||||
return;
|
||||
}
|
||||
emit downloadCompleted(_url);
|
||||
|
||||
QString fileName = QFileInfo(_url.toString()).fileName();
|
||||
QString fileDir = GlobalData::getInstance().getClientsLaunchPath();
|
||||
QString filePath = fileDir + fileName;
|
||||
|
||||
QFile file(filePath);
|
||||
|
||||
// remove file if already exists
|
||||
if (file.exists()) {
|
||||
file.remove();
|
||||
}
|
||||
|
||||
if (file.open(QIODevice::WriteOnly)) {
|
||||
if (fileName == "assignment-client" || fileName == "assignment-client.exe" ||
|
||||
fileName == "domain-server" || fileName == "domain-server.exe") {
|
||||
file.setPermissions(QFile::ExeOwner | QFile::ReadOwner | QFile::WriteOwner);
|
||||
} else {
|
||||
file.setPermissions(QFile::ReadOwner | QFile::WriteOwner);
|
||||
}
|
||||
emit installingFiles(_url);
|
||||
file.write(reply->readAll());
|
||||
bool error = false;
|
||||
file.close();
|
||||
|
||||
if (fileName.endsWith(".zip")) { // we need to unzip the file now
|
||||
QuaZip zip(QFileInfo(file).absoluteFilePath());
|
||||
if (zip.open(QuaZip::mdUnzip)) {
|
||||
QuaZipFile zipFile(&zip);
|
||||
for(bool f = zip.goToFirstFile(); f; f = zip.goToNextFile()) {
|
||||
if (zipFile.open(QIODevice::ReadOnly)) {
|
||||
QFile newFile(QDir::toNativeSeparators(fileDir + "/" + zipFile.getActualFileName()));
|
||||
if (zipFile.getActualFileName().endsWith("/")) {
|
||||
QDir().mkpath(QFileInfo(newFile).absolutePath());
|
||||
zipFile.close();
|
||||
continue;
|
||||
}
|
||||
|
||||
// remove file if already exists
|
||||
if (newFile.exists()) {
|
||||
newFile.remove();
|
||||
}
|
||||
|
||||
if (newFile.open(QIODevice::WriteOnly)) {
|
||||
newFile.setPermissions(QFile::ReadOwner | QFile::WriteOwner);
|
||||
newFile.write(zipFile.readAll());
|
||||
newFile.close();
|
||||
} else {
|
||||
error = true;
|
||||
qDebug() << "Could not open archive file for writing: " << zip.getCurrentFileName();
|
||||
emit filesInstallationFailed(_url);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
error = true;
|
||||
qDebug() << "Could not open archive file: " << zip.getCurrentFileName();
|
||||
emit filesInstallationFailed(_url);
|
||||
break;
|
||||
}
|
||||
zipFile.close();
|
||||
}
|
||||
zip.close();
|
||||
} else {
|
||||
error = true;
|
||||
emit filesInstallationFailed(_url);
|
||||
qDebug() << "Could not open zip file for extraction.";
|
||||
}
|
||||
}
|
||||
if (!error)
|
||||
emit filesSuccessfullyInstalled(_url);
|
||||
} else {
|
||||
emit filesInstallationFailed(_url);
|
||||
qDebug() << "Could not open file: " << filePath;
|
||||
}
|
||||
reply->deleteLater();
|
||||
}
|
||||
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
//
|
||||
// Downloader.h
|
||||
// StackManagerQt/src
|
||||
//
|
||||
// Created by Mohammed Nafees on 07/09/14.
|
||||
// Copyright (c) 2014 High Fidelity. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef hifi_Downloader_h
|
||||
#define hifi_Downloader_h
|
||||
|
||||
#include <QObject>
|
||||
#include <QUrl>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
|
||||
class Downloader : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit Downloader(const QUrl& url, QObject* parent = 0);
|
||||
|
||||
const QUrl& getUrl() { return _url; }
|
||||
|
||||
void start(QNetworkAccessManager* manager);
|
||||
|
||||
private slots:
|
||||
void error(QNetworkReply::NetworkError error);
|
||||
void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
|
||||
void downloadFinished();
|
||||
|
||||
signals:
|
||||
void downloadStarted(Downloader* downloader, const QUrl& url);
|
||||
void downloadCompleted(const QUrl& url);
|
||||
void downloadProgress(const QUrl& url, int percentage);
|
||||
void downloadFailed(const QUrl& url);
|
||||
void installingFiles(const QUrl& url);
|
||||
void filesSuccessfullyInstalled(const QUrl& url);
|
||||
void filesInstallationFailed(const QUrl& url);
|
||||
|
||||
private:
|
||||
QUrl _url;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,84 +0,0 @@
|
|||
//
|
||||
// GlobalData.cpp
|
||||
// StackManagerQt/src
|
||||
//
|
||||
// Created by Mohammed Nafees on 6/25/14.
|
||||
// Copyright (c) 2014 High Fidelity. All rights reserved.
|
||||
//
|
||||
|
||||
#include "GlobalData.h"
|
||||
#include "StackManagerVersion.h"
|
||||
|
||||
#include <QMutex>
|
||||
#include <QStandardPaths>
|
||||
#include <QDir>
|
||||
#include <QDebug>
|
||||
|
||||
GlobalData& GlobalData::getInstance() {
|
||||
static GlobalData staticInstance;
|
||||
return staticInstance;
|
||||
}
|
||||
|
||||
GlobalData::GlobalData() {
|
||||
QString urlBase = URL_BASE;
|
||||
#if defined Q_OS_OSX
|
||||
_platform = "mac";
|
||||
#elif defined Q_OS_WIN32
|
||||
_platform = "win";
|
||||
#elif defined Q_OS_LINUX
|
||||
_platform = "linux";
|
||||
#endif
|
||||
|
||||
_resourcePath = "resources/";
|
||||
_assignmentClientExecutable = "assignment-client";
|
||||
_domainServerExecutable = "domain-server";
|
||||
QString applicationSupportDirectory = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
|
||||
if (PR_BUILD) {
|
||||
applicationSupportDirectory += "/pr-binaries";
|
||||
}
|
||||
|
||||
_clientsLaunchPath = QDir::toNativeSeparators(applicationSupportDirectory + "/");
|
||||
_clientsResourcePath = QDir::toNativeSeparators(applicationSupportDirectory + "/" + _resourcePath);
|
||||
|
||||
_assignmentClientExecutablePath = QDir::toNativeSeparators(_clientsLaunchPath + _assignmentClientExecutable);
|
||||
if (_platform == "win") {
|
||||
_assignmentClientExecutablePath.append(".exe");
|
||||
}
|
||||
_domainServerExecutablePath = QDir::toNativeSeparators(_clientsLaunchPath + _domainServerExecutable);
|
||||
if (_platform == "win") {
|
||||
_domainServerExecutablePath.append(".exe");
|
||||
}
|
||||
|
||||
_requirementsURL = urlBase + "/binaries/" + _platform + "/requirements/requirements.zip";
|
||||
_requirementsZipPath = _clientsLaunchPath + "requirements.zip";
|
||||
_requirementsMD5URL = urlBase + "/binaries/" + _platform + "/requirements/requirements.md5";
|
||||
_assignmentClientURL = urlBase + "/binaries/" + _platform + "/assignment-client" + (_platform == "win" ? "/assignment-client.exe" : "/assignment-client");
|
||||
_domainServerResourcesURL = urlBase + "/binaries/" + _platform + "/domain-server/resources.zip";
|
||||
_domainServerResourcesZipPath = _clientsLaunchPath + "resources.zip";
|
||||
_domainServerResourcesMD5URL = urlBase + "/binaries/" + _platform + "/domain-server/resources.md5";
|
||||
_domainServerURL = urlBase + "/binaries/" + _platform + "/domain-server" + (_platform == "win" ? "/domain-server.exe" : "/domain-server");
|
||||
|
||||
_assignmentClientMD5URL = urlBase + "/binaries/" + _platform + "/assignment-client/assignment-client.md5";
|
||||
_domainServerMD5URL = urlBase + "/binaries/" + _platform + "/domain-server/domain-server.md5";
|
||||
|
||||
_defaultDomain = "localhost";
|
||||
_logsPath = QDir::toNativeSeparators(_clientsLaunchPath + "logs/");
|
||||
_availableAssignmentTypes.insert("audio-mixer", 0);
|
||||
_availableAssignmentTypes.insert("avatar-mixer", 1);
|
||||
_availableAssignmentTypes.insert("entity-server", 6);
|
||||
|
||||
// allow user to override path to binaries so that they can run their own builds
|
||||
_hifiBuildDirectory = "";
|
||||
|
||||
_domainServerBaseUrl = "http://localhost:40100";
|
||||
}
|
||||
|
||||
|
||||
void GlobalData::setHifiBuildDirectory(const QString hifiBuildDirectory) {
|
||||
_hifiBuildDirectory = hifiBuildDirectory;
|
||||
_clientsLaunchPath = QDir::toNativeSeparators(_hifiBuildDirectory + "/assignment-client/");
|
||||
_clientsResourcePath = QDir::toNativeSeparators(_clientsLaunchPath + "/" + _resourcePath);
|
||||
_logsPath = QDir::toNativeSeparators(_clientsLaunchPath + "logs/");
|
||||
_assignmentClientExecutablePath = QDir::toNativeSeparators(_clientsLaunchPath + _assignmentClientExecutable);
|
||||
_domainServerExecutablePath = QDir::toNativeSeparators(_hifiBuildDirectory + "/domain-server/" + _domainServerExecutable);
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
//
|
||||
// GlobalData.h
|
||||
// StackManagerQt/src
|
||||
//
|
||||
// Created by Mohammed Nafees on 6/25/14.
|
||||
// Copyright (c) 2014 High Fidelity. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef hifi_GlobalData_h
|
||||
#define hifi_GlobalData_h
|
||||
|
||||
#include <QString>
|
||||
#include <QHash>
|
||||
|
||||
class GlobalData {
|
||||
public:
|
||||
static GlobalData& getInstance();
|
||||
|
||||
QString getPlatform() { return _platform; }
|
||||
QString getClientsLaunchPath() { return _clientsLaunchPath; }
|
||||
QString getClientsResourcesPath() { return _clientsResourcePath; }
|
||||
QString getAssignmentClientExecutablePath() { return _assignmentClientExecutablePath; }
|
||||
QString getDomainServerExecutablePath() { return _domainServerExecutablePath; }
|
||||
QString getRequirementsURL() { return _requirementsURL; }
|
||||
QString getRequirementsZipPath() { return _requirementsZipPath; }
|
||||
QString getRequirementsMD5URL() { return _requirementsMD5URL; }
|
||||
QString getAssignmentClientURL() { return _assignmentClientURL; }
|
||||
QString getAssignmentClientMD5URL() { return _assignmentClientMD5URL; }
|
||||
QString getDomainServerURL() { return _domainServerURL; }
|
||||
QString getDomainServerResourcesURL() { return _domainServerResourcesURL; }
|
||||
QString getDomainServerResourcesZipPath() { return _domainServerResourcesZipPath; }
|
||||
QString getDomainServerResourcesMD5URL() { return _domainServerResourcesMD5URL; }
|
||||
QString getDomainServerMD5URL() { return _domainServerMD5URL; }
|
||||
QString getDefaultDomain() { return _defaultDomain; }
|
||||
QString getLogsPath() { return _logsPath; }
|
||||
QHash<QString, int> getAvailableAssignmentTypes() { return _availableAssignmentTypes; }
|
||||
|
||||
void setHifiBuildDirectory(const QString hifiBuildDirectory);
|
||||
bool isGetHifiBuildDirectorySet() { return _hifiBuildDirectory != ""; }
|
||||
|
||||
void setDomainServerBaseUrl(const QString domainServerBaseUrl) { _domainServerBaseUrl = domainServerBaseUrl; }
|
||||
QString getDomainServerBaseUrl() { return _domainServerBaseUrl; }
|
||||
|
||||
private:
|
||||
GlobalData();
|
||||
|
||||
QString _platform;
|
||||
QString _clientsLaunchPath;
|
||||
QString _clientsResourcePath;
|
||||
QString _assignmentClientExecutablePath;
|
||||
QString _domainServerExecutablePath;
|
||||
QString _requirementsURL;
|
||||
QString _requirementsZipPath;
|
||||
QString _requirementsMD5URL;
|
||||
QString _assignmentClientURL;
|
||||
QString _assignmentClientMD5URL;
|
||||
QString _domainServerURL;
|
||||
QString _domainServerResourcesURL;
|
||||
QString _domainServerResourcesZipPath;
|
||||
QString _domainServerResourcesMD5URL;
|
||||
QString _domainServerMD5URL;
|
||||
QString _defaultDomain;
|
||||
QString _logsPath;
|
||||
QString _hifiBuildDirectory;
|
||||
|
||||
QString _resourcePath;
|
||||
QString _assignmentClientExecutable;
|
||||
QString _domainServerExecutable;
|
||||
|
||||
QHash<QString, int> _availableAssignmentTypes;
|
||||
|
||||
QString _domainServerBaseUrl;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,16 +0,0 @@
|
|||
//
|
||||
// StackManagerVersion.h
|
||||
// StackManagerQt
|
||||
//
|
||||
// Created by Kai Ludwig on 02/16/15.
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Declaration of version and build data
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
const QString BUILD_VERSION = "@BUILD_SEQ@";
|
||||
const QString URL_BASE = "@BASE_URL@";
|
||||
const bool PR_BUILD = @PR_BUILD@;
|
|
@ -1,15 +0,0 @@
|
|||
//
|
||||
// main.cpp
|
||||
// StackManagerQt/src
|
||||
//
|
||||
// Created by Mohammed Nafees on 06/27/14.
|
||||
// Copyright (c) 2014 High Fidelity. All rights reserved.
|
||||
//
|
||||
|
||||
#include "AppDelegate.h"
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
AppDelegate app(argc, argv);
|
||||
return app.exec();
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>../assets/logo-larger.png</file>
|
||||
<file alias="assignment-run.svg">../assets/assignment-run.svg</file>
|
||||
<file alias="assignment-stop.svg">../assets/assignment-stop.svg</file>
|
||||
<file alias="server-start.svg">../assets/server-start.svg</file>
|
||||
<file alias="server-stop.svg">../assets/server-stop.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
|
@ -1,61 +0,0 @@
|
|||
//
|
||||
// AssignmentWidget.cpp
|
||||
// StackManagerQt/src/ui
|
||||
//
|
||||
// Created by Mohammed Nafees on 10/18/14.
|
||||
// Copyright (c) 2014 High Fidelity. All rights reserved.
|
||||
//
|
||||
|
||||
#include "AssignmentWidget.h"
|
||||
|
||||
#include <QLabel>
|
||||
#include <QHBoxLayout>
|
||||
|
||||
#include "AppDelegate.h"
|
||||
|
||||
AssignmentWidget::AssignmentWidget(QWidget* parent) :
|
||||
QWidget(parent),
|
||||
_processID(0),
|
||||
_isRunning(false),
|
||||
_scriptID(QUuid::createUuid())
|
||||
{
|
||||
setFont(QFont("sans-serif"));
|
||||
|
||||
QHBoxLayout* layout = new QHBoxLayout;
|
||||
|
||||
_runButton = new SvgButton(this);
|
||||
_runButton->setFixedSize(59, 32);
|
||||
_runButton->setSvgImage(":/assignment-run.svg");
|
||||
_runButton->setCheckable(true);
|
||||
_runButton->setChecked(false);
|
||||
|
||||
QLabel* label = new QLabel;
|
||||
label->setText("Pool ID");
|
||||
|
||||
_poolIDLineEdit = new QLineEdit;
|
||||
_poolIDLineEdit->setPlaceholderText("Optional");
|
||||
|
||||
layout->addWidget(_runButton, 5);
|
||||
layout->addWidget(label);
|
||||
layout->addWidget(_poolIDLineEdit);
|
||||
|
||||
setLayout(layout);
|
||||
|
||||
connect(_runButton, &QPushButton::clicked, this, &AssignmentWidget::toggleRunningState);
|
||||
}
|
||||
|
||||
void AssignmentWidget::toggleRunningState() {
|
||||
if (_isRunning && _processID > 0) {
|
||||
AppDelegate::getInstance()->stopScriptedAssignment(_scriptID);
|
||||
_runButton->setSvgImage(":/assignment-run.svg");
|
||||
update();
|
||||
_poolIDLineEdit->setEnabled(true);
|
||||
_isRunning = false;
|
||||
} else {
|
||||
_processID = AppDelegate::getInstance()->startScriptedAssignment(_scriptID, _poolIDLineEdit->text());
|
||||
_runButton->setSvgImage(":/assignment-stop.svg");
|
||||
update();
|
||||
_poolIDLineEdit->setEnabled(false);
|
||||
_isRunning = true;
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
//
|
||||
// AssignmentWidget.h
|
||||
// StackManagerQt/src/ui
|
||||
//
|
||||
// Created by Mohammed Nafees on 10/18/14.
|
||||
// Copyright (c) 2014 High Fidelity. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef hifi_AssignmentWidget_h
|
||||
#define hifi_AssignmentWidget_h
|
||||
|
||||
#include <QWidget>
|
||||
#include <QLineEdit>
|
||||
#include <QUuid>
|
||||
|
||||
#include "SvgButton.h"
|
||||
|
||||
class AssignmentWidget : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AssignmentWidget(QWidget* parent = 0);
|
||||
|
||||
bool isRunning() { return _isRunning; }
|
||||
|
||||
public slots:
|
||||
void toggleRunningState();
|
||||
|
||||
private:
|
||||
int _processID;
|
||||
bool _isRunning;
|
||||
SvgButton* _runButton;
|
||||
QLineEdit* _poolIDLineEdit;
|
||||
QUuid _scriptID;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,63 +0,0 @@
|
|||
//
|
||||
// LogViewer.cpp
|
||||
// StackManagerQt/src/ui
|
||||
//
|
||||
// Created by Mohammed Nafees on 07/10/14.
|
||||
// Copyright (c) 2014 High Fidelity. All rights reserved.
|
||||
//
|
||||
|
||||
#include "LogViewer.h"
|
||||
#include "GlobalData.h"
|
||||
|
||||
#include <QTextCursor>
|
||||
#include <QLabel>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
LogViewer::LogViewer(QWidget* parent) :
|
||||
QWidget(parent)
|
||||
{
|
||||
QVBoxLayout* layout = new QVBoxLayout;
|
||||
QLabel* outputLabel = new QLabel;
|
||||
outputLabel->setText("Standard Output:");
|
||||
outputLabel->setStyleSheet("font-size: 13pt;");
|
||||
|
||||
layout->addWidget(outputLabel);
|
||||
|
||||
_outputView = new QTextEdit;
|
||||
_outputView->setUndoRedoEnabled(false);
|
||||
_outputView->setReadOnly(true);
|
||||
|
||||
layout->addWidget(_outputView);
|
||||
|
||||
QLabel* errorLabel = new QLabel;
|
||||
errorLabel->setText("Standard Error:");
|
||||
errorLabel->setStyleSheet("font-size: 13pt;");
|
||||
|
||||
layout->addWidget(errorLabel);
|
||||
|
||||
_errorView = new QTextEdit;
|
||||
_errorView->setUndoRedoEnabled(false);
|
||||
_errorView->setReadOnly(true);
|
||||
|
||||
layout->addWidget(_errorView);
|
||||
setLayout(layout);
|
||||
}
|
||||
|
||||
void LogViewer::clear() {
|
||||
_outputView->clear();
|
||||
_errorView->clear();
|
||||
}
|
||||
|
||||
void LogViewer::appendStandardOutput(const QString& output) {
|
||||
QTextCursor cursor = _outputView->textCursor();
|
||||
cursor.movePosition(QTextCursor::End);
|
||||
cursor.insertText(output);
|
||||
_outputView->ensureCursorVisible();
|
||||
}
|
||||
|
||||
void LogViewer::appendStandardError(const QString& error) {
|
||||
QTextCursor cursor = _errorView->textCursor();
|
||||
cursor.movePosition(QTextCursor::End);
|
||||
cursor.insertText(error);
|
||||
_errorView->ensureCursorVisible();
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
//
|
||||
// LogViewer.h
|
||||
// StackManagerQt/src/ui
|
||||
//
|
||||
// Created by Mohammed Nafees on 07/10/14.
|
||||
// Copyright (c) 2014 High Fidelity. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef hifi_LogViewer_h
|
||||
#define hifi_LogViewer_h
|
||||
|
||||
#include <QWidget>
|
||||
#include <QTextEdit>
|
||||
|
||||
class LogViewer : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit LogViewer(QWidget* parent = 0);
|
||||
|
||||
void clear();
|
||||
|
||||
void appendStandardOutput(const QString& output);
|
||||
void appendStandardError(const QString& error);
|
||||
|
||||
private:
|
||||
QTextEdit* _outputView;
|
||||
QTextEdit* _errorView;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,329 +0,0 @@
|
|||
//
|
||||
// MainWindow.cpp
|
||||
// StackManagerQt/src/ui
|
||||
//
|
||||
// Created by Mohammed Nafees on 10/17/14.
|
||||
// Copyright (c) 2014 High Fidelity. All rights reserved.
|
||||
//
|
||||
|
||||
#include "MainWindow.h"
|
||||
|
||||
#include <QClipboard>
|
||||
#include <QPainter>
|
||||
#include <QApplication>
|
||||
#include <QDesktopWidget>
|
||||
#include <QFrame>
|
||||
#include <QDesktopServices>
|
||||
#include <QMessageBox>
|
||||
#include <QMutex>
|
||||
#include <QLayoutItem>
|
||||
#include <QCursor>
|
||||
#include <QtWebKitWidgets/qwebview.h>
|
||||
|
||||
#include "AppDelegate.h"
|
||||
#include "AssignmentWidget.h"
|
||||
#include "GlobalData.h"
|
||||
#include "StackManagerVersion.h"
|
||||
|
||||
const int GLOBAL_X_PADDING = 55;
|
||||
const int TOP_Y_PADDING = 25;
|
||||
const int REQUIREMENTS_TEXT_TOP_MARGIN = 19;
|
||||
//const int HORIZONTAL_RULE_TOP_MARGIN = 25;
|
||||
|
||||
const int BUTTON_PADDING_FIX = -5;
|
||||
|
||||
//const int ASSIGNMENT_LAYOUT_RESIZE_FACTOR = 56;
|
||||
//const int ASSIGNMENT_LAYOUT_WIDGET_STRETCH = 0;
|
||||
|
||||
const QColor lightGrayColor = QColor(205, 205, 205);
|
||||
const QColor darkGrayColor = QColor(84, 84, 84);
|
||||
const QColor redColor = QColor(189, 54, 78);
|
||||
const QColor greenColor = QColor(3, 150, 126);
|
||||
|
||||
const QString SHARE_BUTTON_COPY_LINK_TEXT = "Copy link";
|
||||
|
||||
MainWindow::MainWindow() :
|
||||
QWidget(),
|
||||
_domainServerRunning(false),
|
||||
_startServerButton(NULL),
|
||||
_stopServerButton(NULL),
|
||||
_serverAddressLabel(NULL),
|
||||
_viewLogsButton(NULL),
|
||||
_settingsButton(NULL),
|
||||
_copyLinkButton(NULL),
|
||||
_contentSetButton(NULL),
|
||||
_logsWidget(NULL),
|
||||
_localHttpPortSharedMem(NULL)
|
||||
{
|
||||
// Set build version
|
||||
QCoreApplication::setApplicationVersion(BUILD_VERSION);
|
||||
|
||||
setWindowTitle("High Fidelity Stack Manager (build " + QCoreApplication::applicationVersion() + ")");
|
||||
const int WINDOW_FIXED_WIDTH = 640;
|
||||
const int WINDOW_INITIAL_HEIGHT = 170;
|
||||
|
||||
if (GlobalData::getInstance().getPlatform() == "win") {
|
||||
const int windowsYCoord = 30;
|
||||
setGeometry(qApp->desktop()->availableGeometry().width() / 2 - WINDOW_FIXED_WIDTH / 2, windowsYCoord,
|
||||
WINDOW_FIXED_WIDTH, WINDOW_INITIAL_HEIGHT);
|
||||
} else if (GlobalData::getInstance().getPlatform() == "linux") {
|
||||
const int linuxYCoord = 30;
|
||||
setGeometry(qApp->desktop()->availableGeometry().width() / 2 - WINDOW_FIXED_WIDTH / 2, linuxYCoord,
|
||||
WINDOW_FIXED_WIDTH, WINDOW_INITIAL_HEIGHT + 40);
|
||||
} else {
|
||||
const int unixYCoord = 0;
|
||||
setGeometry(qApp->desktop()->availableGeometry().width() / 2 - WINDOW_FIXED_WIDTH / 2, unixYCoord,
|
||||
WINDOW_FIXED_WIDTH, WINDOW_INITIAL_HEIGHT);
|
||||
}
|
||||
setFixedWidth(WINDOW_FIXED_WIDTH);
|
||||
setMaximumHeight(qApp->desktop()->availableGeometry().height());
|
||||
setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowTitleHint |
|
||||
Qt::WindowMinimizeButtonHint | Qt::WindowCloseButtonHint);
|
||||
setMouseTracking(true);
|
||||
setStyleSheet("font-family: 'Helvetica', 'Arial', 'sans-serif';");
|
||||
|
||||
const int SERVER_BUTTON_HEIGHT = 47;
|
||||
|
||||
_startServerButton = new SvgButton(this);
|
||||
|
||||
QPixmap scaledStart(":/server-start.svg");
|
||||
scaledStart.scaledToHeight(SERVER_BUTTON_HEIGHT);
|
||||
|
||||
_startServerButton->setGeometry((width() / 2.0f) - (scaledStart.width() / 2.0f),
|
||||
TOP_Y_PADDING,
|
||||
scaledStart.width(),
|
||||
scaledStart.height());
|
||||
_startServerButton->setSvgImage(":/server-start.svg");
|
||||
|
||||
_stopServerButton = new SvgButton(this);
|
||||
_stopServerButton->setSvgImage(":/server-stop.svg");
|
||||
_stopServerButton->setGeometry(GLOBAL_X_PADDING, TOP_Y_PADDING,
|
||||
scaledStart.width(), scaledStart.height());
|
||||
|
||||
const int SERVER_ADDRESS_LABEL_LEFT_MARGIN = 20;
|
||||
const int SERVER_ADDRESS_LABEL_TOP_MARGIN = 17;
|
||||
_serverAddressLabel = new QLabel(this);
|
||||
_serverAddressLabel->move(_stopServerButton->geometry().right() + SERVER_ADDRESS_LABEL_LEFT_MARGIN,
|
||||
TOP_Y_PADDING + SERVER_ADDRESS_LABEL_TOP_MARGIN);
|
||||
_serverAddressLabel->setOpenExternalLinks(true);
|
||||
|
||||
const int SECONDARY_BUTTON_ROW_TOP_MARGIN = 10;
|
||||
|
||||
int secondaryButtonY = _stopServerButton->geometry().bottom() + SECONDARY_BUTTON_ROW_TOP_MARGIN;
|
||||
|
||||
_viewLogsButton = new QPushButton("View logs", this);
|
||||
_viewLogsButton->adjustSize();
|
||||
_viewLogsButton->setGeometry(GLOBAL_X_PADDING + BUTTON_PADDING_FIX, secondaryButtonY,
|
||||
_viewLogsButton->width(), _viewLogsButton->height());
|
||||
|
||||
_settingsButton = new QPushButton("Settings", this);
|
||||
_settingsButton->adjustSize();
|
||||
_settingsButton->setGeometry(_viewLogsButton->geometry().right(), secondaryButtonY,
|
||||
_settingsButton->width(), _settingsButton->height());
|
||||
|
||||
_copyLinkButton = new QPushButton(SHARE_BUTTON_COPY_LINK_TEXT, this);
|
||||
_copyLinkButton->adjustSize();
|
||||
_copyLinkButton->setGeometry(_settingsButton->geometry().right(), secondaryButtonY,
|
||||
_copyLinkButton->width(), _copyLinkButton->height());
|
||||
|
||||
// add the drop down for content sets
|
||||
_contentSetButton = new QPushButton("Get content set", this);
|
||||
_contentSetButton->adjustSize();
|
||||
_contentSetButton->setGeometry(_copyLinkButton->geometry().right(), secondaryButtonY,
|
||||
_contentSetButton->width(), _contentSetButton->height());
|
||||
|
||||
const QSize logsWidgetSize = QSize(500, 500);
|
||||
_logsWidget = new QTabWidget;
|
||||
_logsWidget->setUsesScrollButtons(true);
|
||||
_logsWidget->setElideMode(Qt::ElideMiddle);
|
||||
_logsWidget->setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowTitleHint |
|
||||
Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint);
|
||||
_logsWidget->resize(logsWidgetSize);
|
||||
|
||||
connect(_startServerButton, &QPushButton::clicked, this, &MainWindow::toggleDomainServerButton);
|
||||
connect(_stopServerButton, &QPushButton::clicked, this, &MainWindow::toggleDomainServerButton);
|
||||
connect(_copyLinkButton, &QPushButton::clicked, this, &MainWindow::handleCopyLinkButton);
|
||||
connect(_contentSetButton, &QPushButton::clicked, this, &MainWindow::showContentSetPage);
|
||||
connect(_viewLogsButton, &QPushButton::clicked, _logsWidget, &QTabWidget::show);
|
||||
connect(_settingsButton, &QPushButton::clicked, this, &MainWindow::openSettings);
|
||||
|
||||
AppDelegate* app = AppDelegate::getInstance();
|
||||
// update the current server address label and change it if the AppDelegate says the address has changed
|
||||
updateServerAddressLabel();
|
||||
connect(app, &AppDelegate::domainAddressChanged, this, &MainWindow::updateServerAddressLabel);
|
||||
connect(app, &AppDelegate::domainAddressChanged, this, &MainWindow::updateServerBaseUrl);
|
||||
|
||||
// handle response for content set download
|
||||
connect(app, &AppDelegate::contentSetDownloadResponse, this, &MainWindow::handleContentSetDownloadResponse);
|
||||
|
||||
// handle response for index path change
|
||||
connect(app, &AppDelegate::indexPathChangeResponse, this, &MainWindow::handleIndexPathChangeResponse);
|
||||
|
||||
// handle stack state change
|
||||
connect(app, &AppDelegate::stackStateChanged, this, &MainWindow::toggleContent);
|
||||
|
||||
toggleContent(false);
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::updateServerAddressLabel() {
|
||||
AppDelegate* app = AppDelegate::getInstance();
|
||||
|
||||
_serverAddressLabel->setText("<html><head/><body style=\"font:14pt 'Helvetica', 'Arial', 'sans-serif';"
|
||||
"font-weight: bold;\"><p><span style=\"color:#545454;\">Accessible at: </span>"
|
||||
"<a href=\"" + app->getServerAddress() + "\">"
|
||||
"<span style=\"color:#29957e;\">" + app->getServerAddress() +
|
||||
"</span></a></p></body></html>");
|
||||
_serverAddressLabel->adjustSize();
|
||||
}
|
||||
|
||||
void MainWindow::updateServerBaseUrl() {
|
||||
quint16 localPort;
|
||||
|
||||
if (getLocalServerPortFromSharedMemory("domain-server.local-http-port", _localHttpPortSharedMem, localPort)) {
|
||||
GlobalData::getInstance().setDomainServerBaseUrl(QString("http://localhost:") + QString::number(localPort));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::handleCopyLinkButton() {
|
||||
QClipboard *clipboard = QApplication::clipboard();
|
||||
clipboard->setText(AppDelegate::getInstance()->getServerAddress());
|
||||
}
|
||||
|
||||
void MainWindow::showContentSetPage() {
|
||||
const QString CONTENT_SET_HTML_URL = "http://hifi-public.s3.amazonaws.com/content-sets/content-sets.html";
|
||||
|
||||
// show a QWebView for the content set page
|
||||
QWebView* contentSetWebView = new QWebView();
|
||||
contentSetWebView->setUrl(CONTENT_SET_HTML_URL);
|
||||
|
||||
// have the widget delete on close
|
||||
contentSetWebView->setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
// setup the page viewport to be the right size
|
||||
const QSize CONTENT_SET_VIEWPORT_SIZE = QSize(800, 480);
|
||||
contentSetWebView->resize(CONTENT_SET_VIEWPORT_SIZE);
|
||||
|
||||
// have our app delegate handle a click on one of the content sets
|
||||
contentSetWebView->page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks);
|
||||
connect(contentSetWebView->page(), &QWebPage::linkClicked, AppDelegate::getInstance(), &AppDelegate::downloadContentSet);
|
||||
connect(contentSetWebView->page(), &QWebPage::linkClicked, contentSetWebView, &QWebView::close);
|
||||
|
||||
contentSetWebView->show();
|
||||
}
|
||||
|
||||
void MainWindow::handleContentSetDownloadResponse(bool wasSuccessful) {
|
||||
if (wasSuccessful) {
|
||||
QMessageBox::information(this, "New content set",
|
||||
"Your new content set has been downloaded and your assignment-clients have been restarted.");
|
||||
} else {
|
||||
QMessageBox::information(this, "Error", "There was a problem downloading that content set. Please try again!");
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::handleIndexPathChangeResponse(bool wasSuccessful) {
|
||||
if (!wasSuccessful) {
|
||||
QString errorMessage = "The content set was downloaded successfully but there was a problem changing your \
|
||||
domain-server index path.\n\nIf you want users to jump to the new content set when they come to your domain \
|
||||
please try and re-download the content set.";
|
||||
QMessageBox::information(this, "Error", errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::setRequirementsLastChecked(const QString& lastCheckedDateTime) {
|
||||
_requirementsLastCheckedDateTime = lastCheckedDateTime;
|
||||
}
|
||||
|
||||
void MainWindow::setUpdateNotification(const QString& updateNotification) {
|
||||
_updateNotification = updateNotification;
|
||||
}
|
||||
|
||||
void MainWindow::toggleContent(bool isRunning) {
|
||||
_stopServerButton->setVisible(isRunning);
|
||||
_startServerButton->setVisible(!isRunning);
|
||||
_domainServerRunning = isRunning;
|
||||
_serverAddressLabel->setVisible(isRunning);
|
||||
_viewLogsButton->setVisible(isRunning);
|
||||
_settingsButton->setVisible(isRunning);
|
||||
_copyLinkButton->setVisible(isRunning);
|
||||
_contentSetButton->setVisible(isRunning);
|
||||
update();
|
||||
}
|
||||
|
||||
void MainWindow::paintEvent(QPaintEvent *) {
|
||||
QPainter painter(this);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
QFont font("Helvetica");
|
||||
font.insertSubstitutions("Helvetica", QStringList() << "Arial" << "sans-serif");
|
||||
|
||||
int currentY = (_domainServerRunning ? _viewLogsButton->geometry().bottom() : _startServerButton->geometry().bottom())
|
||||
+ REQUIREMENTS_TEXT_TOP_MARGIN;
|
||||
|
||||
if (!_updateNotification.isEmpty()) {
|
||||
font.setBold(true);
|
||||
font.setUnderline(false);
|
||||
if (GlobalData::getInstance().getPlatform() == "linux") {
|
||||
font.setPointSize(14);
|
||||
}
|
||||
painter.setFont(font);
|
||||
painter.setPen(redColor);
|
||||
|
||||
QString updateNotificationString = ">>> " + _updateNotification + " <<<";
|
||||
float fontWidth = QFontMetrics(font).width(updateNotificationString) + GLOBAL_X_PADDING;
|
||||
|
||||
painter.drawText(QRectF(_domainServerRunning ? ((width() - fontWidth) / 2.0f) : GLOBAL_X_PADDING,
|
||||
currentY,
|
||||
fontWidth,
|
||||
QFontMetrics(font).height()),
|
||||
updateNotificationString);
|
||||
}
|
||||
else if (!_requirementsLastCheckedDateTime.isEmpty()) {
|
||||
font.setBold(false);
|
||||
font.setUnderline(false);
|
||||
if (GlobalData::getInstance().getPlatform() == "linux") {
|
||||
font.setPointSize(14);
|
||||
}
|
||||
painter.setFont(font);
|
||||
painter.setPen(darkGrayColor);
|
||||
|
||||
QString requirementsString = "Requirements are up to date as of " + _requirementsLastCheckedDateTime;
|
||||
float fontWidth = QFontMetrics(font).width(requirementsString);
|
||||
|
||||
painter.drawText(QRectF(_domainServerRunning ? GLOBAL_X_PADDING : ((width() - fontWidth)/ 2.0f),
|
||||
currentY,
|
||||
fontWidth,
|
||||
QFontMetrics(font).height()),
|
||||
"Requirements are up to date as of " + _requirementsLastCheckedDateTime);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::toggleDomainServerButton() {
|
||||
AppDelegate::getInstance()->toggleStack(!_domainServerRunning);
|
||||
}
|
||||
|
||||
void MainWindow::openSettings() {
|
||||
QDesktopServices::openUrl(QUrl(GlobalData::getInstance().getDomainServerBaseUrl() + "/settings/"));
|
||||
}
|
||||
|
||||
|
||||
// XXX this code is duplicate of LimitedNodeList::getLocalServerPortFromSharedMemory
|
||||
bool MainWindow::getLocalServerPortFromSharedMemory(const QString key, QSharedMemory*& sharedMem, quint16& localPort) {
|
||||
if (!sharedMem) {
|
||||
sharedMem = new QSharedMemory(key, this);
|
||||
|
||||
if (!sharedMem->attach(QSharedMemory::ReadOnly)) {
|
||||
qWarning() << "Could not attach to shared memory at key" << key;
|
||||
}
|
||||
}
|
||||
|
||||
if (sharedMem->isAttached()) {
|
||||
sharedMem->lock();
|
||||
memcpy(&localPort, sharedMem->data(), sizeof(localPort));
|
||||
sharedMem->unlock();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
//
|
||||
// MainWindow.h
|
||||
// StackManagerQt/src/ui
|
||||
//
|
||||
// Created by Mohammed Nafees on 10/17/14.
|
||||
// Copyright (c) 2014 High Fidelity. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef hifi_MainWindow_h
|
||||
#define hifi_MainWindow_h
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QLabel>
|
||||
#include <QMouseEvent>
|
||||
#include <QPushButton>
|
||||
#include <QScrollArea>
|
||||
#include <QTabWidget>
|
||||
#include <QVBoxLayout>
|
||||
#include <QWidget>
|
||||
#include <QSharedMemory>
|
||||
|
||||
|
||||
#include "SvgButton.h"
|
||||
|
||||
class MainWindow : public QWidget {
|
||||
Q_OBJECT
|
||||
public:
|
||||
MainWindow();
|
||||
|
||||
void setRequirementsLastChecked(const QString& lastCheckedDateTime);
|
||||
void setUpdateNotification(const QString& updateNotification);
|
||||
QTabWidget* getLogsWidget() { return _logsWidget; }
|
||||
bool getLocalServerPortFromSharedMemory(const QString key, QSharedMemory*& sharedMem, quint16& localPort);
|
||||
|
||||
protected:
|
||||
virtual void paintEvent(QPaintEvent*);
|
||||
|
||||
private slots:
|
||||
void toggleDomainServerButton();
|
||||
void openSettings();
|
||||
void updateServerAddressLabel();
|
||||
void updateServerBaseUrl();
|
||||
void handleCopyLinkButton();
|
||||
void showContentSetPage();
|
||||
|
||||
void handleContentSetDownloadResponse(bool wasSuccessful);
|
||||
void handleIndexPathChangeResponse(bool wasSuccessful);
|
||||
private:
|
||||
void toggleContent(bool isRunning);
|
||||
|
||||
bool _domainServerRunning;
|
||||
|
||||
QString _requirementsLastCheckedDateTime;
|
||||
QString _updateNotification;
|
||||
SvgButton* _startServerButton;
|
||||
SvgButton* _stopServerButton;
|
||||
QLabel* _serverAddressLabel;
|
||||
QPushButton* _viewLogsButton;
|
||||
QPushButton* _settingsButton;
|
||||
QPushButton* _copyLinkButton;
|
||||
QPushButton* _contentSetButton;
|
||||
QTabWidget* _logsWidget;
|
||||
|
||||
QSharedMemory* _localHttpPortSharedMem; // memory shared with domain server
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,32 +0,0 @@
|
|||
//
|
||||
// SvgButton.cpp
|
||||
// StackManagerQt/src/ui
|
||||
//
|
||||
// Created by Mohammed Nafees on 10/20/14.
|
||||
// Copyright (c) 2014 High Fidelity. All rights reserved.
|
||||
//
|
||||
|
||||
#include "SvgButton.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QSvgRenderer>
|
||||
#include <QCursor>
|
||||
|
||||
SvgButton::SvgButton(QWidget* parent) :
|
||||
QAbstractButton(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void SvgButton::enterEvent(QEvent*) {
|
||||
setCursor(QCursor(Qt::PointingHandCursor));
|
||||
}
|
||||
|
||||
void SvgButton::setSvgImage(const QString& svg) {
|
||||
_svgImage = svg;
|
||||
}
|
||||
|
||||
void SvgButton::paintEvent(QPaintEvent*) {
|
||||
QPainter painter(this);
|
||||
QSvgRenderer renderer(_svgImage);
|
||||
renderer.render(&painter);
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
//
|
||||
// SvgButton.h
|
||||
// StackManagerQt/src/ui
|
||||
//
|
||||
// Created by Mohammed Nafees on 10/20/14.
|
||||
// Copyright (c) 2014 High Fidelity. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef hifi_SvgButton_h
|
||||
#define hifi_SvgButton_h
|
||||
|
||||
#include <QWidget>
|
||||
#include <QAbstractButton>
|
||||
#include <QResizeEvent>
|
||||
|
||||
class SvgButton : public QAbstractButton
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit SvgButton(QWidget* parent = 0);
|
||||
|
||||
void setSvgImage(const QString& svg);
|
||||
|
||||
protected:
|
||||
virtual void enterEvent(QEvent*);
|
||||
virtual void paintEvent(QPaintEvent*);
|
||||
|
||||
private:
|
||||
QString _svgImage;
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1 +0,0 @@
|
|||
IDI_ICON1 ICON DISCARDABLE "assets/icon.ico"
|