diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 2d5c8d338f..f9fe7522b4 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -17,6 +17,49 @@ past entries belonging to author(s): Viktor Szakats. */ +2010-05-02 03:00 UTC-0800 Pritpal Bedi (pritpal@vouchcac.com) + * contrib/hbqt/hbqt_hbqplaintextedit.cpp + * contrib/hbqt/hbqt_hbqplaintextedit.h + + * contrib/hbide/ideeditor.prg + + + Implemented: much-awaited and extremely-required feature - block copy/paste. + This implementation closely follows xMate's footsteps and is highly optimized, + having maximum tasks carried through .prg code. Probably this opens up + hbIDE to wider audience. This has been the most difficult feature so far, + and has consumed an entire week with intensive schedule. + + Here is how it should be used: + + Activation: + Clicking on the "Toggle Selection Mode" top-toolbar icon. + It must appear depressed after activation. + + Selection Process: + Keyboard : Shift + Navigation Keys ( Left, Right, Up, down, PgUp, PgDn, Home, End ). + Mouse : Mouse-move while left-button pressed ( Only available for visible text ). + Copy : Ctrl+C ( text is also available on the clip-board ) + Paste : Ctrl+V ( text only copied through Ctrl+C while in "Column Selection" mode ). + Inserts : Position cursor at first line and column, + Press Shift+Down arraow upto some ending row, + A thin-vertical-line should appear follwoing your cursor path, + Start typing any characters, + Any other navigation key will end this sesion, + Backspace key can be used to deleted previous characters. + If block is already selected, visible through color differentiation, + typing any charcter(s) will merely fill the selection with it, + Deletes : Select the text with Shift+Navigation Keys, + Press "Del". + + It is highly possible that some of the artifacts may have gone not exactly like + xMate, so please report back. Also note that selections left-to-right are known + for accuracy, right-to-left may not produce accurate results. Other thing to + note is that horizontal scrolling has not been possible, so if your text goes + beyond right-edge of the window and you have a need to copy it, then first zoom-in + to brought it into viewport, then start selection process. Vertical length does + not matter. However with mouse you can only select a window-full of text. + xMate does not support column-selection with mouse. + 2010-05-02 12:29 UTC+0200 Viktor Szakats (harbour.01 syenar.hu) * config/darwin/libs.mk ! Fixed to include MacPorts and Fink lib paths only if diff --git a/harbour/contrib/hbide/ideeditor.prg b/harbour/contrib/hbide/ideeditor.prg index 1abacf06fe..7f402e9ddf 100644 --- a/harbour/contrib/hbide/ideeditor.prg +++ b/harbour/contrib/hbide/ideeditor.prg @@ -1411,6 +1411,7 @@ CLASS IdeEdit INHERIT IdeObject DATA isSuspended INIT .f. DATA qFont + DATA aBlockCopyContents INIT {} METHOD new( oEditor, nMode ) METHOD create( oEditor, nMode ) @@ -1470,6 +1471,10 @@ CLASS IdeEdit INHERIT IdeObject METHOD isModified() INLINE ::oEditor:qDocument:isModified() METHOD setFont() METHOD markCurrentFunction() + METHOD copyBlockContents( aCord ) + METHOD pasteBlockContents() + METHOD insertBlockContents( aCord ) + METHOD deleteBlockContents( aCord ) ENDCLASS @@ -1883,6 +1888,18 @@ METHOD IdeEdit:execKeyEvent( nMode, nEvent, p, p1 ) ELSEIF p == 21001 ::handlePreviousWord( .t. ) + ELSEIF p == 21011 + ::copyBlockContents( p1 ) + + ELSEIF p == 21012 + ::pasteBlockContents() + + ELSEIF p == 21013 + ::insertBlockContents( p1 ) + + ELSEIF p == 21014 + ::deleteBlockContents( p1 ) + ELSEIF p == QEvent_Paint // ::oIde:testPainter( p1 ) @@ -1895,6 +1912,178 @@ METHOD IdeEdit:execKeyEvent( nMode, nEvent, p, p1 ) /*----------------------------------------------------------------------*/ +METHOD IdeEdit:copyBlockContents( aCord ) + LOCAL nT, nL, nB, nR, nW, i, cLine, cClip := "" + + nT := iif( aCord[ 1 ] > aCord[ 3 ], aCord[ 3 ], aCord[ 1 ] ) + nB := iif( aCord[ 1 ] > aCord[ 3 ], aCord[ 1 ], aCord[ 3 ] ) + nL := iif( aCord[ 2 ] > aCord[ 4 ], aCord[ 4 ], aCord[ 2 ] ) + nR := iif( aCord[ 2 ] > aCord[ 4 ], aCord[ 2 ], aCord[ 4 ] ) + + nW := nR - nL + + ::aBlockCopyContents := {} + FOR i := nT TO nB + cLine := ::getLine( i + 1 ) + cLine := pad( substr( cLine, nL + 1, nW ), nW ) + aadd( ::aBlockCopyContents, cLine ) + #if defined( __PLATFORM__WINDOWS ) + cClip += cLine + chr( 13 ) + chr( 10 ) + #elif defined( __PLATFORM__OS2 ) + cClip += cLine + chr( 13 ) + chr( 10 ) + #elif defined( __PLATFORM__UNIX ) + cClip += cLine + chr( 10 ) + #endif + NEXT + + QClipboard():new():setText( cClip ) + + RETURN Self + +/*----------------------------------------------------------------------*/ + +METHOD IdeEdit:pasteBlockContents() + LOCAL i, nRow, nCol, qCursor, nMaxCol + + IF empty( ::aBlockCopyContents ) + RETURN Self + ENDIF + + qCursor := QTextCursor():from( ::qEdit:textCursor() ) + nCol := qCursor:columnNumber() + qCursor:beginEditBlock() + // + FOR i := 1 TO len( ::aBlockCopyContents ) + qCursor:insertText( ::aBlockCopyContents[ i ] ) + IF i < len( ::aBlockCopyContents ) + nRow := qCursor:blockNumber() + qCursor:movePosition( QTextCursor_Down, QTextCursor_MoveAnchor ) + IF qCursor:blockNumber() == nRow + qCursor:movePosition( QTextCursor_EndOfBlock, QTextCursor_MoveAnchor ) + qCursor:insertBlock() + qCursor:movePosition( QTextCursor_NextBlock, QTextCursor_MoveAnchor ) + ENDIF + qCursor:movePosition( QTextCursor_EndOfLine, QTextCursor_MoveAnchor ) + nMaxCol := qCursor:columnNumber() + IF nMaxCol < nCol + qCursor:insertText( replicate( " ", nCol - nMaxCol ) ) + ENDIF + qCursor:movePosition( QTextCursor_StartOfBlock, QTextCursor_MoveAnchor ) + qCursor:movePosition( QTextCursor_Right, QTextCursor_MoveAnchor, nCol ) + ENDIF + NEXT + // + qCursor:endEditBlock() + + RETURN Self + +/*----------------------------------------------------------------------*/ + +METHOD IdeEdit:insertBlockContents( aCord ) + LOCAL nT, nL, nB, nR, nW, i, cLine, cKey, qCursor + + nT := iif( aCord[ 1 ] > aCord[ 3 ], aCord[ 3 ], aCord[ 1 ] ) + nB := iif( aCord[ 1 ] > aCord[ 3 ], aCord[ 1 ], aCord[ 3 ] ) + nL := iif( aCord[ 2 ] > aCord[ 4 ], aCord[ 4 ], aCord[ 2 ] ) + nR := iif( aCord[ 2 ] > aCord[ 4 ], aCord[ 2 ], aCord[ 4 ] ) + + nW := nR - nL + + cKey := chr( XbpQKeyEventToAppEvent( aCord[ 5 ] ) ) + + qCursor := QTextCursor():from( ::qEdit:textCursor() ) + qCursor:beginEditBlock() + + IF nW == 0 + FOR i := nT TO nB + cLine := ::getLine( i + 1 ) + cLine := pad( substr( cLine, 1, nL ), nL ) + cKey + substr( cLine, nL + 1 ) + + qCursor:movePosition( QTextCursor_Start , QTextCursor_MoveAnchor ) + qCursor:movePosition( QTextCursor_Down , QTextCursor_MoveAnchor, i ) + qCursor:movePosition( QTextCursor_StartOfBlock, QTextCursor_MoveAnchor ) + qCursor:movePosition( QTextCursor_EndOfLine , QTextCursor_KeepAnchor ) + qCursor:insertText( cLine ) + NEXT + qCursor:movePosition( QTextCursor_Start, QTextCursor_MoveAnchor ) + qCursor:movePosition( QTextCursor_Down , QTextCursor_MoveAnchor, nB ) + qCursor:movePosition( QTextCursor_Right, QTextCursor_MoveAnchor, nR + 1 ) + ELSE + FOR i := nT TO nB + cLine := ::getLine( i + 1 ) + cLine := pad( substr( cLine, 1, nL ), nL ) + replicate( cKey, nW ) + substr( cLine, nR + 1 ) + + qCursor:movePosition( QTextCursor_Start , QTextCursor_MoveAnchor ) + qCursor:movePosition( QTextCursor_Down , QTextCursor_MoveAnchor, i ) + qCursor:movePosition( QTextCursor_StartOfBlock, QTextCursor_MoveAnchor ) + qCursor:movePosition( QTextCursor_EndOfLine , QTextCursor_KeepAnchor ) + qCursor:insertText( cLine ) + NEXT + qCursor:movePosition( QTextCursor_Start, QTextCursor_MoveAnchor ) + qCursor:movePosition( QTextCursor_Down , QTextCursor_MoveAnchor, nB ) + qCursor:movePosition( QTextCursor_Right, QTextCursor_MoveAnchor, nR ) + ENDIF + // + ::qEdit:setCursorWidth( 1 ) + ::qEdit:setTextCursor( qCursor ) + qCursor:endEditBlock() + + RETURN Self + +/*----------------------------------------------------------------------*/ + +METHOD IdeEdit:deleteBlockContents( aCord ) + LOCAL nT, nL, nB, nR, nW, i, cLine, qCursor, k + + nT := iif( aCord[ 1 ] > aCord[ 3 ], aCord[ 3 ], aCord[ 1 ] ) + nB := iif( aCord[ 1 ] > aCord[ 3 ], aCord[ 1 ], aCord[ 3 ] ) + nL := iif( aCord[ 2 ] > aCord[ 4 ], aCord[ 4 ], aCord[ 2 ] ) + nR := iif( aCord[ 2 ] > aCord[ 4 ], aCord[ 2 ], aCord[ 4 ] ) + k := aCord[ 5 ] + + nW := nR - nL + + qCursor := QTextCursor():from( ::qEdit:textCursor() ) + qCursor:beginEditBlock() + IF nW == 0 .AND. k == Qt_Key_Backspace + FOR i := nT TO nB + cLine := ::getLine( i + 1 ) + cLine := pad( substr( cLine, 1, nL - 1 ), nL - 1 ) + substr( cLine, nL + 1 ) + + qCursor:movePosition( QTextCursor_Start , QTextCursor_MoveAnchor ) + qCursor:movePosition( QTextCursor_Down , QTextCursor_MoveAnchor, i ) + qCursor:movePosition( QTextCursor_StartOfLine , QTextCursor_MoveAnchor ) + qCursor:movePosition( QTextCursor_EndOfLine , QTextCursor_KeepAnchor ) + qCursor:insertText( cLine ) + NEXT + qCursor:movePosition( QTextCursor_Start, QTextCursor_MoveAnchor ) + qCursor:movePosition( QTextCursor_Down , QTextCursor_MoveAnchor, nB ) + qCursor:movePosition( QTextCursor_Right, QTextCursor_MoveAnchor, nR - 1 ) + ELSE + IF k == Qt_Key_Delete + FOR i := nT TO nB + cLine := ::getLine( i + 1 ) + cLine := pad( substr( cLine, 1, nL ), nL ) + substr( cLine, nR + 1 ) + + qCursor:movePosition( QTextCursor_Start , QTextCursor_MoveAnchor ) + qCursor:movePosition( QTextCursor_Down , QTextCursor_MoveAnchor, i ) + qCursor:movePosition( QTextCursor_StartOfLine , QTextCursor_MoveAnchor ) + qCursor:movePosition( QTextCursor_EndOfLine , QTextCursor_KeepAnchor ) + qCursor:insertText( cLine ) + NEXT + qCursor:movePosition( QTextCursor_Start, QTextCursor_MoveAnchor ) + qCursor:movePosition( QTextCursor_Down , QTextCursor_MoveAnchor, nT ) + qCursor:movePosition( QTextCursor_Right, QTextCursor_MoveAnchor, nL ) + ENDIF + ENDIF + // + ::qEdit:setTextCursor( qCursor ) + qCursor:endEditBlock() + + RETURN Self + +/*----------------------------------------------------------------------*/ + METHOD IdeEdit:markCurrentFunction() LOCAL n, nCurLine diff --git a/harbour/contrib/hbqt/hbqt_hbqplaintextedit.cpp b/harbour/contrib/hbqt/hbqt_hbqplaintextedit.cpp index 70de5fd892..145e563592 100644 --- a/harbour/contrib/hbqt/hbqt_hbqplaintextedit.cpp +++ b/harbour/contrib/hbqt/hbqt_hbqplaintextedit.cpp @@ -75,6 +75,8 @@ #include "hbqt_hbqplaintextedit.h" +/*----------------------------------------------------------------------*/ + HBQPlainTextEdit::HBQPlainTextEdit( QWidget * parent ) : QPlainTextEdit( parent ) { m_currentLineColor.setNamedColor( "#e8e8ff" ); @@ -104,6 +106,8 @@ HBQPlainTextEdit::HBQPlainTextEdit( QWidget * parent ) : QPlainTextEdit( parent horzRuler->setFrameShadow( QFrame::Sunken ); } +/*----------------------------------------------------------------------*/ + HBQPlainTextEdit::~HBQPlainTextEdit() { disconnect( this, SIGNAL( blockCountChanged( int ) ) ); @@ -116,17 +120,23 @@ HBQPlainTextEdit::~HBQPlainTextEdit() hb_itemRelease( block ); } +/*----------------------------------------------------------------------*/ + void HBQPlainTextEdit::hbSetEventBlock( PHB_ITEM pBlock ) { if( pBlock ) block = hb_itemNew( pBlock ); } +/*----------------------------------------------------------------------*/ + void HBQPlainTextEdit::hbRefresh() { update(); } +/*----------------------------------------------------------------------*/ + void HBQPlainTextEdit::hbShowPrototype( const QString & tip ) { if( tip == ( QString ) "" ) @@ -142,6 +152,8 @@ void HBQPlainTextEdit::hbShowPrototype( const QString & tip ) } } +/*----------------------------------------------------------------------*/ + bool HBQPlainTextEdit::event( QEvent *event ) { if( event->type() == QEvent::KeyPress ) @@ -182,8 +194,274 @@ bool HBQPlainTextEdit::event( QEvent *event ) return QPlainTextEdit::event( event ); } +/*----------------------------------------------------------------------*/ + +static bool isNavableKey( int k ) +{ + return ( k == Qt::Key_Right || k == Qt::Key_Left || k == Qt::Key_Up || k == Qt::Key_Down || + k == Qt::Key_Home || k == Qt::Key_End || k == Qt::Key_PageUp || k == Qt::Key_PageDown ); +} + +/*----------------------------------------------------------------------*/ + +void HBQPlainTextEdit::mouseDoubleClickEvent( QMouseEvent *event ) +{ + if( block ) + { + PHB_ITEM p1 = hb_itemPutNI( NULL, QEvent::MouseButtonDblClick ); + hb_vmEvalBlockV( block, 1, p1 ); + hb_itemRelease( p1 ); + } + QPlainTextEdit::mouseDoubleClickEvent( event ); +} + +/*----------------------------------------------------------------------*/ + +void HBQPlainTextEdit::mousePressEvent( QMouseEvent *event ) +{ + if( isColumnSelectionEnabled ) + { + if( columnBegins >= 0 ) + { + hbClearColumnSelection(); + } + } + QPlainTextEdit::mousePressEvent( event ); +} + +/*----------------------------------------------------------------------*/ + +void HBQPlainTextEdit::mouseReleaseEvent( QMouseEvent *event ) +{ + QPlainTextEdit::mouseReleaseEvent( event ); +} + +/*----------------------------------------------------------------------*/ + +void HBQPlainTextEdit::mouseMoveEvent( QMouseEvent *event ) +{ + if( isColumnSelectionEnabled ) + { + if( event->buttons() & Qt::LeftButton ) + { + if( columnBegins == -1 ) + { + QTextCursor c( textCursor() ); + int col = c.columnNumber(); + int row = c.blockNumber(); + + rowBegins = row; + columnBegins = col; + rowEnds = row; + columnEnds = col; + } + else + { + QTextCursor c( cursorForPosition( QPoint( 1,1 ) ) ); + rowEnds = c.blockNumber() + ( event->y() / fontMetrics().height() ); + columnEnds = event->x() / fontMetrics().averageCharWidth(); + } + update(); + event->accept(); + return; + } + } + QPlainTextEdit::mouseMoveEvent( event ); +} + +/*----------------------------------------------------------------------*/ + +bool HBQPlainTextEdit::hbKeyPressColumnSelection( QKeyEvent * event ) +{ + if( isColumnSelectionEnabled ) + { + bool ctrl = event->modifiers() & Qt::ControlModifier; + bool shift = event->modifiers() & Qt::ShiftModifier; + int k = event->key(); + + if( shift && isNavableKey( k ) ) + { + QTextCursor c( textCursor() ); + int col = c.columnNumber(); + int row = c.blockNumber(); + + setCursorWidth( 0 ); + + if( columnBegins == -1 ) + { + if( c.hasSelection() ) + { + QTextBlock b = c.document()->findBlock( c.selectionStart() ); + columnBegins = c.selectionStart() - b.position(); + columnEnds = c.columnNumber(); + rowBegins = b.blockNumber(); + b = c.document()->findBlock( c.selectionEnd() ); + rowEnds = b.blockNumber(); + update(); + } + else + { + rowBegins = row; + columnBegins = col; + rowEnds = row; + columnEnds = col; + } + } + + switch( k ) + { + case Qt::Key_Left: + if( col == 0 ) + { + columnEnds--; + columnEnds = columnEnds < 0 ? 0 : columnEnds; + update(); + event->ignore(); + return true; + } + break; + case Qt::Key_Right: + c.movePosition( QTextCursor::EndOfLine, QTextCursor::MoveAnchor ); + if( c.columnNumber() <= columnEnds ) + { + columnEnds++; + update(); + event->ignore(); + return true; + } + break; + } + + QPlainTextEdit::keyPressEvent( event ); + + c = textCursor(); + col = c.columnNumber(); + row = c.blockNumber(); + + switch( k ) + { + case Qt::Key_Right: + columnEnds++; + break; + case Qt::Key_Left: + columnEnds--; + columnEnds = columnEnds < 0 ? 0 : columnEnds; + break; + case Qt::Key_Up: + case Qt::Key_PageUp: + case Qt::Key_Down: + case Qt::Key_PageDown: + rowEnds = row; + break; + default: + rowEnds = row; + columnEnds = col; + } + c.clearSelection(); + setTextCursor( c ); + return true; + } + else if( isNavableKey( k ) ) + { + hbClearColumnSelection(); + } + else + { + if( ctrl && k == Qt::Key_C ) + { + if( block ) + { + PHB_ITEM p1 = hb_itemPutNI( NULL, 21011 ); + PHB_ITEM p2 = hb_itemNew( NULL ); + hb_arrayNew( p2, 4 ); + hb_arraySetNI( p2, 1, rowBegins ); + hb_arraySetNI( p2, 2, columnBegins ); + hb_arraySetNI( p2, 3, rowEnds ); + hb_arraySetNI( p2, 4, columnEnds ); + + hb_vmEvalBlockV( block, 2, p1, p2 ); + hb_itemRelease( p1 ); + hb_itemRelease( p2 ); + } + event->ignore(); + return true; + } + if( ctrl && k == Qt::Key_V ) + { + hbClearColumnSelection(); + if( block ) + { + PHB_ITEM p1 = hb_itemPutNI( NULL, 21012 ); + hb_vmEvalBlockV( block, 1, p1 ); + hb_itemRelease( p1 ); + } + event->ignore(); + return true; + } + if( ! ctrl && k >= ' ' && k < 127 && columnBegins >= 0 ) + { + PHB_ITEM p1 = hb_itemPutNI( NULL, 21013 ); + PHB_ITEM p2 = hb_itemNew( NULL ); + hb_arrayNew( p2, 5 ); + hb_arraySetNI( p2, 1, rowBegins ); + hb_arraySetNI( p2, 2, columnBegins ); + hb_arraySetNI( p2, 3, rowEnds ); + hb_arraySetNI( p2, 4, columnEnds ); + hb_arraySetPtr( p2, 5, event ); + + hb_vmEvalBlockV( block, 2, p1, p2 ); + hb_itemRelease( p1 ); + hb_itemRelease( p2 ); + + if( columnBegins == columnEnds ) + { + columnBegins++; + columnEnds++; + } + update(); + event->ignore(); + return true; + } + if( ! ctrl && ( k == Qt::Key_Backspace || k == Qt::Key_Delete ) && columnBegins >= 0 ) + { + PHB_ITEM p1 = hb_itemPutNI( NULL, 21014 ); + PHB_ITEM p2 = hb_itemNew( NULL ); + hb_arrayNew( p2, 5 ); + hb_arraySetNI( p2, 1, rowBegins ); + hb_arraySetNI( p2, 2, columnBegins ); + hb_arraySetNI( p2, 3, rowEnds ); + hb_arraySetNI( p2, 4, columnEnds ); + hb_arraySetNI( p2, 5, k ); + + hb_vmEvalBlockV( block, 2, p1, p2 ); + hb_itemRelease( p1 ); + hb_itemRelease( p2 ); + + if( k == Qt::Key_Backspace ) + { + columnBegins--; + columnEnds--; + } + else + { + columnEnds = columnBegins; + } + update(); + event->ignore(); + return true; + } + } + } + return false; +} + +/*----------------------------------------------------------------------*/ + void HBQPlainTextEdit::keyPressEvent( QKeyEvent * event ) { + if( hbKeyPressColumnSelection( event ) ) + return; + if( c && c->popup()->isVisible() ) { // The following keys are forwarded by the completer to the widget @@ -246,6 +524,8 @@ void HBQPlainTextEdit::keyPressEvent( QKeyEvent * event ) cr.setWidth( c->popup()->sizeHintForColumn( 0 ) + c->popup()->verticalScrollBar()->sizeHint().width() ); c->complete( cr ); // popup it up! } + +/*----------------------------------------------------------------------*/ #if 0 QString HBQPlainTextEdit::hbTextForPrefix() { @@ -254,6 +534,8 @@ QString HBQPlainTextEdit::hbTextForPrefix() return tc.selectedText(); } #endif +/*----------------------------------------------------------------------*/ + QString HBQPlainTextEdit::hbTextUnderCursor() { QTextCursor tc = textCursor(); @@ -261,6 +543,8 @@ QString HBQPlainTextEdit::hbTextUnderCursor() return tc.selectedText(); } +/*----------------------------------------------------------------------*/ + void HBQPlainTextEdit::resizeEvent( QResizeEvent *e ) { QPlainTextEdit::resizeEvent( e ); @@ -271,6 +555,8 @@ void HBQPlainTextEdit::resizeEvent( QResizeEvent *e ) horzRuler->setGeometry( QRect( cr.left(), cr.top(), cr.width(), HORZRULER_HEIGHT ) ); } +/*----------------------------------------------------------------------*/ + void HBQPlainTextEdit::focusInEvent( QFocusEvent * event ) { if( c ) @@ -279,17 +565,7 @@ void HBQPlainTextEdit::focusInEvent( QFocusEvent * event ) QPlainTextEdit::focusInEvent( event ); } -void HBQPlainTextEdit::mouseDoubleClickEvent( QMouseEvent *event ) -{ - HB_TRACE( HB_TR_ALWAYS, ( "void HBQPlainTextEdit::mouseDblClickEvent( QMouseEvent * %p )", event ) ); - if( block ) - { - PHB_ITEM p1 = hb_itemPutNI( NULL, QEvent::MouseButtonDblClick ); - hb_vmEvalBlockV( block, 1, p1 ); - hb_itemRelease( p1 ); - } - QPlainTextEdit::mouseDoubleClickEvent( event ); -} +/*----------------------------------------------------------------------*/ void HBQPlainTextEdit::paintEvent( QPaintEvent * event ) { @@ -389,6 +665,7 @@ void HBQPlainTextEdit::paintEvent( QPaintEvent * event ) QPlainTextEdit::paintEvent( event ); #endif } +/*----------------------------------------------------------------------*/ QBrush HBQPlainTextEdit::brushForBookmark( int index ) { @@ -412,6 +689,8 @@ QBrush HBQPlainTextEdit::brushForBookmark( int index ) return br; } +/*----------------------------------------------------------------------*/ + void HBQPlainTextEdit::horzRulerPaintEvent( QPaintEvent *event ) { QRect cr = event->rect(); @@ -453,6 +732,8 @@ void HBQPlainTextEdit::horzRulerPaintEvent( QPaintEvent *event ) } } +/*----------------------------------------------------------------------*/ + void HBQPlainTextEdit::lineNumberAreaPaintEvent( QPaintEvent *event ) { QPainter painter( lineNumberArea ); @@ -486,6 +767,98 @@ void HBQPlainTextEdit::lineNumberAreaPaintEvent( QPaintEvent *event ) } } +/*----------------------------------------------------------------------*/ + +void HBQPlainTextEdit::hbPaintColumnSelection( QPaintEvent * event ) +{ + HB_SYMBOL_UNUSED( event ); + + if( isColumnSelectionEnabled ) + { + if( columnBegins >= 0 && columnEnds >= 0 ) + { + QPainter p( viewport() ); + + int t = cursorForPosition( QPoint( 1, 1 ) ).blockNumber(); + if( rowEnds < rowBegins ? rowBegins >= t : rowEnds >= t ) + { + QRect cr = contentsRect(); + + int y = ( ( rowBegins <= t ) ? 0 : ( ( rowBegins - t ) * fontMetrics().height() ) ); + + int fontWidth = fontMetrics().averageCharWidth(); + + int x = ( columnBegins ) * fontWidth + cr.left(); + int w = ( columnEnds - columnBegins ) * fontWidth; + + QRect r( x, y, ( w == 0 ? 1 : w ), ( ( rowEnds - t + 1 ) * fontMetrics().height() ) - y ); + + p.fillRect( r, QBrush( QColor( 175, 255, 175 ) ) ); + } + } + } +} + +/*----------------------------------------------------------------------*/ + +void HBQPlainTextEdit::hbClearColumnSelection() +{ + setCursorWidth( 1 ); + + rowBegins = -1; + rowEnds = -1; + columnBegins = -1; + columnEnds = -1; +} + +/*----------------------------------------------------------------------*/ + +void HBQPlainTextEdit::hbHighlightSelectedColumns( bool yes ) +{ + if( yes ) + { + isColumnSelectionEnabled = true; + QTextCursor c = textCursor(); + + if( columnBegins == -1 && c.hasSelection() ) + { + QTextBlock b = c.document()->findBlock( c.selectionStart() ); + columnBegins = c.selectionStart() - b.position(); + columnEnds = c.columnNumber(); + rowBegins = b.blockNumber(); + b = c.document()->findBlock( c.selectionEnd() ); + rowEnds = b.blockNumber(); + c.clearSelection(); + setTextCursor( c ); + } + } + else + { + if( columnBegins >= 0 ) + { + int cb = columnBegins <= columnEnds ? columnBegins : columnEnds; + int ce = columnBegins <= columnEnds ? columnEnds : columnBegins; + int rb = rowBegins <= rowEnds ? rowBegins : rowEnds; + int re = rowBegins <= rowEnds ? rowEnds : rowBegins; + + QTextCursor c = textCursor(); + + c.movePosition( QTextCursor::Start ); + c.movePosition( QTextCursor::Down , QTextCursor::MoveAnchor, rb ); + c.movePosition( QTextCursor::Right , QTextCursor::MoveAnchor, cb ); + c.movePosition( QTextCursor::Down , QTextCursor::KeepAnchor, re - rb ); + c.movePosition( QTextCursor::StartOfLine, QTextCursor::KeepAnchor ); + c.movePosition( QTextCursor::Right , QTextCursor::KeepAnchor, ce ); + setTextCursor( c ); + } + hbClearColumnSelection(); + isColumnSelectionEnabled = false; + } + update(); +} + +/*----------------------------------------------------------------------*/ + void HBQPlainTextEdit::hbBookmarks( int block ) { int found = bookMark.indexOf( block ); @@ -521,6 +894,8 @@ void HBQPlainTextEdit::hbBookmarks( int block ) update(); } +/*----------------------------------------------------------------------*/ + void HBQPlainTextEdit::hbGotoBookmark( int block ) { if( bookMarksGoto.size() > 0 ) @@ -538,6 +913,8 @@ void HBQPlainTextEdit::hbGotoBookmark( int block ) } } +/*----------------------------------------------------------------------*/ + void HBQPlainTextEdit::hbNextBookmark( int block ) { if( bookMark.count() > 0 ) @@ -556,6 +933,8 @@ void HBQPlainTextEdit::hbNextBookmark( int block ) } } +/*----------------------------------------------------------------------*/ + void HBQPlainTextEdit::hbPrevBookmark( int block ) { if( bookMark.count() > 0 ) @@ -577,6 +956,8 @@ void HBQPlainTextEdit::hbPrevBookmark( int block ) } } +/*----------------------------------------------------------------------*/ + void HBQPlainTextEdit::hbNumberBlockVisible( bool b ) { numberBlock = b; @@ -593,11 +974,15 @@ void HBQPlainTextEdit::hbNumberBlockVisible( bool b ) update(); } +/*----------------------------------------------------------------------*/ + bool HBQPlainTextEdit::hbNumberBlockVisible() { return numberBlock; } +/*----------------------------------------------------------------------*/ + int HBQPlainTextEdit::hbLineNumberAreaWidth() { int digits = 1; @@ -615,6 +1000,8 @@ int HBQPlainTextEdit::hbLineNumberAreaWidth() return space; } +/*----------------------------------------------------------------------*/ + void HBQPlainTextEdit::hbUpdateLineNumberAreaWidth( int ) { if( numberBlock ) @@ -627,11 +1014,15 @@ void HBQPlainTextEdit::hbUpdateLineNumberAreaWidth( int ) } } +/*----------------------------------------------------------------------*/ + void HBQPlainTextEdit::hbUpdateHorzRuler() { horzRuler->update(); } +/*----------------------------------------------------------------------*/ + void HBQPlainTextEdit::hbUpdateLineNumberArea( const QRect &rect, int dy ) { if( dy ) @@ -645,6 +1036,8 @@ void HBQPlainTextEdit::hbUpdateLineNumberArea( const QRect &rect, int dy ) } } +/*----------------------------------------------------------------------*/ + void HBQPlainTextEdit::hbSetSpaces( int newSpaces ) { spaces = newSpaces; @@ -662,6 +1055,8 @@ void HBQPlainTextEdit::hbSetSpaces( int newSpaces ) } } +/*----------------------------------------------------------------------*/ + int HBQPlainTextEdit::hbGetIndex( const QTextCursor &crQTextCursor ) { QTextBlock b; @@ -671,6 +1066,8 @@ int HBQPlainTextEdit::hbGetIndex( const QTextCursor &crQTextCursor ) return column; } +/*----------------------------------------------------------------------*/ + int HBQPlainTextEdit::hbGetLine( const QTextCursor &crQTextCursor ) { QTextBlock b,cb; @@ -685,6 +1082,8 @@ int HBQPlainTextEdit::hbGetLine( const QTextCursor &crQTextCursor ) return line; } +/*----------------------------------------------------------------------*/ + void HBQPlainTextEdit::hbSlotCursorPositionChanged() { if( m_currentLineColor.isValid() ) @@ -694,11 +1093,15 @@ void HBQPlainTextEdit::hbSlotCursorPositionChanged() hbBraceHighlight(); } +/*----------------------------------------------------------------------*/ + void HBQPlainTextEdit::hbSetStyleHightlighter( const QString &style ) { styleHightlighter = style; } +/*----------------------------------------------------------------------*/ + void HBQPlainTextEdit::hbShowHighlighter( const QString &style, bool b ) { if( b ) @@ -718,6 +1121,8 @@ void HBQPlainTextEdit::hbShowHighlighter( const QString &style, bool b ) styleHightlighter = style; } +/*----------------------------------------------------------------------*/ + void HBQPlainTextEdit::hbEscapeQuotes() { QTextCursor cursor( textCursor() ); @@ -729,6 +1134,8 @@ void HBQPlainTextEdit::hbEscapeQuotes() insertPlainText( txt ); } +/*----------------------------------------------------------------------*/ + void HBQPlainTextEdit::hbEscapeDQuotes() { QTextCursor cursor( textCursor() ); @@ -740,6 +1147,8 @@ void HBQPlainTextEdit::hbEscapeDQuotes() insertPlainText( txt ); } +/*----------------------------------------------------------------------*/ + void HBQPlainTextEdit::hbUnescapeQuotes() { QTextCursor cursor( textCursor() ); @@ -751,6 +1160,8 @@ void HBQPlainTextEdit::hbUnescapeQuotes() insertPlainText( txt ); } +/*----------------------------------------------------------------------*/ + void HBQPlainTextEdit::hbUnescapeDQuotes() { QTextCursor cursor( textCursor() ); @@ -762,6 +1173,8 @@ void HBQPlainTextEdit::hbUnescapeDQuotes() insertPlainText( txt ); } +/*----------------------------------------------------------------------*/ + void HBQPlainTextEdit::hbCaseUpper() { QTextCursor cursor = textCursor(); @@ -781,6 +1194,8 @@ void HBQPlainTextEdit::hbCaseUpper() setTextCursor( cursor ); } +/*----------------------------------------------------------------------*/ + void HBQPlainTextEdit::hbCaseLower() { QTextCursor cursor = textCursor(); @@ -800,6 +1215,8 @@ void HBQPlainTextEdit::hbCaseLower() setTextCursor( cursor ); } +/*----------------------------------------------------------------------*/ + void HBQPlainTextEdit::hbConvertQuotes() { QTextCursor cursor = textCursor(); @@ -819,6 +1236,8 @@ void HBQPlainTextEdit::hbConvertQuotes() setTextCursor( cursor ); } +/*----------------------------------------------------------------------*/ + void HBQPlainTextEdit::hbConvertDQuotes() { QTextCursor cursor = textCursor(); @@ -838,6 +1257,8 @@ void HBQPlainTextEdit::hbConvertDQuotes() setTextCursor( cursor ); } +/*----------------------------------------------------------------------*/ + void HBQPlainTextEdit::hbReplaceSelection( const QString & txt ) { QTextCursor cursor = textCursor(); @@ -856,6 +1277,8 @@ void HBQPlainTextEdit::hbReplaceSelection( const QString & txt ) setTextCursor( cursor ); } +/*----------------------------------------------------------------------*/ + void HBQPlainTextEdit::hbStreamComment() { QTextCursor cursor = textCursor(); @@ -875,6 +1298,8 @@ void HBQPlainTextEdit::hbStreamComment() setTextCursor( cursor ); } +/*----------------------------------------------------------------------*/ + QString HBQPlainTextEdit::hbGetSelectedText() { QTextCursor cursor( textCursor() ); @@ -886,63 +1311,7 @@ QString HBQPlainTextEdit::hbGetSelectedText() return txt; } -void HBQPlainTextEdit::hbPaintColumnSelection( QPaintEvent * event ) -{ - QTextCursor c = textCursor(); - - HB_SYMBOL_UNUSED( event ); - - if( isColumnSelectionEnabled && c.hasSelection() ) - { - if( columnBegins >= 0 && columnEnds >= 0 ) - { - QTextBlock b = c.document()->findBlock( c.selectionStart() ); - QTextBlock e = c.document()->findBlock( c.selectionEnd() ); - - if( b.isVisible() || e.isVisible() ) - { - if( b.isVisible() ) - { - QPainter p( viewport() ); - - if( b.isValid() && b.isVisible() ) - { - int fontWidth = fontMetrics().averageCharWidth(); - - int x = ( columnBegins + 1 ) * fontWidth; - int w = ( c.columnNumber() - columnBegins ) * fontWidth; - QRect r( x, 0, w, viewport()->height() ); - - p.fillRect( r, QBrush( QColor( 175, 255, 175 ) ) ); - } - } - } - } - } -} - -void HBQPlainTextEdit::hbHighlightSelectedColumns( bool yes ) -{ - if( yes ) - { - isColumnSelectionEnabled = true; - - QTextCursor c = textCursor(); - if( columnBegins == -1 && c.hasSelection() ) - { - int b = c.document()->findBlock( c.selectionStart() ).position(); - columnBegins = c.selectionStart() - b; - columnEnds = c.columnNumber(); - } - } - else - { - columnBegins = -1; - columnEnds = -1; - isColumnSelectionEnabled = false; - } - update(); -} +/*----------------------------------------------------------------------*/ void HBQPlainTextEdit::hbInsertTab( int mode ) { @@ -965,6 +1334,8 @@ void HBQPlainTextEdit::hbInsertTab( int mode ) setTextCursor( c ); } +/*----------------------------------------------------------------------*/ + void HBQPlainTextEdit::hbMoveLine( int iDirection ) { QTextCursor cursor = textCursor(); @@ -1010,6 +1381,8 @@ void HBQPlainTextEdit::hbMoveLine( int iDirection ) setTextCursor( c ); } +/*----------------------------------------------------------------------*/ + void HBQPlainTextEdit::hbDeleteLine() { QTextCursor cursor = textCursor(); @@ -1029,6 +1402,8 @@ void HBQPlainTextEdit::hbDeleteLine() setTextCursor( c ); } +/*----------------------------------------------------------------------*/ + void HBQPlainTextEdit::hbBlockIndent( int steps ) { QTextCursor cursor = textCursor(); @@ -1079,6 +1454,8 @@ void HBQPlainTextEdit::hbBlockIndent( int steps ) } } +/*----------------------------------------------------------------------*/ + void HBQPlainTextEdit::hbBlockComment() { QTextCursor cursor = textCursor(); @@ -1117,6 +1494,8 @@ void HBQPlainTextEdit::hbBlockComment() setTextCursor( c ); } +/*----------------------------------------------------------------------*/ + void HBQPlainTextEdit::hbDuplicateLine() { QTextCursor cursor = textCursor(); @@ -1130,6 +1509,8 @@ void HBQPlainTextEdit::hbDuplicateLine() setTextCursor( c ); } +/*----------------------------------------------------------------------*/ + void HBQPlainTextEdit::hbBraceHighlight() { extraSelections.clear(); @@ -1256,4 +1637,5 @@ void HBQPlainTextEdit::hbBraceHighlight() } } +/*----------------------------------------------------------------------*/ #endif diff --git a/harbour/contrib/hbqt/hbqt_hbqplaintextedit.h b/harbour/contrib/hbqt/hbqt_hbqplaintextedit.h index ec82bf2d1b..555ee08b87 100644 --- a/harbour/contrib/hbqt/hbqt_hbqplaintextedit.h +++ b/harbour/contrib/hbqt/hbqt_hbqplaintextedit.h @@ -75,6 +75,7 @@ class LineNumberArea; class HorzRuler; + class HBQPlainTextEdit : public QPlainTextEdit { Q_OBJECT @@ -129,6 +130,8 @@ private: QTextEdit::ExtraSelection selection; void hbBraceHighlight(); + int rowBegins; + int rowEnds; int columnBegins; int columnEnds; bool isColumnSelectionEnabled; @@ -140,6 +143,9 @@ protected: bool event( QEvent * event ); void resizeEvent( QResizeEvent * event ); void mouseDoubleClickEvent( QMouseEvent * event ); + void mousePressEvent( QMouseEvent * event ); + void mouseReleaseEvent( QMouseEvent * event ); + void mouseMoveEvent( QMouseEvent * event ); void focusInEvent( QFocusEvent * event ); void keyPressEvent( QKeyEvent * event ); @@ -176,6 +182,8 @@ private slots: void hbUpdateLineNumberArea( const QRect &, int ); void hbUpdateHorzRuler(); void hbPaintColumnSelection( QPaintEvent * ); + bool hbKeyPressColumnSelection( QKeyEvent * ); + void hbClearColumnSelection(); };