From 34835e989f214f0aa75cd493012bc3a257aa12ee Mon Sep 17 00:00:00 2001 From: Pritpal Bedi Date: Fri, 19 Mar 2010 04:10:35 +0000 Subject: [PATCH] 2010-03-18 20:49 UTC-0800 Pritpal Bedi (pritpal@vouchcac.com) * contrib/hbide/hbide.hbp * contrib/hbide/hbide.prg * contrib/hbide/ideactions.prg * contrib/hbide/idedocks.prg * contrib/hbide/ideeditor.prg * contrib/hbide/ideobject.prg + contrib/hbide/ideskeletons.prg + Reworked and greatly enhanced "snippets->skeletons" management. How it works: ============= 1. Creating of skelton is as before with same interface. 2. In addition, the selected text in the current editor can be saved as a skeleton via "Save as Skeleton..." option in right-click context menu. A "Name" will be asked via a modal input edit dialog. 3. A new "Skeletons" tree-view is implemented at the Left-hand docking area which displays all skeletons by name. 4. Hovering cursor over the name node shows up the body of skeleton as a tooltip, very handy. 5. Double-click on the node in tree-view will insert the skeleton text at the current cursor position. 6. Alternatively, as before, menu can be activated via CTRL+K. 7. Skeletons body now supports meta data as follows: --- DO WHILE .T. IF cVar == "<-PROMPT>" xVar := <-DtoC( Date() )> ENDIF <-CUR> EXIT ENDDO --- You can see there are 3 occurances of <-*> token. <-PROMPT> will execute an input dialog and the resultant string will be inserted here. <-DtoC( Date() )> will evaluate the expression, which in this case, - "03/18/2010" - will be inserted. This means any valid Harbour expression which returns a string can be designated as meta-expression. <-CUR> will position the cursor at this place. This is what I thought it should behave. Please let me know it anything else can make it more productive. --- harbour/ChangeLog | 56 +++ harbour/contrib/hbide/hbide.hbp | 6 +- harbour/contrib/hbide/hbide.prg | 32 +- harbour/contrib/hbide/ideactions.prg | 1 + harbour/contrib/hbide/idedocks.prg | 148 ++------ harbour/contrib/hbide/ideeditor.prg | 36 +- harbour/contrib/hbide/ideobject.prg | 3 +- harbour/contrib/hbide/ideskeletons.prg | 475 +++++++++++++++++++++++++ 8 files changed, 597 insertions(+), 160 deletions(-) create mode 100644 harbour/contrib/hbide/ideskeletons.prg diff --git a/harbour/ChangeLog b/harbour/ChangeLog index b6073aa477..3c194318ad 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -17,6 +17,62 @@ past entries belonging to author(s): Viktor Szakats. */ +2010-03-18 20:49 UTC-0800 Pritpal Bedi (pritpal@vouchcac.com) + * contrib/hbide/hbide.hbp + * contrib/hbide/hbide.prg + * contrib/hbide/ideactions.prg + * contrib/hbide/idedocks.prg + * contrib/hbide/ideeditor.prg + * contrib/hbide/ideobject.prg + + contrib/hbide/ideskeletons.prg + + Reworked and greatly enhanced "snippets->skeletons" management. + + How it works: + ============= + 1. Creating of skelton is as before with same interface. + + 2. In addition, the selected text in the current editor + can be saved as a skeleton via "Save as Skeleton..." + option in right-click context menu. A "Name" will be + asked via a modal input edit dialog. + + 3. A new "Skeletons" tree-view is implemented at the Left-hand + docking area which displays all skeletons by name. + + 4. Hovering cursor over the name node shows up the body of + skeleton as a tooltip, very handy. + + 5. Double-click on the node in tree-view will insert the + skeleton text at the current cursor position. + + 6. Alternatively, as before, menu can be activated via CTRL+K. + + 7. Skeletons body now supports meta data as follows: + --- + DO WHILE .T. + IF cVar == "<-PROMPT>" + xVar := <-DtoC( Date() )> + ENDIF + <-CUR> + EXIT + ENDDO + --- + + You can see there are 3 occurances of <-*> token. + + <-PROMPT> will execute an input dialog and the resultant + string will be inserted here. + + <-DtoC( Date() )> will evaluate the expression, which in + this case, - "03/18/2010" - will be inserted. This means + any valid Harbour expression which returns a string + can be designated as meta-expression. + + <-CUR> will position the cursor at this place. + + This is what I thought it should behave. + Please let me know it anything else can make it more productive. + 2010-03-18 15:02 UTC-0800 Pritpal Bedi (pritpal@vouchcac.com) * contrib/hbide/hbide.ch * contrib/hbide/idesaveload.prg diff --git a/harbour/contrib/hbide/hbide.hbp b/harbour/contrib/hbide/hbide.hbp index ca0085c235..65be166fee 100644 --- a/harbour/contrib/hbide/hbide.hbp +++ b/harbour/contrib/hbide/hbide.hbp @@ -8,6 +8,9 @@ -ldflag={msvc}-defaultlib:libcmt.lib ../hbxbp/hbxbp.hbc + +ideparseexpr.c + hbide.prg ideobject.prg idestylesheets.prg @@ -27,7 +30,8 @@ ideenviron.prg idehome.prg idefunctions.prg idedocwriter.prg +ideskeletons.prg -ideparseexpr.c +{allwin}hbide.rc diff --git a/harbour/contrib/hbide/hbide.prg b/harbour/contrib/hbide/hbide.prg index 91863fe413..783ff45250 100644 --- a/harbour/contrib/hbide/hbide.prg +++ b/harbour/contrib/hbide/hbide.prg @@ -126,22 +126,22 @@ CLASS HbIde ACCESS pSlots INLINE hbxbp_getSlotsPtr() ACCESS pEvents INLINE hbxbp_getEventsPtr() - DATA oPM /* Project Manager */ - DATA oDK /* Main Window Components Manager */ - DATA oAC /* Actions Manager */ - DATA oEM /* Editor Tabs Manager */ - DATA oSM /* Souces Manager */ - DATA oFR /* Find Replace Manager */ - DATA oEV /* Available Environments */ - DATA oHL /* Harbour Help Manager */ - DATA oHM /* panel manager */ - DATA oFN /* Functions Tags Manager */ - DATA oDW /* Document Writer Manager */ - DATA oThemes + DATA oPM /* Project Manager */ + DATA oDK /* Main Window Components Manager */ + DATA oAC /* Actions Manager */ + DATA oEM /* Editor Tabs Manager */ + DATA oSM /* Souces Manager */ + DATA oFR /* Find Replace Manager */ + DATA oEV /* Available Environments */ + DATA oHL /* Harbour Help Manager */ + DATA oHM /* panel manager */ + DATA oFN /* Functions Tags Manager */ + DATA oDW /* Document Writer Manager */ + DATA oSK /* Skeletons Managet */ + DATA oThemes /* Themes Manager */ DATA oFindInFiles DATA oHelpDock DATA oSkeltnDock - DATA oSkeltnUI DATA oFindDock DATA oUI @@ -224,6 +224,7 @@ CLASS HbIde DATA oDocViewDock DATA oDocWriteDock DATA oFunctionsDock + DATA oSkltnsTreeDock DATA lProjTreeVisible INIT .t. DATA lDockRVisible INIT .f. @@ -367,11 +368,15 @@ METHOD HbIde:create( cProjIni ) /* Functions Tag Manager */ ::oFN := IdeFunctions():new():create( Self ) + /* Skeletons Manager */ + ::oSK := IdeSkeletons():new( Self ):create() + /* Initialte Project Manager */ ::oPM := IdeProjManager():new( Self ):create() /* Load IDE Settings */ hbide_loadINI( Self, cProjIni ) + /* Set variables from last session */ ::cWrkTheme := ::aINI[ INI_HBIDE, CurrentTheme ] ::cWrkCodec := ::aINI[ INI_HBIDE, CurrentCodec ] @@ -543,6 +548,7 @@ METHOD HbIde:create( cProjIni ) hbide_dbg( "Before ::oDlg:destroy()", memory( 1001 ), hbqt_getMemUsed() ) hbide_dbg( " " ) + ::oSK:destroy() ::oDW:destroy() ::oEV:destroy() ::oFN:destroy() diff --git a/harbour/contrib/hbide/ideactions.prg b/harbour/contrib/hbide/ideactions.prg index 4f03587c74..d9b7b20f3b 100644 --- a/harbour/contrib/hbide/ideactions.prg +++ b/harbour/contrib/hbide/ideactions.prg @@ -593,6 +593,7 @@ METHOD IdeActions:buildMainMenu() oSubMenu:oWidget:addSeparator() oSubMenu:oWidget:addAction_4( ::oDockPT:oWidget:toggleViewAction() ) oSubMenu:oWidget:addAction_4( ::oDockED:oWidget:toggleViewAction() ) + oSubMenu:oWidget:addAction_4( ::oSkltnsTreeDock:oWidget:toggleViewAction() ) oSubMenu:oWidget:addSeparator() oSubMenu:oWidget:addAction_4( ::oHelpDock:oWidget:toggleViewAction() ) oSubMenu:oWidget:addAction_4( ::oDocViewDock:oWidget:toggleViewAction() ) diff --git a/harbour/contrib/hbide/idedocks.prg b/harbour/contrib/hbide/idedocks.prg index 0ed04a7ed6..e320d80fca 100644 --- a/harbour/contrib/hbide/idedocks.prg +++ b/harbour/contrib/hbide/idedocks.prg @@ -79,6 +79,8 @@ #define dockDocViewer_visibilityChanged 305 #define docFunctions_visibilityChanged 306 #define dockDocWriter_visibilityChanged 307 +#define docSkeletons_visibilityChanged 308 +#define dockSkltnsTree_visibilityChanged 309 /*----------------------------------------------------------------------*/ @@ -107,6 +109,7 @@ CLASS IdeDocks INHERIT IdeObject METHOD buildEditorTree() METHOD buildFuncList() METHOD buildFunctionsDock() + METHOD buildSkeletonsTree() METHOD buildCompileResults() METHOD buildLinkResults() METHOD buildOutputResults() @@ -121,7 +124,6 @@ CLASS IdeDocks INHERIT IdeObject METHOD setStatusText( nPart, xValue ) METHOD getMarkWidget( nIndex ) METHOD dispEnvironment( cEnviron ) - METHOD execSkeleton( nMode, p ) METHOD addPanelButton( cPanel ) METHOD disblePanelButton( qTBtn ) METHOD getADockWidget( nArea, cObjectName, cWindowTitle, nFlags ) @@ -145,7 +147,6 @@ METHOD IdeDocks:create( oIde ) /*----------------------------------------------------------------------*/ METHOD IdeDocks:destroy() - LOCAL oUI := ::oIde:oSkeltnUI LOCAL qTBtn ::disconnect( ::oOutputResult:oWidget , "copyAvailable(bool)" ) @@ -166,17 +167,6 @@ METHOD IdeDocks:destroy() ::disconnect( ::oSkeltnDock:oWidget , "visibilityChanged(bool)" ) #endif - /* ?? */ - ::disconnect( oUI:q_buttonNew , "clicked()" ) - ::disconnect( oUI:q_buttonRename, "clicked()" ) - ::disconnect( oUI:q_buttonDelete, "clicked()" ) - ::disconnect( oUI:q_buttonClear , "clicked()" ) - ::disconnect( oUI:q_buttonGetSel, "clicked()" ) - ::disconnect( oUI:q_buttonUpdate, "clicked()" ) - ::disconnect( oUI:q_listNames , "itemSelectionChanged()" ) - - oUI:destroy() - FOR EACH qTBtn IN ::aPanels ::disconnect( qTBtn, "clicked()" ) qTBtn := NIL @@ -259,6 +249,7 @@ METHOD IdeDocks:buildDockWidgets() ::buildEditorTree() ::buildFuncList() + ::buildSkeletonsTree() ::buildHelpWidget() ::buildSkeletonWidget() @@ -327,40 +318,32 @@ METHOD IdeDocks:execEvent( nMode, p ) CASE nMode == 2 /* HelpWidget:contextMenuRequested(qPoint) */ hbide_popupBrwContextMenu( ::qHelpBrw, p ) + CASE nMode == dockSkltnsTree_visibilityChanged + IF p; ::oSK:showTree(); ENDIF + + CASE nMode == docSkeletons_visibilityChanged + IF p; ::oSK:show(); ENDIF + CASE nMode == dockDocWriter_visibilityChanged - IF p - ::oDW:show() - ENDIF + IF p; ::oDW:show(); ENDIF CASE nMode == docFunctions_visibilityChanged - IF p - ::oFN:show() - ENDIF + IF p; ::oFN:show(); ENDIF CASE nMode == dockDocViewer_visibilityChanged - IF p - ::oHL:show() - ENDIF + IF p; ::oHL:show(); ENDIF CASE nMode == dockProperties_visibilityChanged - IF p - ::oPM:fetchProperties() - ENDIF + IF p; ::oPM:fetchProperties(); ENDIF CASE nMode == docEnvironments_visibilityChanged - IF p - ::oEV:show() - ENDIF + IF p; ::oEV:show(); ENDIF CASE nMode == dockFindInFiles_visibilityChanged - IF p - ::oFindInFiles:show() - ENDIF + IF p; ::oFindInFiles:show(); ENDIF CASE nMode == dockThemes_visibilityChanged - IF p - ::oThemes:show() - ENDIF + IF p; ::oThemes:show(); ENDIF ENDCASE @@ -574,6 +557,7 @@ METHOD IdeDocks:buildToolBarPanels() aBtns := {} aadd( aBtns, { ::oDockPT , "projtree" } ) aadd( aBtns, { ::oDockED , "editstree" } ) + aadd( aBtns, { ::oSkltnsTreeDock, "projtree" } ) aadd( aBtns, {} ) aadd( aBtns, { ::oHelpDock , "help" } ) aadd( aBtns, { ::oDocViewDock , "harbourhelp" } ) @@ -657,7 +641,7 @@ METHOD IdeDocks:addPanelButton( cPanel ) METHOD IdeDocks:buildProjectTree() LOCAL i, oItem - ::oIde:oDockPT := ::getADockWidget( Qt_LeftDockWidgetArea, "dockProjectTree", "Projects Tree" ) + ::oIde:oDockPT := ::getADockWidget( Qt_LeftDockWidgetArea, "dockProjectTree", "Projects" ) ::oDlg:oWidget:addDockWidget_1( Qt_LeftDockWidgetArea, ::oDockPT:oWidget, Qt_Vertical ) ::oIde:oProjTree := XbpTreeView():new() @@ -705,7 +689,7 @@ METHOD IdeDocks:buildProjectTree() METHOD IdeDocks:buildEditorTree() - ::oIde:oDockED := ::getADockWidget( Qt_LeftDockWidgetArea, "dockEditorTabs", "Editor Tabs" ) + ::oIde:oDockED := ::getADockWidget( Qt_LeftDockWidgetArea, "dockEditorTabs", "Editors" ) ::oDlg:oWidget:addDockWidget_1( Qt_LeftDockWidgetArea, ::oDockED:oWidget, Qt_Vertical ) ::oIde:oEditTree := XbpTreeView():new() @@ -736,6 +720,17 @@ METHOD IdeDocks:buildEditorTree() /*----------------------------------------------------------------------*/ +METHOD IdeDocks:buildSkeletonsTree() + + ::oIde:oSkltnsTreeDock := ::getADockWidget( Qt_LeftDockWidgetArea, "dockSkltnsTree", "Skeletons" ) + ::oDlg:oWidget:addDockWidget_1( Qt_LeftDockWidgetArea, ::oSkltnsTreeDock:oWidget, Qt_Vertical ) + + ::connect( ::oSkltnsTreeDock:oWidget, "visibilityChanged(bool)", {|p| ::execEvent( dockSkltnsTree_visibilityChanged, p ) } ) + + RETURN Self + +/*----------------------------------------------------------------------*/ + METHOD IdeDocks:buildFuncList() ::oIde:oFuncDock := ::getADockWidget( Qt_RightDockWidgetArea, "dockFuncList", "Functions List", QDockWidget_DockWidgetFloatable ) @@ -956,95 +951,16 @@ METHOD IdeDocks:buildEnvironDock() /*----------------------------------------------------------------------*/ METHOD IdeDocks:buildSkeletonWidget() - LOCAL oUI ::oIde:oSkeltnDock := ::getADockWidget( Qt_RightDockWidgetArea, "dockSkeleton", "Code Skeletons", QDockWidget_DockWidgetFloatable ) ::oDlg:oWidget:addDockWidget_1( Qt_RightDockWidgetArea, ::oSkeltnDock:oWidget, Qt_Horizontal ) - ::oIde:oSkeltnUI := HbQtUI():new( ::oIde:resPath + "skeletons.uic" ):build() - - ::oSkeltnDock:oWidget:setWidget( ::oIde:oSkeltnUI:oWidget ) - - oUI := ::oIde:oSkeltnUI - - ::connect( oUI:q_buttonNew , "clicked()", {|| ::execSkeleton( 1 ) } ) - ::connect( oUI:q_buttonRename, "clicked()", {|| ::execSkeleton( 2 ) } ) - ::connect( oUI:q_buttonDelete, "clicked()", {|| ::execSkeleton( 3 ) } ) - ::connect( oUI:q_buttonClear , "clicked()", {|| ::execSkeleton( 4 ) } ) - ::connect( oUI:q_buttonGetSel, "clicked()", {|| ::execSkeleton( 5 ) } ) - ::connect( oUI:q_buttonUpdate, "clicked()", {|| ::execSkeleton( 6 ) } ) - ::connect( oUI:q_listNames , "itemSelectionChanged()", {|| ::execSkeleton( 7 ) } ) - - //::oSkeltnUI:q_editCode:setFontFamily( "Courier New" ) - //::oSkeltnUI:q_editCode:setFontPointSize( 10 ) - - //::oSkeltnUI:q_editCode:setFont( ::oFont:oWidget ) - aeval( ::aSkltns, {|e_| ::oSkeltnUI:q_listNames:addItem( e_[ 1 ] ) } ) + ::connect( ::oSkeltnDock:oWidget, "visibilityChanged(bool)", {|p| ::execEvent( docSkeletons_visibilityChanged, p ) } ) RETURN Self /*----------------------------------------------------------------------*/ -METHOD IdeDocks:execSkeleton( nMode, p ) - LOCAL cName, cNewName, qItem, cCode, n - - HB_SYMBOL_UNUSED( p ) - - SWITCH nMode - - CASE 1 - IF !empty( cName := hbide_fetchAString( ::oSkeltnUI:q_listNames, "", "Name", "New Skeleton" ) ) - ::oSkeltnUI:q_listNames:addItem( cName ) - aadd( ::oIde:aSkltns, { cName, "" } ) - ::oSkeltnUI:q_listNames:setCurrentRow( len( ::aSkltns ) - 1 ) - ENDIF - EXIT - CASE 2 - qItem := QListWidgetItem():configure( ::oSkeltnUI:q_listNames:currentItem() ) - cName := qItem:text() - IF !empty( cNewName := hbide_fetchAString( ::oSkeltnUI:q_listNames, cName, "Name", "Change Skeleton's Name" ) ) - qItem:setText( cNewName ) - n := ascan( ::aSkltns, {|e_| e_[ 1 ] == cName } ) - ::aSkltns[ n, 1 ] := cNewName - ENDIF - EXIT - CASE 3 - qItem := QListWidgetItem():configure( ::oSkeltnUI:q_listNames:currentItem() ) - ::oSkeltnUI:q_listNames:removeItemWidget( qItem ) - EXIT - CASE 4 - ::oSkeltnUI:q_editCode:clear() - EXIT - CASE 5 - IF !empty( cCode := ::oEM:getSelectedText() ) - // TODO: Format cCode - cCode := strtran( cCode, chr( 0x2029 ), chr( 10 ) ) - ::oSkeltnUI:q_editCode:setPlainText( cCode ) - ENDIF - EXIT - CASE 6 - // Update the skeleton code and save the skeleton's buffer | file - qItem := QListWidgetItem():configure( ::oSkeltnUI:q_listNames:currentItem() ) - cName := qItem:text() - IF !empty( cName ) - n := ascan( ::aSkltns, {|e_| e_[ 1 ] == cName } ) - ::aSkltns[ n,2 ] := ::oSkeltnUI:q_editCode:toPlainText() - - hbide_saveSkltns( ::oIde ) - ENDIF - EXIT - CASE 7 - qItem := QListWidgetItem():configure( ::oSkeltnUI:q_listNames:currentItem() ) - cName := qItem:text() - n := ascan( ::aSkltns, {|e_| e_[ 1 ] == cName } ) - ::oSkeltnUI:q_editCode:setPlainText( ::aSkltns[ n,2 ] ) - EXIT - ENDSWITCH - - RETURN NIL - -/*----------------------------------------------------------------------*/ - METHOD IdeDocks:setStatusText( nPart, xValue ) LOCAL oPanel := ::oSBar:getItem( nPart ) diff --git a/harbour/contrib/hbide/ideeditor.prg b/harbour/contrib/hbide/ideeditor.prg index a410344f25..fde2f733b4 100644 --- a/harbour/contrib/hbide/ideeditor.prg +++ b/harbour/contrib/hbide/ideeditor.prg @@ -190,6 +190,7 @@ METHOD IdeEditsManager:create( oIde ) aadd( ::aActions, { "TB_CompilePPO", ::qContextMenu:addAction_4( ::oAC:getAction( "TB_CompilePPO" ) ) } ) aadd( ::aActions, { "" , ::qContextMenu:addSeparator() } ) aadd( ::aActions, { "Apply Theme" , ::qContextMenu:addAction( "Apply Theme" ) } ) + aadd( ::aActions, { "Save as Skltn", ::qContextMenu:addAction( "Save as Skeleton..." ) } ) oSub := QMenu():configure( ::qContextMenu:addMenu_1( "Split" ) ) // @@ -1560,6 +1561,8 @@ METHOD IdeEdit:execEvent( nMode, oEdit, p, p1 ) SWITCH nMode CASE customContextMenuRequested + QAction():from( ::oEM:aActions[ 17, 2 ] ):setEnabled( !empty( qCursor:selectedText() ) ) + pAct := ::oEM:qContextMenu:exec_1( qEdit:mapToGlobal( p ) ) IF !hbqt_isEmptyQtPointer( pAct ) qAct := QAction():configure( pAct ) @@ -1578,6 +1581,8 @@ METHOD IdeEdit:execEvent( nMode, oEdit, p, p1 ) ::oEditor:qCoEdit := ::oEditor:oEdit ::oIde:manageFocusInEditor() ENDIF + CASE qAct:text() == "Save as Skeleton..." + ::oSK:saveAs( ::getSelectedText() ) CASE qAct:text() == "Apply Theme" ::oEditor:applyTheme() CASE qAct:text() == "Goto Function" @@ -1807,36 +1812,8 @@ METHOD IdeEdit:execKeyEvent( nMode, nEvent, p, p1 ) /*----------------------------------------------------------------------*/ METHOD IdeEdit:presentSkeletons() - LOCAL qCrs, qMenu, pAct, cAct, n, a_, qAct, nPos, nCol, s, qRc - IF !empty( ::aSkltns ) - qCrs := QTextCursor():configure( ::qEdit:textCursor() ) - qRc := QRect():configure( ::qEdit:cursorRect( qCrs ) ) - - qMenu := QMenu():new( ::qEdit ) - FOR EACH a_ IN ::aSkltns - qMenu:addAction( a_[ 1 ] ) - NEXT - - pAct := qMenu:exec_1( ::qEdit:mapToGlobal( QPoint():new( qRc:x(), qRc:y() ) ) ) - IF !hbqt_isEmptyQtPointer( pAct ) - qAct := QAction():configure( pAct ) - cAct := qAct:text() - IF ( n := ascan( ::aSkltns, {|e_| e_[ 1 ] == cAct } ) ) > 0 - nPos := qCrs:position() - nCol := qCrs:columnNumber() - a_:= hbide_memoToArray( ::aSkltns[ n,2 ] ) - FOR EACH s IN a_ - IF s:__enumIndex() > 1 - s := space( nCol ) + s - ENDIF - NEXT - qCrs:insertText( hbide_arrayToMemoEx( a_ ) ) - qCrs:setPosition( nPos ) - ::qEdit:setTextCursor( qCrs ) - ENDIF - ENDIF - ENDIF + ::oSK:selectByMenuAndPostText( ::qEdit ) RETURN Self @@ -2493,6 +2470,7 @@ FUNCTION hbide_isHarbourKeyword( cWord ) 'switch' => NIL,; 'do' => NIL,; 'while' => NIL,; + 'enddo' => NIL,; 'exit' => NIL,; 'for' => NIL,; 'each' => NIL,; diff --git a/harbour/contrib/hbide/ideobject.prg b/harbour/contrib/hbide/ideobject.prg index 462e511470..1a96e2c6a0 100644 --- a/harbour/contrib/hbide/ideobject.prg +++ b/harbour/contrib/hbide/ideobject.prg @@ -94,6 +94,7 @@ CLASS IdeObject ACCESS oHM INLINE ::oIde:oHM ACCESS oFN INLINE ::oIde:oFN ACCESS oDW INLINE ::oIde:oDW + ACCESS oSK INLINE ::oIde:oSK ACCESS oFindDock INLINE ::oIde:oFindDock ACCESS oFindInFiles INLINE ::oIde:oFindInFiles @@ -174,7 +175,6 @@ CLASS IdeObject ACCESS oFrame INLINE ::oIde:oFrame ACCESS oHelpDock INLINE ::oIde:oHelpDock ACCESS oSkeltnDock INLINE ::oIde:oSkeltnDock - ACCESS oSkeltnUI INLINE ::oIde:oSkeltnUI ACCESS oGeneral INLINE ::oIde:oGeneral ACCESS oThemesDock INLINE ::oIde:oThemesDock ACCESS oPropertiesDock INLINE ::oIde:oPropertiesDock @@ -183,6 +183,7 @@ CLASS IdeObject ACCESS oDocViewDock INLINE ::oIde:oDocViewDock ACCESS oDocWriteDock INLINE ::oIde:oDocWriteDock ACCESS oFunctionsDock INLINE ::oIde:oFunctionsDock + ACCESS oSkltnsTreeDock INLINE ::oIde:oSkltnsTreeDock ACCESS lProjTreeVisible INLINE ::oIde:lProjTreeVisible ACCESS lDockRVisible INLINE ::oIde:lDockRVisible diff --git a/harbour/contrib/hbide/ideskeletons.prg b/harbour/contrib/hbide/ideskeletons.prg new file mode 100644 index 0000000000..db268b22c0 --- /dev/null +++ b/harbour/contrib/hbide/ideskeletons.prg @@ -0,0 +1,475 @@ +/* + * $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 ) + * + * Harbour-Qt IDE + * + * Pritpal Bedi + * 18Mar2010 + */ +/*----------------------------------------------------------------------*/ +/*----------------------------------------------------------------------*/ +/*----------------------------------------------------------------------*/ + +#include "hbide.ch" +#include "common.ch" +#include "hbclass.ch" +#include "hbqt.ch" + +/*----------------------------------------------------------------------*/ + +#define buttonNew_clicked 101 +#define buttonRename_clicked 102 +#define buttonDelete_clicked 103 +#define buttonClear_clicked 104 +#define buttonGetSel_clicked 105 +#define buttonUpdate_clicked 106 +#define listNames_itemSelectionChanged 107 +#define oTree_itemSelected 108 +#define oTree_contextMenu 109 + +/*----------------------------------------------------------------------*/ + +CLASS IdeSkeletons INHERIT IdeObject + + DATA oRoot + DATA oTree + DATA nPosCursor + DATA aItems INIT {} + + METHOD new( oIde ) + METHOD create( oIde ) + METHOD destroy() + METHOD show() + METHOD execEvent( nMode, p ) + METHOD postSkeleton( cSkeleton ) + METHOD selectByMenuAndPostText( qEdit ) + METHOD getText( cSkeleton ) + METHOD parseText( cText ) + METHOD parseMeta( cMeta ) + METHOD postText( qEdit, cText ) + METHOD showTree() + METHOD clearTree() + METHOD updateTree() + METHOD saveAs( cText, cName ) + + ENDCLASS + +/*----------------------------------------------------------------------*/ + +METHOD IdeSkeletons:new( oIde ) + + ::oIde := oIde + + RETURN Self + +/*----------------------------------------------------------------------*/ + +METHOD IdeSkeletons:create( oIde ) + + DEFAULT oIde TO ::oIde + ::oIde := oIde + + RETURN Self + +/*----------------------------------------------------------------------*/ + +METHOD IdeSkeletons:destroy() + + IF !empty( ::oUI ) + ::disconnect( ::oUI:q_buttonNew , "clicked()" ) + ::disconnect( ::oUI:q_buttonRename, "clicked()" ) + ::disconnect( ::oUI:q_buttonDelete, "clicked()" ) + ::disconnect( ::oUI:q_buttonClear , "clicked()" ) + ::disconnect( ::oUI:q_buttonGetSel, "clicked()" ) + ::disconnect( ::oUI:q_buttonUpdate, "clicked()" ) + ::disconnect( ::oUI:q_listNames , "itemSelectionChanged()" ) + + ::oUI:destroy() + ENDIF + + ::aItems := {} + ::oTree := NIL + + RETURN Self + +/*----------------------------------------------------------------------*/ + +METHOD IdeSkeletons:show() + + IF empty( ::oUI ) + ::oUI := HbQtUI():new( hbide_uic( "skeletons" ) ):build() + + ::oSkeltnDock:oWidget:setWidget( ::oUI:oWidget ) + + ::connect( ::oUI:q_buttonNew , "clicked()" , {|| ::execEvent( buttonNew_clicked ) } ) + ::connect( ::oUI:q_buttonRename, "clicked()" , {|| ::execEvent( buttonRename_clicked ) } ) + ::connect( ::oUI:q_buttonDelete, "clicked()" , {|| ::execEvent( buttonDelete_clicked ) } ) + ::connect( ::oUI:q_buttonClear , "clicked()" , {|| ::execEvent( buttonClear_clicked ) } ) + ::connect( ::oUI:q_buttonGetSel, "clicked()" , {|| ::execEvent( buttonGetSel_clicked ) } ) + ::connect( ::oUI:q_buttonUpdate, "clicked()" , {|| ::execEvent( buttonUpdate_clicked ) } ) + ::connect( ::oUI:q_listNames , "itemSelectionChanged()", {|| ::execEvent( listNames_itemSelectionChanged ) } ) + + //::oUI:q_editCode:setFontFamily( "Courier New" ) + //::oUI:q_editCode:setFontPointSize( 10 ) + + //::oUI:q_editCode:setFont( ::oFont:oWidget ) + aeval( ::aSkltns, {|e_| ::oUI:q_listNames:addItem( e_[ 1 ] ) } ) + ENDIF + + RETURN Self + +/*----------------------------------------------------------------------*/ + +METHOD IdeSkeletons:execEvent( nMode, p ) + LOCAL cName, cNewName, qItem, cCode, n + + HB_SYMBOL_UNUSED( p ) + + SWITCH nMode + + CASE buttonNew_clicked + IF !empty( cName := hbide_fetchAString( ::oUI:q_listNames, "", "Name", "New Skeleton" ) ) + ::oUI:q_listNames:addItem( cName ) + aadd( ::oIde:aSkltns, { cName, "" } ) + ::oUI:q_listNames:setCurrentRow( len( ::aSkltns ) - 1 ) + ENDIF + EXIT + + CASE buttonRename_clicked + qItem := QListWidgetItem():configure( ::oUI:q_listNames:currentItem() ) + cName := qItem:text() + IF !empty( cNewName := hbide_fetchAString( ::oUI:q_listNames, cName, "Name", "Change Skeleton's Name" ) ) + qItem:setText( cNewName ) + n := ascan( ::aSkltns, {|e_| e_[ 1 ] == cName } ) + ::aSkltns[ n, 1 ] := cNewName + ENDIF + EXIT + + CASE buttonDelete_clicked + qItem := QListWidgetItem():configure( ::oUI:q_listNames:currentItem() ) + ::oUI:q_listNames:removeItemWidget( qItem ) + EXIT + + CASE buttonClear_clicked + ::oUI:q_editCode:clear() + EXIT + + CASE buttonGetSel_clicked + IF !empty( cCode := ::oEM:getSelectedText() ) + // TODO: Format cCode + cCode := strtran( cCode, chr( 0x2029 ), chr( 10 ) ) + ::oUI:q_editCode:setPlainText( cCode ) + ENDIF + EXIT + + CASE buttonUpdate_clicked + // Update the skeleton code and save the skeleton's buffer | file + qItem := QListWidgetItem():configure( ::oUI:q_listNames:currentItem() ) + cName := qItem:text() + IF !empty( cName ) + n := ascan( ::aSkltns, {|e_| e_[ 1 ] == cName } ) + ::aSkltns[ n,2 ] := ::oUI:q_editCode:toPlainText() + hbide_saveSkltns( ::oIde ) + ::updateTree() + ENDIF + EXIT + + CASE listNames_itemSelectionChanged + qItem := QListWidgetItem():configure( ::oUI:q_listNames:currentItem() ) + cName := qItem:text() + n := ascan( ::aSkltns, {|e_| e_[ 1 ] == cName } ) + ::oUI:q_editCode:setPlainText( ::aSkltns[ n,2 ] ) + EXIT + + CASE oTree_contextMenu + + EXIT + + CASE oTree_itemSelected + ::oIde:manageFocusInEditor() + ::postSkeleton( p:caption ) + EXIT + + ENDSWITCH + + RETURN NIL + +/*----------------------------------------------------------------------*/ + +METHOD IdeSkeletons:saveAs( cText, cName ) + LOCAL n + + IF empty( cName ) + cName := hbide_fetchAString( ::oDlg, "", "Skeleton's Name" ) + ENDIF + IF !empty( cName ) + n := ascan( ::aSkltns, {|e_| e_[ 1 ] == cName } ) + IF n > 0 + ::aSkltns[ n, 2 ] := cText + ELSE + aadd( ::aSkltns, { cName, cText } ) + ::updateTree() + ENDIF + hbide_saveSkltns( ::oIde ) + ENDIF + + RETURN Self + +/*----------------------------------------------------------------------*/ + +METHOD IdeSkeletons:postSkeleton( cSkeleton ) + LOCAL oEdit, cText := ::getText( cSkeleton ) + + IF !empty( cText ) + IF !empty( oEdit := ::oEM:getEditObjectCurrent() ) + ::postText( oEdit:qEdit, cText ) + ENDIF + ENDIF + + RETURN Self + +/*----------------------------------------------------------------------*/ + +METHOD IdeSkeletons:selectByMenuAndPostText( qEdit ) + LOCAL cText, qCursor, qRect, qMenu, qAct, pAct, a_ + + IF !empty( ::aSkltns ) + qCursor := QTextCursor():from( qEdit:textCursor() ) + qRect := QRect():from( qEdit:cursorRect( qCursor ) ) + + qMenu := QMenu():new( qEdit ) + FOR EACH a_ IN ::aSkltns + qMenu:addAction( a_[ 1 ] ) + NEXT + + pAct := qMenu:exec_1( qEdit:mapToGlobal( QPoint():new( qRect:x(), qRect:y() ) ) ) + IF !hbqt_isEmptyQtPointer( pAct ) + qAct := QAction():from( pAct ) + + IF !empty( cText := ::getText( qAct:text() ) ) + ::postText( qEdit, cText ) + ENDIF + ENDIF + ENDIF + + RETURN Self + +/*----------------------------------------------------------------------*/ + +METHOD IdeSkeletons:parseMeta( cMeta ) + LOCAL xVal := cMeta, cData, n + + IF ( n := at( ":", cMeta ) ) > 0 + cMeta := substr( cMeta, 1, n - 1 ) + cData := substr( cMeta, n + 1 ) + ENDIF + + SWITCH upper( cMeta ) + + CASE "CUR" + xVal := 0 + EXIT + + CASE "PROMPT" + DEFAULT cData TO "A string value ?" + xVal := hbide_fetchAString( ::oDlg, "", cData, "Fetch a skeleton's prompt" ) + EXIT + + ENDSWITCH + + RETURN xVal + +/*----------------------------------------------------------------------*/ + +METHOD IdeSkeletons:parseText( cText ) + LOCAL n, n1, cTkn, xVal + + n := 0 + DO WHILE .t. + IF ( n := hb_at( "<-", cText, n ) ) > 0 + IF ( n1 := hb_at( ">", cText, n ) ) > 0 + IF !empty( cTkn := substr( cText, n + 2, n1 - n - 2 ) ) + + xVal := ::parseMeta( hbide_evalAsString( cTkn ) ) + + IF valtype( xVal ) == "C" + cText := substr( cText, 1, n - 1 ) + xVal + substr( cText, n1 + 1 ) + + ELSEIF valtype( xVal ) == "N" + cText := substr( cText, 1, n - 1 ) + "" + substr( cText, n1 + 1 ) + ::nPosCursor := n + + ENDIF + ENDIF + ENDIF + ELSE + EXIT + ENDIF + ENDDO + + RETURN cText + +/*----------------------------------------------------------------------*/ + +METHOD IdeSkeletons:getText( cSkeleton ) + LOCAL n, cText := "" + + IF ( n := ascan( ::aSkltns, {|e_| e_[ 1 ] == cSkeleton } ) ) > 0 + cText := ::aSkltns[ n, 2 ] + ENDIF + + RETURN cText + +/*----------------------------------------------------------------------*/ + +METHOD IdeSkeletons:postText( qEdit, cText ) + LOCAL s, a_, nCol, nPos, nRowCur, nColCur, n + LOCAL qCursor := QTextCursor():from( qEdit:textCursor() ) + + ::nPosCursor := NIL + + nPos := qCursor:position() + nCol := qCursor:columnNumber() + + a_:= hbide_memoToArray( cText ) + FOR EACH s IN a_ + IF ( n := s:__enumIndex() ) > 0 + s := iif( n > 1, space( nCol ), "" ) + ::parseText( s ) + IF valtype( ::nPosCursor ) == "N" + IF empty( nRowCur ) + nRowCur := n + nColCur := ::nPosCursor + ENDIF + ENDIF + ENDIF + NEXT + + qCursor:insertText( hbide_arrayToMemoEx( a_ ) ) + qCursor:setPosition( nPos ) + IF !empty( nRowCur ) + qCursor:movePosition( QTextCursor_Down, QTextCursor_MoveAnchor, nRowCur -1 ) + ENDIF + IF !empty( nColCur ) + qCursor:movePosition( QTextCursor_StartOfBlock ) + qCursor:movePosition( QTextCursor_Right, QTextCursor_MoveAnchor, nCol + nColCur - 1 ) + ENDIF + qEdit:setTextCursor( qCursor ) + + RETURN Self + +/*----------------------------------------------------------------------*/ + +METHOD IdeSkeletons:showTree() + + IF empty( ::oTree ) + ::oTree := XbpTreeView():new() + ::oTree:hasLines := .T. + ::oTree:hasButtons := .T. + ::oTree:create( ::oSkltnsTreeDock, , { 0,0 }, { 10,10 }, , .t. ) + + ::oTree:setStyleSheet( GetStyleSheet( "QTreeWidgetHB" ) ) + ::oTree:oWidget:setMinimumWidth( 100 ) + ::oTree:oWidget:setSizePolicy_1( QSizePolicy_MinimumExpanding, QSizePolicy_Preferred ) + ::oTree:oWidget:setIconSize( QSize():new( 12,12 ) ) + ::oTree:oWidget:setIndentation( 12 ) + + ::oTree:itemSelected := {|oItem | ::execEvent( oTree_itemSelected, oItem ) } + ::oTree:hbContextMenu := {|mp1, mp2, oXbp| ::execEvent( oTree_contextMenu , { mp1, mp2, oXbp } ) } + + ::oRoot := ::oTree:rootItem:addItem( "Skeletons" ) + + ::updateTree() + + ::oRoot:expand( .t. ) + + ::oSkltnsTreeDock:oWidget:setWidget( ::oTree:oWidget ) + ENDIF + + RETURN Self + +/*----------------------------------------------------------------------*/ + +METHOD IdeSkeletons:updateTree() + LOCAL oItem, a_ + + ::clearTree() + + FOR EACH a_ IN ::aSkltns + oItem := ::oRoot:addItem( a_[ 1 ] ) + oItem:tooltipText := a_[ 2 ] + aadd( ::aItems, oItem ) + NEXT + + ::oRoot:oWidget:sortChildren( 0 ) + + RETURN Self + +/*----------------------------------------------------------------------*/ + +METHOD IdeSkeletons:clearTree() + LOCAL oItem + + FOR EACH oItem IN ::aItems + ::oRoot:delItem( oItem ) + oItem := NIL + NEXT + ::aItems := {} + + RETURN Self + +/*----------------------------------------------------------------------*/ +