diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 809d8c6d24..35d6e0c525 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -17,6 +17,94 @@ past entries belonging to author(s): Viktor Szakats. */ +2010-05-09 17:21 UTC-0800 Pritpal Bedi (pritpal@vouchcac.com) + + contrib/hbide/plugins + + contrib/hbide/plugins/savebackup.hrb + + contrib/hbide/plugins/savebackup.prg + + Source and corresponding .hrb ( -gh ) plugin. + In practice .prg is never required for this purpose. + The source accompanying here is for demonstration purposes + which exposes elements to comprehend. + + + contrib/hbide/resources/selectionline.png + + Image to be activated when "Line" selection mode is on. + + * contrib/hbqt/hbqt_hbqplaintextedit.cpp + + * contrib/hbide/hbide.hbp + + Added ideplugin.prg + + * contrib/hbide/idethemes.prg + + Added more keywords for syntax-highlighting. + + * contrib/hbide/hbide.prg + * contrib/hbide/idedocks.prg + * contrib/hbide/ideedit.prg + * contrib/hbide/ideeditor.prg + + contrib/hbide/ideplugins.prg + + Priliminary commit to handle plugins. + + * contrib/hbide/ideshortcuts.prg + + + Implemented: a very simple yet powerful interface to hook plugins. + The idea got polished with Francesco Perillo's description of the thought. + + Creating a hbIDE plugin + ======================= + A .hrb ( compiled with -gh as the minimum ), i.e., savebackup.prg, + having two mandatory functions: + + 1. hrb_file_name_without_extension_plus_underscrore_plus_INIT() + savebackup_INIT( ... ) -> TRUE/FALSE + 2. hrb_file_name_without_extension_plus_underscrore_plus_EXEC() + savebackup_EXEC( oIde, ... ) -> xValue + + savebackup_INIT() will be used to establish hand-shake and it must + return a logical indicating success or failure. Currently it is + called with "1.0" as version no but is scheduled to be enhanced + in future. + + If hand-shake is successful, means, savebackup_INIT( ... ) returns + with TRUE, savebackup_EXEC( oIde, ... ) is called as per user + request. oIDE is sent as the first argument followed by user supplied + arguments. Within this function in .hrb, all action takes place. + User can write n number of functions withing the same source but + all other functions will always be STATIC ones. + + The whole hbIDE object is passed with each execution and hence + user is having utmost control over what he wants to accomplish. + + Location of the Plugin + ====================== + All plugins ( .hrb ) must reside within "plugins" sub-folder from hbIDE.exe + location. The location is determined with return value of + hb_dirBase() + hb_osPathSeparator() + "plugins" + hb_osPathSeparator(). + + Loading Plugins + =============== + At startup hbIDE looks into "plugins" folder for all .hrb files. + It then tries to establish hand-shake with them. If successful, a + handle is retained in static array. When an execution request is + encountered, this static array is searched for and + savebackup_EXEC( oIDE, ... ) is called and return value is passed + back to the caller macro. + + Executing Plugins in hbIDE + ========================== + A public method ::execPlugin( cPlugin, ... ) is implemented under + "Keyboard Mappings". ::execPlugin is called with plugin name, which + essentially is the .hrb file name. So in demo example, it is + "savebackup". Final expression would be like : + ::execPlugin( "savebackup", "saveas" ) + Here "saveas" is the identifier which is used in this demo to invoke + STATIC FUNCTION savebackup_saveAs( oIde ) + Author of plugin has to decide how and what he would like to pass + what and in how many. So simply build a macro to call a plugin + with parameters, that's it. + + I am hopeful that you, brilliant programmers, with help extending hbIDE + to an amazing levels. Send your critics to the list to enrich this thought. + 2010-05-09 14:10 UTC+0200 Viktor Szakats (harbour.01 syenar.hu) * config/global.mk + Added autodetection of mingw/cygwin compiler versions. diff --git a/harbour/contrib/hbide/hbide.hbp b/harbour/contrib/hbide/hbide.hbp index 36c0832b15..488ac8f654 100644 --- a/harbour/contrib/hbide/hbide.hbp +++ b/harbour/contrib/hbide/hbide.hbp @@ -36,5 +36,6 @@ idewizard.prg idetools.prg ideshortcuts.prg ideedit.prg +ideplugins.prg diff --git a/harbour/contrib/hbide/hbide.prg b/harbour/contrib/hbide/hbide.prg index 85b7d5477c..731758e562 100644 --- a/harbour/contrib/hbide/hbide.prg +++ b/harbour/contrib/hbide/hbide.prg @@ -490,6 +490,8 @@ METHOD HbIde:create( aParams ) /* Load tags last tagged projects */ ::oFN:loadTags( ::aINI[ INI_TAGGEDPROJECTS ] ) + hbide_loadPlugins() + DO WHILE .t. ::nEvent := AppEvent( @::mp1, @::mp2, @::oXbp ) @@ -749,7 +751,6 @@ METHOD HbIde:execEditorAction( cKey ) ::oEM:selectAll() EXIT CASE "SelectionMode" - ::isColumnSelectionEnabled := ! ::isColumnSelectionEnabled ::oEM:toggleSelectionMode() EXIT CASE "DuplicateLine" diff --git a/harbour/contrib/hbide/idedocks.prg b/harbour/contrib/hbide/idedocks.prg index bc16f442e5..1b76cbaba3 100644 --- a/harbour/contrib/hbide/idedocks.prg +++ b/harbour/contrib/hbide/idedocks.prg @@ -1016,7 +1016,6 @@ METHOD IdeDocks:setStatusText( nPart, xValue ) oPanel:caption := xValue EXIT CASE SB_PNL_STREAM -HB_TRACE( HB_TR_ALWAYS, "lllllllllll" ) oPanel:caption := iif( empty( xValue ), "St", xValue ) EXIT CASE SB_PNL_EDIT diff --git a/harbour/contrib/hbide/ideedit.prg b/harbour/contrib/hbide/ideedit.prg index a3fdd85b99..0daa57b857 100644 --- a/harbour/contrib/hbide/ideedit.prg +++ b/harbour/contrib/hbide/ideedit.prg @@ -126,9 +126,11 @@ CLASS IdeEdit INHERIT IdeObject DATA currentPointSize INIT 10 DATA qFont DATA aBlockCopyContents INIT {} - DATA isLineSelectionMode INIT .f. + DATA isLineSelectionON INIT .f. DATA aSelectionInfo INIT { -1,-1,-1,-1,0,0 } + DATA isColumnSelectionON INIT .f. + METHOD new( oEditor, nMode ) METHOD create( oEditor, nMode ) METHOD destroy() @@ -443,7 +445,6 @@ METHOD IdeEdit:execEvent( nMode, oEdit, p, p1 ) ::updateTitleBar() -// qEdit:hbHighlightSelectedColumns( ::isColumnSelectionEnabled ) ::dispStatusInfo() ::oDK:setStatusText( SB_PNL_SELECTEDCHARS, len( ::getSelectedText() ) ) EXIT @@ -506,9 +507,16 @@ METHOD IdeEdit:execEvent( nMode, oEdit, p, p1 ) /*----------------------------------------------------------------------*/ METHOD IdeEdit:dispStatusInfo() + LOCAL nMode + ::qEdit:hbGetSelectionInfo() - ::oDK:setStatusText( SB_PNL_STREAM, iif( ::aSelectionInfo[ 5 ] == 2, "Column", ; - iif( ::aSelectionInfo[ 5 ] == 3, "Line", "Stream" ) ) ) + nMode := ::aSelectionInfo[ 5 ] + + ::oAC:getAction( "TB_SelectionMode" ):setIcon( hbide_image( iif( nMode == 3, "selectionline", "stream" ) ) ) + ::oAC:getAction( "TB_SelectionMode" ):setChecked( nMode > 1 ) + + ::oDK:setStatusText( SB_PNL_STREAM, iif( nMode == 2, "Column", iif( nMode == 3, "Line", "Stream" ) ) ) + RETURN Self /*----------------------------------------------------------------------*/ @@ -938,7 +946,7 @@ METHOD IdeEdit:deleteBlockContents( aCord ) qCursor:movePosition( QTextCursor_StartOfLine, QTextCursor_KeepAnchor ) qCursor:removeSelectedText() ::qEdit:hbSetSelectionInfo( { -1,-1,-1,-1,0 } ) - ::isLineSelectionMode := .f. + ::isLineSelectionON := .f. ENDIF ENDIF @@ -1222,15 +1230,16 @@ METHOD IdeEdit:toggleLineNumbers() /*----------------------------------------------------------------------*/ METHOD IdeEdit:toggleSelectionMode() - ::qEdit:hbHighlightSelectedColumns( ::isColumnSelectionEnabled ) + ::isColumnSelectionON := ! ::isColumnSelectionON + ::qEdit:hbHighlightSelectedColumns( ::isColumnSelectionON ) ::dispStatusInfo() RETURN Self /*----------------------------------------------------------------------*/ METHOD IdeEdit:toggleLineSelectionMode() - ::isLineSelectionMode := ! ::isLineSelectionMode - ::qEdit:hbSetSelectionMode( 3, ::isLineSelectionMode ) + ::isLineSelectionON := ! ::isLineSelectionON + ::qEdit:hbSetSelectionMode( 3, ::isLineSelectionON ) ::dispStatusInfo() RETURN Self @@ -1894,6 +1903,7 @@ FUNCTION hbide_isHarbourKeyword( cWord ) 'hb_symbol_unused' => NIL,; 'error' => NIL,; 'handler' => NIL,; + 'in' => NIL,; 'nil' => NIL,; 'or' => NIL,; 'and' => NIL } diff --git a/harbour/contrib/hbide/ideeditor.prg b/harbour/contrib/hbide/ideeditor.prg index 649cf25a37..557963be24 100644 --- a/harbour/contrib/hbide/ideeditor.prg +++ b/harbour/contrib/hbide/ideeditor.prg @@ -1310,6 +1310,7 @@ METHOD IdeEditor:activateTab( mp1, mp2, oXbp ) oEdit:setDocumentProperties() oEdit:qCoEdit:relayMarkButtons() oEdit:qCoEdit:toggleLineNumbers() + oEdit:qCoEdit:dispStatusInfo() ENDIF RETURN Self diff --git a/harbour/contrib/hbide/ideplugins.prg b/harbour/contrib/hbide/ideplugins.prg new file mode 100644 index 0000000000..cf844d407e --- /dev/null +++ b/harbour/contrib/hbide/ideplugins.prg @@ -0,0 +1,117 @@ +/* + * $Id$ + */ + +/* + * Harbour Project source code: + * + * Copyright 2009-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 + * 08May2010 + */ +/*----------------------------------------------------------------------*/ +/*----------------------------------------------------------------------*/ +/*----------------------------------------------------------------------*/ + +#include "common.ch" +#include "hbclass.ch" +#include "inkey.ch" +#include "hbide.ch" +#include "hbhrb.ch" + +/*----------------------------------------------------------------------*/ + +STATIC s_aPlugins := { { "", NIL } } + +/*----------------------------------------------------------------------*/ + +FUNCTION hbide_loadPlugins() + LOCAL cPath := hb_dirBase() + hb_osPathSeparator() + "plugins" + hb_osPathSeparator() + LOCAL dir_, a_, cFile, pHrb, bBlock + + dir_:= directory( cPath + "*.hrb" ) + + FOR EACH a_ IN dir_ + hb_fNameSplit( a_[ 1 ], , @cFile ) + pHrb := hb_hrbLoad( HB_HRB_BIND_OVERLOAD, cPath + cFile ) + IF ! Empty( pHrb ) .AND. ! Empty( hb_hrbGetFunSym( pHrb, cFile + "_init" ) ) + bBlock := &( "{|...| " + cFile + "_init(...) }" ) + IF eval( bBlock, "1.0" ) /* Shakehand is OK */ + IF ! Empty( hb_hrbGetFunSym( pHrb, cFile + "_exec" ) ) + aadd( s_aPlugins, { lower( cFile ), &( "{|...| " + cFile + "_exec(...) }" ), pHrb } ) + ENDIF + ENDIF + ENDIF + NEXT + + RETURN bBlock + +/*----------------------------------------------------------------------*/ + +FUNCTION hbide_execPlugin( cPlugin, oAPI, ... ) + LOCAL n + + IF empty( cPlugin ) + RETURN NIL + ENDIF + + cPlugin := lower( cPlugin ) + + IF ( n := ascan( s_aPlugins, {|e_| e_[ 1 ] == cPlugin } ) ) > 0 + RETURN eval( s_aPlugins[ n, 2 ], oAPI, ... ) + ENDIF + + RETURN NIL + +/*----------------------------------------------------------------------*/ diff --git a/harbour/contrib/hbide/ideshortcuts.prg b/harbour/contrib/hbide/ideshortcuts.prg index 1dffaa783a..27fd9b7ac5 100644 --- a/harbour/contrib/hbide/ideshortcuts.prg +++ b/harbour/contrib/hbide/ideshortcuts.prg @@ -202,6 +202,7 @@ CLASS IdeShortcuts INHERIT IdeObject METHOD presentSkeletons() METHOD gotoFunction() METHOD clearSelection() + METHOD execPlugin( cPlugin, ... ) ENDCLASS @@ -1128,6 +1129,9 @@ METHOD IdeShortcuts:gotoFunction() METHOD IdeShortcuts:clearSelection() RETURN ::oEM:clearSelection() /*----------------------------------------------------------------------*/ +METHOD IdeShortcuts:execPlugin( cPlugin, ... ) + RETURN hbide_execPlugin( cPlugin, ::oIde, ... ) +/*----------------------------------------------------------------------*/ METHOD IdeShortcuts:loadMethods() @@ -1309,6 +1313,9 @@ METHOD IdeShortcuts:loadMethods() aadd( ::aMethods, { 'gotoFunction()', ; 'gotoFunction()', ; 'Takes under-cursor word and attempts to open the source containing that function in a new tab.' } ) + aadd( ::aMethods, { 'execPlugin( cPlugin )', ; + 'execPlugin( "" )', ; + 'Attempts to execute third-party plugins. First parameter passed is the instance to SELF exposing public API methods. Next parameters are passes as a list.' } ) RETURN Self diff --git a/harbour/contrib/hbide/idethemes.prg b/harbour/contrib/hbide/idethemes.prg index 51ab1e92dd..c79ad25b54 100644 --- a/harbour/contrib/hbide/idethemes.prg +++ b/harbour/contrib/hbide/idethemes.prg @@ -195,7 +195,7 @@ METHOD IdeThemes:create( oIde, cIniFile ) 'docase','case','endcase','otherwise', ; 'switch','endswitch', ; 'do','while','exit','enddo',; - 'for','each','next','step','to',; + 'for','each','next','step','to','in',; 'with','object','endwith',; 'nil','and','or','self',; 'class','endclass','method','data','var','destructor','inline','assign','access',; diff --git a/harbour/contrib/hbide/plugins/savebackup.hrb b/harbour/contrib/hbide/plugins/savebackup.hrb new file mode 100644 index 0000000000..17900a79ab Binary files /dev/null and b/harbour/contrib/hbide/plugins/savebackup.hrb differ diff --git a/harbour/contrib/hbide/plugins/savebackup.prg b/harbour/contrib/hbide/plugins/savebackup.prg new file mode 100644 index 0000000000..9f0ae5b976 --- /dev/null +++ b/harbour/contrib/hbide/plugins/savebackup.prg @@ -0,0 +1,86 @@ +/* + * $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. + * + */ +/*----------------------------------------------------------------------*/ + +FUNCTION savebackup_init( ... ) + + RETURN .t. + +/*----------------------------------------------------------------------*/ + +FUNCTION savebackup_exec( oIde, ... ) + LOCAL c + + FOR EACH c IN { ... } + IF lower( c ) == "saveas" + savebackup_saveAs( oIde ) + ENDIF + + NEXT + RETURN NIL + +/*----------------------------------------------------------------------*/ + +STATIC FUNCTION savebackup_saveAs( oIde ) + LOCAL cFile, oEdit + + oEdit := oIde:oEM:getEditorCurrent() + cFile := oEdit:sourceFile + "_bkp_" + strtran( dtoc( date() ), "/", "-" ) + "_" + strtran( time(), ":", "_" ) + cFile := hbide_pathToOSPath( cFile ) + + hb_memowrit( cFile, oIde:oEM:getEditObjectCurrent():qEdit:toPlainText() ) + + MsgBox( cFile, "Backup Saved" ) + + RETURN NIL + +/*----------------------------------------------------------------------*/ + \ No newline at end of file diff --git a/harbour/contrib/hbide/resources/selectionline.png b/harbour/contrib/hbide/resources/selectionline.png new file mode 100644 index 0000000000..df9e389f8e Binary files /dev/null and b/harbour/contrib/hbide/resources/selectionline.png differ diff --git a/harbour/contrib/hbqt/hbqt_hbqplaintextedit.cpp b/harbour/contrib/hbqt/hbqt_hbqplaintextedit.cpp index 3a53cb31f0..2b9d1ff6a3 100644 --- a/harbour/contrib/hbqt/hbqt_hbqplaintextedit.cpp +++ b/harbour/contrib/hbqt/hbqt_hbqplaintextedit.cpp @@ -165,7 +165,7 @@ void HBQPlainTextEdit::hbShowPrototype( const QString & tip ) else { QRect r = HBQPlainTextEdit::cursorRect(); - QToolTip::showText( mapToGlobal( QPoint( r.x(), r.y() ) ), tip ); + QToolTip::showText( mapToGlobal( QPoint( r.x(), r.y()+20 ) ), tip ); isTipActive = true; } } @@ -325,12 +325,14 @@ void HBQPlainTextEdit::hbSetSelectionMode( int mode, bool on ) rowEnds = c.blockNumber(); columnBegins = 0; columnEnds = 0; + selectionMode = selectionMode_line; } else { isLineSelectionON = false; + selectionMode = selectionMode_stream; } - selectionMode = selectionMode_line; + break; } default: @@ -723,6 +725,17 @@ bool HBQPlainTextEdit::hbKeyPressColumnSelection( QKeyEvent * event ) return true; } } + else if( selectionMode == selectionMode_stream || selectionMode == selectionMode_line ) + { + if( selectionState > 0 && ! ctrl && k == Qt::Key_Delete ) + { + hbCut( k ); + update(); + selectionState = 0; + event->ignore(); + return true; + } + } else { //emit selectionChanged(); @@ -817,7 +830,11 @@ void HBQPlainTextEdit::keyPressEvent( QKeyEvent * event ) c->popup()->setCurrentIndex( c->completionModel()->index( 0, 0 ) ); } QRect cr = cursorRect(); + cr.setWidth( c->popup()->sizeHintForColumn( 0 ) + c->popup()->verticalScrollBar()->sizeHint().width() ); + cr.setTop( cr.top() + 25 ); + cr.setBottom( cr.bottom() + 25 ); + c->complete( cr ); // popup it up! }