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 <Split> item
         3. Select from "Split Horiz..." etc.

    Please report any functionality which may be incorporated hereunder.
This commit is contained in:
Pritpal Bedi
2010-01-12 10:22:14 +00:00
parent 4a1f1743d3
commit d91c217ae4
5 changed files with 181 additions and 48 deletions

View File

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

View File

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

View File

@@ -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 := "<b>Line "+ hb_ntos( ::qCursor:blockNumber() + 1 ) + " of " + ;
hb_ntos( ::qDocument:blockCount() ) + "</b>"
qDocument := QTextDocument():configure( qEdit:document() )
qCursor := QTextCursor():configure( qEdit:textCursor() )
s := "<b>Line "+ hb_ntos( qCursor:blockNumber() + 1 ) + " of " + ;
hb_ntos( qDocument:blockCount() ) + "</b>"
::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"

View File

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

View File

@@ -60,6 +60,8 @@
#if QT_VERSION >= 0x040500
#include <QTextCodec>
#include <QSettings>
#include <QMainWindow>
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