mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2024-11-21 16:27:39 -06:00
Rewrite the runtime as a tray-based server which can launch a web browser. Fixes #3086
This commit is contained in:
parent
25647c16ba
commit
7192a2b675
2
.gitignore
vendored
2
.gitignore
vendored
@ -28,7 +28,7 @@ runtime/.qmake.stash
|
||||
runtime/Makefile
|
||||
runtime/Makefile.Debug
|
||||
runtime/Makefile.Release
|
||||
runtime/moc_BrowserWindow.cpp
|
||||
runtime/moc_TrayIcon.cpp
|
||||
runtime/moc_Server.cpp
|
||||
runtime/pgAdmin4.app/
|
||||
runtime/pgAdmin4.pro.user*
|
||||
|
497
Make-MinGW.bat
497
Make-MinGW.bat
@ -1,497 +0,0 @@
|
||||
@ECHO off
|
||||
SETLOCAL
|
||||
REM
|
||||
REM ****************************************************************
|
||||
SET WD=%CD%
|
||||
SET "PGBUILDPATH=%WD%\win-build"
|
||||
SET CMDOPTION=""
|
||||
IF "%1" == "clean" SET CMDOPTION="VALID"
|
||||
IF "%1" == "x86" SET CMDOPTION="VALID"
|
||||
|
||||
IF NOT %CMDOPTION%=="VALID" ( GOTO USAGE )
|
||||
SET ARCHITECTURE=%1
|
||||
|
||||
IF "%ARCHITECTURE%"=="clean" (
|
||||
GOTO CLEAN_RELEASE
|
||||
GOTO EXIT
|
||||
)
|
||||
|
||||
REM Main Functions
|
||||
|
||||
CALL :SET_PGADMIN4_ENVIRONMENT
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
|
||||
CALL :VALIDATE_ENVIRONMENT
|
||||
|
||||
CALL :CLEAN_RELEASE
|
||||
|
||||
CALL :CREATE_VIRTUAL_ENV
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
|
||||
CALL :CREATE_RUNTIME_ENV
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
|
||||
CALL :CREATE_PYTHON_ENV
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
|
||||
CALL :CLEANUP_ENV
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
|
||||
CALL :CREATE_INSTALLER
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
|
||||
CALL :SIGN_INSTALLER
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
|
||||
CD %WD%
|
||||
GOTO EXIT
|
||||
REM Main function Ends
|
||||
|
||||
:CLEAN_RELEASE
|
||||
ECHO Calling clean target...
|
||||
IF EXIST "%PGBUILDPATH%" rd "%PGBUILDPATH%" /S /Q
|
||||
|
||||
FOR /R "%WD%" %%f in (*.pyc *.pyo) do DEL /q "%%f" > nul
|
||||
IF EXIST "%WD%\pkg\win32\Output" rd "%WD%\pkg\win32\Output" /S /Q
|
||||
IF EXIST DEL /q "%WD%\pkg\win32\installer.iss" > nul
|
||||
CD %WD%
|
||||
GOTO:eof
|
||||
|
||||
:SET_PGADMIN4_ENVIRONMENT
|
||||
IF "%PYTHON_HOME%" == "" SET "PYTHON_HOME=C:\Python27"
|
||||
IF "%PYTHON_DLL%" == "" SET "PYTHON_DLL=C:\Windows\SysWOW64\python27.dll"
|
||||
IF "%QTDIR%" == "" SET "QTDIR=C:\Qt\5.9.1\mingw53_32"
|
||||
IF "%PGDIR%" == "" SET "PGDIR=C:\Program Files (x86)\PostgreSQL\9.6"
|
||||
IF "%INNOTOOL%" == "" SET "INNOTOOL=C:\Program Files (x86)\Inno Setup 5"
|
||||
IF "%YARNDIR%" == "" SET "YARNDIR=C:\Program Files\Yarn"
|
||||
IF "%NODEJSDIR%" == "" SET "NODEJSDIR=C:\Program Files\nodejs"
|
||||
IF "%VCDIR%" == "" SET "VCDIR=C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC"
|
||||
IF "%VCREDIST%" == "" SET "VCREDIST=C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\redist\1033\vcredist_x86.exe"
|
||||
IF "%SIGNTOOL%" == "" SET "SIGNTOOL=C:\Program Files\Microsoft SDKs\Windows\v7.1A\Bin\signtool.exe"
|
||||
SET "VCREDISTNAME=vcredist_x86.exe"
|
||||
|
||||
GOTO:eof
|
||||
|
||||
:VALIDATE_ENVIRONMENT
|
||||
REM SET the variables IF not availalbe in windows environment
|
||||
SET "QMAKE=%QTDIR%\bin\qmake.exe"
|
||||
SET "VIRTUALENV=venv"
|
||||
SET "TARGETINSTALLER=%WD%\dist"
|
||||
SET "VCREDIST=%VCDIR%\redist\1033\%VCREDISTNAME%"
|
||||
|
||||
FOR /F "tokens=3" %%a IN ('findstr /C:"APP_RELEASE =" %WD%\web\config.py') DO SET APP_RELEASE=%%a
|
||||
FOR /F "tokens=3" %%a IN ('findstr /C:"APP_REVISION =" %WD%\web\config.py') DO SET APP_REVISION_VERSION=%%a
|
||||
FOR /F "tokens=3" %%a IN ('findstr /C:"APP_SUFFIX =" %WD%\web\config.py') DO SET APP_SUFFIX_VERSION=%%a
|
||||
REM remove single quote from the string
|
||||
SET APP_SUFFIX_VERSION=%APP_SUFFIX_VERSION:'=%
|
||||
SET APP_NAME=""
|
||||
FOR /F "tokens=2* DELims='" %%a IN ('findstr /C:"APP_NAME =" web\config.py') DO SET APP_NAME=%%a
|
||||
FOR /f "tokens=1 DELims=." %%G IN ('%PYTHON_HOME%/python.exe -c "print('%APP_NAME%'.lower().replace(' ', ''))"') DO SET APP_SHORTNAME=%%G
|
||||
FOR /F "tokens=4,5 delims=. " %%a IN ('%QMAKE% -v ^| findstr /B /C:"Using Qt version "') DO SET QT_VERSION=%%a.%%b
|
||||
|
||||
SET INSTALLERNAME=%APP_SHORTNAME%-%APP_RELEASE%.%APP_REVISION_VERSION%-%APP_SUFFIX_VERSION%-%ARCHITECTURE%.exe
|
||||
IF "%APP_SUFFIX_VERSION%" == "" SET INSTALLERNAME=%APP_SHORTNAME%-%APP_RELEASE%.%APP_REVISION_VERSION%-%ARCHITECTURE%.exe
|
||||
|
||||
SET PGADMIN4_VERSION=v%APP_RELEASE%
|
||||
SET PGADMIN4_APP_VERSION=%APP_RELEASE%.%APP_REVISION_VERSION%
|
||||
|
||||
ECHO ****************************************************************
|
||||
ECHO S U M M A R Y
|
||||
ECHO ****************************************************************
|
||||
ECHO Target mode = x86
|
||||
ECHO INNOTOOL = %INNOTOOL%
|
||||
ECHO VCDIR = %VCDIR%
|
||||
ECHO VCDIST = %VCREDIST%
|
||||
ECHO SIGNTOOL = %SIGNTOOL%
|
||||
ECHO QTDIR = %QTDIR%
|
||||
ECHO QMAKE = %QMAKE%
|
||||
ECHO QT_VERSION = %QT_VERSION%
|
||||
ECHO YARNDIR = %YARNDIR%
|
||||
ECHO NODEJSDIR = %NODEJSDIR%
|
||||
ECHO BROWSER = QtWebKit
|
||||
ECHO PYTHON_HOME = %PYTHON_HOME%
|
||||
ECHO PYTHON_DLL = %PYTHON_DLL%
|
||||
ECHO PGDIR = %PGDIR%
|
||||
ECHO ****************************************************************
|
||||
|
||||
REM Check IF path SET in enviroments really exist or not ?
|
||||
IF NOT EXIST "%INNOTOOL%" GOTO err_handle_inno
|
||||
IF NOT EXIST "%VCDIR%" GOTO err_handle_visualstudio
|
||||
IF NOT EXIST "%VCREDIST%" GOTO err_handle_visualstudio_dist
|
||||
IF NOT EXIST "%QTDIR%" GOTO err_handle_qt
|
||||
IF NOT EXIST "%QMAKE%" GOTO err_handle_qt
|
||||
IF NOT EXIST "%PYTHON_HOME%" GOTO err_handle_python
|
||||
IF NOT EXIST "%PYTHON_DLL%" GOTO err_handle_python
|
||||
IF NOT EXIST "%PGDIR%" GOTO err_handle_pg
|
||||
IF NOT EXIST "%YARNDIR%" GOTO err_handle_yarn
|
||||
IF NOT EXIST "%NODEJSDIR%" GOTO err_handle_nodejs
|
||||
|
||||
REM get Python version ex. 2.7.1 will get as 27
|
||||
FOR /f "tokens=1 DELims=." %%G IN ('%PYTHON_HOME%/python.exe -c "import sys; print(sys.version.split(' ')[0])"') DO SET PYTHON_MAJOR=%%G
|
||||
FOR /f "tokens=2 DELims=." %%G IN ('%PYTHON_HOME%/python.exe -c "import sys; print(sys.version.split(' ')[0])"') DO SET PYTHON_MINOR=%%G
|
||||
SET "PYTHON_VERSION=%PYTHON_MAJOR%%PYTHON_MINOR%"
|
||||
|
||||
IF NOT EXIST "%PYTHON_HOME%\Scripts\virtualenv.exe" GOTO err_handle_pythonvirtualenv
|
||||
|
||||
SET PATH=%PGDIR%;%PGDIR%\bin;%QTDIR%\..\..\Tools\mingw530_32\bin;%NODEJSDIR%;%YARNDIR%\bin;%PATH%;
|
||||
GOTO:eof
|
||||
|
||||
:CREATE_VIRTUAL_ENV
|
||||
ECHO Creating Virtual Enviroment...
|
||||
IF NOT EXIST "%PGBUILDPATH%" MKDIR "%PGBUILDPATH%"
|
||||
|
||||
CD "%PGBUILDPATH%"
|
||||
"%PYTHON_HOME%\Scripts\virtualenv.exe" "%VIRTUALENV%"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
|
||||
ECHO Activating Virtual Enviroment - %PGBUILDPATH%\%VIRTUALENV%\Scripts\activate...
|
||||
CALL "%PGBUILDPATH%\%VIRTUALENV%\Scripts\activate"
|
||||
SET PATH=%PGDIR%\bin;%PATH%
|
||||
|
||||
ECHO Installing dependencies...
|
||||
pip install -r "%WD%\requirements.txt"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
pip install sphinx
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
ECHO Virtual Environment created successfully.
|
||||
|
||||
ECHO Deactivating Virtual Enviroment - %PGBUILDPATH%\%VIRTUALENV%\Scripts\deactivate...
|
||||
CALL "%PGBUILDPATH%\%VIRTUALENV%\Scripts\deactivate"
|
||||
|
||||
CD %WD%
|
||||
GOTO:eof
|
||||
|
||||
:CREATE_RUNTIME_ENV
|
||||
ECHO Compiling source code...
|
||||
MKDIR "%PGBUILDPATH%\runtime" > nul
|
||||
|
||||
REM --- Processing WEB ---
|
||||
CD "%WD%\web"
|
||||
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
|
||||
ECHO Install Javascript dependencies
|
||||
call yarn install
|
||||
ECHO Bundle all Javascript
|
||||
call yarn run bundle
|
||||
|
||||
XCOPY /S /I /E /H /Y "%WD%\web" "%PGBUILDPATH%\web" > nul
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
|
||||
REM Clean up .pyc, .pyo, pgadmin4.db, config_local.py
|
||||
ECHO Cleaning up unnecessary files...
|
||||
FOR /R "%PGBUILDPATH%\web" %%f in (*.pyc *.pyo) do DEL /q "%%f"
|
||||
FOR /R "%PGBUILDPATH%\web" %%f in (tests feature_tests __pycache__ node_modules) do RD /Q /S "%%f"
|
||||
RD /Q /S "%PGBUILDPATH%\web\regression"
|
||||
RD /Q /S "%PGBUILDPATH%\web\tools"
|
||||
DEL /q "%PGBUILDPATH%\web\pgadmin4.db"
|
||||
DEL /q "%PGBUILDPATH%\web\config_local.py"
|
||||
|
||||
ECHO Creating config_distro.py
|
||||
ECHO SERVER_MODE = False > "%PGBUILDPATH%\web\config_distro.py"
|
||||
ECHO HELP_PATH = '../../../docs/en_US/html/' >> "%PGBUILDPATH%\web\config_distro.py"
|
||||
ECHO DEFAULT_BINARY_PATHS = { >> "%PGBUILDPATH%\web\config_distro.py"
|
||||
ECHO 'pg': '$DIR/../runtime', >> "%PGBUILDPATH%\web\config_distro.py"
|
||||
ECHO 'ppas': '' >> "%PGBUILDPATH%\web\config_distro.py"
|
||||
ECHO } >> "%PGBUILDPATH%\web\config_distro.py"
|
||||
|
||||
ECHO Activating Virtual Enviroment - %PGBUILDPATH%\%VIRTUALENV%\Scripts\activate...
|
||||
CALL "%PGBUILDPATH%\%VIRTUALENV%\Scripts\activate"
|
||||
|
||||
ECHO Building docs...
|
||||
MKDIR "%PGBUILDPATH%\docs\en_US\html"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
|
||||
CD "%WD%\docs\en_US"
|
||||
"%PGBUILDPATH%\%VIRTUALENV%\Scripts\python.exe" build_code_snippet.py
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
|
||||
"%PGBUILDPATH%\%VIRTUALENV%\Scripts\sphinx-build.exe" "%WD%\docs\en_US" "%PGBUILDPATH%\docs\en_US\html"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
|
||||
ECHO Removing Sphinx
|
||||
pip uninstall -y sphinx Pygments alabaster colorama docutils imagesize requests snowballstemmer
|
||||
|
||||
ECHO Fixing backports.csv - adding missing __init__.py
|
||||
type nul >> "%PGBUILDPATH%\%VIRTUALENV%\Lib\site-packages\backports\__init__.py"
|
||||
|
||||
ECHO Assembling runtime environment...
|
||||
CD "%WD%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
|
||||
CALL "%QMAKE%" "DEFINES+=PGADMIN4_USE_WEBKIT"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
|
||||
CALL mingw32-make.exe clean
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
|
||||
CALL mingw32-make.exe
|
||||
IF ERRORLEVEL 1 GOTO ERR_HANDLER
|
||||
|
||||
REM Copy binary to Release Folder
|
||||
copy "%WD%\runtime\release\pgAdmin4.exe" "%PGBUILDPATH%\runtime"
|
||||
IF ERRORLEVEL 1 GOTO ERR_HANDLER
|
||||
|
||||
REM Copy QT dependences
|
||||
copy "%QTDIR%\bin\Qt5Core.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\Qt5Sql.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\Qt5Gui.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\Qt5Qml.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\Qt5OpenGL.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\Qt5Quick.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\Qt5Sensors.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\Qt5Widgets.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\Qt5Network.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\Qt5Multimedia.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\Qt5WebChannel.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\Qt5Positioning.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\Qt5PrintSupport.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\Qt5MultimediaWidgets.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
|
||||
IF %QT_VERSION% GEQ 5.9 (
|
||||
copy "%QTDIR%\bin\Qt5WebKit.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\Qt5WebKitWidgets.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
) ELSE (
|
||||
copy "%QTDIR%\bin\libQt5WebKit.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\libQt5WebKitWidgets.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
)
|
||||
|
||||
copy "%QTDIR%\bin\icudt57.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\icuin57.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\icuuc57.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\libgcc_s_dw2-1.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\libstdc++-6.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\libwinpthread-1.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\libxml2-2.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\libxslt-1.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
MKDIR "%PGBUILDPATH%\runtime\platforms"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\plugins\platforms\qwindows.dll" "%PGBUILDPATH%\runtime\platforms" > nul
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
|
||||
ECHO [Paths] > "%PGBUILDPATH%\runtime\qt.conf"
|
||||
ECHO Plugins=plugins >> "%PGBUILDPATH%\runtime\qt.conf"
|
||||
|
||||
copy "%PGDIR%\bin\libpq.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%PGDIR%\bin\ssleay32.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%PGDIR%\bin\libeay32.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%PGDIR%\bin\libintl-*.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%PGDIR%\bin\libiconv-*.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%PGDIR%\bin\zlib1.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%PGDIR%\bin\pg_dump.exe" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%PGDIR%\bin\pg_dumpall.exe" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%PGDIR%\bin\pg_restore.exe" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%PGDIR%\bin\psql.exe" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
|
||||
MKDIR "%PGBUILDPATH%\installer"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%VCREDIST%" "%PGBUILDPATH%\installer" > nul
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
|
||||
ECHO Runtime built successfully.
|
||||
|
||||
CD %WD%
|
||||
GOTO:eof
|
||||
|
||||
:CREATE_PYTHON_ENV
|
||||
copy %PYTHON_DLL% "%PGBUILDPATH%\runtime" > nul
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
|
||||
REM Copy Python interpretor as it's needed to run background processes
|
||||
copy %PYTHON_HOME%\python.exe "%PGBUILDPATH%\runtime" > nul
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy %PYTHON_HOME%\pythonw.exe "%PGBUILDPATH%\runtime" > nul
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
|
||||
XCOPY /S /I /E /H /Y "%PYTHON_HOME%\DLLs" "%PGBUILDPATH%\%VIRTUALENV%\DLLs" > nul
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
XCOPY /S /I /E /H /Y "%PYTHON_HOME%\Lib" "%PGBUILDPATH%\%VIRTUALENV%\Lib" > nul
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
|
||||
ECHO Cleaning up unnecessary files...
|
||||
FOR /R "%PGBUILDPATH%\%VIRTUALENV%" %%f in (*.pyc *.pyo) do DEL /q "%%f"
|
||||
FOR /R "%PGBUILDPATH%\%VIRTUALENV%\Lib" %%f in (test tests) do RD /Q /S "%%f"
|
||||
RD /Q /S "%PGBUILDPATH%\%VIRTUALENV%\tcl"
|
||||
|
||||
CD %WD%
|
||||
GOTO:eof
|
||||
|
||||
:CREATE_INSTALLER
|
||||
ECHO Preparing for creation of windows installer...
|
||||
IF NOT EXIST "%TARGETINSTALLER%" MKDIR "%TARGETINSTALLER%"
|
||||
|
||||
copy "%WD%\pkg\win32\Resources\pgAdmin4.ico" "%PGBUILDPATH%"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
|
||||
CD "%WD%"
|
||||
CD pkg
|
||||
CD win32
|
||||
|
||||
"%PYTHON_HOME%\python" "%WD%\pkg\win32\replace.py" "-i" "%WD%\pkg\win32\installer.iss.in" "-o" "%WD%\pkg\win32\installer.iss.in_stage1" "-s" MYAPP_NAME -r """%APP_NAME%"""
|
||||
"%PYTHON_HOME%\python" "%WD%\pkg\win32\replace.py" "-i" "%WD%\pkg\win32\installer.iss.in_stage1" "-o" "%WD%\pkg\win32\installer.iss.in_stage2" "-s" MYAPP_FULLVERSION -r """%PGADMIN4_APP_VERSION%"""
|
||||
"%PYTHON_HOME%\python" "%WD%\pkg\win32\replace.py" "-i" "%WD%\pkg\win32\installer.iss.in_stage2" "-o" "%WD%\pkg\win32\installer.iss.in_stage3" "-s" MYAPP_VERSION -r """%PGADMIN4_VERSION%"""
|
||||
|
||||
set ARCMODE=
|
||||
IF "%ARCHITECTURE%"=="amd64" (
|
||||
set ARCMODE="x64"
|
||||
)
|
||||
"%PYTHON_HOME%\python" "%WD%\pkg\win32\replace.py" "-i" "%WD%\pkg\win32\installer.iss.in_stage3" "-o" "%WD%\pkg\win32\installer.iss.in_stage4" "-s" MYAPP_ARCHITECTURESMODE -r """%ARCMODE%"""
|
||||
"%PYTHON_HOME%\python" "%WD%\pkg\win32\replace.py" "-i" "%WD%\pkg\win32\installer.iss.in_stage4" "-o" "%WD%\pkg\win32\installer.iss" "-s" MYAPP_VCDIST -r """%VCREDISTNAME%"""
|
||||
|
||||
|
||||
DEL /s "%WD%\pkg\win32\installer.iss.in_stage*" > nul
|
||||
ECHO Creating windows installer... using INNO tool
|
||||
|
||||
CALL "%INNOTOOL%\ISCC.exe" /q "%WD%\pkg\win32\installer.iss"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
|
||||
MOVE "%WD%\pkg\win32\Output\Setup.exe" "%TARGETINSTALLER%\%INSTALLERNAME%"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
|
||||
ECHO "Location - %TARGETINSTALLER%\%INSTALLERNAME%"
|
||||
ECHO Installer generated successfully.
|
||||
|
||||
CD %WD%
|
||||
GOTO:eof
|
||||
|
||||
:SIGN_INSTALLER
|
||||
ECHO Attempting to sign the installer...
|
||||
"%SIGNTOOL%" sign /t http://timestamp.verisign.com/scripts/timstamp.dll "%TARGETINSTALLER%\%INSTALLERNAME%"
|
||||
IF %ERRORLEVEL% NEQ 0 (
|
||||
ECHO
|
||||
ECHO ************************************************************
|
||||
ECHO * Failed to sign the installer
|
||||
ECHO ************************************************************
|
||||
PAUSE
|
||||
)
|
||||
|
||||
CD %WD%
|
||||
GOTO:eof
|
||||
|
||||
:CLEANUP_ENV
|
||||
ECHO Cleaning up private environment...
|
||||
rd "%PGBUILDPATH%\%VIRTUALENV%\Include" /S /Q
|
||||
DEL /s "%PGBUILDPATH%\%VIRTUALENV%\pip-selfcheck.json"
|
||||
|
||||
ECHO Cleaned up private environment successfully.
|
||||
CD %WD%
|
||||
GOTO:eof
|
||||
|
||||
:err_handle_inno
|
||||
ECHO %INNOTOOL% does not exist
|
||||
ECHO Please Install Innotool and SET INNOTOOL enviroment Variable.
|
||||
ECHO SET "INNOTOOL=<PATH>"
|
||||
exit /B 1
|
||||
GOTO EXIT
|
||||
|
||||
:err_handle_visualstudio
|
||||
ECHO %VCDIR% does not exist
|
||||
ECHO Please Install Microsoft Visual studio and SET the VCDIR enviroment Variable.
|
||||
ECHO SET "VCDIR=<PATH>"
|
||||
exit /B 1
|
||||
GOTO EXIT
|
||||
|
||||
:err_handle_visualstudio_dist
|
||||
ECHO %VCREDIST% does not exist
|
||||
ECHO Please Install Microsoft Visual studio and SET the VCDIST enviroment Variable.
|
||||
ECHO SET "VCDIST=<PATH>"
|
||||
exit /B 1
|
||||
GOTO EXIT
|
||||
|
||||
|
||||
:err_handle_python
|
||||
ECHO %PYTHON_HOME% does not exist, or
|
||||
ECHO PYTHON_VERSION is not SET, or
|
||||
ECHO %PYTHON_DLL% does not exist.
|
||||
ECHO Please install Python and SET the PYTHON_HOME enviroment Variable.
|
||||
ECHO SET "PYTHON_VERSION=<VERSION NUMBER>"
|
||||
ECHO SET "PYTHON_HOME=<PATH>"
|
||||
ECHO SET "PYTHON_DLL=<PATH>"
|
||||
exit /B 1
|
||||
GOTO EXIT
|
||||
|
||||
:err_handle_qt
|
||||
ECHO %QTDIR% does not exist.
|
||||
ECHO Please Install QT SDK and SET the QTDIR enviroment variable.
|
||||
ECHO SET "QTDIR=<PATH>"
|
||||
exit /B 1
|
||||
GOTO EXIT
|
||||
|
||||
:err_handle_yarn
|
||||
ECHO %YARNDIR% does not exist.
|
||||
ECHO Please Install YARN and SET the YARNDIR enviroment variable.
|
||||
ECHO SET "YARNDIR=<YARN PATH>"
|
||||
exit /B 1
|
||||
GOTO EXIT
|
||||
|
||||
:err_handle_nodejs
|
||||
ECHO %NODEJSDIR% does not exist.
|
||||
ECHO Please Install NodeJs and SET the NODEJSDIR enviroment variable.
|
||||
ECHO SET "NODEJSDIR=<NODEJS PATH>"
|
||||
exit /B 1
|
||||
GOTO EXIT
|
||||
|
||||
:err_handle_pg
|
||||
ECHO %PGDIR% does not exist.
|
||||
ECHO Please Install Postgres and SET enviroment Variable
|
||||
ECHO SET "PGDIR=<PATH>"
|
||||
exit /B 1
|
||||
GOTO EXIT
|
||||
|
||||
:err_handle_pythonvirtualenv
|
||||
ECHO Python virtualenv is missing @ location - %PYTHON_HOME%\Scripts\virtualenv.exe
|
||||
exit /B 1
|
||||
GOTO EXIT
|
||||
|
||||
:ERR_HANDLER
|
||||
ECHO.
|
||||
ECHO Aborting build!
|
||||
CD %WD%
|
||||
exit /B 1
|
||||
GOTO EXIT
|
||||
|
||||
:USAGE
|
||||
ECHO Invalid command line options....
|
||||
ECHO Usage: "Make.bat <x86 | clean>"
|
||||
ECHO.
|
||||
exit /B 1
|
||||
GOTO EXIT
|
||||
|
||||
:EXIT
|
||||
|
241
Make.bat
241
Make.bat
@ -7,7 +7,6 @@ SET "PGBUILDPATH=%WD%\win-build"
|
||||
SET CMDOPTION=""
|
||||
IF "%1" == "clean" SET CMDOPTION="VALID"
|
||||
IF "%1" == "x86" SET CMDOPTION="VALID"
|
||||
IF "%1" == "amd64" SET CMDOPTION="VALID"
|
||||
|
||||
IF NOT %CMDOPTION%=="VALID" ( GOTO USAGE )
|
||||
SET ARCHITECTURE=%1
|
||||
@ -59,65 +58,22 @@ REM Main function Ends
|
||||
GOTO:eof
|
||||
|
||||
:SET_PGADMIN4_ENVIRONMENT
|
||||
REM Check os architecture x86 or amd64
|
||||
SET RegQry=HKLM\Hardware\Description\System\CentralProcessor\0
|
||||
REG.exe Query %RegQry% > checkOS.txt
|
||||
Find /i "x86" < CheckOS.txt > StringCheck.txt
|
||||
SET OSTYPE=""
|
||||
IF %ERRORLEVEL% == 0 (
|
||||
SET OSTYPE=x86
|
||||
) else (
|
||||
SET OSTYPE=amd64
|
||||
)
|
||||
DEL CheckOS.txt StringCheck.txt
|
||||
SET OSVALUE=""
|
||||
IF "%OSTYPE%"=="x86" (
|
||||
IF "%ARCHITECTURE%"=="amd64" (
|
||||
ECHO ARCHITECTURE - %ARCHITECTURE% cannot be run on 32 bit machine
|
||||
GOTO EXIT
|
||||
)
|
||||
SET OSVALUE=%OSTYPE%
|
||||
)
|
||||
IF "%PYTHON_HOME%" == "" SET "PYTHON_HOME=C:\Python27"
|
||||
IF "%PYTHON_DLL%" == "" SET "PYTHON_DLL=C:\Windows\SysWOW64\python27.dll"
|
||||
IF "%QTDIR%" == "" SET "QTDIR=C:\Qt\5.9.1\mingw53_32"
|
||||
IF "%PGDIR%" == "" SET "PGDIR=C:\Program Files (x86)\PostgreSQL\10"
|
||||
IF "%INNOTOOL%" == "" SET "INNOTOOL=C:\Program Files (x86)\Inno Setup 5"
|
||||
IF "%YARNDIR%" == "" SET "YARNDIR=C:\Program Files\Yarn"
|
||||
IF "%NODEJSDIR%" == "" SET "NODEJSDIR=C:\Program Files\nodejs"
|
||||
IF "%VCDIR%" == "" SET "VCDIR=C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC"
|
||||
IF "%VCREDIST%" == "" SET "VCREDIST=C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\redist\1033\vcredist_x86.exe"
|
||||
IF "%SIGNTOOL%" == "" SET "SIGNTOOL=C:\Program Files\Microsoft SDKs\Windows\v7.1A\Bin\signtool.exe"
|
||||
SET "VCREDISTNAME=vcredist_x86.exe"
|
||||
|
||||
REM Check IF its is windows 32 bit machine and selected architecture is x86
|
||||
IF %OSVALUE%=="x86" (
|
||||
IF "%PYTHON_HOME%" == "" SET "PYTHON_HOME=C:\Python27"
|
||||
IF "%PYTHON_DLL%" == "" SET "PYTHON_DLL=C:\Windows\System32\python27.dll"
|
||||
IF "%QTDIR%" == "" SET "QTDIR=C:\Qt\5.7\msvc2013"
|
||||
IF "%PGDIR%" == "" SET "PGDIR=C:\Program Files\PostgreSQL\9.6"
|
||||
IF "%INNOTOOL%" == "" SET "INNOTOOL=C:\Program Files\Inno Setup 5"
|
||||
IF "%VCDIR%" == "" SET "VCDIR=C:\Program Files\Microsoft Visual Studio 12.0\VC"
|
||||
SET "VCREDISTNAME=vcredist_x86.exe"
|
||||
)
|
||||
|
||||
REM Check IF its is windows 64 bit machine and selected architecture is x86 or amd64
|
||||
IF "%ARCHITECTURE%"=="x86" (
|
||||
IF "%PYTHON_HOME%" == "" SET "PYTHON_HOME=C:\Python27"
|
||||
IF "%PYTHON_DLL%" == "" SET "PYTHON_DLL=C:\Windows\SysWOW64\python27.dll"
|
||||
IF "%QTDIR%" == "" SET "QTDIR=C:\Qt\5.7\msvc2013"
|
||||
IF "%PGDIR%" == "" SET "PGDIR=C:\Program Files (x86)\PostgreSQL\9.6"
|
||||
IF "%INNOTOOL%" == "" SET "INNOTOOL=C:\Program Files (x86)\Inno Setup 5"
|
||||
IF "%VCDIR%" == "" SET "VCDIR=C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC"
|
||||
IF "%VCREDIST%" == "" SET "VCREDIST=C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\redist\1033\vcredist_x86.exe"
|
||||
SET "VCREDISTNAME=vcredist_x86.exe"
|
||||
)
|
||||
|
||||
IF "%ARCHITECTURE%"=="amd64" (
|
||||
IF "%PYTHON_HOME%" == "" SET "PYTHON_HOME=C:\Python27-x64"
|
||||
IF "%PYTHON_DLL%" == "" SET "PYTHON_DLL=C:\Windows\System32\python27.dll"
|
||||
IF "%QTDIR%" == "" SET "QTDIR=C:\Qt\5.7\msvc2013"
|
||||
IF "%PGDIR%" == "" SET "PGDIR=C:\Program Files\PostgreSQL\9.6"
|
||||
IF "%INNOTOOL%" == "" SET "INNOTOOL=C:\Program Files\Inno Setup 5"
|
||||
IF "%VCDIR%" == "" SET "VCDIR=C:\Program Files\Microsoft Visual Studio 12.0\VC"
|
||||
IF "%VCREDIST%" == "" SET "VCREDIST=C:\Program Files\Microsoft Visual Studio 12.0\VC\redist\1033\vcredist_x64.exe"
|
||||
SET "VCREDISTNAME=vcredist_x64.exe"
|
||||
)
|
||||
GOTO:eof
|
||||
|
||||
:VALIDATE_ENVIRONMENT
|
||||
REM SET the variables IF not availalbe in windows environment
|
||||
SET "VCVAR=%VCDIR%\vcvarsall.bat"
|
||||
SET "VCNMAKE=%VCDIR%\bin\nmake.exe"
|
||||
REM SET the variables IF not available in windows environment
|
||||
SET "QMAKE=%QTDIR%\bin\qmake.exe"
|
||||
SET "VIRTUALENV=venv"
|
||||
SET "TARGETINSTALLER=%WD%\dist"
|
||||
@ -142,19 +98,16 @@ REM Main function Ends
|
||||
ECHO ****************************************************************
|
||||
ECHO S U M M A R Y
|
||||
ECHO ****************************************************************
|
||||
ECHO Target mode = %ARCHITECTURE%
|
||||
ECHO Target mode = x86
|
||||
ECHO INNOTOOL = %INNOTOOL%
|
||||
ECHO VCDIR = %VCDIR%
|
||||
ECHO VCDIST = %VCREDIST%
|
||||
ECHO NMAKE = %VCNMAKE%
|
||||
ECHO SIGNTOOL = %SIGNTOOL%
|
||||
ECHO QTDIR = %QTDIR%
|
||||
ECHO QMAKE = %QMAKE%
|
||||
ECHO QT_VERSION = %QT_VERSION%
|
||||
IF %QT_VERSION% GEQ 5.5 (
|
||||
ECHO BROWSER = QtWebEngine
|
||||
) ELSE (
|
||||
ECHO BROWSER = QtWebKit
|
||||
)
|
||||
ECHO YARNDIR = %YARNDIR%
|
||||
ECHO NODEJSDIR = %NODEJSDIR%
|
||||
ECHO PYTHON_HOME = %PYTHON_HOME%
|
||||
ECHO PYTHON_DLL = %PYTHON_DLL%
|
||||
ECHO PGDIR = %PGDIR%
|
||||
@ -164,35 +117,13 @@ REM Main function Ends
|
||||
IF NOT EXIST "%INNOTOOL%" GOTO err_handle_inno
|
||||
IF NOT EXIST "%VCDIR%" GOTO err_handle_visualstudio
|
||||
IF NOT EXIST "%VCREDIST%" GOTO err_handle_visualstudio_dist
|
||||
IF NOT EXIST "%VCVAR%" GOTO err_handle_visualstudio
|
||||
IF NOT EXIST "%VCNMAKE%" GOTO err_handle_visualstudio
|
||||
IF NOT EXIST "%QTDIR%" GOTO err_handle_qt
|
||||
IF NOT EXIST "%QMAKE%" GOTO err_handle_qt
|
||||
IF NOT EXIST "%PYTHON_HOME%" GOTO err_handle_python
|
||||
IF NOT EXIST "%PYTHON_DLL%" GOTO err_handle_python
|
||||
IF NOT EXIST "%PGDIR%" GOTO err_handle_pg
|
||||
|
||||
REM Check for QT and VC dependences
|
||||
FOR /L %%G IN (15,1,19) DO "%VCDIR%\bin\cl.exe" /? 2>&1 | findstr /C:"Version %%G" > nul && SET MSVC_MAJOR_VERSION=%%G
|
||||
|
||||
IF %MSVC_MAJOR_VERSION%==19 SET QT_MSVC_PATH=msvc2015
|
||||
IF %MSVC_MAJOR_VERSION%==18 SET QT_MSVC_PATH=msvc2013
|
||||
IF %MSVC_MAJOR_VERSION%==17 SET QT_MSVC_PATH=msvc2012
|
||||
IF %MSVC_MAJOR_VERSION%==16 SET QT_MSVC_PATH=msvc2010
|
||||
IF %MSVC_MAJOR_VERSION%==15 SET QT_MSVC_PATH=msvc2008
|
||||
|
||||
REM on 64 bit machine if x86 is selected and QTDIR is set to 64 bit is should not allow
|
||||
IF "%OSTYPE%"=="amd64" (
|
||||
IF "%ARCHITECTURE%"=="x86" (
|
||||
echo "%QTDIR%" | findstr /C:"_64" > nul && ( GOTO err_handle_qt_compactissue )
|
||||
)
|
||||
)
|
||||
|
||||
IF "%ARCHITECTURE%"=="amd64" (
|
||||
SET QT_MSVC_PATH=%QT_MSVC_PATH%_64
|
||||
)
|
||||
|
||||
IF NOT EXIST "%QTDIR%\..\%QT_MSVC_PATH%" GOTO err_handle_qt_mismatch
|
||||
IF NOT EXIST "%YARNDIR%" GOTO err_handle_yarn
|
||||
IF NOT EXIST "%NODEJSDIR%" GOTO err_handle_nodejs
|
||||
|
||||
REM get Python version ex. 2.7.1 will get as 27
|
||||
FOR /f "tokens=1 DELims=." %%G IN ('%PYTHON_HOME%/python.exe -c "import sys; print(sys.version.split(' ')[0])"') DO SET PYTHON_MAJOR=%%G
|
||||
@ -201,8 +132,7 @@ REM Main function Ends
|
||||
|
||||
IF NOT EXIST "%PYTHON_HOME%\Scripts\virtualenv.exe" GOTO err_handle_pythonvirtualenv
|
||||
|
||||
SET PATH=%PGDIR%;%PGDIR%\bin;%PATH%
|
||||
|
||||
SET PATH=%PGDIR%;%PGDIR%\bin;%QTDIR%\..\..\Tools\mingw530_32\bin;%NODEJSDIR%;%YARNDIR%\bin;%PATH%;
|
||||
GOTO:eof
|
||||
|
||||
:CREATE_VIRTUAL_ENV
|
||||
@ -244,6 +174,9 @@ REM Main function Ends
|
||||
ECHO Bundle all Javascript
|
||||
call yarn run bundle
|
||||
|
||||
REM Remove any cache
|
||||
RD /Q /S "%WD%\web\pgadmin\static\js\generated\.cache"
|
||||
|
||||
XCOPY /S /I /E /H /Y "%WD%\web" "%PGBUILDPATH%\web" > nul
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
|
||||
@ -288,17 +221,15 @@ REM Main function Ends
|
||||
CD "%WD%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
|
||||
CALL "%VCVAR%" %ARCHITECTURE%
|
||||
CALL "%QMAKE%" "DEFINES+=PGADMIN4_USE_WEBKIT"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
|
||||
CALL "%QMAKE%"
|
||||
CALL mingw32-make.exe clean
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
|
||||
CALL "%VCNMAKE%" clean
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
|
||||
CALL "%VCNMAKE%"
|
||||
CALL mingw32-make.exe
|
||||
IF ERRORLEVEL 1 GOTO ERR_HANDLER
|
||||
|
||||
REM Copy binary to Release Folder
|
||||
copy "%WD%\runtime\release\pgAdmin4.exe" "%PGBUILDPATH%\runtime"
|
||||
IF ERRORLEVEL 1 GOTO ERR_HANDLER
|
||||
@ -306,97 +237,24 @@ REM Main function Ends
|
||||
REM Copy QT dependences
|
||||
copy "%QTDIR%\bin\Qt5Core.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\Qt5Sql.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\Qt5Gui.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\Qt5Qml.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\Qt5OpenGL.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\Qt5Quick.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\Qt5Sensors.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\Qt5Widgets.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\Qt5Network.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\Qt5Multimedia.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\Qt5WebChannel.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\Qt5Positioning.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\Qt5PrintSupport.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\Qt5MultimediaWidgets.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
|
||||
REM Install the appropriate browser components. We use QtWebEngine with Qt 5.5+
|
||||
IF %QT_VERSION% GEQ 5.7 (
|
||||
copy "%QTDIR%\bin\Qt5QuickWidgets.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
)
|
||||
|
||||
IF %QT_VERSION% GEQ 5.7 (
|
||||
copy "%QTDIR%\resources\icudtl.dat" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\resources\qtwebengine_resources.pak" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\resources\qtwebengine_devtools_resources.pak" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\resources\qtwebengine_resources_100p.pak" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\resources\qtwebengine_resources_200p.pak" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\Qt5WebEngine.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\Qt5WebEngineCore.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\Qt5WebEngineWidgets.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\QtWebEngineProcess.exe" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\opengl32sw.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
) ELSE (
|
||||
IF %QT_VERSION% GEQ 5.5 (
|
||||
copy "%QTDIR%\bin\icudt54.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\icuin54.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\icuuc54.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\icudtl.dat" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\qtwebengine_resources.pak" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\qtwebengine_resources_100p.pak" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\qtwebengine_resources_200p.pak" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\Qt5WebEngine.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\Qt5WebEngineCore.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\Qt5WebEngineWidgets.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\QtWebEngineProcess.exe" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
) ELSE (
|
||||
copy "%QTDIR%\bin\Qt5WebKit.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\Qt5WebKitWidgets.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
)
|
||||
)
|
||||
|
||||
copy "%QTDIR%\bin\libgcc_s_dw2-1.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\libstdc++-6.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
copy "%QTDIR%\bin\libwinpthread-1.dll" "%PGBUILDPATH%\runtime"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
MKDIR "%PGBUILDPATH%\runtime\platforms"
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
|
||||
copy "%QTDIR%\plugins\platforms\qwindows.dll" "%PGBUILDPATH%\runtime\platforms" > nul
|
||||
IF %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
|
||||
|
||||
ECHO [Paths] > "%PGBUILDPATH%\runtime\qt.conf"
|
||||
ECHO Plugins=plugins >> "%PGBUILDPATH%\runtime\qt.conf"
|
||||
|
||||
@ -494,13 +352,13 @@ REM Main function Ends
|
||||
|
||||
:SIGN_INSTALLER
|
||||
ECHO Attempting to sign the installer...
|
||||
signtool sign /t http://timestamp.verisign.com/scripts/timstamp.dll "%TARGETINSTALLER%\%INSTALLERNAME%"
|
||||
"%SIGNTOOL%" sign /t http://timestamp.verisign.com/scripts/timstamp.dll "%TARGETINSTALLER%\%INSTALLERNAME%"
|
||||
IF %ERRORLEVEL% NEQ 0 (
|
||||
ECHO
|
||||
ECHO ************************************************************
|
||||
ECHO * Failed to sign the installer
|
||||
ECHO ************************************************************
|
||||
SLEEP 5
|
||||
PAUSE
|
||||
)
|
||||
|
||||
CD %WD%
|
||||
@ -523,20 +381,16 @@ REM Main function Ends
|
||||
GOTO EXIT
|
||||
|
||||
:err_handle_visualstudio
|
||||
ECHO %VCDIR% does not exist, or
|
||||
ECHO %VCVAR% does not exist, or
|
||||
ECHO %VCNMAKE% does not exist.
|
||||
ECHO %VCDIR% does not exist
|
||||
ECHO Please Install Microsoft Visual studio and SET the VCDIR enviroment Variable.
|
||||
ECHO SET "VCDIR%=<PATH>"
|
||||
ECHO SET "VCVAR%=<PATH>"
|
||||
ECHO SET "VCNMAKE%=<PATH>"
|
||||
ECHO SET "VCDIR=<PATH>"
|
||||
exit /B 1
|
||||
GOTO EXIT
|
||||
|
||||
:err_handle_visualstudio_dist
|
||||
ECHO %VCREDIST% does not exist
|
||||
ECHO Please Install Microsoft Visual studio and SET the VCDIST enviroment Variable.
|
||||
ECHO SET "VCDIST%=<PATH>"
|
||||
ECHO SET "VCDIST=<PATH>"
|
||||
exit /B 1
|
||||
GOTO EXIT
|
||||
|
||||
@ -559,18 +413,17 @@ REM Main function Ends
|
||||
exit /B 1
|
||||
GOTO EXIT
|
||||
|
||||
:err_handle_qt_mismatch
|
||||
ECHO %QTDIR%\..\%QT_MSVC_PATH%" does not match with your current Visual Studio, version %QT_MSVC_PATH%
|
||||
ECHO Your current QT installation willraise a linking error with an MSVC version mismatch.
|
||||
ECHO Please use a valid QT installation with a folder %QT_MSVC_PATH%. You can use the Qt Maintenance
|
||||
ECHO Tool to add or remove compiler kits.
|
||||
:err_handle_yarn
|
||||
ECHO %YARNDIR% does not exist.
|
||||
ECHO Please Install YARN and SET the YARNDIR enviroment variable.
|
||||
ECHO SET "YARNDIR=<YARN PATH>"
|
||||
exit /B 1
|
||||
GOTO EXIT
|
||||
|
||||
:err_handle_qt_compactissue
|
||||
ECHO %QTDIR%" does support the current architecture selected %ARCHITECTURE%
|
||||
ECHO Please use a valid QT installation with a folder %QT_MSVC_PATH%. You can use the Qt Maintenance
|
||||
ECHO Tool to add or remove compiler kits.
|
||||
:err_handle_nodejs
|
||||
ECHO %NODEJSDIR% does not exist.
|
||||
ECHO Please Install NodeJs and SET the NODEJSDIR enviroment variable.
|
||||
ECHO SET "NODEJSDIR=<NODEJS PATH>"
|
||||
exit /B 1
|
||||
GOTO EXIT
|
||||
|
||||
@ -595,7 +448,7 @@ REM Main function Ends
|
||||
|
||||
:USAGE
|
||||
ECHO Invalid command line options....
|
||||
ECHO Usage: "Make.bat <x86 | amd64 | clean>"
|
||||
ECHO Usage: "Make.bat <x86 | clean>"
|
||||
ECHO.
|
||||
exit /B 1
|
||||
GOTO EXIT
|
||||
|
3
Makefile
3
Makefile
@ -19,9 +19,6 @@ all: docs pip src
|
||||
appbundle: docs
|
||||
./pkg/mac/build.sh
|
||||
|
||||
appbundle-webkit: docs
|
||||
PGADMIN4_USE_WEBKIT=1 ./pkg/mac/build.sh
|
||||
|
||||
install-node:
|
||||
cd web && yarn install
|
||||
|
||||
|
18
README
18
README
@ -18,18 +18,16 @@ utilised.
|
||||
Although developed using web technologies, pgAdmin 4 can be deployed either on
|
||||
a web server using a browser, or standalone on a workstation. The runtime/
|
||||
subdirectory contains a QT based runtime application intended to allow this -
|
||||
it is essentially a browser and Python interpreter in one package which is
|
||||
capable of hosting the Python application and presenting it to the user as a
|
||||
desktop application.
|
||||
it is essentially a Python application server that runs in the system tray
|
||||
and allows the user to connect to the application using their web browser.
|
||||
|
||||
Building the Runtime
|
||||
--------------------
|
||||
|
||||
To build the runtime, the following packages must be installed:
|
||||
|
||||
- QT 4.6 or above, up to 5.5 (older versions may work, but haven't been tested,
|
||||
newer versions are not yet supported as Qt Webkit has been deprecated).
|
||||
- Python 2.6, 2.7 or 3.3+
|
||||
- QT 4.6 or above
|
||||
- Python 2.6, 2.7 or 3.3+ (2.7 only on Windows)
|
||||
|
||||
Assuming both qmake and python-config are in the path:
|
||||
|
||||
@ -230,8 +228,8 @@ a number of known locations for the pgAdmin4.py file needed to run pgAdmin
|
||||
an alternate path if needed.
|
||||
|
||||
If either a working environment or pgAdmin4.py cannot be found at startup, the
|
||||
runtime will prompt for the locations. Alternatively, you can use Alt+Shift+P
|
||||
to open the path configuration dialogue.
|
||||
runtime will prompt for the locations. Alternatively, you can click the try
|
||||
icon and select the Configuration option to open the configuration dialogue.
|
||||
|
||||
On a Linux/Mac system, the Python Path will typically consist of a single path
|
||||
to the virtual environment's site-packages directory, e.g.
|
||||
@ -308,11 +306,11 @@ Qt 5.5.1, Python 2.7 and Visual Studio 2013. The examples below are for a
|
||||
similar 32 bit system:
|
||||
|
||||
INNOTOOL=C:\Program Files\Inno Setup 5
|
||||
PGDIR=C:\Program Files\PostgreSQL\9.6
|
||||
PGDIR=C:\Program Files\PostgreSQL\10
|
||||
PYTHON_DLL=C:\Windows\System32\Python27.dll
|
||||
PYTHON_HOME=C:\Python27
|
||||
PYTHON_VERSION=27
|
||||
QTDIR=C:\Qt\5.5\msvc2013
|
||||
QTDIR=C:\Qt\5.9\msvc2013
|
||||
VCDIR=C:\Program Files\Microsoft Visual Studio 12.0\VC
|
||||
|
||||
To build the installer:
|
||||
|
@ -5,8 +5,16 @@ Desktop Deployment
|
||||
******************
|
||||
|
||||
pgAdmin may be deployed as a desktop application by configuring the application
|
||||
to run in desktop mode and then utilising the desktop runtime to host and
|
||||
display the program on a supported Windows, Mac OS X or Linux installation.
|
||||
to run in desktop mode and then utilising the desktop runtime to host the
|
||||
program on a supported Windows, Mac OS X or Linux installation.
|
||||
|
||||
The desktop runtime is a system-tray application that when launched, runs the
|
||||
pgAdmin server and launches a web browser to render the user interface. If
|
||||
additional instances of pgAdmin are launched, a new browser tab will be opened
|
||||
and be served by the existing instance of the server in order to minimise system
|
||||
resource utilisation. Clicking the icon in the system tray will present a menu
|
||||
offering options to open a new pgAdmin window, configure the runtime, view the
|
||||
server log and shutdown the server.
|
||||
|
||||
.. note:: Pre-compiled and configured installation packages are available for
|
||||
a number of platforms. These packages should be used by end-users whereever
|
||||
|
@ -28,11 +28,11 @@ Contents:
|
||||
change_user_password
|
||||
|
||||
In a Desktop Deployment, the pgAdmin application is configured to use the
|
||||
desktop runtime environment to host and display the program on a supported
|
||||
platform. Typically, users will install a pre-built package to run pgAdmin
|
||||
in desktop mode, but a manual desktop deployment can be installed and though
|
||||
it is more difficult to setup, it may be useful for developers interested
|
||||
in understanding how pgAdmin works.
|
||||
desktop runtime environment to host the program on a supported platform.
|
||||
Typically, users will install a pre-built package to run pgAdmin in desktop
|
||||
mode, but a manual desktop deployment can be installed and though it is more
|
||||
difficult to setup, it may be useful for developers interested in understanding
|
||||
how pgAdmin works.
|
||||
|
||||
Contents:
|
||||
|
||||
|
@ -6,7 +6,11 @@ pgAdmin 4
|
||||
:align: right
|
||||
:alt: pgAdmin Logo
|
||||
|
||||
Welcome to pgAdmin 4. pgAdmin is the leading Open Source management tool for Postgres, the world's most advanced Open Source database. pgAdmin 4 is designed to meet the needs of both novice and experienced Postgres users alike, providing a powerful graphical interface that simplifies the creation, maintenance and use of database objects.
|
||||
Welcome to pgAdmin 4. pgAdmin is the leading Open Source management tool for
|
||||
Postgres, the world's most advanced Open Source database. pgAdmin 4 is designed
|
||||
to meet the needs of both novice and experienced Postgres users alike, providing
|
||||
a powerful graphical interface that simplifies the creation, maintenance and use
|
||||
of database objects.
|
||||
|
||||
Contents:
|
||||
|
||||
|
@ -2,31 +2,9 @@
|
||||
Keyboard Shortcuts
|
||||
******************
|
||||
|
||||
Keyboard shortcuts are provided in pgAdmin to allow easy access to specific functions.
|
||||
The shortcuts can be configured through File > Preferences dialogue as per the need.
|
||||
|
||||
|
||||
**Desktop Runtime**
|
||||
|
||||
When running in the Desktop Runtime, the following keyboard shortcuts are available:
|
||||
|
||||
+--------------------------+----------------+---------------------------------------+
|
||||
| Shortcut (Windows/Linux) | Shortcut (Mac) | Function |
|
||||
+==========================+================+=======================================+
|
||||
| Alt+Shift+A | Option+Shift+A | Display the runtime's About box |
|
||||
+--------------------------+----------------+---------------------------------------+
|
||||
| Alt+Shift+P | Option+Shift+U | Open the runtime preferences dialogue |
|
||||
+--------------------------+----------------+---------------------------------------+
|
||||
| Alt+Shift+U | Option+Shift+U | Open an arbitrary URL |
|
||||
+--------------------------+----------------+---------------------------------------+
|
||||
| Ctrl+Q | Cmd+Q | Quit |
|
||||
+--------------------------+----------------+---------------------------------------+
|
||||
| Ctrl+Plus | Cmd+Plus | Zoom in |
|
||||
+--------------------------+----------------+---------------------------------------+
|
||||
| Ctrl+Minus | Cmd+Minus | Zoom out |
|
||||
+--------------------------+----------------+---------------------------------------+
|
||||
| Ctrl+0 | Cmd+0 | Reset the zoom level |
|
||||
+--------------------------+----------------+---------------------------------------+
|
||||
Keyboard shortcuts are provided in pgAdmin to allow easy access to specific
|
||||
functions. Alternate shortcuts can be configured through File > Preferences if
|
||||
desired.
|
||||
|
||||
**Main Browser Window**
|
||||
|
||||
|
@ -60,7 +60,9 @@ pushd web
|
||||
yarn install
|
||||
yarn run bundle
|
||||
|
||||
for FILE in `ls -d pgAdmin/static/js/generated/*`
|
||||
rm -rf pgadmin/static/js/generated/.cache
|
||||
|
||||
for FILE in `ls -d pgadmin/static/js/generated/*`
|
||||
do
|
||||
echo Adding $FILE
|
||||
tar cf - $FILE | (cd ../docker-build/web; tar xf -)
|
||||
|
@ -137,11 +137,7 @@ _build_runtime() {
|
||||
_create_python_virtualenv || exit 1
|
||||
cd $SOURCEDIR/runtime
|
||||
make clean
|
||||
if [ "$PGADMIN4_USE_WEBKIT" == "1" ]; then
|
||||
$QMAKE DEFINES+=PGADMIN4_USE_WEBKIT || { echo qmake failed; exit 1; }
|
||||
else
|
||||
$QMAKE || { echo qmake failed; exit 1; }
|
||||
fi
|
||||
$QMAKE || { echo qmake failed; exit 1; }
|
||||
make || { echo make failed; exit 1; }
|
||||
cp -r pgAdmin4.app "$BUILDROOT/$APP_BUNDLE_NAME"
|
||||
}
|
||||
@ -187,7 +183,7 @@ _complete_bundle() {
|
||||
cp -r $SOURCEDIR/web "$BUILDROOT/$APP_BUNDLE_NAME/Contents/Resources/" || exit 1
|
||||
cd "$BUILDROOT/$APP_BUNDLE_NAME/Contents/Resources/web"
|
||||
rm -f pgadmin4.db config_local.*
|
||||
rm -rf karma.conf.js package.json node_modules/ regression/ tools/
|
||||
rm -rf karma.conf.js package.json node_modules/ regression/ tools/ pgadmin/static/js/generated/.cache
|
||||
find . -name "tests" -type d -exec rm -rf "{}" \;
|
||||
find . -name "feature_tests" -type d -exec rm -rf "{}" \;
|
||||
find . -name ".DS_Store" -exec rm -f "{}" \;
|
||||
|
@ -86,13 +86,6 @@ function CompleteSingleApp() {
|
||||
test -d $lib_loc || mkdir -p $lib_loc
|
||||
echo Copying -R $QTDIR/lib/$qtfw_path/$lib_bn to $lib_loc/
|
||||
cp $QTDIR/lib/$qtfw_path/$lib_bn $lib_loc/
|
||||
|
||||
if [ "$lib_bn" = "QtWebEngineCore" ]; then
|
||||
# QtWebEngineCore has some required resources
|
||||
cp -R $QTDIR/lib/$qtfw_path/Resources $lib_loc/
|
||||
cp -R $QTDIR/lib/$qtfw_path/Helpers $lib_loc/
|
||||
ln -s Versions/Current/Helpers "$bundle/Contents/Frameworks/QtWebEngineCore.Framework/Helpers"
|
||||
fi
|
||||
elif echo $lib | grep Python > /dev/null ; then
|
||||
test -d $lib_loc || mkdir -p $lib_loc
|
||||
cp -R "$lib" "$lib_loc/$lib_bn"
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,170 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
// BrowserWindow.h - Declaration of the main window class
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef BROWSERWINDOW_H
|
||||
#define BROWSERWINDOW_H
|
||||
|
||||
#include "pgAdmin4.h"
|
||||
#include "TabWindow.h"
|
||||
#include "WebViewWindow.h"
|
||||
|
||||
#if QT_VERSION >= 0x050000
|
||||
#include <QtWidgets>
|
||||
|
||||
#ifdef PGADMIN4_USE_WEBENGINE
|
||||
#include <QtWebEngineWidgets>
|
||||
#else
|
||||
#include <QtWebKitWidgets>
|
||||
#include <QNetworkCookieJar>
|
||||
#include <QNetworkAccessManager>
|
||||
#endif
|
||||
#else
|
||||
#include <QMainWindow>
|
||||
|
||||
#ifdef PGADMIN4_USE_WEBENGINE
|
||||
#include <QtWebEngineView>
|
||||
#else
|
||||
#include <QWebView>
|
||||
#include <QNetworkCookieJar>
|
||||
#include <QNetworkAccessManager>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef PGADMIN4_USE_WEBENGINE
|
||||
#include <QWebEngineHistory>
|
||||
#else
|
||||
#include <QWebHistory>
|
||||
#endif
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QAction;
|
||||
class QMenu;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
class BrowserWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
BrowserWindow(QString url);
|
||||
~BrowserWindow();
|
||||
|
||||
#ifdef _WIN32
|
||||
void setRegistryMessage(const QString &msg);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent *event);
|
||||
|
||||
protected slots:
|
||||
void urlLinkClicked(const QUrl &);
|
||||
void tabTitleChanged(const QString &);
|
||||
#ifdef __APPLE__
|
||||
#ifdef PGADMIN4_USE_WEBENGINE
|
||||
void onMacCut();
|
||||
void onMacCopy();
|
||||
void onMacPaste();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
private slots:
|
||||
void openUrl();
|
||||
void preferences();
|
||||
void about();
|
||||
void setZoomLevel(int zoomFlag);
|
||||
#ifdef PGADMIN4_USE_WEBENGINE
|
||||
void downloadRequested(QWebEngineDownloadItem *download);
|
||||
#endif
|
||||
void urlLoadingFinished(bool);
|
||||
|
||||
public slots:
|
||||
void download(const QNetworkRequest &request);
|
||||
void unsupportedContent(QNetworkReply * reply);
|
||||
void downloadFinished();
|
||||
void downloadFileProgress(qint64 , qint64 );
|
||||
void progressCanceled();
|
||||
void current_dir_path(const QString &dir);
|
||||
void replyReady();
|
||||
#ifdef PGADMIN4_USE_WEBENGINE
|
||||
void createNewTabWindow(QWebEnginePage * &);
|
||||
void downloadEngineFileProgress(qint64 , qint64 );
|
||||
void downloadEngineFinished();
|
||||
#else
|
||||
void createNewTabWindowKit(QWebPage * &);
|
||||
#endif
|
||||
|
||||
private:
|
||||
QString m_appServerUrl;
|
||||
WebViewWindow *m_mainWebView;
|
||||
|
||||
QShortcut *openUrlShortcut;
|
||||
QShortcut *preferencesShortcut;
|
||||
QShortcut *exitShortcut;
|
||||
QShortcut *aboutShortcut;
|
||||
QShortcut *zoomInShortcut;
|
||||
QShortcut *zoomOutShortcut;
|
||||
QShortcut *zoomResetShortcut;
|
||||
QSignalMapper *signalMapper;
|
||||
|
||||
QGridLayout *m_tabGridLayout;
|
||||
QGridLayout *m_mainGridLayout;
|
||||
DockTabWidget *m_tabWidget;
|
||||
QWidget *m_pgAdminMainTab;
|
||||
|
||||
QWidget *m_addNewTab;
|
||||
QGridLayout *m_addNewGridLayout;
|
||||
WebViewWindow *m_addNewWebView;
|
||||
QHBoxLayout *m_horizontalLayout;
|
||||
|
||||
QWidget *m_widget;
|
||||
QToolButton *m_toolBtnBack;
|
||||
QToolButton *m_toolBtnForward;
|
||||
QToolButton *m_toolBtnClose;
|
||||
|
||||
QString m_downloadFilename;
|
||||
int m_downloadStarted;
|
||||
int m_downloadCancelled;
|
||||
QFile *m_file;
|
||||
QProgressDialog *m_progressDialog;
|
||||
QString m_defaultFilename;
|
||||
QString m_last_open_folder_path;
|
||||
QString m_dir;
|
||||
QNetworkReply *m_reply;
|
||||
bool is_readyReadSignaled;
|
||||
qint64 m_readBytes;
|
||||
|
||||
#ifdef _WIN32
|
||||
QString m_regMessage;
|
||||
#endif
|
||||
|
||||
#ifdef PGADMIN4_USE_WEBENGINE
|
||||
QWebEngineDownloadItem *m_download;
|
||||
#else
|
||||
QNetworkCookieJar *m_cookieJar;
|
||||
QNetworkAccessManager *m_netAccessMan;
|
||||
#endif
|
||||
|
||||
void createActions();
|
||||
void pause(int seconds = 1);
|
||||
int findURLTab(const QUrl &name);
|
||||
void enableDisableToolButtons(WebViewWindow *webViewPtr);
|
||||
#ifdef _WIN32
|
||||
QString getRegistryMessage();
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#ifdef PGADMIN4_USE_WEBENGINE
|
||||
void triggerWebViewWindowEvents(QWebEnginePage::WebAction action);
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // BROWSERWINDOW_H
|
@ -1,37 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Form</class>
|
||||
<widget class="QWidget" name="Form">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>911</width>
|
||||
<height>688</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QWebView" name="webView">
|
||||
<property name="url">
|
||||
<url>
|
||||
<string>about:blank</string>
|
||||
</url>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>QWebView</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>QtWebKitWidgets/QWebView</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
@ -34,6 +34,11 @@ void ConfigWindow::on_buttonBox_rejected()
|
||||
this->close();
|
||||
}
|
||||
|
||||
QString ConfigWindow::getBrowserCommand()
|
||||
{
|
||||
return ui->browserCommandLineEdit->text();
|
||||
}
|
||||
|
||||
QString ConfigWindow::getPythonPath()
|
||||
{
|
||||
return ui->pythonPathLineEdit->text();
|
||||
@ -45,6 +50,11 @@ QString ConfigWindow::getApplicationPath()
|
||||
}
|
||||
|
||||
|
||||
void ConfigWindow::setBrowserCommand(QString command)
|
||||
{
|
||||
ui->browserCommandLineEdit->setText(command);
|
||||
}
|
||||
|
||||
void ConfigWindow::setPythonPath(QString path)
|
||||
{
|
||||
ui->pythonPathLineEdit->setText(path);
|
||||
|
@ -26,9 +26,11 @@ public:
|
||||
explicit ConfigWindow(QWidget *parent = 0);
|
||||
~ConfigWindow();
|
||||
|
||||
QString getBrowserCommand();
|
||||
QString getPythonPath();
|
||||
QString getApplicationPath();
|
||||
|
||||
void setBrowserCommand(QString command);
|
||||
void setPythonPath(QString path);
|
||||
void setApplicationPath(QString path);
|
||||
|
||||
@ -38,7 +40,6 @@ private slots:
|
||||
|
||||
private:
|
||||
Ui::ConfigWindow *ui;
|
||||
QString m_pythonpath, m_applicationpath;
|
||||
};
|
||||
|
||||
#endif // CONFIGWINDOW_H
|
||||
|
@ -6,49 +6,211 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>608</width>
|
||||
<height>118</height>
|
||||
<width>625</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>625</width>
|
||||
<height>300</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetDefaultConstraint</enum>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::ExpandingFieldsGrow</enum>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="pythonPathLabel">
|
||||
<property name="text">
|
||||
<string>Python Path</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="pythonPathLineEdit"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="applicationPathLabel">
|
||||
<property name="text">
|
||||
<string>Application Path</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="applicationPathLineEdit"/>
|
||||
</item>
|
||||
</layout>
|
||||
<widget class="QWidget" name="tab">
|
||||
<attribute name="title">
|
||||
<string>Runtime</string>
|
||||
</attribute>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetMaximumSize</enum>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>589</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Enter a command line to be used to start the browser. If blank, the system default browser will be used. %URL% will be replaced with the appropriate URL when executing the browser.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>10</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetMaximumSize</enum>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="pythonPathLabel_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Browser Command</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="browserCommandLineEdit"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_2">
|
||||
<attribute name="title">
|
||||
<string>Python</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>The options below are intended for expert users only, and may not behave as expected as they modify fixed search paths and are not alternate values. Modify with care!</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>10</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Enter the path to the directory containing pgAdmin.py if desired.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="pythonPathLabel">
|
||||
<property name="text">
|
||||
<string>Python Path</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLineEdit" name="pythonPathLineEdit"/>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Enter a PYTHONPATH if desired. Path elements should be semi-colon delimited.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="applicationPathLabel">
|
||||
<property name="text">
|
||||
<string>Application Path</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="applicationPathLineEdit"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
|
@ -29,5 +29,7 @@
|
||||
<string>org.pgadmin.@EXECUTABLE@</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
<key>LSUIElement</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
88
runtime/LogWindow.cpp
Normal file
88
runtime/LogWindow.cpp
Normal file
@ -0,0 +1,88 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
// LogWindow.cpp - Log viewer window
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "LogWindow.h"
|
||||
#include "ui_LogWindow.h"
|
||||
|
||||
#include <QTime>
|
||||
|
||||
|
||||
LogWindow::LogWindow(QWidget *parent, QString logFile) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::LogWindow),
|
||||
m_logFile(logFile)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
}
|
||||
|
||||
|
||||
LogWindow::~LogWindow()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
|
||||
void LogWindow::reload()
|
||||
{
|
||||
this->ReadLog();
|
||||
}
|
||||
|
||||
|
||||
// Read the logfile
|
||||
void LogWindow::ReadLog()
|
||||
{
|
||||
FILE *log;
|
||||
char *buffer;
|
||||
long len = 0;
|
||||
int i, lines = 0;
|
||||
|
||||
// Look busy!
|
||||
QApplication::setOverrideCursor(Qt::WaitCursor);
|
||||
ui->lblStatus->setText(tr("Loading logfile..."));
|
||||
this->setDisabled(true);
|
||||
QCoreApplication::processEvents( QEventLoop::AllEvents, 100 );
|
||||
|
||||
ui->textLog->clear();
|
||||
|
||||
// Attempt to open the file
|
||||
log = fopen(m_logFile.toUtf8().data(), "r");
|
||||
if (log == NULL)
|
||||
{
|
||||
ui->textLog->setPlainText(QString(tr("The log file (%1) could not be opened.")).arg(m_logFile));
|
||||
this->setDisabled(false);
|
||||
QApplication::restoreOverrideCursor();
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the file size, and read the data
|
||||
fseek(log, 0, SEEK_END);
|
||||
len = ftell(log);
|
||||
rewind(log);
|
||||
buffer = (char *)malloc((len + 1) * sizeof(char));
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (fread(buffer + i, 1, 1, log) > 0)
|
||||
{
|
||||
if (buffer[i] == '\n')
|
||||
lines++;
|
||||
}
|
||||
}
|
||||
|
||||
buffer[i] = 0;
|
||||
|
||||
fclose(log);
|
||||
ui->textLog->setPlainText(buffer);
|
||||
|
||||
// And... relax
|
||||
ui->lblStatus->setText(QString(tr("Loaded logfile (%1 lines).")).arg(lines));
|
||||
this->setDisabled(false);
|
||||
QApplication::restoreOverrideCursor();
|
||||
}
|
40
runtime/LogWindow.h
Normal file
40
runtime/LogWindow.h
Normal file
@ -0,0 +1,40 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
// LogWindow.h - Log viewer window
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef LOGWINDOW_H
|
||||
#define LOGWINDOW_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
namespace Ui {
|
||||
class LogWindow;
|
||||
}
|
||||
|
||||
class LogWindow : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit LogWindow(QWidget *parent = 0, QString logFile = "");
|
||||
~LogWindow();
|
||||
|
||||
void ReadLog();
|
||||
|
||||
private slots:
|
||||
void reload();
|
||||
|
||||
private:
|
||||
Ui::LogWindow *ui;
|
||||
|
||||
QString m_logFile;
|
||||
};
|
||||
|
||||
#endif // LOGWINDOW_H
|
106
runtime/LogWindow.ui
Normal file
106
runtime/LogWindow.ui
Normal file
@ -0,0 +1,106 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>LogWindow</class>
|
||||
<widget class="QDialog" name="LogWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>800</width>
|
||||
<height>500</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QPlainTextEdit" name="textLog">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Courier</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="plainText">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="centerOnScroll">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnReload">
|
||||
<property name="text">
|
||||
<string>Reload</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lblStatus">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnClose">
|
||||
<property name="text">
|
||||
<string>Close</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>btnReload</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>LogWindow</receiver>
|
||||
<slot>reload()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>53</x>
|
||||
<y>471</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>399</x>
|
||||
<y>249</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>btnClose</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>LogWindow</receiver>
|
||||
<slot>close()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>731</x>
|
||||
<y>471</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>399</x>
|
||||
<y>249</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
<slots>
|
||||
<slot>reload()</slot>
|
||||
</slots>
|
||||
</ui>
|
@ -53,11 +53,12 @@ static void add_to_path(QString &python_path, QString path, bool prepend=false)
|
||||
}
|
||||
}
|
||||
|
||||
Server::Server(quint16 port, QString key)
|
||||
Server::Server(quint16 port, QString key, QString logFileName)
|
||||
{
|
||||
// Appserver port etc
|
||||
m_port = port;
|
||||
m_key = key;
|
||||
m_logFileName = logFileName;
|
||||
m_wcAppName = NULL;
|
||||
m_wcPythonHome = NULL;
|
||||
|
||||
@ -206,6 +207,11 @@ Server::Server(quint16 port, QString key)
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
// Redirect stderr
|
||||
PyObject *sys = PyImport_ImportModule("sys");
|
||||
PyObject *err = PyFile_FromString(m_logFileName.toUtf8().data(), (char *)"w");
|
||||
PyObject_SetAttrString(sys, "stderr", err);
|
||||
}
|
||||
|
||||
Server::~Server()
|
||||
@ -315,3 +321,4 @@ void Server::run()
|
||||
|
||||
fclose(cp);
|
||||
}
|
||||
|
||||
|
@ -23,26 +23,29 @@ class Server : public QThread
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Server(quint16 port, QString key);
|
||||
Server(quint16 port, QString key, QString logFileName);
|
||||
~Server();
|
||||
|
||||
bool Init();
|
||||
QString getError() { return m_error; };
|
||||
QString getError() { return m_error; }
|
||||
|
||||
protected:
|
||||
void run();
|
||||
|
||||
private:
|
||||
void setError(QString error) { m_error = error; };
|
||||
void setError(QString error) { m_error = error; }
|
||||
|
||||
QString m_appfile;
|
||||
QString m_error;
|
||||
|
||||
quint16 m_port;
|
||||
QString m_key;
|
||||
QString m_logFileName;
|
||||
|
||||
// Application name in UTF-8 for Python
|
||||
wchar_t *m_wcAppName;
|
||||
QByteArray PGA_APP_NAME_UTF8;
|
||||
|
||||
// PythonHome for Python
|
||||
wchar_t *m_wcPythonHome;
|
||||
QByteArray pythonHome_utf8;
|
||||
|
@ -1,713 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
// TabWindow.cpp - Implementation of the custom tab widget
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "pgAdmin4.h"
|
||||
|
||||
// App headers
|
||||
#include "TabWindow.h"
|
||||
|
||||
#ifdef PGADMIN4_USE_WEBENGINE
|
||||
#include <QWebEngineHistory>
|
||||
#else
|
||||
#include <QWebHistory>
|
||||
#endif
|
||||
|
||||
DockTabWidget *DockTabWidget::mainTabWidget = NULL;
|
||||
|
||||
DockTabWidget::DockTabWidget(QWidget *parent) :
|
||||
QTabWidget(parent)
|
||||
{
|
||||
floatingWidget = NULL;
|
||||
floatingEnabled = false;
|
||||
|
||||
setParent(parent);
|
||||
setTabsClosable(false);
|
||||
setElideMode(Qt::ElideRight);
|
||||
|
||||
// set custom tab bar in tab widget to receive events for docking.
|
||||
setTabBar(new DockTabBar(this));
|
||||
setDocumentMode(true);
|
||||
setAcceptDrops(true);
|
||||
|
||||
// Get the system colours we need
|
||||
QPalette palette = QApplication::palette("QPushButton");
|
||||
QColor activebg = palette.color(QPalette::Button);
|
||||
QColor activefg = palette.color(QPalette::ButtonText);
|
||||
QColor inactivebg = palette.color(QPalette::Dark);
|
||||
QColor inactivefg = palette.color(QPalette::ButtonText);
|
||||
QColor border = palette.color(QPalette::Mid);
|
||||
|
||||
setStyleSheet(
|
||||
"QTabBar::tab { "
|
||||
"background-color: " + inactivebg.name() + "; "
|
||||
"color: " + inactivefg.name() + "; "
|
||||
"border: 1px solid " + border.name() + "; "
|
||||
"padding: 1px 0px; "
|
||||
"margin-left: 0px; "
|
||||
"margin-top: 1px; "
|
||||
#ifndef __APPLE__
|
||||
"width: 15em; "
|
||||
"height: 1.5em; "
|
||||
#endif
|
||||
"} "
|
||||
"QTabBar::tab:selected { "
|
||||
"background-color: " + activebg.name() + "; "
|
||||
"color: " + activefg.name() + "; "
|
||||
"border-bottom-style: none; "
|
||||
"} "
|
||||
"QTabWidget::pane { "
|
||||
"border: 0; "
|
||||
"} "
|
||||
"QTabWidget::tab-bar {"
|
||||
"alignment: left; "
|
||||
"}"
|
||||
);
|
||||
|
||||
if (mainTabWidget == NULL)
|
||||
mainTabWidget = this;
|
||||
}
|
||||
|
||||
DockTabWidget::DockTabWidget(DockTabWidget *other, QWidget *parent) :
|
||||
QTabWidget(parent)
|
||||
{
|
||||
setFloatingBaseWidget(other->floatingBaseWidget());
|
||||
setFloatingEnabled(other->isFloatingEnabled());
|
||||
resize(other->size());
|
||||
|
||||
// set custom tab bar in tab widget to receive events for docking.
|
||||
setTabBar(new DockTabBar(this));
|
||||
setDocumentMode(true);
|
||||
setAcceptDrops(true);
|
||||
|
||||
// Get the system colours we need
|
||||
QPalette palette = QApplication::palette("QPushButton");
|
||||
QColor activebg = palette.color(QPalette::Button);
|
||||
QColor activefg = palette.color(QPalette::ButtonText);
|
||||
QColor inactivebg = palette.color(QPalette::Dark);
|
||||
QColor inactivefg = palette.color(QPalette::ButtonText);
|
||||
QColor border = palette.color(QPalette::Mid);
|
||||
|
||||
setStyleSheet(
|
||||
"QTabBar::tab { "
|
||||
"background-color: " + inactivebg.name() + "; "
|
||||
"color: " + inactivefg.name() + "; "
|
||||
"border: 1px solid " + border.name() + "; "
|
||||
"padding: 1px 0px; "
|
||||
"margin-left: 0px; "
|
||||
"margin-top: 1px; "
|
||||
#ifndef __APPLE__
|
||||
"width: 15em; "
|
||||
"height: 1.5em; "
|
||||
#else
|
||||
"font: 11pt; "
|
||||
"width: 19em; "
|
||||
"height: 1.5em; "
|
||||
#endif
|
||||
"} "
|
||||
"QTabBar::tab:selected { "
|
||||
"background-color: " + activebg.name() + "; "
|
||||
"color: " + activefg.name() + "; "
|
||||
"border-bottom-style: none; "
|
||||
"} "
|
||||
"QTabWidget::pane { "
|
||||
"border: 0; "
|
||||
"} "
|
||||
"QTabWidget::tab-bar {"
|
||||
"alignment: left; "
|
||||
"}"
|
||||
);
|
||||
}
|
||||
|
||||
void DockTabWidget::setFloatingBaseWidget(QWidget *widget)
|
||||
{
|
||||
floatingWidget = widget;
|
||||
if (floatingEnabled && parentWidget() == 0)
|
||||
setParent(widget);
|
||||
}
|
||||
|
||||
void DockTabWidget::setFloatingEnabled(bool x)
|
||||
{
|
||||
floatingEnabled = x;
|
||||
|
||||
if (parent() == 0)
|
||||
{
|
||||
if (x)
|
||||
setWindowFlags(Qt::Tool);
|
||||
else
|
||||
setWindowFlags(Qt::Window);
|
||||
}
|
||||
}
|
||||
|
||||
// Slot: go back to page and enable/disable toolbutton
|
||||
void DockTabWidget::dockGoBackPage()
|
||||
{
|
||||
WebViewWindow *webviewPtr = NULL;
|
||||
|
||||
QWidget *tab = this->widget(this->currentIndex());
|
||||
if (tab != NULL)
|
||||
{
|
||||
QList<QWidget*> widgetList = tab->findChildren<QWidget*>();
|
||||
foreach( QWidget* widgetPtr, widgetList )
|
||||
{
|
||||
if (widgetPtr != NULL)
|
||||
{
|
||||
webviewPtr = dynamic_cast<WebViewWindow*>(widgetPtr);
|
||||
if (webviewPtr != NULL)
|
||||
webviewPtr->back();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Slot: go forward to page and enable/disable toolbutton
|
||||
void DockTabWidget::dockGoForwardPage()
|
||||
{
|
||||
WebViewWindow *webviewPtr = NULL;
|
||||
|
||||
QWidget *tab = this->widget(this->currentIndex());
|
||||
if (tab != NULL)
|
||||
{
|
||||
QList<QWidget*> widgetList = tab->findChildren<QWidget*>();
|
||||
foreach( QWidget* widgetPtr, widgetList )
|
||||
{
|
||||
if (widgetPtr != NULL)
|
||||
{
|
||||
webviewPtr = dynamic_cast<WebViewWindow*>(widgetPtr);
|
||||
if (webviewPtr != NULL)
|
||||
webviewPtr->forward();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Close the tab and remove the memory of the given index tab
|
||||
void DockTabWidget::dockClosetabs()
|
||||
{
|
||||
int totalTabs = 0;
|
||||
QToolButton *btn = NULL;
|
||||
QWidget *tab = NULL;
|
||||
DockTabWidget *l_tab_widget = NULL;
|
||||
|
||||
QObject *senderPtr = QObject::sender();
|
||||
if (senderPtr != NULL)
|
||||
{
|
||||
btn = dynamic_cast<QToolButton*>(senderPtr);
|
||||
if (btn != NULL)
|
||||
{
|
||||
l_tab_widget = dynamic_cast<DockTabWidget*>(btn->parent()->parent());
|
||||
int current_tab_index = 0;
|
||||
|
||||
if (l_tab_widget != NULL)
|
||||
{
|
||||
totalTabs = l_tab_widget->count();
|
||||
for (int loopCount = l_tab_widget->count();loopCount >= 0;loopCount--)
|
||||
{
|
||||
QWidget *l_tab = l_tab_widget->tabBar()->tabButton(loopCount, QTabBar::RightSide);
|
||||
if (l_tab != NULL)
|
||||
{
|
||||
QToolButton *nextBtnPtr = dynamic_cast<QToolButton*>(l_tab);
|
||||
if (nextBtnPtr != NULL && btn != NULL && nextBtnPtr == btn)
|
||||
current_tab_index = loopCount;
|
||||
}
|
||||
}
|
||||
|
||||
QList<QWidget*> widgetList = l_tab_widget->tabBar()->findChildren<QWidget*>();
|
||||
foreach(QWidget* widgetPtr, widgetList)
|
||||
{
|
||||
if (widgetPtr != NULL)
|
||||
{
|
||||
QToolButton *toolBtnPtr = dynamic_cast<QToolButton*>(widgetPtr);
|
||||
if (toolBtnPtr != NULL && toolBtnPtr == btn)
|
||||
{
|
||||
tab = l_tab_widget->widget(current_tab_index);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tab != NULL)
|
||||
tab->deleteLater();
|
||||
|
||||
// If user close the last tab then close the parent tab widget also.
|
||||
if (totalTabs == 1 && l_tab_widget != NULL)
|
||||
l_tab_widget->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
if (tab != NULL)
|
||||
{
|
||||
WebViewWindow *webviewPtr = NULL;
|
||||
|
||||
QList<QWidget*> widgetList = tab->findChildren<QWidget*>();
|
||||
foreach (QWidget* widgetPtr, widgetList)
|
||||
{
|
||||
if (widgetPtr != NULL)
|
||||
{
|
||||
webviewPtr = dynamic_cast<WebViewWindow*>(widgetPtr);
|
||||
if (webviewPtr != NULL)
|
||||
{
|
||||
/* Trigger the action for tab window close so unload event will be called and
|
||||
* resources will be freed properly.
|
||||
* Trigger 'RequestClose' action from Qt5 onwards. Here we have triggerred the action
|
||||
* 'ToggleVideoFullscreen + 1' because we do not know from which webkit
|
||||
* version 'RequestClose' action was added so increment with previous enum value so that
|
||||
* it will be backward webkit version compatible.
|
||||
*/
|
||||
#if QT_VERSION >= 0x050000
|
||||
#ifndef PGADMIN4_USE_WEBENGINE
|
||||
webviewPtr->page()->triggerAction(static_cast<QWebPage::WebAction>(QWebPage::ToggleVideoFullscreen + 1));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if main pgAdmin4 application has only one tab then close tab bar.
|
||||
// Here - check for count 2 because tab will be deleted later.
|
||||
DockTabWidget *mainTab = DockTabWidget::getMainTabWidget();
|
||||
if (mainTab != NULL && l_tab_widget != NULL && l_tab_widget == mainTab && mainTab->count() == 2)
|
||||
mainTab->tabBar()->setVisible(false);
|
||||
}
|
||||
|
||||
// This function is used to set back/forward/close buttons on new tabbar.
|
||||
void DockTabWidget::setButtonsNewTabbar(int index)
|
||||
{
|
||||
QWidget *m_widget = new QWidget();
|
||||
|
||||
QToolButton *m_toolBtnBack = new QToolButton(m_widget);
|
||||
m_toolBtnBack->setFixedHeight(PGA_BTN_SIZE);
|
||||
m_toolBtnBack->setFixedWidth(PGA_BTN_SIZE);
|
||||
m_toolBtnBack->setIcon(QIcon(":/back.png"));
|
||||
m_toolBtnBack->setToolTip(tr("Go back"));
|
||||
|
||||
QToolButton *m_toolBtnForward = new QToolButton(m_widget);
|
||||
m_toolBtnForward->setFixedHeight(PGA_BTN_SIZE);
|
||||
m_toolBtnForward->setFixedWidth(PGA_BTN_SIZE);
|
||||
m_toolBtnForward->setIcon(QIcon(":/forward.png"));
|
||||
m_toolBtnForward->setToolTip(tr("Go forward"));
|
||||
|
||||
QToolButton *m_btnClose = new QToolButton(m_widget);
|
||||
m_btnClose->setFixedHeight(PGA_BTN_SIZE);
|
||||
m_btnClose->setFixedWidth(PGA_BTN_SIZE);
|
||||
m_btnClose->setIcon(QIcon(":/close.png"));
|
||||
m_btnClose->setToolTip(tr("Close tab"));
|
||||
|
||||
QHBoxLayout *m_horizontalLayout = new QHBoxLayout(m_widget);
|
||||
m_horizontalLayout->setContentsMargins(0,1,0,0);
|
||||
m_horizontalLayout->setSizeConstraint(QLayout::SetMinAndMaxSize);
|
||||
m_horizontalLayout->setSpacing(1);
|
||||
m_horizontalLayout->addWidget(m_toolBtnBack);
|
||||
m_horizontalLayout->addWidget(m_toolBtnForward);
|
||||
|
||||
// Register the slot on toolbutton to show the previous history of web
|
||||
connect(m_toolBtnBack, SIGNAL(clicked()), this, SLOT(dockGoBackPage()));
|
||||
|
||||
// Register the slot on toolbutton to show the next history of web
|
||||
connect(m_toolBtnForward, SIGNAL(clicked()), this, SLOT(dockGoForwardPage()));
|
||||
|
||||
// Register the slot on close button , added manually
|
||||
connect(m_btnClose, SIGNAL(clicked()), SLOT(dockClosetabs()));
|
||||
|
||||
// Register the slot on tab index change
|
||||
connect(this, SIGNAL(currentChanged(int )), this,SLOT(tabIndexChanged(int )));
|
||||
|
||||
// Set the back and forward button on tab
|
||||
this->tabBar()->setTabButton(index, QTabBar::LeftSide, m_widget);
|
||||
this->tabBar()->setTabButton(index, QTabBar::RightSide, m_btnClose);
|
||||
|
||||
// find the webview and hide/show button depending on flag set with web view.
|
||||
QWidget *tab = this->widget(index);
|
||||
if (tab != NULL)
|
||||
{
|
||||
QList<QWidget*> widgetList = tab->findChildren<QWidget*>();
|
||||
foreach( QWidget* widgetPtr, widgetList )
|
||||
{
|
||||
if (widgetPtr != NULL)
|
||||
{
|
||||
WebViewWindow *webViewPtr = dynamic_cast<WebViewWindow*>(widgetPtr);
|
||||
if (webViewPtr != NULL)
|
||||
{
|
||||
// If user open any file in query tool then "Query -" name will not appear
|
||||
// but it is still query tool so hide the tool button.
|
||||
if (!webViewPtr->getBackForwardButtonHidden())
|
||||
{
|
||||
m_toolBtnBack->show();
|
||||
m_toolBtnForward->show();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_toolBtnBack->hide();
|
||||
m_toolBtnForward->hide();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This function is used to move to old tab widget to new tab widget.
|
||||
void DockTabWidget::moveTab(DockTabWidget *source, int sourceIndex, DockTabWidget *dest, int destIndex)
|
||||
{
|
||||
if (source == dest && sourceIndex < destIndex)
|
||||
destIndex--;
|
||||
|
||||
QWidget *widget = source->widget(sourceIndex);
|
||||
QString text = source->tabText(sourceIndex);
|
||||
|
||||
source->removeTab(sourceIndex);
|
||||
|
||||
dest->insertTab(destIndex, widget, text);
|
||||
dest->setCurrentIndex(destIndex);
|
||||
}
|
||||
|
||||
// This function is used to decode actual drop event on tab widget.
|
||||
void DockTabWidget::decodeTabDropEvent(QDropEvent *event, DockTabWidget **p_tabWidget, int *p_index)
|
||||
{
|
||||
DockTabBar *tabBar = qobject_cast<DockTabBar *>(event->source());
|
||||
if (!tabBar)
|
||||
{
|
||||
*p_tabWidget = NULL;
|
||||
*p_index = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
QByteArray data = event->mimeData()->data(MIMETYPE_TABINDEX);
|
||||
QDataStream stream(&data, QIODevice::ReadOnly);
|
||||
|
||||
int index;
|
||||
stream >> index;
|
||||
|
||||
*p_tabWidget = tabBar->tabWidget();
|
||||
*p_index = index;
|
||||
}
|
||||
|
||||
// This function is used to check event is actually drop event or not.
|
||||
bool DockTabWidget::eventIsTabDrag(QDragEnterEvent *event)
|
||||
{
|
||||
return event->mimeData()->hasFormat(MIMETYPE_TABINDEX) && qobject_cast<DockTabBar *>(event->source());
|
||||
}
|
||||
|
||||
// This function is used to delete tab widget when there is no tab inside.
|
||||
void DockTabWidget::deleteIfEmpty()
|
||||
{
|
||||
if (count() == 0)
|
||||
{
|
||||
emit willBeAutomaticallyDeleted(this);
|
||||
deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
// This is function is used to create another tab widget from parent window.
|
||||
DockTabWidget *DockTabWidget::createAnotherTabWidget(QWidget *parent)
|
||||
{
|
||||
DockTabWidget *tab_widget = new DockTabWidget(this, parent);
|
||||
tab_widget->tabBar()->setVisible(true);
|
||||
return tab_widget;
|
||||
}
|
||||
|
||||
// Check wether tab is insertable or not.
|
||||
bool DockTabWidget::isInsertable(QWidget *widget)
|
||||
{
|
||||
Q_UNUSED(widget)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Hide the close button of given index displayed on right side of tab
|
||||
void DockTabWidget::enableDisableToolButton(const int &index)
|
||||
{
|
||||
QToolButton *toolBtnPtr = NULL;
|
||||
WebViewWindow *tmpwebviewPtr = NULL;
|
||||
WebViewWindow *webviewPtr = NULL;
|
||||
|
||||
// Enable/disable the toolbutton based on the history
|
||||
QWidget *tab1 = this->widget(index);
|
||||
if (tab1 != NULL)
|
||||
{
|
||||
QList<QWidget*> widgetList = tab1->findChildren<QWidget*>();
|
||||
foreach( QWidget* widgetPtr, widgetList )
|
||||
{
|
||||
if (widgetPtr != NULL)
|
||||
tmpwebviewPtr = dynamic_cast<WebViewWindow*>(widgetPtr);
|
||||
|
||||
if (tmpwebviewPtr != NULL)
|
||||
webviewPtr = tmpwebviewPtr;
|
||||
}
|
||||
}
|
||||
|
||||
QWidget *tab = tabBar()->tabButton(index, QTabBar::LeftSide);
|
||||
if (tab != NULL)
|
||||
{
|
||||
QList<QWidget*> widgetList = tab->findChildren<QWidget*>();
|
||||
foreach( QWidget* widgetPtr, widgetList )
|
||||
{
|
||||
if (widgetPtr != NULL)
|
||||
{
|
||||
toolBtnPtr = dynamic_cast<QToolButton*>(widgetPtr);
|
||||
if (webviewPtr != NULL && toolBtnPtr != NULL)
|
||||
{
|
||||
if (!QString::compare(toolBtnPtr->toolTip(), tr("Go back"), Qt::CaseInsensitive))
|
||||
{
|
||||
if (webviewPtr->page()->history()->canGoBack())
|
||||
toolBtnPtr->setDisabled(false);
|
||||
else
|
||||
toolBtnPtr->setDisabled(true);
|
||||
}
|
||||
|
||||
if (!QString::compare(toolBtnPtr->toolTip(), tr("Go forward"), Qt::CaseInsensitive))
|
||||
{
|
||||
if (webviewPtr->page()->history()->canGoForward())
|
||||
toolBtnPtr->setDisabled(false);
|
||||
else
|
||||
toolBtnPtr->setDisabled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Slot: When the tab index change, hide/show the toolbutton displayed on tab
|
||||
void DockTabWidget::tabIndexChanged(int index)
|
||||
{
|
||||
int tabCount = 0;
|
||||
WebViewWindow *webViewPtr = NULL;
|
||||
|
||||
for (tabCount = 0; tabCount < this->count(); tabCount++)
|
||||
{
|
||||
// if main pgAdmin4 application tab then do nothing.
|
||||
if (!QString::compare(this->tabText(tabCount), tr("pgAdmin 4"), Qt::CaseInsensitive))
|
||||
continue;
|
||||
|
||||
QWidget *tab = this->widget(tabCount);
|
||||
if (tab != NULL)
|
||||
{
|
||||
QList<QWidget*> widgetList = tab->findChildren<QWidget*>();
|
||||
foreach( QWidget* widgetPtr, widgetList )
|
||||
{
|
||||
if (widgetPtr != NULL)
|
||||
{
|
||||
webViewPtr = dynamic_cast<WebViewWindow*>(widgetPtr);
|
||||
if (webViewPtr != NULL)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tabCount != index)
|
||||
this->showHideToolButton(tabCount, 0);
|
||||
else
|
||||
{
|
||||
if (!webViewPtr->getBackForwardButtonHidden())
|
||||
this->showHideToolButton(tabCount, 1);
|
||||
else
|
||||
this->showHideToolButton(tabCount, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// paint the tab text again as index of the tab widget changed.
|
||||
this->tabBar()->update();
|
||||
}
|
||||
|
||||
// Show and Hide the toolbutton once the tab is deselected depending on the option
|
||||
// option 0: Hide the toolButton
|
||||
// option 1: Show the toolButton
|
||||
void DockTabWidget::showHideToolButton(const int &index, const int &option)
|
||||
{
|
||||
QToolButton *toolBtnPtr = NULL;
|
||||
|
||||
QWidget *tab = tabBar()->tabButton(index, QTabBar::LeftSide);
|
||||
if (tab != NULL)
|
||||
{
|
||||
QList<QWidget*> widgetList = tab->findChildren<QWidget*>();
|
||||
foreach( QWidget* widgetPtr, widgetList )
|
||||
{
|
||||
if (widgetPtr != NULL)
|
||||
{
|
||||
toolBtnPtr = dynamic_cast<QToolButton*>(widgetPtr);
|
||||
if (toolBtnPtr != NULL)
|
||||
{
|
||||
if (!option)
|
||||
toolBtnPtr->hide();
|
||||
else
|
||||
toolBtnPtr->show();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set the tab tool tip text
|
||||
void DockTabWidget::setTabToolTipText(const int &index, const QString &toolTipString)
|
||||
{
|
||||
tabBar()->setTabToolTip(index, toolTipString);
|
||||
}
|
||||
|
||||
// Implementation of custom tab bar for docking window.
|
||||
DockTabBar::DockTabBar(DockTabWidget *tabWidget, QWidget *parent) :
|
||||
QTabBar(parent),
|
||||
tab_widget(tabWidget)
|
||||
{
|
||||
isStartingDrag = false;
|
||||
setAcceptDrops(true);
|
||||
}
|
||||
|
||||
// Insert new tab at specified index.
|
||||
int DockTabBar::insertionIndexAt(const QPoint &pos)
|
||||
{
|
||||
int index = count();
|
||||
for (int i = 0; i < count(); ++i)
|
||||
{
|
||||
QRect rect = tabRect(i);
|
||||
QRect rect1(rect.x(), rect.y(), rect.width() / 2, rect.height());
|
||||
QRect rect2(rect.x() + rect1.width(), rect.y(), rect.width() - rect1.width(), rect.height());
|
||||
if (rect1.contains(pos))
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
if (rect2.contains(pos))
|
||||
{
|
||||
index = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
// Mouse press event handler for tab drag.
|
||||
void DockTabBar::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
if (event->button() == Qt::LeftButton)
|
||||
{
|
||||
dragStartPos = event->pos();
|
||||
isStartingDrag = true;
|
||||
}
|
||||
QTabBar::mousePressEvent(event);
|
||||
}
|
||||
|
||||
// Mouse move event handler for tab drag.
|
||||
void DockTabBar::mouseMoveEvent(QMouseEvent *event)
|
||||
{
|
||||
if (!isStartingDrag)
|
||||
return;
|
||||
|
||||
if ((!event->buttons()) && Qt::LeftButton)
|
||||
return;
|
||||
|
||||
if ((event->pos() - dragStartPos).manhattanLength() < QApplication::startDragDistance())
|
||||
return;
|
||||
|
||||
int index = tabAt(event->pos());
|
||||
|
||||
if (index < 0)
|
||||
return;
|
||||
|
||||
// Don't allow to drag the pgAdmin4 main tab.
|
||||
if (!QString::compare(tab_widget->tabText(index), tr("pgAdmin 4"), Qt::CaseInsensitive))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// create data
|
||||
QMimeData *mimeData = new QMimeData;
|
||||
|
||||
QByteArray data;
|
||||
QDataStream stream(&data, QIODevice::WriteOnly);
|
||||
stream << index;
|
||||
|
||||
mimeData->setData(MIMETYPE_TABINDEX, data);
|
||||
|
||||
// create pixmap
|
||||
QRect rect = tabRect(index);
|
||||
QPixmap pixmap(rect.size());
|
||||
|
||||
render(&pixmap, QPoint(), QRegion(rect));
|
||||
|
||||
// exec drag
|
||||
QDrag *drag = new QDrag(this);
|
||||
drag->setMimeData(mimeData);
|
||||
drag->setPixmap(pixmap);
|
||||
QPoint offset = dragStartPos - rect.topLeft();
|
||||
drag->setHotSpot(offset);
|
||||
Qt::DropAction dropAction = drag->exec(Qt::MoveAction | Qt::IgnoreAction);
|
||||
|
||||
if (dropAction != Qt::MoveAction)
|
||||
{
|
||||
DockTabWidget *newTabWidget = tab_widget->createAnotherTabWidget();
|
||||
if (!newTabWidget->isInsertable(tab_widget, index))
|
||||
{
|
||||
newTabWidget->deleteLater();
|
||||
return;
|
||||
}
|
||||
|
||||
DockTabWidget::moveTab(tab_widget, index, newTabWidget, 0);
|
||||
|
||||
newTabWidget->setButtonsNewTabbar(0);
|
||||
newTabWidget->enableDisableToolButton(0);
|
||||
|
||||
QRect newGeometry = newTabWidget->geometry();
|
||||
newGeometry.moveTopLeft(QCursor::pos() - offset);
|
||||
newTabWidget->setGeometry(newGeometry);
|
||||
newTabWidget->show();
|
||||
|
||||
// Check if main pgAdmin4 application has only one tab then close tab bar.
|
||||
// Here - check for count 2 because tab will be deleted later.
|
||||
DockTabWidget *mainTab = DockTabWidget::getMainTabWidget();
|
||||
if (mainTab != NULL && tab_widget != NULL && tab_widget == mainTab && mainTab->count() == 1)
|
||||
mainTab->tabBar()->setVisible(false);
|
||||
}
|
||||
|
||||
tab_widget->deleteIfEmpty();
|
||||
isStartingDrag = false;
|
||||
}
|
||||
|
||||
// Actual tab drag started.
|
||||
void DockTabBar::dragEnterEvent(QDragEnterEvent *event)
|
||||
{
|
||||
if (DockTabWidget::eventIsTabDrag(event))
|
||||
event->acceptProposedAction();
|
||||
}
|
||||
|
||||
// Drag event leave the actual area.
|
||||
void DockTabBar::dragLeaveEvent(QDragLeaveEvent * event)
|
||||
{
|
||||
Q_UNUSED(event)
|
||||
}
|
||||
|
||||
// Drop event handler for tabbar.
|
||||
void DockTabBar::dropEvent(QDropEvent *event)
|
||||
{
|
||||
DockTabWidget *oldTabWidget = NULL;
|
||||
int oldIndex;
|
||||
DockTabWidget::decodeTabDropEvent(event, &oldTabWidget, &oldIndex);
|
||||
|
||||
if (oldTabWidget && tab_widget && tab_widget->isInsertable(oldTabWidget, oldIndex))
|
||||
{
|
||||
|
||||
int newIndex = insertionIndexAt(event->pos());
|
||||
DockTabWidget::moveTab(oldTabWidget, oldIndex, tab_widget, newIndex);
|
||||
|
||||
// create new back/forward/close buttons and register its events.
|
||||
tab_widget->setButtonsNewTabbar(newIndex);
|
||||
tab_widget->enableDisableToolButton(newIndex);
|
||||
|
||||
// Check if main pgAdmin4 application has only one tab then close tab bar.
|
||||
// Here - check for count 2 because tab will be deleted later.
|
||||
DockTabWidget *mainTab = DockTabWidget::getMainTabWidget();
|
||||
if (mainTab != NULL && oldTabWidget != NULL && oldTabWidget == mainTab && mainTab->count() == 1)
|
||||
mainTab->tabBar()->setVisible(false);
|
||||
|
||||
event->acceptProposedAction();
|
||||
}
|
||||
}
|
@ -1,188 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
// TabWindow.h - Declaration of the custom tab widget
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TABWINDOW_H
|
||||
#define TABWINDOW_H
|
||||
|
||||
#include "pgAdmin4.h"
|
||||
#include "WebViewWindow.h"
|
||||
|
||||
// Define button sizes
|
||||
#ifdef _WIN32
|
||||
const int PGA_BTN_SIZE = 18;
|
||||
#else
|
||||
const int PGA_BTN_SIZE = 16;
|
||||
#endif
|
||||
|
||||
#include <QTabBar>
|
||||
#include <QTabWidget>
|
||||
|
||||
#define MIMETYPE_TABINDEX "x-paintfield-tabindex"
|
||||
|
||||
class DockTabBar;
|
||||
|
||||
class DockTabWidget : public QTabWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
friend class DockTabBar;
|
||||
public:
|
||||
|
||||
explicit DockTabWidget(QWidget *parent = 0);
|
||||
|
||||
DockTabWidget(DockTabWidget *other, QWidget *parent = 0);
|
||||
|
||||
// Drop event handlers of parent tab widget.
|
||||
static void moveTab(DockTabWidget *source, int sourceIndex, DockTabWidget *dest, int destIndex);
|
||||
static void decodeTabDropEvent(QDropEvent *event, DockTabWidget **p_tabWidget, int *p_index);
|
||||
static bool eventIsTabDrag(QDragEnterEvent *event);
|
||||
void setButtonsNewTabbar(int index);
|
||||
|
||||
static DockTabWidget *mainTabWidget;
|
||||
static DockTabWidget* getMainTabWidget()
|
||||
{
|
||||
return mainTabWidget;
|
||||
}
|
||||
|
||||
void setFloatingBaseWidget(QWidget *widget);
|
||||
QWidget *floatingBaseWidget()
|
||||
{
|
||||
return floatingWidget;
|
||||
}
|
||||
|
||||
void setFloatingEnabled(bool x);
|
||||
bool isFloatingEnabled() const
|
||||
{
|
||||
return floatingEnabled;
|
||||
}
|
||||
|
||||
virtual bool isInsertable(QWidget *widget);
|
||||
bool isInsertable(DockTabWidget *other, int index)
|
||||
{
|
||||
return isInsertable(other->widget(index));
|
||||
}
|
||||
virtual DockTabWidget *createAnotherTabWidget(QWidget *parent = 0);
|
||||
|
||||
int getButtonIndex(QPushButton *btn);
|
||||
void showHideToolButton(const int &index,const int &option);
|
||||
void enableDisableToolButton(const int &index);
|
||||
void setTabToolTipText(const int &index, const QString &toolTipString);
|
||||
QTabBar *tabBar() const
|
||||
{
|
||||
return QTabWidget::tabBar();
|
||||
}
|
||||
|
||||
signals:
|
||||
void willBeAutomaticallyDeleted(DockTabWidget *widget);
|
||||
|
||||
public slots:
|
||||
void deleteIfEmpty();
|
||||
void dockClosetabs();
|
||||
void dockGoBackPage();
|
||||
void dockGoForwardPage();
|
||||
void tabIndexChanged(int index);
|
||||
|
||||
private:
|
||||
QWidget *floatingWidget;
|
||||
bool floatingEnabled;
|
||||
};
|
||||
|
||||
class DockTabBar : public QTabBar
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
DockTabBar(DockTabWidget *tabWidget, QWidget *parent = 0);
|
||||
// return tab widget of respective tab bar widget.
|
||||
DockTabWidget *tabWidget()
|
||||
{
|
||||
return tab_widget;
|
||||
}
|
||||
|
||||
protected:
|
||||
// re-implemnted mouse event to detect tab drag started or not.
|
||||
void mousePressEvent(QMouseEvent *event);
|
||||
void mouseMoveEvent(QMouseEvent *event);
|
||||
|
||||
// re-implemnted drag-drop event for docking of tabs.
|
||||
void dragEnterEvent(QDragEnterEvent *event);
|
||||
void dropEvent(QDropEvent *event);
|
||||
void dragLeaveEvent(QDragLeaveEvent * event);
|
||||
|
||||
// re-implemented paint event to draw the text on tab bar of tab widget control.
|
||||
void paintEvent(QPaintEvent *event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
bool isToolBtnVisible = false;
|
||||
|
||||
DockTabWidget *l_tab_widget = dynamic_cast<DockTabWidget*>(this->parent());
|
||||
|
||||
if (l_tab_widget != NULL)
|
||||
{
|
||||
int current_index = l_tab_widget->currentIndex();
|
||||
QStylePainter painter(this);
|
||||
for(int i = 0; i < l_tab_widget->count(); ++i)
|
||||
{
|
||||
QString str = l_tab_widget->tabText(i);
|
||||
if (!str.startsWith("pgAdmin 4") && !str.startsWith("Query -") && !str.startsWith("Debugger"))
|
||||
isToolBtnVisible = true;
|
||||
|
||||
QStyleOptionTab option;
|
||||
initStyleOption(&option, i);
|
||||
QString tempText = this->tabText(i);
|
||||
if (tempText.length() > 28)
|
||||
{
|
||||
tempText = tempText.mid(0,27);
|
||||
tempText += QString("...");
|
||||
}
|
||||
|
||||
QRect rect(option.rect);
|
||||
|
||||
// If toolButton is visible then only draw text after tool button pixel area.
|
||||
// If tool button is not visible - draw the text after margin of 10px.
|
||||
if (isToolBtnVisible)
|
||||
{
|
||||
if ((current_index != -1) && i == current_index)
|
||||
{
|
||||
if (str.startsWith("Query -") || str.startsWith("Debugger"))
|
||||
rect.setX(option.rect.x() + 10);
|
||||
else
|
||||
rect.setX(option.rect.x() + 45);
|
||||
}
|
||||
else
|
||||
rect.setX(option.rect.x() + 10);
|
||||
}
|
||||
else
|
||||
rect.setX(option.rect.x() + 10);
|
||||
|
||||
rect.setY(option.rect.y() + 7);
|
||||
|
||||
option.text = QString();
|
||||
|
||||
painter.drawControl(QStyle::CE_TabBarTab, option);
|
||||
painter.drawItemText(rect, 0, palette(), 1, tempText);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
QSize tabSizeHint(int) const
|
||||
{
|
||||
return QSize(250, 26);
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
int insertionIndexAt(const QPoint &pos);
|
||||
DockTabWidget *tab_widget;
|
||||
bool isStartingDrag;
|
||||
QPoint dragStartPos;
|
||||
};
|
||||
|
||||
#endif // TABWINDOW_H
|
244
runtime/TrayIcon.cpp
Normal file
244
runtime/TrayIcon.cpp
Normal file
@ -0,0 +1,244 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
// TrayIcon.cpp - Manages the tray icon
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "pgAdmin4.h"
|
||||
|
||||
// QT headers
|
||||
#include <QMessageBox>
|
||||
|
||||
// App headers
|
||||
#include "ConfigWindow.h"
|
||||
#include "LogWindow.h"
|
||||
#include "TrayIcon.h"
|
||||
|
||||
|
||||
TrayIcon::TrayIcon(QString logFile) :
|
||||
m_logFile(logFile)
|
||||
{
|
||||
m_logWindow = NULL;
|
||||
|
||||
m_trayIcon = NULL;
|
||||
m_trayIconMenu = NULL;
|
||||
|
||||
m_newAction = NULL;
|
||||
m_configAction = NULL;
|
||||
m_logAction = NULL;
|
||||
m_quitAction = NULL;
|
||||
}
|
||||
|
||||
|
||||
TrayIcon::~TrayIcon()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool TrayIcon::Init()
|
||||
{
|
||||
if (! isSystemTrayAvailable())
|
||||
return false;
|
||||
|
||||
createTrayIcon();
|
||||
|
||||
if (m_trayIcon)
|
||||
m_trayIcon->show();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void TrayIcon::setAppServerUrl(QString appServerUrl)
|
||||
{
|
||||
m_appServerUrl = appServerUrl;
|
||||
}
|
||||
|
||||
// Check whether system tray exists
|
||||
bool TrayIcon::isSystemTrayAvailable()
|
||||
{
|
||||
int timeout = 10; // 30 sec * 10 = 5 minutes, thus we timeout after 5 minutes
|
||||
int iteration = 0;
|
||||
bool trayFound = false;
|
||||
|
||||
while (iteration < timeout)
|
||||
{
|
||||
// Check we can find the system tray.
|
||||
if (!QSystemTrayIcon::isSystemTrayAvailable())
|
||||
{
|
||||
// Wait for 30 seconds.
|
||||
wait(3000);
|
||||
trayFound = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
trayFound = true;
|
||||
break;
|
||||
}
|
||||
iteration++;
|
||||
}
|
||||
|
||||
return trayFound;
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Make application wait for msec milliseconds
|
||||
void TrayIcon::wait(int msec)
|
||||
{
|
||||
QMutex mutex;
|
||||
QWaitCondition wc;
|
||||
mutex.lock();
|
||||
wc.wait(&mutex, msec);
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
|
||||
// Create the tray icon
|
||||
void TrayIcon::createTrayIcon()
|
||||
{
|
||||
createActions();
|
||||
|
||||
if (m_trayIconMenu)
|
||||
{
|
||||
delete m_trayIconMenu;
|
||||
m_trayIconMenu = NULL;
|
||||
}
|
||||
|
||||
m_trayIconMenu = new QMenu(this);
|
||||
m_trayIconMenu->addAction(m_newAction);
|
||||
m_trayIconMenu->addSeparator();
|
||||
m_trayIconMenu->addAction(m_configAction);
|
||||
m_trayIconMenu->addAction(m_logAction);
|
||||
m_trayIconMenu->addSeparator();
|
||||
m_trayIconMenu->addAction(m_quitAction);
|
||||
|
||||
if (!m_trayIcon)
|
||||
m_trayIcon = new QSystemTrayIcon(this);
|
||||
m_trayIcon->setContextMenu(m_trayIconMenu);
|
||||
|
||||
// Setup the icon itself. For convenience, we'll also use it for the dialogue.
|
||||
#ifdef Q_OS_MAC
|
||||
QIcon icon(":pgAdmin4-mac.png");
|
||||
#else
|
||||
QIcon icon(":pgAdmin4.png");
|
||||
#endif
|
||||
|
||||
m_trayIcon->setIcon(icon);
|
||||
setWindowIcon(icon);
|
||||
}
|
||||
|
||||
|
||||
// Create the menu actions
|
||||
void TrayIcon::createActions()
|
||||
{
|
||||
m_newAction = new QAction(QString(tr("&New %1 window...")).arg(PGA_APP_NAME), this);
|
||||
connect(m_newAction, SIGNAL(triggered()), this, SLOT(onNew()));
|
||||
|
||||
m_configAction = new QAction(tr("&Configure..."), this);
|
||||
connect(m_configAction, SIGNAL(triggered()), this, SLOT(onConfig()));
|
||||
|
||||
m_logAction = new QAction(tr("&View log..."), this);
|
||||
connect(m_logAction, SIGNAL(triggered()), this, SLOT(onLog()));
|
||||
|
||||
m_quitAction = new QAction(tr("&Shutdown server"), this);
|
||||
connect(m_quitAction, SIGNAL(triggered()), this, SLOT(onQuit()));
|
||||
}
|
||||
|
||||
|
||||
// Create a new application browser window on user request
|
||||
void TrayIcon::onNew()
|
||||
{
|
||||
QSettings settings;
|
||||
QString cmd = settings.value("BrowserCommand").toString();
|
||||
|
||||
if (!cmd.isEmpty())
|
||||
{
|
||||
cmd.replace("%URL%", m_appServerUrl);
|
||||
QProcess::startDetached(cmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!QDesktopServices::openUrl(m_appServerUrl))
|
||||
{
|
||||
QString error(QWidget::tr("Failed to open the system default web browser. Is one installed?."));
|
||||
QMessageBox::critical(NULL, QString(QWidget::tr("Fatal Error")), error);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Show the config dialogue
|
||||
void TrayIcon::onConfig()
|
||||
{
|
||||
QSettings settings;
|
||||
bool ok;
|
||||
|
||||
ConfigWindow *dlg = new ConfigWindow();
|
||||
dlg->setWindowTitle(QString(tr("%1 Configuration")).arg(PGA_APP_NAME));
|
||||
dlg->setBrowserCommand(settings.value("BrowserCommand").toString());
|
||||
dlg->setPythonPath(settings.value("PythonPath").toString());
|
||||
dlg->setApplicationPath(settings.value("ApplicationPath").toString());
|
||||
dlg->setModal(true);
|
||||
ok = dlg->exec();
|
||||
|
||||
QString browsercommand = dlg->getBrowserCommand();
|
||||
QString pythonpath = dlg->getPythonPath();
|
||||
QString applicationpath = dlg->getApplicationPath();
|
||||
|
||||
if (ok)
|
||||
{
|
||||
bool needRestart = (settings.value("PythonPath").toString() != pythonpath ||
|
||||
settings.value("ApplicationPath").toString() != applicationpath);
|
||||
|
||||
settings.setValue("BrowserCommand", browsercommand);
|
||||
settings.setValue("PythonPath", pythonpath);
|
||||
settings.setValue("ApplicationPath", applicationpath);
|
||||
|
||||
if (needRestart)
|
||||
{
|
||||
if (QMessageBox::Yes == QMessageBox::question(this, tr("Shutdown server?"), QString(tr("The %1 server must be restarted for changes to take effect. Do you want to shutdown the server now?")).arg(PGA_APP_NAME), QMessageBox::Yes | QMessageBox::No))
|
||||
{
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Show the log window
|
||||
void TrayIcon::onLog()
|
||||
{
|
||||
QSettings settings;
|
||||
|
||||
if (!m_logWindow)
|
||||
{
|
||||
m_logWindow = new LogWindow(NULL, m_logFile);
|
||||
m_logWindow->setWindowTitle(QString(tr("%1 Log")).arg(PGA_APP_NAME));
|
||||
}
|
||||
|
||||
m_logWindow->show();
|
||||
m_logWindow->raise();
|
||||
m_logWindow->activateWindow();
|
||||
|
||||
QCoreApplication::processEvents( QEventLoop::AllEvents, 100 );
|
||||
|
||||
m_logWindow->ReadLog();
|
||||
}
|
||||
|
||||
|
||||
// Exit
|
||||
void TrayIcon::onQuit()
|
||||
{
|
||||
if (QMessageBox::Yes == QMessageBox::question(this, tr("Shutdown server?"), QString(tr("Are you sure you want to shutdown the %1 server?")).arg(PGA_APP_NAME), QMessageBox::Yes | QMessageBox::No))
|
||||
{
|
||||
exit(0);
|
||||
}
|
||||
}
|
61
runtime/TrayIcon.h
Normal file
61
runtime/TrayIcon.h
Normal file
@ -0,0 +1,61 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
// TrayIcon.h - Manages the tray icon
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef TRAYICON_H
|
||||
#define TRAYICON_H
|
||||
|
||||
#include "pgAdmin4.h"
|
||||
|
||||
// QT headers
|
||||
#include <QWidget>
|
||||
#include <QMessageBox>
|
||||
|
||||
// App headers
|
||||
#include "LogWindow.h"
|
||||
|
||||
class TrayIcon : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TrayIcon(QString logFile);
|
||||
~TrayIcon();
|
||||
|
||||
bool Init();
|
||||
void setAppServerUrl(QString appServerUrl);
|
||||
|
||||
private:
|
||||
void createTrayIcon();
|
||||
bool isSystemTrayAvailable();
|
||||
void createActions();
|
||||
|
||||
void wait(int msec);
|
||||
|
||||
QAction *m_newAction;
|
||||
QAction *m_configAction;
|
||||
QAction *m_logAction;
|
||||
QAction *m_quitAction;
|
||||
|
||||
QSystemTrayIcon *m_trayIcon;
|
||||
QMenu *m_trayIconMenu;
|
||||
|
||||
QString m_appServerUrl, m_logFile;
|
||||
|
||||
LogWindow *m_logWindow;
|
||||
|
||||
private slots:
|
||||
void onNew();
|
||||
void onConfig();
|
||||
void onLog();
|
||||
void onQuit();
|
||||
};
|
||||
|
||||
#endif // TRAYICON_H
|
@ -1,195 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
// WebViewWindow.cpp - Implementation of the custom web view widget
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "pgAdmin4.h"
|
||||
|
||||
// App headers
|
||||
#include "WebViewWindow.h"
|
||||
#include "TabWindow.h"
|
||||
|
||||
#ifndef PGADMIN4_USE_WEBENGINE
|
||||
#include <QWebPage>
|
||||
#include <QNetworkRequest>
|
||||
#endif
|
||||
|
||||
WebViewWindow *WebViewWindow::mainWebViewWindow = NULL;
|
||||
|
||||
// Override QWebEnginePage to handle link delegation
|
||||
#ifdef PGADMIN4_USE_WEBENGINE
|
||||
bool WebEnginePage::acceptNavigationRequest(const QUrl & url, NavigationType type, bool isMainFrame)
|
||||
{
|
||||
Q_UNUSED(type);
|
||||
Q_UNUSED(url);
|
||||
Q_UNUSED(isMainFrame);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QWebEnginePage *WebEnginePage::createWindow(QWebEnginePage::WebWindowType type)
|
||||
{
|
||||
if (type == QWebEnginePage::WebBrowserTab)
|
||||
{
|
||||
QWebEnginePage *_page = NULL;
|
||||
emit createTabWindow(_page);
|
||||
return _page;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
WebViewWindow::WebViewWindow(QWidget *parent) :
|
||||
#ifdef PGADMIN4_USE_WEBENGINE
|
||||
QWebEngineView(parent)
|
||||
#else
|
||||
QWebView(parent)
|
||||
#endif
|
||||
{
|
||||
m_url = QString("");
|
||||
m_tabIndex = 0;
|
||||
m_backForwardBtnHide = false;
|
||||
|
||||
// Accept drop event for only main pgAdmin4 application window.
|
||||
if (mainWebViewWindow == NULL)
|
||||
mainWebViewWindow = this;
|
||||
|
||||
setAcceptDrops(true);
|
||||
}
|
||||
|
||||
// Actual tab drag started.
|
||||
void WebViewWindow::dragEnterEvent(QDragEnterEvent *event)
|
||||
{
|
||||
//DockTabWidget *mainTabWidget = DockTabWidget::getMainTabWidget();
|
||||
//if (this->parent()->parent()->parent() == mainTabWidget)
|
||||
event->accept();
|
||||
}
|
||||
|
||||
void WebViewWindow::dragMoveEvent(QDragMoveEvent *event)
|
||||
{
|
||||
event->acceptProposedAction();
|
||||
}
|
||||
|
||||
// Drop event handler for tabbar.
|
||||
void WebViewWindow::dropEvent(QDropEvent *event)
|
||||
{
|
||||
DockTabWidget *oldTabWidget;
|
||||
int oldIndex;
|
||||
DockTabWidget::decodeTabDropEvent(event, &oldTabWidget, &oldIndex);
|
||||
|
||||
//DockTabWidget *mainTabWidget = DockTabWidget::getMainTabWidget();
|
||||
DockTabWidget *mainTabWidget = dynamic_cast<DockTabWidget*>(this->parent()->parent()->parent());
|
||||
|
||||
if (oldTabWidget && mainTabWidget && oldTabWidget != mainTabWidget)
|
||||
//if (oldTabWidget && mainTabWidget)
|
||||
{
|
||||
mainTabWidget->tabBar()->setVisible(true);
|
||||
QPoint pos = event->pos();
|
||||
int index = mainTabWidget->tabBar()->count();
|
||||
for (int i = 0; i < mainTabWidget->tabBar()->count(); ++i)
|
||||
{
|
||||
QRect rect = mainTabWidget->tabBar()->tabRect(i);
|
||||
QRect rect1(rect.x(), rect.y(), rect.width() / 2, rect.height());
|
||||
QRect rect2(rect.x() + rect1.width(), rect.y(), rect.width() - rect1.width(), rect.height());
|
||||
if (rect1.contains(pos))
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
if (rect2.contains(pos))
|
||||
{
|
||||
index = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DockTabWidget::moveTab(oldTabWidget, oldIndex, mainTabWidget, index);
|
||||
|
||||
// create new back/forward/close buttons and register its events.
|
||||
mainTabWidget->setButtonsNewTabbar(index);
|
||||
mainTabWidget->enableDisableToolButton(index);
|
||||
|
||||
// Check if main pgAdmin4 application has only one tab then close tab bar.
|
||||
// Here - check for count 2 because tab will be deleted later.
|
||||
DockTabWidget *mainTab = DockTabWidget::getMainTabWidget();
|
||||
if (mainTab != NULL && oldTabWidget != NULL && oldTabWidget == mainTab && mainTab->count() == 1)
|
||||
mainTab->tabBar()->setVisible(false);
|
||||
|
||||
event->acceptProposedAction();
|
||||
}
|
||||
}
|
||||
|
||||
void WebViewWindow::setBackForwardButtonHidden(const bool hideButton)
|
||||
{
|
||||
m_backForwardBtnHide = hideButton;
|
||||
}
|
||||
|
||||
bool WebViewWindow::getBackForwardButtonHidden() const
|
||||
{
|
||||
return m_backForwardBtnHide;
|
||||
}
|
||||
|
||||
void WebViewWindow::setFirstLoadURL(const QString &url)
|
||||
{
|
||||
m_url = url;
|
||||
}
|
||||
|
||||
QString WebViewWindow::getFirstLoadURL() const
|
||||
{
|
||||
return m_url;
|
||||
}
|
||||
|
||||
void WebViewWindow::setTabIndex(const int &tabIndex)
|
||||
{
|
||||
m_tabIndex = tabIndex;
|
||||
}
|
||||
|
||||
int WebViewWindow::getTabIndex() const
|
||||
{
|
||||
return m_tabIndex;
|
||||
}
|
||||
|
||||
#ifndef PGADMIN4_USE_WEBENGINE
|
||||
WebViewPage::WebViewPage(QObject *parent)
|
||||
: QWebPage(parent)
|
||||
{
|
||||
}
|
||||
|
||||
bool WebViewPage::acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, NavigationType type)
|
||||
{
|
||||
Q_UNUSED(type);
|
||||
Q_UNUSED(request);
|
||||
Q_UNUSED(frame);
|
||||
return true;
|
||||
}
|
||||
|
||||
QWebPage *WebViewPage::createWindow(QWebPage::WebWindowType type)
|
||||
{
|
||||
if (type == QWebPage::WebBrowserWindow)
|
||||
{
|
||||
QWebPage *_page = NULL;
|
||||
emit createTabWindowKit(_page);
|
||||
return _page;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool WebViewPage::javaScriptConfirm(QWebFrame * frame, const QString & msg)
|
||||
{
|
||||
// If required, override the QDialog to give custom confirmation message to user.
|
||||
Q_UNUSED(frame);
|
||||
Q_UNUSED(msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
WebViewPage::~WebViewPage()
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
@ -1,95 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2018, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
// WebViewWindow.h - Declaration of the custom web view widget
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef WEBVIEWWINDOW_H
|
||||
#define WEBVIEWWINDOW_H
|
||||
|
||||
#include "pgAdmin4.h"
|
||||
|
||||
#if QT_VERSION >= 0x050000
|
||||
#ifdef PGADMIN4_USE_WEBENGINE
|
||||
#include <QtWebEngineWidgets>
|
||||
#else
|
||||
#include <QtWebKitWidgets>
|
||||
#endif
|
||||
#else
|
||||
#include <QWebView>
|
||||
#endif
|
||||
|
||||
// Override QWebEnginePage to handle link delegation
|
||||
#ifdef PGADMIN4_USE_WEBENGINE
|
||||
class WebEnginePage : public QWebEnginePage
|
||||
{
|
||||
Q_OBJECT
|
||||
protected:
|
||||
virtual bool acceptNavigationRequest(const QUrl & url, NavigationType type, bool isMainFrame);
|
||||
QWebEnginePage *createWindow(QWebEnginePage::WebWindowType type);
|
||||
|
||||
signals:
|
||||
void createTabWindow(QWebEnginePage * &);
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef PGADMIN4_USE_WEBENGINE
|
||||
class WebViewWindow : public QWebEngineView
|
||||
#else
|
||||
class WebViewWindow : public QWebView
|
||||
#endif
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
WebViewWindow(QWidget *parent = NULL);
|
||||
void setFirstLoadURL(const QString &url);
|
||||
QString getFirstLoadURL() const;
|
||||
void setTabIndex(const int &tabIndex);
|
||||
int getTabIndex() const;
|
||||
void setBackForwardButtonHidden(const bool hideButton);
|
||||
bool getBackForwardButtonHidden() const;
|
||||
|
||||
// Store main webview window of pgAdmin4 application.
|
||||
static WebViewWindow *mainWebViewWindow;
|
||||
static WebViewWindow* getMainWebViewWindow()
|
||||
{
|
||||
return mainWebViewWindow;
|
||||
}
|
||||
|
||||
protected:
|
||||
// re-implemnted drag-drop event for docking of tabs.
|
||||
void dragEnterEvent(QDragEnterEvent *event);
|
||||
void dragMoveEvent(QDragMoveEvent *event);
|
||||
void dropEvent(QDropEvent *event);
|
||||
|
||||
private:
|
||||
QString m_url;
|
||||
int m_tabIndex;
|
||||
bool m_backForwardBtnHide;
|
||||
};
|
||||
|
||||
#ifndef PGADMIN4_USE_WEBENGINE
|
||||
class WebViewPage : public QWebPage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
WebViewPage(QObject *parent = 0);
|
||||
~WebViewPage();
|
||||
|
||||
protected:
|
||||
virtual bool acceptNavigationRequest(QWebFrame *frame, const QNetworkRequest &request, NavigationType type);
|
||||
QWebPage *createWindow(QWebPage::WebWindowType type);
|
||||
bool javaScriptConfirm(QWebFrame * frame, const QString & msg);
|
||||
|
||||
signals:
|
||||
void createTabWindowKit(QWebPage * &);
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif // WEBVIEWWINDOW_H
|
BIN
runtime/pgAdmin4-mac.png
Normal file
BIN
runtime/pgAdmin4-mac.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 80 KiB |
@ -28,153 +28,22 @@
|
||||
#include <QSplashScreen>
|
||||
#include <QUuid>
|
||||
#include <QNetworkProxyFactory>
|
||||
#include <QSslConfiguration>
|
||||
#endif
|
||||
|
||||
// App headers
|
||||
#include "BrowserWindow.h"
|
||||
#include "ConfigWindow.h"
|
||||
#include "Server.h"
|
||||
#include "TrayIcon.h"
|
||||
|
||||
#include <QTime>
|
||||
|
||||
// Implement support for system proxies for Qt 4.x on Linux
|
||||
#if defined (Q_OS_LINUX) && QT_VERSION < 0x050000
|
||||
|
||||
#include "qnetworkproxy.h"
|
||||
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtCore/QUrl>
|
||||
|
||||
#ifndef QT_NO_NETWORKPROXY
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
static bool ignoreProxyFor(const QNetworkProxyQuery &query)
|
||||
{
|
||||
const QByteArray noProxy = qgetenv("no_proxy").trimmed();
|
||||
if (noProxy.isEmpty())
|
||||
return false;
|
||||
|
||||
const QList<QByteArray> noProxyTokens = noProxy.split(',');
|
||||
|
||||
foreach (const QByteArray &rawToken, noProxyTokens) {
|
||||
QByteArray token = rawToken.trimmed();
|
||||
QString peerHostName = query.peerHostName();
|
||||
|
||||
// Since we use suffix matching, "*" is our 'default' behaviour
|
||||
if (token.startsWith("*"))
|
||||
token = token.mid(1);
|
||||
|
||||
// Harmonize trailing dot notation
|
||||
if (token.endsWith('.') && !peerHostName.endsWith('.'))
|
||||
token = token.left(token.length()-1);
|
||||
|
||||
// We prepend a dot to both values, so that when we do a suffix match,
|
||||
// we don't match "donotmatch.com" with "match.com"
|
||||
if (!token.startsWith('.'))
|
||||
token.prepend('.');
|
||||
|
||||
if (!peerHostName.startsWith('.'))
|
||||
peerHostName.prepend('.');
|
||||
|
||||
if (peerHostName.endsWith(QString::fromLatin1(token)))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static QList<QNetworkProxy> pgAdminSystemProxyForQuery(const QNetworkProxyQuery &query)
|
||||
{
|
||||
QList<QNetworkProxy> proxyList;
|
||||
|
||||
if (ignoreProxyFor(query))
|
||||
return proxyList << QNetworkProxy::NoProxy;
|
||||
|
||||
// No need to care about casing here, QUrl lowercases values already
|
||||
const QString queryProtocol = query.protocolTag();
|
||||
QByteArray proxy_env;
|
||||
|
||||
if (queryProtocol == QLatin1String("http"))
|
||||
proxy_env = qgetenv("http_proxy");
|
||||
else if (queryProtocol == QLatin1String("https"))
|
||||
proxy_env = qgetenv("https_proxy");
|
||||
else if (queryProtocol == QLatin1String("ftp"))
|
||||
proxy_env = qgetenv("ftp_proxy");
|
||||
else
|
||||
proxy_env = qgetenv("all_proxy");
|
||||
|
||||
// Fallback to http_proxy is no protocol specific proxy was found
|
||||
if (proxy_env.isEmpty())
|
||||
proxy_env = qgetenv("http_proxy");
|
||||
|
||||
if (!proxy_env.isEmpty())
|
||||
{
|
||||
QUrl url = QUrl(QString::fromLocal8Bit(proxy_env));
|
||||
if (url.scheme() == QLatin1String("socks5"))
|
||||
{
|
||||
QNetworkProxy proxy(QNetworkProxy::Socks5Proxy, url.host(),
|
||||
url.port() ? url.port() : 1080, url.userName(), url.password());
|
||||
proxyList << proxy;
|
||||
} else if (url.scheme() == QLatin1String("socks5h"))
|
||||
{
|
||||
QNetworkProxy proxy(QNetworkProxy::Socks5Proxy, url.host(),
|
||||
url.port() ? url.port() : 1080, url.userName(), url.password());
|
||||
proxy.setCapabilities(QNetworkProxy::HostNameLookupCapability);
|
||||
proxyList << proxy;
|
||||
} else if ((url.scheme() == QLatin1String("http") || url.scheme() == QLatin1String("https") || url.scheme().isEmpty())
|
||||
&& query.queryType() != QNetworkProxyQuery::UdpSocket
|
||||
&& query.queryType() != QNetworkProxyQuery::TcpServer)
|
||||
{
|
||||
QNetworkProxy proxy(QNetworkProxy::HttpProxy, url.host(),
|
||||
url.port() ? url.port() : 8080, url.userName(), url.password());
|
||||
proxyList << proxy;
|
||||
}
|
||||
}
|
||||
if (proxyList.isEmpty())
|
||||
proxyList << QNetworkProxy::NoProxy;
|
||||
|
||||
return proxyList;
|
||||
}
|
||||
|
||||
class pgAdminSystemConfigurationProxyFactory : public QNetworkProxyFactory
|
||||
{
|
||||
public:
|
||||
pgAdminSystemConfigurationProxyFactory() : QNetworkProxyFactory() {}
|
||||
|
||||
virtual QList<QNetworkProxy> queryProxy(const QNetworkProxyQuery& query)
|
||||
{
|
||||
QList<QNetworkProxy> proxies = pgAdminSystemProxyForQuery(query);
|
||||
|
||||
// Make sure NoProxy is in the list, so that QTcpServer can work:
|
||||
// it searches for the first proxy that can has the ListeningCapability capability
|
||||
// if none have (as is the case with HTTP proxies), it fails to bind.
|
||||
// NoProxy allows it to fallback to the 'no proxy' case and bind.
|
||||
proxies.append(QNetworkProxy::NoProxy);
|
||||
|
||||
return proxies;
|
||||
}
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QT_NO_NETWORKINTERFACE
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
void delay( int milliseconds )
|
||||
{
|
||||
QTime endTime = QTime::currentTime().addMSecs( milliseconds );
|
||||
while( QTime::currentTime() < endTime )
|
||||
{
|
||||
QCoreApplication::processEvents( QEventLoop::AllEvents, 100 );
|
||||
}
|
||||
}
|
||||
QString logFileName;
|
||||
QString addrFileName;
|
||||
|
||||
int main(int argc, char * argv[])
|
||||
{
|
||||
QSettings settings;
|
||||
|
||||
/*
|
||||
* Before starting main application, need to set 'QT_X11_NO_MITSHM=1'
|
||||
* to make the runtime work with IBM PPC machine.
|
||||
@ -186,6 +55,7 @@ int main(int argc, char * argv[])
|
||||
|
||||
// Create the QT application
|
||||
QApplication app(argc, argv);
|
||||
app.setQuitOnLastWindowClosed(false);
|
||||
|
||||
// Setup the settings management
|
||||
QCoreApplication::setOrganizationName("pgadmin");
|
||||
@ -197,36 +67,84 @@ int main(int argc, char * argv[])
|
||||
QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
// Set registry "HKEY_CLASSES_ROOT\.css\Content Type" to value "text/css" to avoid rendering issue in windows OS.
|
||||
QString infoMsgStr("");
|
||||
QSettings css_keys("HKEY_CLASSES_ROOT", QSettings::NativeFormat);
|
||||
// Create a hash of the executable path so we can run copies side-by-side
|
||||
QString homeDir = QDir::homePath();
|
||||
unsigned long exeHash = sdbm((unsigned char *)argv[0]);
|
||||
|
||||
// If key already exists then check for existing value and it differs then only change it.
|
||||
if (css_keys.childGroups().contains(".css", Qt::CaseInsensitive))
|
||||
{
|
||||
QSettings set("HKEY_CLASSES_ROOT\\.css", QSettings::NativeFormat);
|
||||
if (set.value("Content Type").toString() != "text/css")
|
||||
{
|
||||
set.setValue("Content Type", "text/css");
|
||||
// If error while setting registry then it should be issue with permissions.
|
||||
if (set.status() == QSettings::NoError)
|
||||
infoMsgStr = "pgAdmin 4 application has reset the registry key 'HKEY_CLASSES_ROOT\\css\\Content Type' to 'text/css' to fix a system misconfiguration that can lead to rendering problems.";
|
||||
else
|
||||
infoMsgStr = "Failed to reset the registry key 'HKEY_CLASSES_ROOT\\css\\Content Type' to 'text/css'. Try to run with Administrator privileges.";
|
||||
}
|
||||
}
|
||||
// Create the address file, that will be used to store the appserver URL for this instance
|
||||
addrFileName = homeDir + QString("/.%1.%2.addr").arg(PGA_APP_NAME).arg(exeHash);
|
||||
addrFileName.remove(" ");
|
||||
QFile addrFile(addrFileName);
|
||||
|
||||
// Create a system-wide semaphore keyed by app name, exe hash and the username
|
||||
// to ensure instances are unique to the user and path
|
||||
QString userName = qgetenv("USER"); // *nix
|
||||
if (userName.isEmpty())
|
||||
userName = qgetenv("USERNAME"); // Windows
|
||||
|
||||
QString semaName = QString("%1-%2-%3-sema").arg(PGA_APP_NAME).arg(userName).arg(exeHash);
|
||||
QString shmemName = QString("%1-%2-%3-shmem").arg(PGA_APP_NAME).arg(userName).arg(exeHash);
|
||||
|
||||
QSystemSemaphore sema(semaName, 1);
|
||||
sema.acquire();
|
||||
|
||||
#ifndef Q_OS_WIN32
|
||||
// We may need to clean up stale shmem segments on *nix. Attaching and detaching
|
||||
// should remove the segment if it is orphaned.
|
||||
QSharedMemory stale_shmem(shmemName);
|
||||
if (stale_shmem.attach())
|
||||
stale_shmem.detach();
|
||||
#endif
|
||||
|
||||
/* In windows and linux, it is required to set application level proxy
|
||||
* becuase socket bind logic to find free port gives socket creation error
|
||||
* when system proxy is configured. We are also setting
|
||||
* "setUseSystemConfiguration"=true to use the system proxy which will
|
||||
* override this application level proxy. As this bug is fixed in Qt 5.9 so
|
||||
* need to set application proxy for Qt version < 5.9.
|
||||
*/
|
||||
#ifndef PGADMIN4_USE_WEBENGINE
|
||||
#if defined (Q_OS_WIN) && QT_VERSION <= 0x050800
|
||||
QSharedMemory shmem(shmemName);
|
||||
bool is_running;
|
||||
if (shmem.attach())
|
||||
{
|
||||
is_running = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
shmem.create(1);
|
||||
is_running = false;
|
||||
}
|
||||
sema.release();
|
||||
|
||||
if (is_running){
|
||||
addrFile.open(QIODevice::ReadOnly | QIODevice::Text);
|
||||
QTextStream in(&addrFile);
|
||||
QString addr = in.readLine();
|
||||
|
||||
QString cmd = settings.value("BrowserCommand").toString();
|
||||
|
||||
if (!cmd.isEmpty())
|
||||
{
|
||||
cmd.replace("%URL%", addr);
|
||||
QProcess::startDetached(cmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!QDesktopServices::openUrl(addr))
|
||||
{
|
||||
QString error(QWidget::tr("Failed to open the system default web browser. Is one installed?."));
|
||||
QMessageBox::critical(NULL, QString(QWidget::tr("Fatal Error")), error);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
atexit(cleanup);
|
||||
|
||||
// In windows and linux, it is required to set application level proxy
|
||||
// because socket bind logic to find free port gives socket creation error
|
||||
// when system proxy is configured. We are also setting
|
||||
// "setUseSystemConfiguration"=true to use the system proxy which will
|
||||
// override this application level proxy. As this bug is fixed in Qt 5.9 so
|
||||
// need to set application proxy for Qt version < 5.9.
|
||||
//
|
||||
#if defined (Q_OS_WIN) && QT_VERSION <= 0x050800
|
||||
// Give dummy URL required to find proxy server configured in windows.
|
||||
QNetworkProxyQuery proxyQuery(QUrl("https://www.pgadmin.org"));
|
||||
QNetworkProxy l_proxy;
|
||||
@ -241,18 +159,15 @@ int main(int argc, char * argv[])
|
||||
QNetworkProxy::setApplicationProxy(QNetworkProxy());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef PGADMIN4_USE_WEBENGINE
|
||||
#if defined (Q_OS_LINUX) && QT_VERSION <= 0x050800
|
||||
#if defined (Q_OS_LINUX) && QT_VERSION <= 0x050800
|
||||
QByteArray proxy_env;
|
||||
proxy_env = qgetenv("http_proxy");
|
||||
// If http_proxy environment is defined in linux then proxy server is configured.
|
||||
if (!proxy_env.isEmpty()) {
|
||||
QNetworkProxy::setApplicationProxy(QNetworkProxy());
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Display the spash screen
|
||||
@ -288,19 +203,20 @@ int main(int argc, char * argv[])
|
||||
QString key = QUuid::createUuid().toString();
|
||||
key = key.mid(1, key.length() - 2);
|
||||
|
||||
#if defined (Q_OS_LINUX) && QT_VERSION < 0x050000
|
||||
QNetworkProxyFactory::setApplicationProxyFactory(new pgAdminSystemConfigurationProxyFactory);
|
||||
QSslConfiguration sslCfg = QSslConfiguration::defaultConfiguration();
|
||||
QList<QSslCertificate> ca_list = sslCfg.caCertificates();
|
||||
QList<QSslCertificate> ca_new = QSslCertificate::fromData("CaCertificates");
|
||||
ca_list += ca_new;
|
||||
// Generate the filename for the log
|
||||
logFileName = homeDir + QString("/.%1.%2.log").arg(PGA_APP_NAME).arg(exeHash);
|
||||
logFileName.remove(" ");
|
||||
|
||||
sslCfg.setCaCertificates(ca_list);
|
||||
sslCfg.setProtocol(QSsl::AnyProtocol);
|
||||
QSslConfiguration::setDefaultConfiguration(sslCfg);
|
||||
#else
|
||||
QNetworkProxyFactory::setUseSystemConfiguration(true);
|
||||
#endif
|
||||
// Start the tray service
|
||||
TrayIcon *trayicon = new TrayIcon(logFileName);
|
||||
|
||||
if (!trayicon->Init())
|
||||
{
|
||||
QString error = QString(QWidget::tr("An error occurred initialising the tray icon"));
|
||||
QMessageBox::critical(NULL, QString(QWidget::tr("Fatal Error")), error);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Fire up the webserver
|
||||
Server *server;
|
||||
@ -309,7 +225,7 @@ int main(int argc, char * argv[])
|
||||
|
||||
while (done != true)
|
||||
{
|
||||
server = new Server(port, key);
|
||||
server = new Server(port, key, logFileName);
|
||||
|
||||
if (!server->Init())
|
||||
{
|
||||
@ -325,6 +241,13 @@ int main(int argc, char * argv[])
|
||||
|
||||
server->start();
|
||||
|
||||
// This is a hack to give the server a chance to start and potentially fail. As
|
||||
// the Python interpreter is a synchronous call, we can't check for proper startup
|
||||
// easily in a more robust way - we have to rely on a clean startup not returning.
|
||||
// It should always fail pretty quickly, and take longer to start if it succeeds, so
|
||||
// we don't really get a visible delay here.
|
||||
delay(1000);
|
||||
|
||||
// Any errors?
|
||||
if (server->isFinished() || server->getError().length() > 0)
|
||||
{
|
||||
@ -341,16 +264,19 @@ int main(int argc, char * argv[])
|
||||
|
||||
ConfigWindow *dlg = new ConfigWindow();
|
||||
dlg->setWindowTitle(QWidget::tr("Configuration"));
|
||||
dlg->setBrowserCommand(settings.value("BrowserCommand").toString());
|
||||
dlg->setPythonPath(settings.value("PythonPath").toString());
|
||||
dlg->setApplicationPath(settings.value("ApplicationPath").toString());
|
||||
dlg->setModal(true);
|
||||
ok = dlg->exec();
|
||||
|
||||
QString browsercommand = dlg->getBrowserCommand();
|
||||
QString pythonpath = dlg->getPythonPath();
|
||||
QString applicationpath = dlg->getApplicationPath();
|
||||
|
||||
if (ok)
|
||||
{
|
||||
settings.setValue("BrowserCommand", browsercommand);
|
||||
settings.setValue("PythonPath", pythonpath);
|
||||
settings.setValue("ApplicationPath", applicationpath);
|
||||
settings.sync();
|
||||
@ -371,7 +297,6 @@ int main(int argc, char * argv[])
|
||||
QString appServerUrl = QString("http://127.0.0.1:%1/?key=%2").arg(port).arg(key);
|
||||
|
||||
// Read the server connection timeout from the registry or set the default timeout.
|
||||
QSettings settings;
|
||||
int timeout = settings.value("ConnectionTimeout", 30).toInt();
|
||||
|
||||
// Now the server should be up, we'll attempt to connect and get a response.
|
||||
@ -393,7 +318,7 @@ int main(int argc, char * argv[])
|
||||
}
|
||||
|
||||
// Attempt to connect one more time in case of a long network timeout while looping
|
||||
if(!alive && !PingServer(QUrl(appServerUrl)))
|
||||
if (!alive && !PingServer(QUrl(appServerUrl)))
|
||||
{
|
||||
splash->finish(NULL);
|
||||
QString error(QWidget::tr("The application server could not be contacted."));
|
||||
@ -402,26 +327,35 @@ int main(int argc, char * argv[])
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Create & show the main window
|
||||
BrowserWindow browserWindow(appServerUrl);
|
||||
browserWindow.setWindowTitle(PGA_APP_NAME);
|
||||
browserWindow.setWindowIcon(QIcon(":/pgAdmin4.ico"));
|
||||
#ifdef _WIN32
|
||||
browserWindow.setRegistryMessage(infoMsgStr);
|
||||
#endif
|
||||
browserWindow.show();
|
||||
// Stash the URL for any duplicate processes to open
|
||||
if (addrFile.open(QIODevice::WriteOnly))
|
||||
{
|
||||
QTextStream out(&addrFile);
|
||||
out << appServerUrl << endl;
|
||||
}
|
||||
|
||||
// Go!
|
||||
splash->finish(NULL);
|
||||
trayicon->setAppServerUrl(appServerUrl);
|
||||
|
||||
// Set global application stylesheet.
|
||||
QFile file(":/qss/pgadmin4.qss");
|
||||
if(file.open(QFile::ReadOnly))
|
||||
QString cmd = settings.value("BrowserCommand").toString();
|
||||
|
||||
if (!cmd.isEmpty())
|
||||
{
|
||||
QString StyleSheet = QLatin1String(file.readAll());
|
||||
qApp->setStyleSheet(StyleSheet);
|
||||
file.close();
|
||||
cmd.replace("%URL%", appServerUrl);
|
||||
QProcess::startDetached(cmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!QDesktopServices::openUrl(appServerUrl))
|
||||
{
|
||||
QString error(QWidget::tr("Failed to open the system default web browser. Is one installed?."));
|
||||
QMessageBox::critical(NULL, QString(QWidget::tr("Fatal Error")), error);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
splash->finish(NULL);
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
@ -468,3 +402,36 @@ bool PingServer(QUrl url)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void delay(int milliseconds)
|
||||
{
|
||||
QTime endTime = QTime::currentTime().addMSecs(milliseconds);
|
||||
while(QTime::currentTime() < endTime)
|
||||
{
|
||||
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void cleanup()
|
||||
{
|
||||
// Remove the address file
|
||||
QFile addrFile(addrFileName);
|
||||
addrFile.remove();
|
||||
|
||||
// Remove the log file
|
||||
QFile logFile(logFileName);
|
||||
logFile.remove();
|
||||
}
|
||||
|
||||
|
||||
unsigned long sdbm(unsigned char *str)
|
||||
{
|
||||
unsigned long hash = 0;
|
||||
int c;
|
||||
|
||||
while ((c = *str++))
|
||||
hash = c + (hash << 6) + (hash << 16) - hash;
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
@ -36,5 +36,8 @@ const QString PGA_APP_NAME = QString("pgAdmin 4");
|
||||
// Global function prototypes
|
||||
int main(int argc, char * argv[]);
|
||||
bool PingServer(QUrl url);
|
||||
void delay(int milliseconds);
|
||||
void cleanup();
|
||||
unsigned long sdbm(unsigned char *str);
|
||||
|
||||
#endif // PGADMIN4_H
|
||||
|
BIN
runtime/pgAdmin4.png
Normal file
BIN
runtime/pgAdmin4.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 97 KiB |
@ -1,4 +1,4 @@
|
||||
VERSION = 2.1.0.0
|
||||
VERSION = 3.0.0.0
|
||||
QMAKE_TARGET_COMPANY = "The pgAdmin Development Team"
|
||||
QMAKE_TARGET_PRODUCT = "pgAdmin 4"
|
||||
QMAKE_TARGET_DESCRIPTION = "pgAdmin 4 Desktop Runtime"
|
||||
@ -7,52 +7,17 @@ QMAKE_TARGET_COPYRIGHT = "Copyright 2013 - 2018, The pgAdmin Development Team"
|
||||
# Configure QT modules for the appropriate version of QT
|
||||
greaterThan(QT_MAJOR_VERSION, 4) {
|
||||
message(Building for QT5+...)
|
||||
|
||||
# Users can force the use of WebKit in Qt5, e.g. qmake "DEFINES += PGADMIN4_USE_WEBKIT"
|
||||
contains(DEFINES, PGADMIN4_USE_WEBKIT) {
|
||||
message(Forcing use of QWebKit...)
|
||||
message()
|
||||
message(************************************** WARNING **************************************)
|
||||
message(* It is strongly advised that Qt 5.5.0 or later is used to build the pgAdmin runtime.)
|
||||
message(*************************************************************************************)
|
||||
message()
|
||||
QT += webkitwidgets network widgets
|
||||
} else {
|
||||
greaterThan(QT_MINOR_VERSION, 4) {
|
||||
message(Using QWebEngine...)
|
||||
DEFINES += PGADMIN4_USE_WEBENGINE
|
||||
QT += webenginewidgets network widgets
|
||||
} else {
|
||||
message(Using QWebKit...)
|
||||
message()
|
||||
message(************************************** WARNING **************************************)
|
||||
message(* It is strongly advised that Qt 5.5.0 or later is used to build the pgAdmin runtime.)
|
||||
message(*************************************************************************************)
|
||||
message()
|
||||
DEFINES *= PGADMIN4_USE_WEBKIT
|
||||
QT += webkitwidgets network widgets
|
||||
}
|
||||
}
|
||||
message()
|
||||
QT += network widgets
|
||||
} else {
|
||||
message(Building for QT4...)
|
||||
message(Using QWebKit...)
|
||||
message()
|
||||
message(************************************** WARNING **************************************)
|
||||
message(* It is strongly advised that Qt 5.5.0 or later is used to build the pgAdmin runtime.)
|
||||
message(*************************************************************************************)
|
||||
message()
|
||||
DEFINES += PGADMIN4_USE_WEBKIT
|
||||
QT += webkit network
|
||||
QT += network
|
||||
}
|
||||
win32 {
|
||||
RC_ICONS += pgAdmin4.ico
|
||||
}
|
||||
|
||||
CONFIG(debug, debug|release) {
|
||||
DEFINES += PGADMIN4_DEBUG
|
||||
message(Configure pgAdmin4 to run in debug mode...)
|
||||
}
|
||||
|
||||
# Environment settings for the build
|
||||
QMAKE_CFLAGS += $$(PGADMIN_CFLAGS)
|
||||
QMAKE_CXXFLAGS += $$(PGADMIN_CXXFLAGS)
|
||||
@ -122,23 +87,21 @@ else {
|
||||
}
|
||||
|
||||
# Source code
|
||||
HEADERS = BrowserWindow.h \
|
||||
HEADERS = \
|
||||
Server.h \
|
||||
pgAdmin4.h \
|
||||
TabWindow.h \
|
||||
WebViewWindow.h \
|
||||
ConfigWindow.h
|
||||
ConfigWindow.h \
|
||||
TrayIcon.h \
|
||||
LogWindow.h
|
||||
SOURCES = pgAdmin4.cpp \
|
||||
BrowserWindow.cpp \
|
||||
Server.cpp \
|
||||
TabWindow.cpp \
|
||||
WebViewWindow.cpp \
|
||||
ConfigWindow.cpp
|
||||
FORMS = BrowserWindow.ui \
|
||||
ConfigWindow.ui
|
||||
ConfigWindow.cpp \
|
||||
TrayIcon.cpp \
|
||||
LogWindow.cpp
|
||||
FORMS = ConfigWindow.ui \
|
||||
LogWindow.ui
|
||||
ICON = pgAdmin4.icns
|
||||
QMAKE_INFO_PLIST = Info.plist
|
||||
|
||||
RESOURCES += \
|
||||
pgadmin4.qrc
|
||||
RESOURCES += pgadmin4.qrc
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
<file>forward.png</file>
|
||||
<file>close.png</file>
|
||||
<file>splash.png</file>
|
||||
<file>qss/pgadmin4.qss</file>
|
||||
<file>pgAdmin4.png</file>
|
||||
<file>pgAdmin4-mac.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
@ -1,3 +0,0 @@
|
||||
QTabBar::tab {
|
||||
background-color: #E8E8E8;
|
||||
}
|
Loading…
Reference in New Issue
Block a user