From d91c217ae44626c5850cec025df7425955f4a132 Mon Sep 17 00:00:00 2001 From: Pritpal Bedi Date: Tue, 12 Jan 2010 10:22:14 +0000 Subject: [PATCH] 2010-01-11 01:52 UTC-0800 Pritpal Bedi (pritpal@vouchcac.com) * contrib/hbqt/hbqt_destruct.cpp + Added .prg callable hbqt_QMainWindow_saveSettings() and hbqt_QMainWindow_restSettings(). These two functions are essential to save and restore last hbIDE interface exactly in the same state it was closed last. This I could not achieve via pure .prg code. * contrib/hbide/hbide.prg * contrib/hbide/ideeditor.prg * contrib/hbide/idesaveload.prg + Implemented restoring exact geometry of main window plus all the docking windows plus toolbars. hbIDE creates idesettings.ini in the folder returned by hb_dirBase(). Note that idesettings.ini is not a windows .ini format and please do not try to change even a single byte of its contents. + Implemented splitting any source into multiple windows. This implementation allows you to edit different parts of same source simultaneously. This feature allows you to split window horizontally or vertically. You can split many times. This feature can be activated as such: 1. Right-click somewhere in the editing tab 2. Context menu will be displayed, point to item 3. Select from "Split Horiz..." etc. Please report any functionality which may be incorporated hereunder. --- harbour/ChangeLog | 29 +++++ harbour/contrib/hbide/hbide.prg | 9 +- harbour/contrib/hbide/ideeditor.prg | 159 +++++++++++++++++++------ harbour/contrib/hbide/idesaveload.prg | 16 +-- harbour/contrib/hbqt/hbqt_destruct.cpp | 16 +++ 5 files changed, 181 insertions(+), 48 deletions(-) diff --git a/harbour/ChangeLog b/harbour/ChangeLog index b33d5d9cca..d88fb4d4f9 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -17,6 +17,35 @@ past entries belonging to author(s): Viktor Szakats. */ +2010-01-11 01:52 UTC-0800 Pritpal Bedi (pritpal@vouchcac.com) + * contrib/hbqt/hbqt_destruct.cpp + + Added .prg callable hbqt_QMainWindow_saveSettings() and + hbqt_QMainWindow_restSettings(). These two functions are + essential to save and restore last hbIDE interface exactly + in the same state it was closed last. This I could not achieve + via pure .prg code. + + * contrib/hbide/hbide.prg + * contrib/hbide/ideeditor.prg + * contrib/hbide/idesaveload.prg + + Implemented restoring exact geometry of main window plus + all the docking windows plus toolbars. hbIDE creates + idesettings.ini in the folder returned by hb_dirBase(). + Note that idesettings.ini is not a windows .ini format + and please do not try to change even a single byte of its + contents. + + + Implemented splitting any source into multiple windows. + This implementation allows you to edit different parts of + same source simultaneously. This feature allows you to split + window horizontally or vertically. You can split many times. + This feature can be activated as such: + 1. Right-click somewhere in the editing tab + 2. Context menu will be displayed, point to item + 3. Select from "Split Horiz..." etc. + + Please report any functionality which may be incorporated hereunder. + 2010-01-11 08:12 UTC-0800 Pritpal Bedi (pritpal@vouchcac.com) + contrib/hbide/resources/findsource.ui %+ TOBE implemented in "Sources List" tabpage of "Project Properties" dialog. diff --git a/harbour/contrib/hbide/hbide.prg b/harbour/contrib/hbide/hbide.prg index 57a7c30484..2e43e0bf97 100644 --- a/harbour/contrib/hbide/hbide.prg +++ b/harbour/contrib/hbide/hbide.prg @@ -326,6 +326,9 @@ METHOD HbIde:create( cProjIni ) ::setSizeByIni( ::oProjTree:oWidget, ProjectTreeGeometry ) ::setSizeByIni( ::oEditTree:oWidget, ProjectTreeGeometry ) + /* Restore Settings */ + hbide_restSettings( Self ) + /* Request Main Window to Appear on the Screen */ ::oDlg:Show() @@ -348,8 +351,8 @@ METHOD HbIde:create( cProjIni ) CASE ::mp1 == xbeK_INS IF !empty( ::qCurEdit ) - ::qCurEdit:setOverwriteMode( ! ::qCurEdit:overwriteMode() ) - ::oCurEditor:dispEditInfo() + ::qCurEdit:setOverwriteMode( !::qCurEdit:overwriteMode() ) + ::oCurEditor:dispEditInfo( ::qCurEdit ) ENDIF CASE ::mp1 == xbeK_ESC @@ -498,6 +501,8 @@ METHOD HbIde:execAction( cKey ) ::oEM:convertSelection( cKey ) CASE cKey == "Invert" ::oEM:convertSelection( cKey ) + CASE cKey == "MatchPairs" + // CASE cKey == "InsertDateTime" ::oEM:insertText( cKey ) CASE cKey == "InsertRandomName" diff --git a/harbour/contrib/hbide/ideeditor.prg b/harbour/contrib/hbide/ideeditor.prg index cf81cea72c..56a2a2253d 100644 --- a/harbour/contrib/hbide/ideeditor.prg +++ b/harbour/contrib/hbide/ideeditor.prg @@ -118,6 +118,7 @@ CLASS IdeEditsManager INHERIT IdeObject METHOD exeBlock() METHOD addSourceInTree() METHOD removeSourceInTree() + METHOD splitEdit() ENDCLASS @@ -132,6 +133,7 @@ METHOD IdeEditsManager:new( oIde ) /*----------------------------------------------------------------------*/ METHOD IdeEditsManager:create( oIde ) + LOCAL oSub DEFAULT oIde TO ::oIde @@ -154,6 +156,12 @@ METHOD IdeEditsManager:create( oIde ) aadd( ::aActions, { "" , ::qContextMenu:addSeparator() } ) aadd( ::aActions, { "Apply Theme" , ::qContextMenu:addAction( "Apply Theme" ) } ) + oSub := QMenu():configure( ::qContextMenu:addMenu_1( "Split" ) ) + // + aadd( ::aActions, { "Split H" , oSub:addAction( "Split Horiz..." ) } ) + aadd( ::aActions, { "Split V" , oSub:addAction( "Split Verti..." ) } ) + aadd( ::aActions, { "Close Split" , oSub:addAction( "Close Split" ) } ) + RETURN Self /*----------------------------------------------------------------------*/ @@ -234,6 +242,17 @@ METHOD IdeEditsManager:exeBlock( nMode, p ) /*----------------------------------------------------------------------*/ +METHOD IdeEditsManager:splitEdit() + LOCAL oEdit + + IF !empty( oEdit := ::getEditorCurrent() ) + oEdit:split() + ENDIF + + RETURN Self + +/*----------------------------------------------------------------------*/ + METHOD IdeEditsManager:buildEditor( cSourceFile, nPos, nHPos, nVPos, cTheme ) aadd( ::aEdits, IdeEditor():new():create( ::oIde, cSourceFile, nPos, nHPos, nVPos, cTheme ) ) @@ -648,12 +667,14 @@ CLASS IdeEditor INHERIT IdeObject DATA aTab INIT {} DATA qCursor + DATA aSplits INIT {} METHOD new() METHOD create() METHOD destroy() METHOD buildTabPage() + METHOD buildEditor() METHOD removeTabPage() METHOD activateTab() METHOD closeTab() @@ -662,6 +683,7 @@ CLASS IdeEditor INHERIT IdeObject METHOD applyTheme() METHOD setDocumentProperties() METHOD exeBlock() + METHOD split() ENDCLASS @@ -712,42 +734,26 @@ METHOD IdeEditor:create( oIde, cSourceFile, nPos, nHPos, nVPos, cTheme ) ::buildTabPage( ::sourceFile ) - ::qEdit := QPlainTextEdit():new( ::oTab:oWidget ) - ::qEdit:setLineWrapMode( QTextEdit_NoWrap ) - ::qEdit:setFont( ::oFont:oWidget ) - ::qEdit:ensureCursorVisible() - * ::qEdit:setStyleSheet( GetStyleSheet( "QPlainTextEdit" ) ) + ::qEdit := ::buildEditor( 0 ) /* Main Editor */ ::qDocument := QTextDocument():configure( ::qEdit:document() ) + // + ::Connect( ::qDocument, "blockCountChanged(int)" , {|o,p | ::exeBlock( 21, p, o ) } ) + ::Connect( ::qDocument, "contentsChanged()" , {| | ::exeBlock( 22 ) } ) - ::qLayout := QBoxLayout():new() - ::qLayout:setDirection( 0 ) + ::qLayout := QGridLayout():new() ::qLayout:setContentsMargins( 0,0,0,0 ) - ::qLayout:addWidget( ::qEdit ) - + ::qLayout:setHorizontalSpacing( 5 ) + ::qLayout:setVerticalSpacing( 5 ) + // ::oTab:oWidget:setLayout( ::qLayout ) + // Row Col RSpn CSpn + ::qLayout:addWidget_1( ::qEdit, 0, 1, 1, 1 ) IF ::cType != "U" ::qHiliter := ::oThemes:SetSyntaxHilighting( ::qEdit, @::cTheme ) ENDIF - ::qEdit:setContextMenuPolicy( Qt_CustomContextMenu ) - ::connect( ::qEdit , "customContextMenuRequested(QPoint)", {|o,p| ::exeBlock( 1, p, o ) } ) - - /* QPlainTextEdit */ - ::Connect( ::qEdit , "textChanged()" , {| | ::setTabImage() } ) - ::Connect( ::qEdit , "cursorPositionChanged()" , {| | ::dispEditInfo() } ) - ::Connect( ::qEdit , "copyAvailable(bool)" , {|o,p | ::exeBlock( 3, p, o ) } ) - ::Connect( ::qEdit , "modificationChanged(bool)", {|o,p | ::exeBlock( 4, p, o ) } ) - ::Connect( ::qEdit , "redoAvailable(bool)" , {|o,p | ::exeBlock( 5, p, o ) } ) - ::Connect( ::qEdit , "selectionChanged()" , {|o,p | ::exeBlock( 6, p, o ) } ) - ::Connect( ::qEdit , "undoAvailable(bool)" , {|o,p | ::exeBlock( 7, p, o ) } ) - ::Connect( ::qEdit , "updateRequest(QRect,int)" , {|o,p,p1| ::exeBlock( 8, p, p1, o ) } ) - /* QTextDocument */ - ::Connect( ::qDocument, "blockCountChanged(int)" , {|o,p | ::exeBlock( 21, p, o ) } ) - ::Connect( ::qDocument, "contentsChanged()" , {| | ::exeBlock( 22 ) } ) - - ::qEdit:show() ::qCursor := QTextCursor():configure( ::qEdit:textCursor() ) @@ -767,19 +773,81 @@ METHOD IdeEditor:create( oIde, cSourceFile, nPos, nHPos, nVPos, cTheme ) /*----------------------------------------------------------------------*/ -METHOD IdeEditor:exeBlock( nMode, p, p1 ) - LOCAL pAct, qAct +METHOD IdeEditor:split( nMode, qEditP ) + LOCAL qEdit, nRows, nCols + + HB_SYMBOL_UNUSED( qEditP ) + + nRows := ::qLayout:rowCount() + nCols := ::qlayout:columnCount() + + qEdit := ::buildEditor() + IF nMode == 1 /* Horizontal */ + ::qLayout:addWidget( qEdit, nRows - 1, nCols ) + ELSEIF nMode == 2 /* Vertical */ + ::qLayout:addWidget( qEdit, nRows, nCols - 1 ) + ENDIF + + aadd( ::aSplits, qEdit ) + + qEdit:setDocument( ::qEdit:document() ) + + qEdit:show() + + RETURN Self + +/*----------------------------------------------------------------------*/ + +METHOD IdeEditor:buildEditor() + LOCAL qEdit + + qEdit := QPlainTextEdit():new() + qEdit:setLineWrapMode( QTextEdit_NoWrap ) + qEdit:setFont( ::oFont:oWidget ) + qEdit:ensureCursorVisible() + + qEdit:setContextMenuPolicy( Qt_CustomContextMenu ) + ::connect( qEdit, "customContextMenuRequested(QPoint)", {|o,p| ::exeBlock( 1, p, o, qEdit ) } ) + + ::Connect( qEdit, "textChanged()" , {| | ::setTabImage() } ) + ::Connect( qEdit, "cursorPositionChanged()" , {| | ::dispEditInfo( qEdit ) } ) + ::Connect( qEdit, "updateRequest(QRect,int)" , {|o,p,p1| ::exeBlock( 8, p, p1, o ) } ) + ::Connect( qEdit, "copyAvailable(bool)" , {|o,p | ::exeBlock( 3, p, o ) } ) + ::Connect( qEdit, "modificationChanged(bool)", {|o,p | ::exeBlock( 4, p, o ) } ) + ::Connect( qEdit, "redoAvailable(bool)" , {|o,p | ::exeBlock( 5, p, o ) } ) + ::Connect( qEdit, "selectionChanged()" , {|o,p | ::exeBlock( 6, p, o ) } ) + ::Connect( qEdit, "undoAvailable(bool)" , {|o,p | ::exeBlock( 7, p, o ) } ) + ::Connect( qEdit, "updateRequest(QRect,int)" , {|o,p,p1| ::exeBlock( 8, p, p1, o ) } ) + + RETURN qEdit + +/*----------------------------------------------------------------------*/ + +METHOD IdeEditor:exeBlock( nMode, p, p1, qEdit ) + LOCAL pAct, qAct, n //LOCAL qRect HB_SYMBOL_UNUSED( p ) HB_SYMBOL_UNUSED( p1 ) SWITCH nMode + /* QPlainTextEdit */ CASE 1 // "customContextMenuRequested(QPoint)" - IF !empty( pAct := ::oEM:qContextMenu:exec_1( ::qEdit:mapToGlobal( p ) ) ) + IF !empty( pAct := ::oEM:qContextMenu:exec_1( qEdit:mapToGlobal( p ) ) ) qAct := QAction():configure( pAct ) DO CASE + CASE qAct:text() == "Split Horiz..." + ::split( 1, qEdit ) + CASE qAct:text() == "Split Verti..." + ::split( 2, qEdit ) + CASE qAct:text() == "Close Split" + IF ( n := ascan( ::aSplits, {|o| o == qEdit } ) ) > 0 + ::qLayout:removeWidget( qEdit ) + hb_adel( ::aSplits, n, .t. ) + qEdit:close() + qEdit:pPtr := 0 + ENDIF CASE qAct:text() == "Apply Theme" ::applyTheme() ENDCASE @@ -806,6 +874,7 @@ METHOD IdeEditor:exeBlock( nMode, p, p1 ) //qRect := QRect():configure( p ) //hbide_dbg( "updateRequest(QRect,int)", qRect:x(), qRect:y(), qRect:width(), qRect:height(), p1 ) EXIT + /* QTabPage */ CASE 11 // QEvent_ContextMenu hbide_dbg( "QEvent_ContextMenu" ) @@ -813,6 +882,7 @@ METHOD IdeEditor:exeBlock( nMode, p, p1 ) CASE 12 // QEvent_ContextMenu hbide_dbg( "QEvent_ContextMenu" ) EXIT + /* QTextDocument */ CASE 21 // "blockCountChanged(int)" ::nBlock := QTextCursor():configure( ::qEdit:textCursor() ):blockNumber() @@ -851,7 +921,7 @@ METHOD IdeEditor:setDocumentProperties() ::oIde:updateFuncList() ::oIde:updateTitleBar() - ::dispEditInfo() + ::dispEditInfo( ::qEdit ) ::oIde:manageFocusInEditor() @@ -933,7 +1003,15 @@ METHOD IdeEditor:closeTab( mp1, mp2, oXbp ) */ METHOD IdeEditor:removeTabPage() LOCAL cSource := ::sourceFile - LOCAL n + LOCAL n, qEdit + + FOR EACH qEdit IN ::aSplits + ::qLayout:removeWidget( qEdit ) + qEdit:close() + qEdit:pPtr := 0 + qEdit := NIL + NEXT + ::aSplits := {} n := aScan( ::oIde:aTabs, {|e_| e_[ TAB_OEDITOR ]:nID == ::nID } ) IF n > 0 @@ -990,20 +1068,23 @@ METHOD IdeEditor:removeTabPage() /*----------------------------------------------------------------------*/ -METHOD IdeEditor:dispEditInfo() - LOCAL s +METHOD IdeEditor:dispEditInfo( qEdit ) + LOCAL s, qDocument, qCursor - ::qCursor := QTextCursor():configure( ::qEdit:textCursor() ) + DEFAULT qEdit TO ::qEdit - s := "Line "+ hb_ntos( ::qCursor:blockNumber() + 1 ) + " of " + ; - hb_ntos( ::qDocument:blockCount() ) + "" + qDocument := QTextDocument():configure( qEdit:document() ) + qCursor := QTextCursor():configure( qEdit:textCursor() ) + + s := "Line "+ hb_ntos( qCursor:blockNumber() + 1 ) + " of " + ; + hb_ntos( qDocument:blockCount() ) + "" ::oIde:oSBar:getItem( SB_PNL_MAIN ):caption := "Success" ::oIde:oSBar:getItem( SB_PNL_READY ):caption := "Ready" ::oIde:oSBar:getItem( SB_PNL_LINE ):caption := s - ::oIde:oSBar:getItem( SB_PNL_COLUMN ):caption := "Col " + hb_ntos( ::qCursor:columnNumber() + 1 ) - ::oIde:oSBar:getItem( SB_PNL_INS ):caption := iif( ::qEdit:overwriteMode() , " ", "Ins" ) - ::oIde:oSBar:getItem( SB_PNL_MODIFIED ):caption := iif( ::qDocument:isModified(), "Modified", iif( ::qEdit:isReadOnly(), "ReadOnly", " " ) ) + ::oIde:oSBar:getItem( SB_PNL_COLUMN ):caption := "Col " + hb_ntos( qCursor:columnNumber() + 1 ) + ::oIde:oSBar:getItem( SB_PNL_INS ):caption := iif( qEdit:overwriteMode() , " ", "Ins" ) + ::oIde:oSBar:getItem( SB_PNL_MODIFIED ):caption := iif( qDocument:isModified(), "Modified", iif( qEdit:isReadOnly(), "ReadOnly", " " ) ) ::oIde:oSBar:getItem( SB_PNL_STREAM ):caption := "Stream" ::oIde:oSBar:getItem( SB_PNL_EDIT ):caption := "Edit" diff --git a/harbour/contrib/hbide/idesaveload.prg b/harbour/contrib/hbide/idesaveload.prg index c5cc7d2785..b377285ab6 100644 --- a/harbour/contrib/hbide/idesaveload.prg +++ b/harbour/contrib/hbide/idesaveload.prg @@ -286,14 +286,16 @@ FUNCTION hbide_loadINI( oIde, cHbideIni ) /*----------------------------------------------------------------------*/ STATIC FUNCTION hbide_saveSettings( oIde ) - LOCAL qSet, qWidget - qWidget := oIde:oDlg:oWidget - - qSet := QSettings():new( hb_dirBase() + "idesettings.ini", 1 ) - - qSet:setValue( "hbIDE" , qWidget:saveState() ) - qSet:setValue( "hbIDE-g", qWidget:geometry() ) + hbqt_QMainWindow_saveSettings( hb_dirBase() + "idesettings.ini", "hbIDE", oIde:oDlg:oWidget:pPtr ) + + RETURN nil + +/*----------------------------------------------------------------------*/ + +FUNCTION hbide_restSettings( oIde ) + + hbqt_QMainWindow_restSettings( hb_dirBase() + "idesettings.ini", "hbIDE", oIde:oDlg:oWidget:pPtr ) RETURN nil diff --git a/harbour/contrib/hbqt/hbqt_destruct.cpp b/harbour/contrib/hbqt/hbqt_destruct.cpp index a31523b79a..f4df9ce0d8 100644 --- a/harbour/contrib/hbqt/hbqt_destruct.cpp +++ b/harbour/contrib/hbqt/hbqt_destruct.cpp @@ -60,6 +60,8 @@ #if QT_VERSION >= 0x040500 #include +#include +#include static int s_iObjectReleaseMethod = HBQT_RELEASE_WITH_DELETE_LATER; @@ -133,6 +135,20 @@ HB_FUNC( HBQT_SETCODECFORCSTRINGS ) QTextCodec::setCodecForCStrings( codec ); } +HB_FUNC( HBQT_QMAINWINDOW_SAVESETTINGS ) +{ + QSettings qSet( hbqt_par_QString( 1 ), QSettings::IniFormat ); + + qSet.setValue( hbqt_par_QString( 2 ), hbqt_par_QMainWindow( 3 )->saveState() ); +} + +HB_FUNC( HBQT_QMAINWINDOW_RESTSETTINGS ) +{ + QSettings qSet( hbqt_par_QString( 1 ), QSettings::IniFormat ); + + hbqt_par_QMainWindow( 3 )->restoreState( qSet.value( hbqt_par_QString( 2 ) ).toByteArray() ); +} + /*----------------------------------------------------------------------*/ #endif // #if QT_VERSION >= 0x040500