diff --git a/harbour/ChangeLog b/harbour/ChangeLog index cc67daf7ef..d3dd2cb471 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -17,6 +17,96 @@ past entries belonging to author(s): Viktor Szakats. */ +2010-01-24 22:28 UTC-0800 Pritpal Bedi (pritpal@vouchcac.com) + * contrib/hbxbp/Makefile + * contrib/hbxbp/hbpprocess.prg + + Implemented first HbpProcess() class ( Harbour Extension ) + which is based on Qt's process management classes. + The usage concept is well defined in + /contrib/hbide/ideprojmanager.prg. + I will write the documentation at some later date. + + * contrib/hbide/resources/projectproperties.ui + + More components. + + * contrib/hbide/projects/hbide.hbi + + More info. + + * contrib/hbide/hbide.ch + * contrib/hbide/hbide.prg + * contrib/hbide/idedocks.prg + * contrib/hbide/idemisc.prg + * contrib/hbide/ideobject.prg + * contrib/hbide/ideprojmanager.prg + * contrib/hbide/idesaveload.prg + ! Updated to hold Development Environments concept introduced. + Read below. + - contrib/hbide/hbide.env + + contrib/hbide/resources/hbide.env + + The environment skeletons (working) on my machine connecting + hbIDE to hbMK2 engine. You can copy it and place it + in projects folder with suitable path amendments and + call it in hbIDE. This implementation facilitae to + generate any project on any compiler from within + single instance of hbIDE without leaving it. + + Here are the implementation details: + + FORMAT + ====== + [ BCC55 5.5.1 Command Line Tools ] + {hb_comp} bcc + {shell} cmd.exe + {ext} bat + # + {content} set HB_COMPILER=bcc + {content} set PATH=c:\harbour_dev;c:\harbour_dev\bcc\bin;C:\harbour_dev\harbour\bcc\bin; + + [ MINGW 4.4.2 Windows ] + {hb_plat} win + {hb_comp} mingw + {content} set PATH=c:\mingw\bin;c:\qt\2009.03\qt\bin; + {content} set PATH=c:\harbour_dev;c:\harbour_dev\harbour\mingw\bin;%path% + {content} set HB_WITH_QT=c:\qt\2009.03\qt + ... + + {hb_plat} == set HB_ARCHITECTURE= + {hb_comp} == set HB_COMPILER= + {shell} == shell command to execute + {ext} == the extension of shell commands file + {content} == active contents placed in the shell commands file + Any lines with {contents} marker will form the + body of commands file. You can place remarks + preceded with # sign. + + Currently {contents} are implemented, rest will take a couple of days. + + PLACEHOLDER + =========== + in dialog but with separate + button to save this and its path information alone. Just avoided one + more dialog. + + ACTIVATION + ========== + Right-click on node in "Projects" tree and select . + The selected environment will become the default for current session and will + be saved for next invocation until it is changed. Next build will respect + this setting. + + EFFECTIVENESS + ============= + Create a desktop icon pointing to hbIDE.exe and place the only parameter + poing to "hbide.env" file. You can copy it anywhere in your project tree, + amend it to suit your requirements, and just execute hbIDE on your desktop. + NOTE: you _MUST NOT_ set any compiler specific variables before invoking + hbIDE. Your working slate must be clean. + + WHAT_IS_NOT_DONE + ================ + The bash commands and their shell invocation. But I know a lot of you + will implement that in no time. + 2010-01-25 05:09 UTC+0100 Viktor Szakats (harbour.01 syenar.hu) * contrib/hbwin/win_tprn.prg * contrib/hbwin/win_bmp.c diff --git a/harbour/contrib/hbide/hbide.ch b/harbour/contrib/hbide/hbide.ch index 63f487509e..6fee196d78 100644 --- a/harbour/contrib/hbide/hbide.ch +++ b/harbour/contrib/hbide/hbide.ch @@ -82,8 +82,11 @@ #define ThemesDialogGeometry 11 #define CurrentTheme 12 #define CurrentCodec 13 +#define PathMk2 14 +#define PathEnv 15 +#define CurrentEnvironment 16 -#define INI_HBIDE_VRBLS 13 +#define INI_HBIDE_VRBLS 16 /* .hbi structure constants */ #define PRJ_PRP_PROPERTIES 1 @@ -101,8 +104,9 @@ #define PRJ_PRP_OUTPUT 6 #define PRJ_PRP_LPARAMS 7 #define PRJ_PRP_LPROGRAM 8 +#define PRJ_PRP_BACKUP 9 // -#define PRJ_PRP_PRP_VRBLS 8 +#define PRJ_PRP_PRP_VRBLS 9 /* Project Properties array elements */ #define E_qPrjType 1 @@ -127,6 +131,7 @@ #define SB_PNL_SELECTEDCHARS 6 #define SB_PNL_MODIFIED 7 #define SB_PNL_M_2 8 +#define SB_PNL_ENVIRON 8 #define SB_PNL_STREAM 9 #define SB_PNL_EDIT 10 #define SB_PNL_SEARCH 11 diff --git a/harbour/contrib/hbide/hbide.env b/harbour/contrib/hbide/hbide.env deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/harbour/contrib/hbide/hbide.prg b/harbour/contrib/hbide/hbide.prg index 47ea60abc3..5aa81a6f1d 100644 --- a/harbour/contrib/hbide/hbide.prg +++ b/harbour/contrib/hbide/hbide.prg @@ -115,6 +115,7 @@ CLASS HbIde DATA oEM /* Editor Tabs Manager */ DATA oSM /* Souces Manager */ DATA oFR /* Find Replace Manager */ + DATA oEV /* Available Environments */ DATA oThemes DATA aMeta INIT {} /* Holds current definition only */ @@ -177,16 +178,22 @@ CLASS HbIde DATA lDockBVisible INIT .f. DATA lTabCloseRequested INIT .f. + DATA cWrkProject INIT "" + DATA cWrkTheme INIT "" + DATA cWrkCodec INIT "" + DATA cWrkPathMk2 INIT hb_getenv( "HBIDE_DIR_HBMK2" ) + DATA cWrkPathEnv INIT hb_DirBase() + "resources" + DATA cWrkEnvironment INIT "" + + DATA oEnvironment + DATA cSaveTo INIT "" DATA oOpenedSources DATA resPath INIT hb_DirBase() + "resources" + hb_OsPathSeparator() DATA pathSep INIT hb_OsPathSeparator() DATA cLastFileOpenPath INIT hb_DirBase() + "projects" - DATA cWrkProject INIT "" - DATA cWrkTheme INIT "" DATA cProcessInfo DATA cIniThemes - DATA cWrkCodec INIT "" DATA cSeparator INIT "/*" + replicate( "-", 70 ) + "*/" DATA nTabSpaces INIT 3 /* Via User Setup */ @@ -262,8 +269,9 @@ METHOD HbIde:create( cProjIni ) /* Load IDE Settings */ hbide_loadINI( Self, cProjIni ) /* Set variables from last session */ - ::cWrkTheme := ::aINI[ INI_HBIDE, CurrentTheme ] - ::cWrkCodec := ::aINI[ INI_HBIDE, CurrentCodec ] + ::cWrkTheme := ::aINI[ INI_HBIDE, CurrentTheme ] + ::cWrkCodec := ::aINI[ INI_HBIDE, CurrentCodec ] + ::cWrkEnvironment := ::aINI[ INI_HBIDE, CurrentEnvironment ] /* Set Codec at the Begining */ HbXbp_SetCodec( ::cWrkCodec ) @@ -294,6 +302,9 @@ METHOD HbIde:create( cProjIni ) /* Load IDE|User defined Themes */ hbide_loadThemes( Self ) + /* Load Environments */ + ::oEV := IdeEnvironments():new( Self, hbide_pathToOSPath( ::aINI[ INI_HBIDE, PathEnv ] + ::pathSep + "hbide.env" ) ):create() + /* Prepare Editor's Tabs */ ::oEM:prepareTabWidget() @@ -334,6 +345,9 @@ METHOD HbIde:create( cProjIni ) /* Again to be displayed in Statusbar */ HbXbp_SetCodec( ::cWrkCodec ) + /* Display cWrkEnvironment in StatusBar */ + ::oDK:dispEnvironment( ::cWrkEnvironment ) + /* Request Main Window to Appear on the Screen */ ::oDlg:Show() @@ -908,8 +922,8 @@ METHOD HbIde:manageItemSelected( oXbpTreeItem ) /*----------------------------------------------------------------------*/ METHOD HbIde:manageProjectContext( mp1, mp2, oXbpTreeItem ) - LOCAL n, cHbi, aPrj - LOCAL aPops := {} + LOCAL n, cHbi, aPrj, s + LOCAL aPops := {}, aSub :={} HB_SYMBOL_UNUSED( mp2 ) @@ -930,6 +944,16 @@ METHOD HbIde:manageProjectContext( mp1, mp2, oXbpTreeItem ) aadd( aPops, { "New Project" , {|| ::oPM:loadProperties( , .t., .t., .t. ) } } ) aadd( aPops, { "" } ) aadd( aPops, { "Load Project" , {|| ::oPM:loadProperties( , .f., .f., .t. ) } } ) + aadd( aPops, { "" } ) + // + IF !empty( ::oEV:getNames ) + aadd( aPops, { "" } ) + FOR EACH s IN ::oEV:getNames() + aadd( aSub, { s , {|x| ::cWrkEnvironment := x, ::oDK:dispEnvironment( x ) } } ) + NEXT + aadd( aPops, { aSub, "Environment..." } ) + ENDIF + // hbide_ExecPopup( aPops, mp1, ::oProjTree:oWidget ) CASE ::aProjData[ n, TRE_TYPE ] == "Project Name" @@ -951,7 +975,15 @@ METHOD HbIde:manageProjectContext( mp1, mp2, oXbpTreeItem ) aadd( aPops, { "Launch" , {|| ::oPM:launchProject( oXbpTreeItem:caption ) } } ) aadd( aPops, { "" } ) aadd( aPops, { "Close This Project" , {|| ::oPM:closeProject( oXbpTreeItem:caption ) } } ) - // + /* + IF !empty( ::oEV:getNames ) + aadd( aPops, { "" } ) + FOR EACH s IN ::oEV:getNames() + aadd( aSub, { s , {|x| ::cWrkEnvironment := x, ::oDK:dispEnvironment( x ) } } ) + NEXT + aadd( aPops, { aSub, "Select an environment" } ) + ENDIF + */ hbide_ExecPopup( aPops, mp1, ::oProjTree:oWidget ) CASE ::aProjData[ n, TRE_TYPE ] == "Source File" diff --git a/harbour/contrib/hbide/idedocks.prg b/harbour/contrib/hbide/idedocks.prg index 196c777e98..050d43cf32 100644 --- a/harbour/contrib/hbide/idedocks.prg +++ b/harbour/contrib/hbide/idedocks.prg @@ -72,7 +72,7 @@ /*----------------------------------------------------------------------*/ -CLASS IdeDockS INHERIT IdeObject +CLASS IdeDocks INHERIT IdeObject DATA nPass INIT 0 @@ -94,6 +94,7 @@ CLASS IdeDockS INHERIT IdeObject METHOD toggleBottomDocks() METHOD setStatusText( nPart, xValue ) METHOD getMarkWidget( nIndex ) + METHOD dispEnvironment( cEnviron ) ENDCLASS @@ -413,7 +414,7 @@ METHOD IdeDocks:buildStatusBar() ::oSBar:addItem( "", , , , "Ins" ):oWidget:setMinimumWidth( 30 ) ::oSBar:addItem( "", , , , "M_1" ):oWidget:setMinimumWidth( 30 ) ::oSBar:addItem( "", , , , "Modified" ):oWidget:setMinimumWidth( 50 ) - ::oSBar:addItem( "", , , , "M_2" ):oWidget:setMinimumWidth( 30 ) + ::oSBar:addItem( "", , , , "Environ" ):oWidget:setMinimumWidth( 30 ) ::oSBar:addItem( "", , , , "Stream" ):oWidget:setMinimumWidth( 20 ) ::oSBar:addItem( "", , , , "Edit" ):oWidget:setMinimumWidth( 20 ) ::oSBar:addItem( "", , , , "Search" ):oWidget:setMinimumWidth( 20 ) @@ -489,6 +490,12 @@ METHOD IdeDocks:toggleBottomDocks() /*----------------------------------------------------------------------*/ +METHOD IdeDocks:dispEnvironment( cEnviron ) + ::setStatusText( SB_PNL_ENVIRON, cEnviron ) + RETURN Self + +/*----------------------------------------------------------------------*/ + METHOD IdeDocks:setStatusText( nPart, xValue ) LOCAL oPanel := ::oSBar:getItem( nPart ) @@ -510,6 +517,8 @@ METHOD IdeDocks:setStatusText( nPart, xValue ) oPanel:caption := iif( xValue, "Modified", "" ) EXIT CASE SB_PNL_M_2 + CASE SB_PNL_ENVIRON + oPanel:caption := "Env: " + xValue EXIT CASE SB_PNL_STREAM EXIT diff --git a/harbour/contrib/hbide/idemisc.prg b/harbour/contrib/hbide/idemisc.prg index 77aceaf290..74c29e7b31 100644 --- a/harbour/contrib/hbide/idemisc.prg +++ b/harbour/contrib/hbide/idemisc.prg @@ -98,7 +98,7 @@ PROCEDURE hbide_justACall() /*----------------------------------------------------------------------*/ FUNCTION hbide_execPopup( aPops, aPos, qParent ) - LOCAL i, qPop, qPoint, qAct, cAct, xRet, pAct, a_ + LOCAL i, qPop, qPoint, qAct, cAct, xRet, pAct, a_, qSub, b_ qPop := QMenu():new( iif( hb_isObject( qParent ), qParent, NIL ) ) @@ -108,6 +108,13 @@ FUNCTION hbide_execPopup( aPops, aPos, qParent ) ELSE IF hb_isObject( aPops[ i, 1 ] ) qPop:addAction_4( aPops[ i, 1 ] ) + ELSEIF hb_isArray( aPops[ i, 1 ] ) /* Sub-menu */ + qSub := QMenu():new( qPop ) + FOR EACH a_ IN aPops[ i, 1 ] + qSub:addAction( a_[ 1 ] ) + NEXT + qSub:setTitle( aPops[ i,2 ] ) + qPop:addMenu( qSub ) ELSE qPop:addAction( aPops[ i, 1 ] ) ENDIF @@ -125,9 +132,16 @@ FUNCTION hbide_execPopup( aPops, aPos, qParent ) xRet := eval( aPops[ a_:__enumIndex(), 2 ] ) EXIT ENDIF + ELSEIF hb_isArray( a_[ 1 ] ) + FOR EACH b_ IN a_[ 1 ] + IF b_[ 1 ] == cAct + xRet := eval( b_[ 2 ], cAct ) + EXIT + ENDIF + NEXT ELSE IF a_[ 1 ] == cAct - xRet := eval( aPops[ a_:__enumIndex(), 2 ] ) + xRet := eval( aPops[ a_:__enumIndex(), 2 ], cAct ) EXIT ENDIF ENDIF @@ -335,7 +349,7 @@ FUNCTION hbide_fetchHbiStructFromFile( cProject ) STATIC FUNCTION hbide_pullHbiStruct( a_ ) LOCAL n, s, nPart, cKey, cVal, ss LOCAL aPrp := { "Type", "Title", "Location", "WorkingFolder", "DestinationFolder", ; - "Output", "LaunchParams", "LaunchProgram" } + "Output", "LaunchParams", "LaunchProgram", "BackupFolder" } LOCAL a1_0 := afill( array( PRJ_PRP_PRP_VRBLS ), "" ) LOCAL a1_1 := {} @@ -565,6 +579,12 @@ FUNCTION hbide_pathNormalized( cPath, lLower ) /*----------------------------------------------------------------------*/ +FUNCTION hbide_pathFile( cPath, cFile ) + cPath := iif( right( cPath, 1 ) $ "\/", substr( cPath, 1, len( cPath ) - 1 ), cPath ) + RETURN hbide_pathToOSPath( cPath + "\" + cFile ) + +/*----------------------------------------------------------------------*/ + FUNCTION hbide_pathToOSPath( cPath ) cPath := strtran( cPath, "/" , hb_osPathSeparator() ) @@ -763,8 +783,22 @@ FUNCTION hbide_parseKeyValPair( s, cKey, cVal ) /*----------------------------------------------------------------------*/ +FUNCTION hbide_parseFilter( s, cKey, cVal ) + LOCAL n, n1, lYes := .f. + + IF ( n := at( "{", s ) ) > 0 + IF ( n1 := at( "}", s ) ) > 0 + cKey := alltrim( substr( s, n+1, n1-n-1 ) ) + cVal := alltrim( substr( s, n1+1 ) ) + lYes := .t. + ENDIF + ENDIF + RETURN lYes + +/*----------------------------------------------------------------------*/ + FUNCTION hbide_dbg( ... ) - HB_TRACE( HB_TR_ALWAYS, procname(1),... ) + HB_TRACE( HB_TR_ALWAYS, ... ) RETURN nil /*----------------------------------------------------------------------*/ @@ -805,8 +839,7 @@ FUNCTION hbide_checkDefaultExtension( cFileName, cDefaultExt ) /*----------------------------------------------------------------------*/ FUNCTION hbide_pathProc( cPathR, cPathA ) - LOCAL cDirA - LOCAL cDirR, cDriveR, cNameR, cExtR + LOCAL cDirA, cDirR, cDriveR, cNameR, cExtR IF Empty( cPathA ) RETURN cPathR diff --git a/harbour/contrib/hbide/ideobject.prg b/harbour/contrib/hbide/ideobject.prg index 94e5e71472..1afdc8a1fe 100644 --- a/harbour/contrib/hbide/ideobject.prg +++ b/harbour/contrib/hbide/ideobject.prg @@ -89,6 +89,7 @@ CLASS IdeObject ACCESS oDK INLINE ::oIde:oDK ACCESS oAC INLINE ::oIde:oAC ACCESS oSM INLINE ::oIde:oSM + ACCESS oEV INLINE ::oIde:oEV ACCESS aMeta INLINE ::oIde:aMeta @@ -108,6 +109,10 @@ CLASS IdeObject ACCESS cWrkProject INLINE ::oIde:cWrkProject ACCESS cWrkTheme INLINE ::oIde:cWrkTheme ACCESS cWrkCodec INLINE ::oIde:cWrkCodec + ACCESS cWrkPathMk2 INLINE ::oIde:cWrkPathMk2 + ACCESS cWrkPathEnv INLINE ::oIde:cWrkPathEnv + ACCESS cWrkEnvironment INLINE ::oIde:cWrkEnvironment + // ACCESS resPath INLINE ::oIde:resPath ACCESS pathSep INLINE ::oIde:pathSep ACCESS cLastFileOpenPath INLINE ::oIde:cLastFileOpenPath diff --git a/harbour/contrib/hbide/ideprojmanager.prg b/harbour/contrib/hbide/ideprojmanager.prg index 9cbff2dbf9..9e1260ebdc 100644 --- a/harbour/contrib/hbide/ideprojmanager.prg +++ b/harbour/contrib/hbide/ideprojmanager.prg @@ -69,19 +69,129 @@ #include "common.ch" #include "hbclass.ch" +/*----------------------------------------------------------------------*/ +// +// Class IdeEnvironments +// /*----------------------------------------------------------------------*/ -#define CHN_BGN 1 -#define CHN_OUT 2 -#define CHN_ERR 3 -#define CHN_FIN 4 -#define CHN_STT 5 -#define CHN_ERE 6 -#define CHN_CLO 7 -#define CHN_BYT 8 -#define CHN_RCF 9 -#define CHN_REA 10 +CLASS IdeEnvironments + DATA oIde + DATA cEnvFile + DATA aNames INIT {} + DATA aEnvrns INIT {} + DATA aShellContents INIT {} + DATA aCommons INIT {} + + METHOD new( oIde, cEnvFile ) + METHOD create( oIde, cEnvFile ) + METHOD parse( aContents ) + METHOD prepareBatch( cEnviron ) + METHOD getNames() INLINE ::aNames + + ENDCLASS + +/*----------------------------------------------------------------------*/ + +METHOD IdeEnvironments:new( oIde, cEnvFile ) + + ::oIde := oIde + ::cEnvFile := cEnvFile + + RETURN Self + +/*----------------------------------------------------------------------*/ + +METHOD IdeEnvironments:create( oIde, cEnvFile ) + LOCAL a_ + + DEFAULT oIde TO ::oIde + DEFAULT cEnvFile TO ::cEnvFile + + ::oIde := oIde + ::cEnvFile := cEnvFile + + IF empty( ::cEnvFile ) .OR. !hb_fileExists( ::cEnvFile ) + RETURN Self + ENDIF + + a_:= hbide_readSource( ::cEnvFile ) + + ::parse( a_ ) + + RETURN Self + +/*----------------------------------------------------------------------*/ + +METHOD IdeEnvironments:parse( aContents ) + LOCAL s, cPart, cEnv, a_, cKey, cVal + + a_:= {} + cEnv := "" + FOR EACH s IN aContents + s := alltrim( s ) + IF empty( s ) .OR. left( s, 1 ) == "#" /* Remark */ + LOOP + ENDIF + IF left( s, 1 ) == "[" + s := alltrim( strtran( s, "[", "" ) ) + s := alltrim( strtran( s, "]", "" ) ) + IF lower( s ) == "common" + cPart := "common" + ELSE + cPart := "environment" + IF ( s != cEnv ) .AND. !empty( cEnv ) + aadd( ::aNames, cEnv ) + aadd( ::aEnvrns, { cEnv, a_ } ) + ENDIF + cEnv := s + a_:= {} + ENDIF + ELSE + IF cPart == "common" + IF hbide_parseKeyValPair( s, @cKey, @cVal ) + aadd( ::aCommons, { lower( cKey ), cVal } ) /* Format Later */ + ENDIF + ELSEIF cPart == "environment" + IF hbide_parseFilter( s, @cKey, @cVal ) + aadd( a_, { lower( cKey ), cVal } ) + ENDIF + ENDIF + ENDIF + NEXT + IF !empty( cEnv ) .AND. !empty( a_ ) + aadd( ::aNames, cEnv ) + aadd( ::aEnvrns, { cKey, a_ } ) + ENDIF + + RETURN Self + +/*----------------------------------------------------------------------*/ + +METHOD IdeEnvironments:prepareBatch( cEnviron ) + LOCAL n, cFile := space( 255 ), s, k, nHandle, a_ + + IF ( n := ascan( ::aEnvrns, {|e_| e_[ 1 ] == cEnviron } ) ) > 0 + IF ( nHandle := HB_FTempCreateEx( @cFile, NIL, "ide_", ".bat" ) ) > 0 + k := "" + FOR EACH a_ IN ::aEnvrns[ n, 2 ] + s := a_[ 1 ] + IF s == "content" + k += a_[ 2 ] + CRLF + ENDIF + NEXT + fWrite( nHandle, k ) + fClose( nHandle ) + ENDIF + ENDIF + + RETURN cFile + +/*----------------------------------------------------------------------*/ +// +// Class IdeProject +// /*----------------------------------------------------------------------*/ CLASS IdeProject @@ -97,6 +207,7 @@ CLASS IdeProject DATA wrkDirectory INIT hb_dirBase() + "projects" DATA destination INIT hb_dirBase() + "projects" DATA outputName INIT hb_dirBase() + "projects" + DATA backup INIT "" DATA launchParams INIT "" DATA launchProgram INIT "" DATA hbpFlags INIT {} @@ -104,9 +215,10 @@ CLASS IdeProject DATA metaData INIT {} DATA dotHbp INIT "" DATA compilers INIT "" - DATA hbmk2dir INIT hb_getenv( "HBIDE_DIR_HBMK2" ) + DATA cPathMk2 INIT hb_getenv( "HBIDE_DIR_HBMK2" ) + DATA cPathEnv INIT hb_DirBase() + "resources" - METHOD new( aProps ) + METHOD new( oIde, aProps ) METHOD applyMeta( s ) METHOD expandMeta( s ) @@ -114,7 +226,7 @@ CLASS IdeProject /*----------------------------------------------------------------------*/ -METHOD IdeProject:new( aProps ) +METHOD IdeProject:new( oIde, aProps ) LOCAL b_, a_ IF hb_isArray( aProps ) .AND. !empty( aProps ) @@ -148,6 +260,12 @@ METHOD IdeProject:new( aProps ) IF empty( ::wrkDirectory ) ::wrkDirectory := ::location ENDIF + IF !empty( oIde:aINI[ INI_HBIDE, PathMk2 ] ) + ::cPathMk2 := oIde:aINI[ INI_HBIDE, PathMk2 ] + ENDIF + IF !empty( oIde:aINI[ INI_HBIDE, PathEnv ] ) + ::cPathEnv := oIde:aINI[ INI_HBIDE, PathEnv ] + ENDIF FOR EACH a_ IN ::metaData a_[ 2 ] := hbide_pathNormalized( a_[ 2 ], .f. ) @@ -193,7 +311,6 @@ CLASS IdeProjManager INHERIT IdeObject DATA cSaveTo DATA aPrjProps INIT {} - DATA qProcess DATA nStarted INIT 0 DATA lLaunch INIT .f. @@ -201,6 +318,8 @@ CLASS IdeProjManager INHERIT IdeObject DATA cPPO INIT "" DATA lPPO INIT .f. DATA oProject + DATA cBatch + DATA oProcess METHOD new( oIde ) METHOD create( oIde ) @@ -224,10 +343,10 @@ CLASS IdeProjManager INHERIT IdeObject METHOD closeProject( cProject ) METHOD promptForPath( cObjPathName, cTitle, cObjFileName, cObjPath2, cObjPath3 ) METHOD buildProject( cProject, lLaunch, lRebuild, lPPO, lViaQt ) - METHOD buildProcess() - METHOD readProcessInfo( nMode, i, ii ) METHOD launchProject( cProject ) - + METHOD showOutput( cOutput, mp2, oProcess ) + METHOD finished( nExitCode, nExitStatus, oProcess ) + METHOD saveEnvironments() ENDCLASS /*----------------------------------------------------------------------*/ @@ -327,7 +446,7 @@ METHOD IdeProjManager:loadProperties( cProjFileName, lNew, lFetch, lUpdateTree ) IF lFetch /* Access/Assign via this object */ - ::oProject := IdeProject():new( ::aPrjProps ) + ::oProject := IdeProject():new( ::oIde, ::aPrjProps ) // ::fetchProperties() IF !empty( ::cSaveTo ) .and. hb_FileExists( ::cSaveTo ) @@ -380,13 +499,18 @@ METHOD IdeProjManager:fetchProperties() ENDCASE cLukupPng := ::resPath + "folder.png" + // ::oUI:q_buttonChoosePrjLoc:setIcon( cLukupPng ) - ::oUI:q_buttonChooseWd:setIcon( cLukupPng ) - ::oUI:q_buttonChooseDest:setIcon( cLukupPng ) + ::oUI:q_buttonChooseWd :setIcon( cLukupPng ) + ::oUI:q_buttonChooseDest :setIcon( cLukupPng ) + ::oUI:q_buttonBackup :setIcon( cLukupPng ) + ::oUI:q_buttonPathMk2 :setIcon( cLukupPng ) + ::oUI:q_buttonPathEnv :setIcon( cLukupPng ) + ::oUI:q_buttonSaveEnv :setIcon( ::resPath + "save.png" ) - ::oUI:q_buttonSelect:setIcon( ::resPath + "open.png" ) - ::oUI:q_buttonSort:setIcon( ::resPath + "toupper.png" ) // TODO: toupper.png => atoz.png - ::oUI:q_buttonSortZA:setIcon( ::resPath + "tolower.png" ) // tolower.png => ztoa.png + ::oUI:q_buttonSelect :setIcon( ::resPath + "open.png" ) + ::oUI:q_buttonSort :setIcon( ::resPath + "toupper.png" ) // TODO: toupper.png => atoz.png + ::oUI:q_buttonSortZA :setIcon( ::resPath + "tolower.png" ) // tolower.png => ztoa.png ::oUI:q_buttonSortOrg:setIcon( ::resPath + "invertcase.png" ) // tolower.png => ztoa.png ::oUI:signal( "buttonCn" , "clicked()", {|| ::oUI:oWidget:close() } ) @@ -396,14 +520,22 @@ METHOD IdeProjManager:fetchProperties() ::oUI:signal( "buttonSort" , "clicked()", {|| ::sortSources( "az" ) } ) ::oUI:signal( "buttonSortZA" , "clicked()", {|| ::sortSources( "za" ) } ) ::oUI:signal( "buttonSortOrg" , "clicked()", {|| ::sortSources( "org" ) } ) + ::oUI:signal( "buttonSaveEnv" , "clicked()", {|| ::saveEnvironments() } ) // ::oUI:signal( "tabWidget" , "currentChanged(int)", {|o,p| ::updateHbp( p, o ) } ) - ::oUI:signal( "editMetaData" , "textChanged()", {|o| ::updateMetaData( o ) } ) + ::oUI:signal( "editMetaData" , "textChanged()" , {|o| ::updateMetaData( o ) } ) - ::oUI:signal( "buttonChoosePrjLoc", "clicked()", {|| ::PromptForPath( 'editPrjLoctn', 'Choose the Project Location...' ) } )//, ; - // 'editOutName', "editWrkFolder", "editDstFolder" ) } ) - ::oUI:signal( "buttonChooseWd" , "clicked()", {|| ::PromptForPath( 'editWrkFolder', 'Choose a Working Folder...' ) } ) - ::oUI:signal( "buttonChooseDest" , "clicked()", {|| ::PromptForPath( 'editDstFolder', 'Choose a Destination Folder...' ) } ) + ::oUI:signal( "buttonChoosePrjLoc", "clicked()", {|| ::PromptForPath( 'editPrjLoctn' , 'Choose Project Location...' ) } ) + ::oUI:signal( "buttonChooseWd" , "clicked()", {|| ::PromptForPath( 'editWrkFolder', 'Choose Working Folder...' ) } ) + ::oUI:signal( "buttonChooseDest" , "clicked()", {|| ::PromptForPath( 'editDstFolder', 'Choose Destination Folder...' ) } ) + ::oUI:signal( "buttonBackup" , "clicked()", {|| ::PromptForPath( 'editBackup' , 'Choose Backup Folder...' ) } ) + ::oUI:signal( "buttonPathMk2" , "clicked()", {|| ::PromptForPath( 'editPathMk2' , 'Choose hbMK2.exe Folder...' ) } ) + ::oUI:signal( "buttonPathEnv" , "clicked()", {|| ::PromptForPath( 'editPathEnv' , 'Choose hbIDE.env Folder...' ), ; + ::oUI:q_editCompilers:setPlainText( hb_memoread( hbide_pathToOSPath( ::oUI:q_editPathEnv:text() + ::pathSep + "hbide.env" ) ) ) } ) + + ::oUI:q_editPathMk2 :setText( ::aINI[ INI_HBIDE, PathMk2 ] ) + ::oUI:q_editPathEnv :setText( ::aINI[ INI_HBIDE, PathEnv ] ) + ::oUI:q_editCompilers:setPlainText( hb_memoread( hbide_pathToOSPath( ::aINI[ INI_HBIDE, PathEnv ] + ::pathSep + "hbide.env" ) ) ) IF empty( ::aPrjProps ) /* @@ -414,16 +546,16 @@ METHOD IdeProjManager:fetchProperties() ::oUI:q_editPrjLoctn:setText( hbide_pathNormalized( cPrjLoc, .F. ) ) ELSE - ::oUI:q_editPrjTitle:setText( ::oProject:applyMeta( ::oProject:title ) ) - ::oUI:q_editPrjLoctn:setText( ::oProject:applyMeta( ::oProject:location ) ) + ::oUI:q_editPrjTitle :setText( ::oProject:applyMeta( ::oProject:title ) ) + ::oUI:q_editPrjLoctn :setText( ::oProject:applyMeta( ::oProject:location ) ) ::oUI:q_editWrkFolder:setText( ::oProject:applyMeta( ::oProject:wrkDirectory ) ) - ::oUI:q_editDstFolder:setText( ::oProject:applyMeta( ::oProject:destination ) ) - ::oUI:q_editOutName:setText( ::oProject:outputName ) + ::oUI:q_editDstFolder:setText( ::oProject:applyMeta( ::oProject:destination ) ) + ::oUI:q_editBackup :setText( ::oProject:applyMeta( ::oProject:backup ) ) + ::oUI:q_editOutName :setText( ::oProject:outputName ) - ::oUI:q_editFlags:setPlainText( hbide_arrayToMemo( ::aPrjProps[ PRJ_PRP_FLAGS , 1 ] ) ) - ::oUI:q_editSources:setPlainText( hbide_arrayToMemo( ::aPrjProps[ PRJ_PRP_SOURCES , 1 ] ) ) - ::oUI:q_editMetaData:setPlainText( hbide_arrayToMemo( ::aPrjProps[ PRJ_PRP_METADATA, 1 ] ) ) - ::oUI:q_editCompilers:setPlainText( memoread( hb_dirBase() + "hbide.env" ) ) + ::oUI:q_editFlags :setPlainText( hbide_arrayToMemo( ::aPrjProps[ PRJ_PRP_FLAGS , 1 ] ) ) + ::oUI:q_editSources :setPlainText( hbide_arrayToMemo( ::aPrjProps[ PRJ_PRP_SOURCES , 1 ] ) ) + ::oUI:q_editMetaData :setPlainText( hbide_arrayToMemo( ::aPrjProps[ PRJ_PRP_METADATA, 1 ] ) ) #if 0 ::oUI:q_editLaunchParams:setText() @@ -453,6 +585,169 @@ METHOD IdeProjManager:fetchProperties() /*----------------------------------------------------------------------*/ +METHOD IdeProjManager:save( lCanClose ) + LOCAL a_, lOk, cPath, txt_ + + * Validate certain parameters before continuing ... (vailtom) + + /* Title cannot be the output name, but reverse is possible + -------------------------------------------------------- + We must also consider that user may be building the project in parts + OR may be basic definition must be in place + */ + IF Empty( ::oUI:q_editPrjTitle:text() ) + ::oUI:q_editPrjTitle:setText( ::oUI:q_editOutName:text() ) + ENDIF + + IF Empty( ::oUI:q_editOutName:text() ) + MsgBox( 'Invalid Output FileName' ) + ::oUI:q_editOutName:setFocus() + RETURN .F. + ENDIF + + /* This must be valid, we cannot skip */ + IF !hbide_isValidPath( ::oProject:expandMeta( ::oUI:q_editPrjLoctn:text() ), 'Project Location' ) + ::oUI:q_editPrjLoctn:setFocus() + RETURN .F. + ENDIF + + /* This we can skip now: later at project building we can check: TO:RECONSIDER */ + IF !empty( cPath := ::oUI:q_editWrkFolder:text() ) + IF !hbide_isValidPath( ::oProject:expandMeta( cPath ), 'Working Folder' ) + // ::oUI:q_editWrkFolder:setText( ::oUI:q_editPrjLoctn:text() ) + RETURN .F. + ENDIF + ENDIF + + /* This we can skip now: later at project building we can check: TO:RECONSIDER */ + IF !empty( cPath := ::oUI:q_editDstFolder:text() ) + IF !hbide_isValidPath( ::oProject:expandMeta( cPath ), 'Destination Folder' ) + // ::oUI:q_editDstFolder:setText( ::oUI:q_editPrjLoctn:text() ) + RETURN .F. + ENDIF + ENDIF + + txt_:= {} + // + aadd( txt_, "[ PROPERTIES ]" ) + aadd( txt_, "Type = " + { "Executable", "Lib", "Dll" }[ ::oUI:q_comboPrjType:currentIndex()+1 ] ) + aadd( txt_, "Title = " + ::oUI:q_editPrjTitle :text() ) + aadd( txt_, "Location = " + ::oUI:q_editPrjLoctn :text() ) + aadd( txt_, "WorkingFolder = " + ::oUI:q_editWrkFolder :text() ) + aadd( txt_, "DestinationFolder = " + ::oUI:q_editDstFolder :text() ) + aadd( txt_, "Output = " + ::oUI:q_editOutName :text() ) + aadd( txt_, "LaunchParams = " + ::oUI:q_editLaunchParams:text() ) + aadd( txt_, "LaunchProgram = " + ::oUI:q_editLaunchExe :text() ) + aadd( txt_, "BackupFolder = " + ::oUI:q_editBackup :text() ) + aadd( txt_, " " ) + // + aadd( txt_, "[ FLAGS ]" ) + a_:= hbide_memoToArray( ::oUI:q_editFlags:toPlainText() ) ; aeval( a_, {|e| aadd( txt_, e ) } ) ; aadd( txt_, " " ) + aadd( txt_, "[ SOURCES ]" ) + a_:= hbide_memoToArray( ::oUI:q_editSources:toPlainText() ) ; aeval( a_, {|e| aadd( txt_, e ) } ) ; aadd( txt_, " " ) + aadd( txt_, "[ METADATA ]" ) + a_:= hbide_memoToArray( ::oUI:q_editMetaData:toPlainText() ); aeval( a_, {|e| aadd( txt_, e ) } ) ; aadd( txt_, " " ) + + #if 0 + /* Setup Meta Keys */ + a4_1 := hbide_setupMetaKeys( a_ ) + + ::cSaveTo := hbide_parseWithMetaData( ::oUI:q_editPrjLoctn:text(), a4_1 ) + ; + ::pathSep + ; + hbide_parseWithMetaData( ::oUI:q_editOutName:text(), a4_1 ) + ; + ".hbi" + ::cSaveTo := hbide_pathToOSPath( ::cSaveTo ) + #endif + + ::cSaveTo := ::oProject:expandMeta( ::oUI:q_editPrjLoctn:text() ) + ; + ::pathSep + ; + ::oProject:expandMeta( ::oUI:q_editOutName:text() ) + ; + ".hbi" + ::cSaveTo := hbide_pathToOSPath( ::cSaveTo ) + + IF ( lOk := hbide_createTarget( ::cSaveTo, txt_ ) ) +* MsgBox( 'The project file is saved successfully: ' + ::cSaveTo, 'Saving project ...' ) + ELSE + MsgBox( 'Error saving project file: ' + ::cSaveTo, 'Error saving project ...' ) + ENDIF + + IF lCanClose .AND. lOk + ::oUI:oWidget:close() + ENDIF + + RETURN lOk + +/*----------------------------------------------------------------------*/ + +METHOD IdeProjManager:saveEnvironments() + LOCAL cText + + ::oProject:cPathMk2 := ::oUI:q_editPathMk2:text() + ::oProject:cPathEnv := ::oUI:q_editPathEnv:text() + + ::oIde:aINI[ INI_HBIDE, PathMk2 ] := ::oProject:cPathMk2 + ::oIde:aINI[ INI_HBIDE, PathEnv ] := ::oProject:cPathEnv + // + ::oIde:cWrkPathMk2 := ::oProject:cPathMk2 + ::oIde:cWrkPathEnv := ::oProject:cPathEnv + + IF !empty( cText := ::oUI:q_editCompilers:toPlainText() ) + hb_MemoWrit( hbide_pathFile( ::oProject:cPathEnv, "hbide.env" ), cText ) + ENDIF + + RETURN Self + +/*----------------------------------------------------------------------*/ + +METHOD IdeProjManager:updateHbp( iIndex ) + LOCAL a_, a4_1, txt_, s + LOCAL cExt + + IF iIndex != 3 + RETURN nil + ENDIF + + a_:= hb_atokens( strtran( ::oUI:q_editMetaData:toPlainText(), chr( 13 ) ), _EOL ) + a4_1 := hbide_setupMetaKeys( a_ ) + + txt_:= {} + /* This block will be absent when submitting to hbmk engine */ + aadd( txt_, "# " + hbide_parseWithMetaData( ::oUI:q_editWrkFolder:text(), a4_1 ) + ::pathSep + ; + hbide_parseWithMetaData( ::oUI:q_editOutName:text(), a4_1 ) + ".hbp" ) + aadd( txt_, " " ) + + /* Flags */ + a_:= hb_atokens( ::oUI:q_editFlags:toPlainText(), _EOL ) + FOR EACH s IN a_ + s := alltrim( s ) + IF !( "#" == left( s,1 ) ) .and. !empty( s ) + s := hbide_parseWithMetaData( s, a4_1 ) + aadd( txt_, s ) + ENDIF + NEXT + aadd( txt_, " " ) + + /* Sources */ + a_:= hb_atokens( ::oUI:q_editSources:toPlainText(), _EOL ) + FOR EACH s IN a_ + s := alltrim( s ) + IF !( "#" == left( s,1 ) ) .and. !empty( s ) + s := hbide_parseWithMetaData( s, a4_1 ) + hb_FNameSplit( s, , , @cExt ) + IF lower( cExt ) $ ".c,.cpp,.prg,.rc,.res" + aadd( txt_, s ) + ENDIF + ENDIF + NEXT + aadd( txt_, " " ) + + /* Final assault */ + ::oUI:q_editHbp:setPlainText( hbide_arrayToMemo( txt_ ) ) + + RETURN txt_ + +/*----------------------------------------------------------------------*/ + METHOD IdeProjManager:sortSources( cMode ) LOCAL a_, cTyp, s, d_, n LOCAL aSrc := { ".ch", ".prg", ".c", ".cpp", ".h", ".obj", ".o", ".lib", ".a", ".rc", ".res" } @@ -531,149 +826,6 @@ METHOD IdeProjManager:updateMetaData() /*----------------------------------------------------------------------*/ -METHOD IdeProjManager:save( lCanClose ) - LOCAL a_, lOk, cPath, txt_ - - * Validate certain parameters before continuing ... (vailtom) - - /* Title cannot be the output name, but reverse is possible - -------------------------------------------------------- - We must also consider that user may be building the project in parts - OR may be basic definition must be in place - */ - IF Empty( ::oUI:q_editPrjTitle:text() ) - ::oUI:q_editPrjTitle:setText( ::oUI:q_editOutName:text() ) - ENDIF - - IF Empty( ::oUI:q_editOutName:text() ) - MsgBox( 'Invalid Output FileName' ) - ::oUI:q_editOutName:setFocus() - RETURN .F. - ENDIF - - /* This must be valid, we cannot skip */ - IF !hbide_isValidPath( ::oProject:expandMeta( ::oUI:q_editPrjLoctn:text() ), 'Project Location' ) - ::oUI:q_editPrjLoctn:setFocus() - RETURN .F. - ENDIF - - /* This we can skip now: later at project building we can check: TO:RECONSIDER */ - IF !empty( cPath := ::oUI:q_editWrkFolder:text() ) - IF !hbide_isValidPath( ::oProject:expandMeta( cPath ), 'Working Folder' ) - // ::oUI:q_editWrkFolder:setText( ::oUI:q_editPrjLoctn:text() ) - RETURN .F. - ENDIF - ENDIF - - /* This we can skip now: later at project building we can check: TO:RECONSIDER */ - IF !empty( cPath := ::oUI:q_editDstFolder:text() ) - IF !hbide_isValidPath( ::oProject:expandMeta( cPath ), 'Destination Folder' ) - // ::oUI:q_editDstFolder:setText( ::oUI:q_editPrjLoctn:text() ) - RETURN .F. - ENDIF - ENDIF - - txt_:= {} - // - aadd( txt_, "[ PROPERTIES ]" ) - aadd( txt_, "Type = " + { "Executable", "Lib", "Dll" }[ ::oUI:q_comboPrjType:currentIndex()+1 ] ) - aadd( txt_, "Title = " + ::oUI:q_editPrjTitle:text() ) - aadd( txt_, "Location = " + ::oUI:q_editPrjLoctn:text() ) - aadd( txt_, "WorkingFolder = " + ::oUI:q_editWrkFolder:text() ) - aadd( txt_, "DestinationFolder = " + ::oUI:q_editDstFolder:text() ) - aadd( txt_, "Output = " + ::oUI:q_editOutName:text() ) - aadd( txt_, "LaunchParams = " + ::oUI:q_editLaunchParams:text() ) - aadd( txt_, "LaunchProgram = " + ::oUI:q_editLaunchExe:text() ) - aadd( txt_, " " ) - // - aadd( txt_, "[ FLAGS ]" ) - a_:= hbide_memoToArray( ::oUI:q_editFlags:toPlainText() ) ; aeval( a_, {|e| aadd( txt_, e ) } ) ; aadd( txt_, " " ) - aadd( txt_, "[ SOURCES ]" ) - a_:= hbide_memoToArray( ::oUI:q_editSources:toPlainText() ) ; aeval( a_, {|e| aadd( txt_, e ) } ) ; aadd( txt_, " " ) - aadd( txt_, "[ METADATA ]" ) - a_:= hbide_memoToArray( ::oUI:q_editMetaData:toPlainText() ); aeval( a_, {|e| aadd( txt_, e ) } ) ; aadd( txt_, " " ) - - #if 0 - /* Setup Meta Keys */ - a4_1 := hbide_setupMetaKeys( a_ ) - - ::cSaveTo := hbide_parseWithMetaData( ::oUI:q_editPrjLoctn:text(), a4_1 ) + ; - ::pathSep + ; - hbide_parseWithMetaData( ::oUI:q_editOutName:text(), a4_1 ) + ; - ".hbi" - ::cSaveTo := hbide_pathToOSPath( ::cSaveTo ) - #endif - - ::cSaveTo := ::oProject:expandMeta( ::oUI:q_editPrjLoctn:text() ) + ; - ::pathSep + ; - ::oProject:expandMeta( ::oUI:q_editOutName:text() ) + ; - ".hbi" - ::cSaveTo := hbide_pathToOSPath( ::cSaveTo ) - - IF ( lOk := hbide_createTarget( ::cSaveTo, txt_ ) ) - *MsgBox( 'The project file was saved successfully: ' + ::cSaveTo, 'Saving project ...' ) - hb_MemoWrit( hb_dirBase() + "hbide.env", ::oUI:q_editCompilers:toPlainText() ) - ELSE - MsgBox( 'Error saving project file: ' + ::cSaveTo, 'Error saving project ...' ) - ENDIF - - IF lCanClose .AND. lOk - ::oUI:oWidget:close() - ENDIF - - RETURN lOk - -/*----------------------------------------------------------------------*/ - -METHOD IdeProjManager:updateHbp( iIndex ) - LOCAL a_, a4_1, txt_, s - LOCAL cExt - - IF iIndex != 3 - RETURN nil - ENDIF - - a_:= hb_atokens( strtran( ::oUI:q_editMetaData:toPlainText(), chr( 13 ) ), _EOL ) - a4_1 := hbide_setupMetaKeys( a_ ) - - txt_:= {} - /* This block will be absent when submitting to hbmk engine */ - aadd( txt_, "# " + hbide_parseWithMetaData( ::oUI:q_editWrkFolder:text(), a4_1 ) + ::pathSep + ; - hbide_parseWithMetaData( ::oUI:q_editOutName:text(), a4_1 ) + ".hbp" ) - aadd( txt_, " " ) - - /* Flags */ - a_:= hb_atokens( ::oUI:q_editFlags:toPlainText(), _EOL ) - FOR EACH s IN a_ - s := alltrim( s ) - IF !( "#" == left( s,1 ) ) .and. !empty( s ) - s := hbide_parseWithMetaData( s, a4_1 ) - aadd( txt_, s ) - ENDIF - NEXT - aadd( txt_, " " ) - - /* Sources */ - a_:= hb_atokens( ::oUI:q_editSources:toPlainText(), _EOL ) - FOR EACH s IN a_ - s := alltrim( s ) - IF !( "#" == left( s,1 ) ) .and. !empty( s ) - s := hbide_parseWithMetaData( s, a4_1 ) - hb_FNameSplit( s, , , @cExt ) - IF lower( cExt ) $ ".c,.cpp,.prg,.rc,.res" - aadd( txt_, s ) - ENDIF - ENDIF - NEXT - aadd( txt_, " " ) - - /* Final assault */ - ::oUI:q_editHbp:setPlainText( hbide_arrayToMemo( txt_ ) ) - - RETURN txt_ - -/*----------------------------------------------------------------------*/ - METHOD IdeProjManager:addSources() LOCAL aFiles, a_, b_, a4_1, s @@ -827,7 +979,7 @@ METHOD IdeProjManager:getProjectByFile( cProjectFile ) aProj := ::aProjects[ n ] ENDIF - RETURN IdeProject():new( aProj ) + RETURN IdeProject():new( ::oIde, aProj ) /*----------------------------------------------------------------------*/ @@ -838,7 +990,7 @@ METHOD IdeProjManager:getProjectByTitle( cProjectTitle ) aProj := ::aProjects[ n, 3 ] ENDIF - RETURN IdeProject():new( aProj ) + RETURN IdeProject():new( ::oIde, aProj ) /*----------------------------------------------------------------------*/ @@ -912,8 +1064,9 @@ METHOD IdeProjManager:promptForPath( cObjPathName, cTitle, cObjFileName, cObjPat /*----------------------------------------------------------------------*/ METHOD IdeProjManager:buildProject( cProject, lLaunch, lRebuild, lPPO, lViaQt ) - LOCAL cOutput, cErrors, cHbpPath, qStringList, oEdit, cHbpFN, cTmp, nResult, cTargetFN - LOCAL aHbp := {} + LOCAL cHbpPath, oEdit, cHbpFN, cTmp, cTargetFN, cExeHbMk2, aHbp, cCmd + + aHbp := {} DEFAULT lLaunch TO .F. DEFAULT lRebuild TO .F. @@ -970,15 +1123,16 @@ METHOD IdeProjManager:buildProject( cProject, lLaunch, lRebuild, lPPO, lViaQt ) aadd( aHbp, "-o" + cTargetFN ) aadd( aHbp, "-workdir=" + ::oProject:wrkDirectory + "/${hb_plat}/${hb_comp}" ) ENDIF - aadd( aHbp, "-q" ) - aadd( aHbp, "-trace" ) - aadd( aHbp, "-info" ) + aadd( aHbp, "-q" ) + aadd( aHbp, "-trace" ) + aadd( aHbp, "-info" ) IF lRebuild - aadd( aHbp, "-rebuild" ) + aadd( aHbp, "-rebuild" ) ENDIF aadd( aHbp, " " ) IF !( ::lPPO ) + /* Add all sources to .hbp */ aadd( aHbp, "# Source Files" ) aadd( aHbp, " " ) aeval( hbide_filesToSources( ::oProject:sources ), {|e| aadd( aHbp, e ) } ) @@ -991,7 +1145,7 @@ METHOD IdeProjManager:buildProject( cProject, lLaunch, lRebuild, lPPO, lViaQt ) aadd( aHbp, "-p" ) aadd( aHbp, " " ) aadd( aHbp, "# Source File - PPO" ) - aadd( aHbp, " " ) + aadd( aHbp, " " ) // TODO: We have to test if the current file is part of a project, and we // pull your settings, even though this is not the active project - vailtom @@ -1018,8 +1172,6 @@ METHOD IdeProjManager:buildProject( cProject, lLaunch, lRebuild, lPPO, lViaQt ) ::oOutputResult:oWidget:append( 'Error saving: ' + cHbpPath ) ELSE - ::nStarted := seconds() - cTmp := hbide_outputLine() + CRLF + ; "Project [ " + cProject + " ] " + ; "Launch [ " + iif( lLaunch , 'Yes', 'No' ) + " ] " + ; @@ -1028,140 +1180,72 @@ METHOD IdeProjManager:buildProject( cProject, lLaunch, lRebuild, lPPO, lViaQt ) hbide_outputLine() + CRLF ::oOutputResult:oWidget:append( cTmp ) - IF lViaQt - ::buildProcess() + ::oIde:oEV := IdeEnvironments():new():create( ::oIde, hbide_pathFile( ::aINI[ INI_HBIDE, PathEnv ], "hbide.env" ) ) + ::cBatch := ::oEV:prepareBatch( ::cWrkEnvironment ) + #if 0 /* This does not works - reason being it picks up hbmk2 from fixed location */ + cExeHbMk2 := hbide_pathFile( ::oProject:cPathMk2, "hbmk2" ) + #else /* This works properly */ + cExeHbMk2 := "hbmk2" /* Needs that path is already set before calling hbmk2 */ + #endif - #if 0 /* Mechanism to supply environment variables to called process */ - /* I do not know nixes but assume that Qt must be issueing proper */ - /* shell command for the target OS to set them. */ - /* If I am not wrong, HBMK2 can have these variables alread set */ - /* and hence developer can choose any compiler of his choice. */ - /* */ - /* Actually, this was the intension in hbIDE.env I commited in IDE root */ - qStringList := QStringList():new() - qStringList:append( "HB_WITH_QT=c:\qt\4.5.3\lib" ) - ::qProcess:setEnvironment( qStringList ) + ::oProcess := HbpProcess():new() + // + ::oProcess:output := {|cOut, mp2, oHbp| ::showOutput( cOut,mp2,oHbp ) } + ::oProcess:finished := {|nEC , nES, oHbp| ::finished( nEC ,nES,oHbp ) } + ::oProcess:workingPath := ::oProject:wrkDirectory - qStringList := QStringList():new() - qStringList:append( [/c c:\batches\SetMinGW-harbour-E.bat && hbMK2.exe ] + cHbpPath ) - ::qProcess:start( "cmd.exe", qStringList ) - #else - - qStringList := QStringList():new() - IF ::lPPO - qStringList:append( "-hbraw" ) + #if 1 + cCmd := "cmd.exe" + IF empty( ::cBatch ) + ::oProcess:addArg( "/c " + cExeHbMk2 + " " + cHbpPath + iif( ::lPPO, " -hbraw", "" ) ) + ELSE + ::oProcess:addArg( "/c " + ::cBatch + " && " + cExeHbMk2 + " " + cHbpPath + iif( ::lPPO, " -hbraw", "" ) ) ENDIF - qStringList:append( cHbpPath ) - // - ::qProcess:setWorkingDirectory( ::oProject:wrkDirectory ) - // - ::qProcess:start( ::oProject:hbmk2dir + "hbmk2", qStringList ) - #endif - ELSE - cOutput := "" ; cErrors := "" - nResult := hb_processRun( ::oProject:hbmk2dir + "hbmk2 " + iif( ::lPPO, "-hbraw ", "" ) + cHbpPath, , @cOutput, @cErrors ) - - cTmp := cOutput + CRLF - cTmp += IIF( empty( cErrors ), "", cErrors ) + CRLF - cTmp += hbide_outputLine() + CRLF - cTmp += "Exit Code [ " + hb_ntos( nResult ) + " ] " + ; - "Finished at [ " + time() + " ] " + ; - "Done in [ " + hb_ntos( seconds() - ::nStarted ) + " Secs ]" + CRLF - cTmp += hbide_outputLine() + CRLF - - hbide_convertBuildStatusMsgToHtml( cTmp, ::oOutputResult:oWidget ) - - IF ( nResult == 0 ) .AND. ( lLaunch ) - ::LaunchProject( cProject ) - ENDIF - - IF ::lPPO .AND. hb_FileExists( ::cPPO ) - ::editSource( ::cPPO ) - ENDIF - ENDIF + #else + cCmd := "cmd.exe /c " + ::cBatch + " && " + cExeHbMk2 + " " + cHbpPath + iif( ::lPPO, " -hbraw", "" ) + #endif + ::oProcess:start( cCmd ) ENDIF RETURN Self /*----------------------------------------------------------------------*/ -METHOD IdeProjManager:buildProcess() +METHOD IdeProjManager:showOutput( cOutput, mp2, oProcess ) - ::qProcess := QProcess():new() - ::qProcess:setReadChannel( 1 ) + hbide_justACall( mp2, oProcess ) - Qt_Slots_Connect( ::pSlots, ::qProcess, "readyRead()" , {|o,i| ::readProcessInfo( CHN_REA, i, o ) } ) - Qt_Slots_Connect( ::pSlots, ::qProcess, "readChannelFinished()" , {|o,i| ::readProcessInfo( CHN_RCF, i, o ) } ) - Qt_Slots_Connect( ::pSlots, ::qProcess, "aboutToClose()" , {|o,i| ::readProcessInfo( CHN_CLO, i, o ) } ) - Qt_Slots_Connect( ::pSlots, ::qProcess, "bytesWritten(int)" , {|o,i| ::readProcessInfo( CHN_BYT, i, o ) } ) - Qt_Slots_Connect( ::pSlots, ::qProcess, "stateChanged(int)" , {|o,i| ::readProcessInfo( CHN_STT, i, o ) } ) - Qt_Slots_Connect( ::pSlots, ::qProcess, "error(int)" , {|o,i| ::readProcessInfo( CHN_ERE, i, o ) } ) - Qt_Slots_Connect( ::pSlots, ::qProcess, "started()" , {|o,i| ::readProcessInfo( CHN_BGN, o, i ) } ) - Qt_Slots_Connect( ::pSlots, ::qProcess, "readyReadStandardOutput()", {|o,i| ::readProcessInfo( CHN_OUT, i, o ) } ) - Qt_Slots_Connect( ::pSlots, ::qProcess, "readyReadStandardError()" , {|o,i| ::readProcessInfo( CHN_ERR, i, o ) } ) - Qt_Slots_Connect( ::pSlots, ::qProcess, "finished(int,int)" , {|o,i,ii| ::readProcessInfo( CHN_FIN, i, ii, o ) } ) + hbide_convertBuildStatusMsgToHtml( cOutput, ::oOutputResult:oWidget ) RETURN Self /*----------------------------------------------------------------------*/ -METHOD IdeProjManager:readProcessInfo( nMode, i, ii ) - LOCAL cLine, cTmp, nSize +METHOD IdeProjManager:finished( nExitCode, nExitStatus, oProcess ) + LOCAL cTmp - nSize := 16384 + hbide_justACall( oProcess ) - DO CASE - CASE nMode == CHN_REA // ReadReady() + cTmp := hbide_outputLine() + CRLF + cTmp += "Exit Code [ " + hb_ntos( nExitCode ) + " ] Exit Status [ " + hb_ntos( nExitStatus ) + " ] " +; + "Finished at [ " + time() + " ] Done in [ " + hb_ntos( seconds() - oProcess:started ) +" Secs ]" + CRLF + cTmp += hbide_outputLine() + CRLF - CASE nMode == CHN_OUT - ::qProcess:setReadChannel( 0 ) - cLine := space( nSize ) - ::qProcess:read( @cLine, nSize ) - IF !empty( cLine ) - hbide_convertBuildStatusMsgToHtml( trim( cLine ), ::oOutputResult:oWidget ) - ENDIF + ::oOutputResult:oWidget:append( cTmp ) - CASE nMode == CHN_ERR - ::qProcess:setReadChannel( 1 ) - cLine := space( nSize ) - ::qProcess:read( @cLine, nSize ) - IF !empty( cLine ) - hbide_convertBuildStatusMsgToHtml( trim( cLine ), ::oOutputResult:oWidget ) - ENDIF + ferase( ::cBatch ) - CASE nMode == CHN_FIN - cTmp := hbide_outputLine() + CRLF - cTmp += "Exit Code [ " + hb_ntos( i ) + " ] Exit Status [ " + hb_ntos( ii ) + " ] " +; - "Finished at [ " + time() + " ] Done in [ " + hb_ntos( seconds() - ::nStarted ) +" Secs ]" + CRLF - cTmp += hbide_outputLine() + CRLF - - ::oOutputResult:oWidget:append( cTmp ) - - Qt_Slots_disConnect( ::pSlots, ::qProcess, "readyRead()" ) - Qt_Slots_disConnect( ::pSlots, ::qProcess, "readChannelFinished()" ) - Qt_Slots_disConnect( ::pSlots, ::qProcess, "aboutToClose()" ) - Qt_Slots_disConnect( ::pSlots, ::qProcess, "bytesWritten(int)" ) - Qt_Slots_disConnect( ::pSlots, ::qProcess, "stateChanged(int)" ) - Qt_Slots_disConnect( ::pSlots, ::qProcess, "error(int)" ) - Qt_Slots_disConnect( ::pSlots, ::qProcess, "started()" ) - Qt_Slots_disConnect( ::pSlots, ::qProcess, "readyReadStandardOutput()" ) - Qt_Slots_disConnect( ::pSlots, ::qProcess, "readyReadStandardError()" ) - Qt_Slots_disConnect( ::pSlots, ::qProcess, "finished(int,int)" ) - - ::qProcess:kill() - ::qProcess:pPtr := 0 - ::qProcess := NIL - - IF ::lLaunch + IF ::lLaunch + IF nExitCode == 0 ::launchProject( ::cProjectInProcess ) ENDIF - IF ::lPPO .AND. hb_FileExists( ::cPPO ) - ::editSource( ::cPPO ) - ENDIF - ENDCASE + ENDIF + IF ::lPPO .AND. hb_FileExists( ::cPPO ) + ::editSource( ::cPPO ) + ENDIF - RETURN nil + RETURN Self /*----------------------------------------------------------------------*/ /* @@ -1193,19 +1277,43 @@ METHOD IdeProjManager:launchProject( cProject ) cTmp := "Launch application error: file not found " + cTargetFN + "!" ELSEIF oProject:type == "Executable" - cTmp := "Launch application " + cTargetFN + "... " - qProcess := QProcess():new() + // + //qProcess:setWorkingDirectory( hbide_pathToOSPath( oProject:wrkDirectory ) ) - qProcess:setWorkingDirectory( hbide_pathToOSPath( oProject:wrkDirectory ) ) -hbide_dbg( oProject:wrkDirectory, qProcess:workingDirectory() ) - qProcess:startDetached_2( cTargetFN ) - //qProcess:waitForStarted() - qProcess:pPtr := 0 - qProcess := NIL + #if 1 + cTmp := "Launching application with environment [ " + cTargetFN + " ]" + + #if 0 + qStrList := QStringList():new() + ::cBatch := ::oEV:prepareBatch( ::cWrkEnvironment ) /* at this point we only know default environment */ + IF empty( ::cBatch ) + qStrList:append( "/c " + cTargetFN ) + ELSE + qStrList:append( "/c " + ::cBatch + " && " + cTargetFN ) + ENDIF + qProcess:startDetached_1( "cmd.exe", qStrList ) + #endif + + qProcess:startDetached_2( cTargetFN ) + qProcess:waitForStarted() + qProcess:pPtr := 0 + qProcess := NIL + + //qProcess:start( "cmd.exe", qStrList ) + + #else + cTmp := "Launching application [ " + cTargetFN + " ]" + + qProcess:startDetached_2( cTargetFN ) + qProcess:waitForStarted() + qProcess:pPtr := 0 + qProcess := NIL + + #endif ELSE - cTmp := "Launch application " + cTargetFN + "... (not applicable)" + cTmp := "Launching application [ " + cTargetFN + " ] ( not applicable )." ENDIF diff --git a/harbour/contrib/hbide/idesaveload.prg b/harbour/contrib/hbide/idesaveload.prg index dfbcca85ab..cb2dd8ceda 100644 --- a/harbour/contrib/hbide/idesaveload.prg +++ b/harbour/contrib/hbide/idesaveload.prg @@ -91,6 +91,9 @@ FUNCTION hbide_saveINI( oIde ) aadd( txt_, "ThemesDialogGeometry = " + oIde:aIni[ INI_HBIDE, ThemesDialogGeometry ] ) aadd( txt_, "CurrentTheme = " + oIde:cWrkTheme ) aadd( txt_, "CurrentCodec = " + oIde:cWrkCodec ) + aadd( txt_, "PathMk2 = " + oIde:aIni[ INI_HBIDE, PathMk2 ] ) + aadd( txt_, "PathEnv = " + oIde:aIni[ INI_HBIDE, PathEnv ] ) + aadd( txt_, "CurrentEnvironment = " + oIde:cWrkEnvironment ) aadd( txt_, " " ) aadd( txt_, "[PROJECTS]" ) @@ -161,8 +164,9 @@ FUNCTION hbide_loadINI( oIde, cHbideIni ) LOCAL aIdeEle := { "mainwindowgeometry" , "projecttreevisible" , "projecttreegeometry", ; "functionlistvisible", "functionlistgeometry", "recenttabindex" , ; "currentproject" , "gotodialoggeometry" , "propsdialoggeometry", ; - "finddialoggeometry" , "themesdialoggeometry", "currenttheme", ; - "currentcodec" } + "finddialoggeometry" , "themesdialoggeometry", "currenttheme" , ; + "currentcodec" , "pathmk2" , "pathenv" , ; + "currentenvironment" } /* Initiate the place holders */ oIde:aIni := Array( INI_SECTIONS_COUNT ) diff --git a/harbour/contrib/hbide/projects/hbide.hbi b/harbour/contrib/hbide/projects/hbide.hbi index fca67fe086..2e3fdf81ca 100644 --- a/harbour/contrib/hbide/projects/hbide.hbi +++ b/harbour/contrib/hbide/projects/hbide.hbi @@ -7,6 +7,7 @@ DestinationFolder = projects Output = hbide LaunchParams = LaunchProgram = +BackupFolder = [ FLAGS ] ../../hbxbp/hbxbp.hbc diff --git a/harbour/contrib/hbide/resources/hbide.env b/harbour/contrib/hbide/resources/hbide.env new file mode 100644 index 0000000000..ee199b882b --- /dev/null +++ b/harbour/contrib/hbide/resources/hbide.env @@ -0,0 +1,55 @@ + [ COMMON ] +PLATFORM = win +COMPILER = bcc +SHELL = cmd.exe +EXT = bat + + [ BCC55 5.5.1 Command Line Tools ] +{hb_comp} bcc +{shell} cmd.exe +{ext} bat +{content} set HB_COMPILER=bcc +{content} set PATH=c:\harbour;c:\harbour\bcc\bin;C:\harbour\harbour\bcc\bin; + + [ MINGW 4.4.2 Windows ] +{hb_plat} win +{hb_comp} mingw +{content} set PATH=c:\mingw\bin;c:\qt\2009.03\qt\bin; +{content} set PATH=c:\harbour;c:\harbour\harbour\mingw\bin;%path% +{content} set HB_WITH_QT=c:\qt\2009.03\qt + + [ MSVC 8.0 ] +{hb_comp} msvc +{shell} cmd.exe +{ext} bat +{content} call "%ProgramFiles%\Microsoft Visual Studio 9.0\VC\vcvarsall.bat" x86 +{content} set PATH=c:\harbour;%ProgramFiles%\Microsoft Visual Studio 9.0\VC\bin;%path% +{content} set PATH=c:\harbour;;C:\harbour\harbour\msvc\bin;%path% +{content} set HB_COMPILER=msvc +{content} set HB_WITH_QT=c:\qt\2009.03\qt + + [ Pelles C ] +{hb_comp} pocc +{shell} cmd.exe +{ext} bat +{content} set PATH=c:\harbour\pellesc\bin; +{content} set INCLUDE=c:\harbour\pellesc\include;c:\harbour\pellesc\include\win;%INCLUDE% +{content} set LIB=c:\harbour\pellesc\lib;c:\harbour\pellesc\lib\win;%LIB% +{content} set PATH=c:\harbour;c:\harbour\harbour\pellesc\bin;%path% + + [ Watcom ] +{hb_comp} owatcom +{content} set PATH=C:\WATCOM\BINNT; +{content} set PATH=C:\WATCOM\BINW;%PATH% +{content} set INCLUDE=C:\WATCOM\H;%INCLUDE% +{content} set INCLUDE=C:\WATCOM\H\NT;%INCLUDE% +{content} set WATCOM=C:\WATCOM +{content} set EDPATH=C:\WATCOM\EDDAT +{content} set PATH=c:\harbour;c:\harbour\harbour\watcom\bin;%PATH% + + [ MINGW 4.0.0 Linux - A Skeleton ] +{hb_comp} mingw +{shell}.sh +{content} shell command 1 +{content} shell command 2 + diff --git a/harbour/contrib/hbide/resources/projectproperties.ui b/harbour/contrib/hbide/resources/projectproperties.ui index dd58065a6e..487b9279fc 100644 --- a/harbour/contrib/hbide/resources/projectproperties.ui +++ b/harbour/contrib/hbide/resources/projectproperties.ui @@ -105,23 +105,7 @@ p, li { white-space: pre-wrap; } - - - - - - - - 21 - 20 - - - - true - - - - + Working Folder: @@ -131,7 +115,7 @@ p, li { white-space: pre-wrap; } - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -142,20 +126,7 @@ p, li { white-space: pre-wrap; } - - - - - - - - 21 - 20 - - - - - + Destination Folder: @@ -165,7 +136,7 @@ p, li { white-space: pre-wrap; } - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -177,41 +148,7 @@ p, li { white-space: pre-wrap; } - - - - - - - - 21 - 20 - - - - - - - - Output Name: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> -<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Output name is used as final name for .hbi .hbp .exe .lib .a and will be added to the paths retrieved via &lt;Project Location&gt;, &lt;Working Folder&gt;, &lt;Destination Folder&gt;, etc. So this is a very important component.</p></body></html> - - - - + Compile/Link Flags: @@ -221,7 +158,7 @@ p, li { white-space: pre-wrap; } - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -238,7 +175,7 @@ p, li { white-space: pre-wrap; } - + Launch Parameters: @@ -248,10 +185,10 @@ p, li { white-space: pre-wrap; } - + - + Launch Program: @@ -261,9 +198,71 @@ p, li { white-space: pre-wrap; } - + + + + + Backup Location: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p align="center" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Output name is used as final name for .hbi .hbp .exe .lib .a and will be added to the paths retrieved via &lt;Project Location&gt;, &lt;Working Folder&gt;, &lt;Destination Folder&gt;, etc. So this is a very important component.</p></body></html> + + + + + + + Output Name: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + ... + + + + + + + ... + + + + + + + ... + + + + + + + ... + + + @@ -425,10 +424,10 @@ p, li { white-space: pre-wrap; } - Compilers + Environments - + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> @@ -449,6 +448,88 @@ p, li { white-space: pre-wrap; } + + + + + + + 100 + 0 + + + + + 100 + 16777215 + + + + Path to hbMK2.exe + + + + + + + + + + + 0 + 0 + + + + + + + + + + + + + + + + 100 + 0 + + + + + 100 + 16777215 + + + + Path to hbIDE.env + + + + + + + + + + + + + + + + + + + The environment definitions will not be saved along the project details. You need to click me in order to save it permanently. + + + ... + + + @@ -493,12 +574,8 @@ p, li { white-space: pre-wrap; } comboPrjType editPrjTitle editPrjLoctn - buttonChoosePrjLoc editWrkFolder - buttonChooseWd editDstFolder - buttonChooseDest - editOutName editFlags editLaunchParams editLaunchExe diff --git a/harbour/contrib/hbxbp/Makefile b/harbour/contrib/hbxbp/Makefile index 27c3059ea1..bb1a9da181 100644 --- a/harbour/contrib/hbxbp/Makefile +++ b/harbour/contrib/hbxbp/Makefile @@ -9,6 +9,7 @@ include $(TOP)$(ROOT)config/global.mk LIBNAME := hbxbp PRG_SOURCES := \ + hbpprocess.prg \ xbp3state.prg \ xbpappevent.prg \ xbpbitmap.prg \ diff --git a/harbour/contrib/hbxbp/hbpprocess.prg b/harbour/contrib/hbxbp/hbpprocess.prg new file mode 100644 index 0000000000..558a7f62dd --- /dev/null +++ b/harbour/contrib/hbxbp/hbpprocess.prg @@ -0,0 +1,298 @@ +/* + * $Id$ + */ + +/* + * Harbour Project source code: + * + * Copyright 2010 Pritpal Bedi + * www - http://www.harbour-project.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/). + * + * As a special exception, the Harbour Project gives permission for + * additional uses of the text contained in its release of Harbour. + * + * The exception is that, if you link the Harbour libraries with other + * files to produce an executable, this does not by itself cause the + * resulting executable to be covered by the GNU General Public License. + * Your use of that executable is in no way restricted on account of + * linking the Harbour library code into it. + * + * This exception does not however invalidate any other reasons why + * the executable file might be covered by the GNU General Public License. + * + * This exception applies only to the code released by the Harbour + * Project under the name Harbour. If you copy code from other + * Harbour Project or Free Software Foundation releases into a copy of + * Harbour, as the General Public License permits, the exception does + * not apply to the code that you add in this way. To avoid misleading + * anyone as to the status of such modified files, you must delete + * this exception notice from them. + * + * If you write modifications of your own for Harbour, it is your choice + * whether to permit this exception to apply to your modifications. + * If you do not wish that, delete this exception notice. + * + */ +/*----------------------------------------------------------------------*/ +/*----------------------------------------------------------------------*/ +/*----------------------------------------------------------------------*/ +/* + * EkOnkar + * ( The LORD is ONE ) + * + * Xbase++ Compatible Library + * Harbour Extension + * + * Pritpal Bedi + * 24Jan2010 + */ +/*----------------------------------------------------------------------*/ +/*----------------------------------------------------------------------*/ +/*----------------------------------------------------------------------*/ + +#include "hbqt.ch" +#include "common.ch" +#include "hbclass.ch" + +/*----------------------------------------------------------------------*/ + +#define CHN_BGN 1 +#define CHN_OUT 2 +#define CHN_ERR 3 +#define CHN_FIN 4 +#define CHN_STT 5 +#define CHN_ERE 6 +#define CHN_CLO 7 +#define CHN_BYT 8 +#define CHN_RCF 9 +#define CHN_REA 10 + +/*----------------------------------------------------------------------*/ +// +// Class HbpProcess +// +/*----------------------------------------------------------------------*/ + +CLASS HbpProcess + + DATA cShellCmd + DATA lDetatched INIT .f. + + METHOD new( cShellCmd ) + METHOD create( cShellCmd ) + METHOD destroy() VIRTUAL + METHOD addArg( cArg ) + METHOD start( cShellCmd ) + + METHOD finished( bBlock ) SETGET // Slot + METHOD output( bBlock ) SETGET // Slot + METHOD workingPath( cPath ) SETGET // Slot + + ACCESS started INLINE ::nStarted + ACCESS ended INLINE ::nEnded + ACCESS exitCode INLINE ::nExitCode + ACCESS exitStatus INLINE ::nExitStatus + + PROTECTED: + + DATA nStarted INIT 0 + DATA nEnded INIT 0 + DATA nExitCode INIT -1 + DATA nExitStatus INIT -1 + DATA cWrkDirectory INIT "" + DATA qProcess + DATA qStrList + DATA bFinish + DATA bOutput + + METHOD read( nMode, i, ii ) + METHOD outputMe( cLine ) + METHOD finish() + + ACCESS pSlots INLINE hbxbp_getSlotsPtr() + + ENDCLASS + +/*----------------------------------------------------------------------*/ + +METHOD HbpProcess:new( cShellCmd ) + + ::cShellCmd := cShellCmd + + RETURN Self + +/*----------------------------------------------------------------------*/ + +METHOD HbpProcess:create( cShellCmd ) + + DEFAULT cShellCmd TO ::cShellCmd + + ::cShellCmd := cShellCmd + + RETURN Self + +/*----------------------------------------------------------------------*/ + +METHOD HbpProcess:workingPath( cPath ) + + IF !empty( cPath ) + ::cWrkDirectory := cPath + ENDIF + RETURN ::cWrkDirectory + +/*----------------------------------------------------------------------*/ + +METHOD HbpProcess:finished( bBlock ) + + IF hb_isBlock( bBlock ) + ::bFinish := bBlock + ENDIF + + RETURN ::bFinish + +/*----------------------------------------------------------------------*/ + +METHOD HbpProcess:output( bBlock ) + + IF hb_isBlock( bBlock ) + ::bOutput := bBlock + ENDIF + + RETURN ::bFinish + +/*----------------------------------------------------------------------*/ + +METHOD HbpProcess:addArg( cArg ) + + IF empty( ::qStrList ) + ::qStrList := QStringList():new() + ENDIF + ::qStrList:append( cArg ) + + RETURN Self + +/*----------------------------------------------------------------------*/ + +METHOD HbpProcess:start( cShellCmd ) + + DEFAULT cShellCmd TO ::cShellCmd + + ::cShellCmd := cShellCmd + + ::qProcess := QProcess():new() + + ::qProcess:setReadChannel( 1 ) + + #if 0 + Qt_Slots_Connect( ::pSlots, ::qProcess, "readyRead()" , {|o,i| ::read( CHN_REA, i, o ) } ) + Qt_Slots_Connect( ::pSlots, ::qProcess, "readChannelFinished()" , {|o,i| ::read( CHN_RCF, i, o ) } ) + Qt_Slots_Connect( ::pSlots, ::qProcess, "aboutToClose()" , {|o,i| ::read( CHN_CLO, i, o ) } ) + Qt_Slots_Connect( ::pSlots, ::qProcess, "bytesWritten(int)" , {|o,i| ::read( CHN_BYT, i, o ) } ) + Qt_Slots_Connect( ::pSlots, ::qProcess, "stateChanged(int)" , {|o,i| ::read( CHN_STT, i, o ) } ) + Qt_Slots_Connect( ::pSlots, ::qProcess, "error(int)" , {|o,i| ::read( CHN_ERE, i, o ) } ) + Qt_Slots_Connect( ::pSlots, ::qProcess, "started()" , {|o,i| ::read( CHN_BGN, i, o ) } ) + #endif + + Qt_Slots_Connect( ::pSlots, ::qProcess, "readyReadStandardOutput()", {|o,i| ::read( CHN_OUT, i, o ) } ) + Qt_Slots_Connect( ::pSlots, ::qProcess, "readyReadStandardError()" , {|o,i| ::read( CHN_ERR, i, o ) } ) + Qt_Slots_Connect( ::pSlots, ::qProcess, "finished(int,int)" , {|o,i,ii| ::read( CHN_FIN, i, ii, o ) } ) + + IF !empty( ::cWrkDirectory ) + ::qProcess:setWorkingDirectory( ::cWrkDirectory ) + ENDIF + ::nStarted := seconds() + + IF !empty( ::qStrList ) + ::qProcess:start( ::cShellCmd, ::qStrList ) + ELSE + ::qProcess:start_1( ::cShellCmd ) + ENDIF + + RETURN Self + +/*----------------------------------------------------------------------*/ + +METHOD HbpProcess:read( nMode, i, ii ) + LOCAL cLine, nSize + + nSize := 16384 + + DO CASE + CASE nMode == CHN_REA + + CASE nMode == CHN_OUT + ::qProcess:setReadChannel( 0 ) + cLine := space( nSize ) + ::qProcess:read( @cLine, nSize ) + ::outputMe( cLine ) + + CASE nMode == CHN_ERR + ::qProcess:setReadChannel( 1 ) + cLine := space( nSize ) + ::qProcess:read( @cLine, nSize ) + ::outputMe( cLine ) + + CASE nMode == CHN_FIN + ::nExitCode := i + ::nExitStatus := ii + ::nEnded := Seconds() + ::finish() + + ENDCASE + + RETURN nil + +/*----------------------------------------------------------------------*/ + +METHOD HbpProcess:outputMe( cLine ) + + IF hb_isBlock( ::bOutput ) .AND. !empty( cLine ) + eval( ::bOutput, trim( cLine ), NIL, Self ) + ENDIF + + RETURN Self + +/*----------------------------------------------------------------------*/ + +METHOD HbpProcess:finish() + + #if 0 + Qt_Slots_disConnect( ::pSlots, ::qProcess, "readyRead()" ) + Qt_Slots_disConnect( ::pSlots, ::qProcess, "readChannelFinished()" ) + Qt_Slots_disConnect( ::pSlots, ::qProcess, "aboutToClose()" ) + Qt_Slots_disConnect( ::pSlots, ::qProcess, "bytesWritten(int)" ) + Qt_Slots_disConnect( ::pSlots, ::qProcess, "stateChanged(int)" ) + Qt_Slots_disConnect( ::pSlots, ::qProcess, "error(int)" ) + Qt_Slots_disConnect( ::pSlots, ::qProcess, "started()" ) + #endif + Qt_Slots_disConnect( ::pSlots, ::qProcess, "readyReadStandardOutput()" ) + Qt_Slots_disConnect( ::pSlots, ::qProcess, "readyReadStandardError()" ) + Qt_Slots_disConnect( ::pSlots, ::qProcess, "finished(int,int)" ) + + IF hb_isBlock( ::bFinish ) + eval( ::bFinish, ::nExitCode, ::nExitStatus, Self ) + ENDIF + + ::qProcess:kill() + // + ::qProcess:pPtr := 0 + ::qProcess := NIL + + RETURN Self + +/*----------------------------------------------------------------------*/