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.
This commit is contained in:
Pritpal Bedi
2010-03-19 04:10:35 +00:00
parent 3540d78691
commit 34835e989f
8 changed files with 597 additions and 160 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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 /* <Stats> 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 /* <Stats> 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()

View File

@@ -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() )

View File

@@ -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 )

View File

@@ -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,;

View File

@@ -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

View File

@@ -0,0 +1,475 @@
/*
* $Id$
*/
/*
* Harbour Project source code:
*
* Copyright 2010 Pritpal Bedi <pritpal@vouchcac.com>
* 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 <bedipritpal@hotmail.com>
* 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
/*----------------------------------------------------------------------*/