Files
harbour-core/harbour/contrib/hbqt/hbqt_hbqplaintextedit.cpp
Pritpal Bedi 05fd080872 2010-06-13 19:27 UTC-0800 Pritpal Bedi (bedipritpal@hotmail.com)
* contrib/hbide/resources/curlinehilight.png
  + contrib/hbide/resources/horzruler.png
  * contrib/hbide/resources/togglelinenumber.png
  * contrib/hbide/resources/toolsutilities.ui
  * contrib/hbide/resources/toolsutilities.uic
  * contrib/hbide/resources/setup.ui
  * contrib/hbide/resources/setup.uic

  * contrib/hbqt/qth/HBQPlainTextEdit.qth
  * contrib/hbqt/qth/QTableWidget.qth
  - contrib/hbqt/qth/HBQSyntaxHighLighter.qth
  + contrib/hbqt/qth/HBQSyntaxHighlighter.qth

  * contrib/hbqt/doc/en/class_hbqplaintextedit.txt
  * contrib/hbqt/doc/en/class_hbqsyntaxhighlighter.txt
  * contrib/hbqt/qtgui/HBQPlainTextEdit.cpp
  * contrib/hbqt/qtgui/QTableWidget.cpp
  * contrib/hbqt/qtgui/THBQPlainTextEdit.prg
  * contrib/hbqt/qtgui/HBQSyntaxHighlighter.cpp
  * contrib/hbqt/qtgui/THBQSyntaxHighlighter.prg

  * contrib/hbqt/hbqt_hbqplaintextedit.cpp
  * contrib/hbqt/hbqt_hbqplaintextedit.h
  * contrib/hbqt/hbqt_hbqsyntaxhighlighter.cpp
  * contrib/hbqt/hbqt_hbqsyntaxhighlighter.h

  * contrib/hbide/hbide.hbp

  * contrib/hbide/hbide.ch

  * contrib/hbide/hbide.prg
  + contrib/hbide/idedict.prg
  * contrib/hbide/idedocks.prg
  * contrib/hbide/ideedit.prg
  * contrib/hbide/ideeditor.prg
  * contrib/hbide/idemisc.prg
  * contrib/hbide/ideobject.prg
  * contrib/hbide/idesaveload.prg
  * contrib/hbide/ideshortcuts.prg
  * contrib/hbide/idestylesheets.prg
  * contrib/hbide/idethemes.prg
  * contrib/hbide/idetools.prg

    % Widened padding for menubar prompts to show up at a proper distance.  

    + Controlled "RETURN" keyword not to jump to first indentation place,
      with env variable - HBIDE_RETURN_ATBEGINING=yes. Scheduled to be 
      included in "Setup" interface.

    + Allowed hbIDE execution with any text type file. It was accepting .PRG.CPP only.

    + Broadened the scope of keyword coloring for any case, mixed or absolute.
      It was all lower or all upper previously.

    + Prepared ground for user defined keywords through user dictionaries.

    + Added new flags in "Setup" dialog ( yet not active ).
      Please have a look into the contents of different pages and 
      let me know what else can qualify to be included therein.

    + More macro for Tools parameter - ${source_fullname_less_ext}

    % Tools & Utilities dialog made modeless. At times it is desirable 
      to execute a tool multiple times and also to gather output logs.

    + Tools & Utilities dialog now remembers its last opened position.

    + Implemented: user-configurable 5 toolbars which can be populated 
      through Tool & Utilities interface. Invoke "Tools & Utilities"
      interface and play with the toolbars. You will find it really 
      rewarding. I am also trying to find a way to hook 
      "Kayboard Mappings" macros to be included under this interface.
      Your input is welcome. I will write the help in about a week, 
      but interface is straight enough to grab/grasp/use.

    + Implemented: to switch on/off horizontal ruler. 

    + Implemented: to remember the last settings for next run for
      Horizontal Ruler, Line Numbers display and Current Line highlighting.
2010-06-14 02:31:15 +00:00

2493 lines
70 KiB
C++

/*
* $Id$
*/
/*
* Harbour Project source code:
* Harbour-Qt wrapper generator.
*
* Copyright 2010 Pritpal Bedi <pritpal@vouchcac.com>
* Copyright 2009 Gancov Kostya <kossne@mail.ru>
* www - http://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.
*
*/
/*----------------------------------------------------------------------*/
/*
* The code below is puled from TextEdit.cpp of QWriter by Gancov Kotsya
*
* and adopted for Harbour's hbIDE interface. The code has been intensively
* formatted and changed to suit hbIDE and Harbour's wrappers for Qt.
* The special hilight for this adoption is <braces matching>, current line
* coloring and bookmarks.
*
* So a big thank you.
*
* Pritpal Bedi
*/
/*----------------------------------------------------------------------*/
#include "hbqt.h"
#include "hbapiitm.h"
#include "hbthread.h"
#include "hbvm.h"
#if QT_VERSION >= 0x040500
#include "hbqt_hbqplaintextedit.h"
#include <QtGui/QApplication>
#define selectionState_off 0
#define selectionState_on 1
#define selectionMode_none 0
#define selectionMode_stream 1
#define selectionMode_column 2
#define selectionMode_line 3
#define selectionDisplay_none 0
#define selectionDisplay_qt 1
#define selectionDisplay_ide 2
/*----------------------------------------------------------------------*/
HBQPlainTextEdit::HBQPlainTextEdit( QWidget * parent ) : QPlainTextEdit( parent )
{
m_currentLineColor.setNamedColor( "#e8e8ff" );
m_lineAreaBkColor.setNamedColor( "#e4e4e4" );
m_horzRulerBkColor.setNamedColor( "whitesmoke" );
m_matchBracesAll = false;
spaces = 3;
spacesTab = "";
styleHightlighter = "prg";
numberBlock = true;
lineNumberArea = new LineNumberArea( this );
isTipActive = false;
columnBegins = -1;
columnEnds = -1;
rowBegins = -1;
rowEnds = -1;
selectionState = selectionState_off;
selectionMode = selectionMode_stream;
selectionDisplay = selectionDisplay_none;
isColumnSelectionON = false;
isLineSelectionON = false;
horzRulerHeight = 20;
horzRuler = new HorzRuler( this );
caretState = 0;
isSelectionByApplication = false;
hitTestRow = -1;
hitTestColumn = -1;
highlight = QRect( -1, -1, -1, -1 );
isSelectionPersistent = false;
isShiftPressed = false;
connect( this, SIGNAL( blockCountChanged( int ) ) , this, SLOT( hbUpdateLineNumberAreaWidth( int ) ) );
connect( this, SIGNAL( updateRequest( const QRect &, int ) ), this, SLOT( hbUpdateLineNumberArea( const QRect &, int ) ) );
hbUpdateLineNumberAreaWidth( 0 );
connect( this, SIGNAL( cursorPositionChanged() ) , this, SLOT( hbSlotCursorPositionChanged() ) );
connect( this, SIGNAL( updateRequest( const QRect &, int ) ), this, SLOT( hbUpdateHorzRuler( const QRect &, int ) ) );
horzRuler->setFrameShape( QFrame::Panel );
horzRuler->setFrameShadow( QFrame::Sunken );
QPalette pl( QPlainTextEdit::palette() );
m_selectionColor = pl.color( QPalette::Highlight );
setContentsMargins( 0,0,0,0 );
#if 0
timer = new QTimer( this );
connect( timer, SIGNAL( timeout() ), this, SLOT( hbUpdateCaret() ) );
timer->start( 500 );
#endif
}
/*----------------------------------------------------------------------*/
HBQPlainTextEdit::~HBQPlainTextEdit()
{
#if 0
if( timer )
timer->stop();
#endif
disconnect( this, SIGNAL( blockCountChanged( int ) ) );
disconnect( this, SIGNAL( updateRequest( const QRect &, int ) ) );
disconnect( this, SIGNAL( cursorPositionChanged() ) );
delete lineNumberArea;
if( block )
hb_itemRelease( block );
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbSetEventBlock( PHB_ITEM pBlock )
{
if( pBlock )
block = hb_itemNew( pBlock );
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbApplyKey( int key, Qt::KeyboardModifiers modifiers, const QString & txt )
{
QKeyEvent * ev = new QKeyEvent( QEvent::KeyPress, key, modifiers, txt );
QPlainTextEdit::keyPressEvent( ev );
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbTogglePersistentSelection()
{
isSelectionPersistent = ! isSelectionPersistent;
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbRefresh()
{
repaint();
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbUpdateCaret()
{
if( caretState == 0 )
caretState = 1;
else
caretState = 0;
QRect r( cursorRect() );
r.setX( r.x() + 100 );
repaint( r );
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbShowPrototype( const QString & tip )
{
if( tip == ( QString ) "" )
{
QToolTip::hideText();
isTipActive = false;
}
else
{
QRect r = HBQPlainTextEdit::cursorRect();
QToolTip::showText( mapToGlobal( QPoint( r.x(), r.y()+20 ) ), tip );
isTipActive = true;
}
}
/*----------------------------------------------------------------------*/
bool HBQPlainTextEdit::event( QEvent *event )
{
if( event->type() == QEvent::KeyPress )
{
QKeyEvent *keyEvent = ( QKeyEvent * ) event;
if( ( keyEvent->key() == Qt::Key_Tab ) && ( keyEvent->modifiers() & Qt::ControlModifier ) )
{
return false;
}
else
{
if( ( keyEvent->key() == Qt::Key_Tab ) && !( keyEvent->modifiers() & Qt::ControlModifier & Qt::AltModifier & Qt::ShiftModifier ) )
{
this->hbInsertTab( 0 );
return true;
}
else if( ( keyEvent->key() == Qt::Key_Backtab ) && ( keyEvent->modifiers() & Qt::ShiftModifier ) )
{
this->hbInsertTab( 1 );
return true;
}
}
}
else if( event->type() == QEvent::ToolTip )
{
event->ignore();
#if 0
QHelpEvent * helpEvent = static_cast<QHelpEvent *>( event );
if( helpEvent && isTipActive )
{
event->ignore();
}
#endif
return false;//true;
}
return QPlainTextEdit::event( event );
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbHighlightArea( int top, int left, int bottom, int right, int mode )
{
HB_SYMBOL_UNUSED( mode );
highlight.setTop( top );
highlight.setLeft( left );
highlight.setBottom( bottom );
highlight.setRight( right );
repaint();
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbSetSelectionColor( const QColor & color )
{
m_selectionColor = color;
QPalette pl( QPlainTextEdit::palette() );
pl.setColor( QPalette::Highlight, m_selectionColor );
pl.setColor( QPalette::HighlightedText, QColor( 0,0,0 ) );
setPalette( pl );
}
/*----------------------------------------------------------------------*/
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 );
}
/*----------------------------------------------------------------------*/
bool HBQPlainTextEdit::isCursorInSelection()
{
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();
int col = c.columnNumber();
int row = c.blockNumber();
return( col >= cb && col <= ce && row >= rb && row <= re );
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbClearSelection()
{
setCursorWidth( 1 );
rowBegins = -1;
rowEnds = -1;
columnBegins = -1;
columnEnds = -1;
emit selectionChanged();
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbHitTest( const QPoint & pt )
{
QTextCursor ct = cursorForPosition( QPoint( 2,2 ) );
int t = ct.blockNumber();
int c = ct.columnNumber();
hitTestRow = t + ( pt.y() / fontMetrics().height() );
hitTestColumn = c + ( pt.x() / fontMetrics().averageCharWidth() );
}
/*----------------------------------------------------------------------*/
int HBQPlainTextEdit::hbFirstVisibleColumn()
{
return ( horizontalScrollBar()->value() / fontMetrics().averageCharWidth() );
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbGetViewportInfo()
{
if( block )
{
PHB_ITEM p1 = hb_itemPutNI( NULL, 21017 );
PHB_ITEM p2 = hb_itemNew( NULL );
hb_arrayNew( p2, 6 );
int t = firstVisibleBlock().blockNumber();
int c = hbFirstVisibleColumn();
int rows = viewport()->height() / fontMetrics().height();
int cols = viewport()->width() / fontMetrics().averageCharWidth();
hb_arraySetNI( p2, 1, t );
hb_arraySetNI( p2, 2, c );
hb_arraySetNI( p2, 3, rows );
hb_arraySetNI( p2, 4, cols );
hb_arraySetNI( p2, 5, textCursor().blockNumber() );
hb_arraySetNI( p2, 6, textCursor().columnNumber() );
hb_vmEvalBlockV( block, 2, p1, p2 );
hb_itemRelease( p1 );
hb_itemRelease( p2 );
}
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbSetSelectionInfo( PHB_ITEM selectionInfo )
{
rowBegins = hb_arrayGetNI( selectionInfo, 1 );
columnBegins = hb_arrayGetNI( selectionInfo, 2 );
rowEnds = hb_arrayGetNI( selectionInfo, 3 );
columnEnds = hb_arrayGetNI( selectionInfo, 4 );
selectionMode = hb_arrayGetNI( selectionInfo, 5 );
emit selectionChanged();
update();
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbGetSelectionInfo()
{
if( block )
{
PHB_ITEM p1 = hb_itemPutNI( NULL, 21000 );
PHB_ITEM p2 = hb_itemNew( NULL );
hb_arrayNew( p2, 6 );
hb_arraySetNI( p2, 1, rowBegins );
hb_arraySetNI( p2, 2, columnBegins );
hb_arraySetNI( p2, 3, rowEnds );
hb_arraySetNI( p2, 4, columnEnds );
hb_arraySetNI( p2, 5, selectionMode );
hb_arraySetNI( p2, 6, selectionState );
hb_vmEvalBlockV( block, 2, p1, p2 );
hb_itemRelease( p1 );
hb_itemRelease( p2 );
}
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbSetSelectionMode( int mode, bool byApplication )
{
if( byApplication )
{
if( mode == 0 )
{
isSelectionByApplication = false;
isStreamSelectionON = false;
isColumnSelectionON = false;
isLineSelectionON = false;
hbClearSelection();
repaint();
return;
}
isSelectionByApplication = ! isSelectionByApplication;
if( ! isSelectionByApplication )
{
isStreamSelectionON = false;
isColumnSelectionON = false;
isLineSelectionON = false;
if( mode == selectionMode_column )
{
QTextCursor c( textCursor() );
c.movePosition( QTextCursor::EndOfLine );
if( c.columnNumber() > columnEnds )
{
c.movePosition( QTextCursor::StartOfLine );
c.movePosition( QTextCursor::Right, QTextCursor::MoveAnchor, columnEnds );
}
setTextCursor( c );
}
setCursorWidth( 1 );
}
else
{
switch( mode )
{
case selectionMode_stream:
{
setCursorWidth( 1 );
selectionMode = selectionMode_stream;
isStreamSelectionON = true;
isColumnSelectionON = false;
isLineSelectionON = false;
QTextCursor c( textCursor() );
rowBegins = c.blockNumber();
rowEnds = rowBegins;
columnBegins = c.columnNumber();
columnEnds = columnBegins;
break;
}
case selectionMode_column:
{
setCursorWidth( 0 );
selectionMode = selectionMode_column;
isStreamSelectionON = false;
isColumnSelectionON = true;
isLineSelectionON = false;
QTextCursor c( textCursor() );
rowBegins = c.blockNumber();
rowEnds = rowBegins;
columnBegins = c.columnNumber();
columnEnds = columnBegins;
break;
}
case selectionMode_line:
{
setCursorWidth( 1 );
selectionMode = selectionMode_line;
isStreamSelectionON = false;
isColumnSelectionON = false;
isLineSelectionON = true;
QTextCursor c( textCursor() );
rowBegins = c.blockNumber();
rowEnds = rowBegins;
columnBegins = 0;
columnEnds = 0;
break;
}
}
}
}
else
{
if( ! isSelectionByApplication )
{
switch( mode )
{
case selectionMode_stream:
{
setCursorWidth( 1 );
if( columnBegins >= 0 )
{
hbToStream();
}
selectionMode = selectionMode_stream;
isColumnSelectionON = false;
isLineSelectionON = false;
break;
}
case selectionMode_column:
{
setCursorWidth( 0 );
selectionMode = selectionMode_column;
isColumnSelectionON = true;
isLineSelectionON = false;
break;
}
}
}
}
emit selectionChanged();
repaint();
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbToStream()
{
int rb = rowBegins <= rowEnds ? rowBegins : rowEnds;
int re = rowBegins <= rowEnds ? rowEnds : rowBegins;
if( selectionMode == selectionMode_line )
{
QTextCursor c = textCursor();
c.movePosition( QTextCursor::Start );
c.movePosition( QTextCursor::Down , QTextCursor::MoveAnchor, rb );
c.movePosition( QTextCursor::Right , QTextCursor::MoveAnchor, columnBegins );
c.movePosition( QTextCursor::Down , QTextCursor::MoveAnchor, re - rb );
c.movePosition( QTextCursor::EndOfLine, QTextCursor::MoveAnchor );
int cce = c.columnNumber();
if( cce > columnEnds )
{
c.movePosition( QTextCursor::StartOfLine, QTextCursor::MoveAnchor );
c.movePosition( QTextCursor::Right , QTextCursor::MoveAnchor, columnEnds );
}
else
{
columnEnds = cce;
}
columnBegins = 0; rowBegins = rb; rowEnds = re;
setTextCursor( c );
}
else if( selectionMode == selectionMode_column )
{
QTextCursor c = textCursor();
c.movePosition( QTextCursor::Start );
c.movePosition( QTextCursor::Down , QTextCursor::MoveAnchor, re );
c.movePosition( QTextCursor::EndOfLine, QTextCursor::MoveAnchor );
if( c.columnNumber() > columnEnds )
{
c.movePosition( QTextCursor::StartOfLine, QTextCursor::MoveAnchor );
c.movePosition( QTextCursor::Right , QTextCursor::MoveAnchor, columnEnds );
}
columnEnds = c.columnNumber(); rowBegins = rb; rowEnds = re;
setTextCursor( c );
}
else if( selectionMode == selectionMode_stream )
{
QTextCursor c = textCursor();
rowBegins = c.blockNumber();
rowEnds = rowBegins;
columnBegins = c.columnNumber();
columnEnds = columnBegins;
}
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbCut( int k )
{
if( block )
{
PHB_ITEM p1 = hb_itemPutNI( NULL, 21014 );
PHB_ITEM p2 = hb_itemNew( NULL );
hb_arrayNew( p2, 7 );
hb_arraySetNI( p2, 1, rowBegins );
hb_arraySetNI( p2, 2, columnBegins );
hb_arraySetNI( p2, 3, rowEnds );
hb_arraySetNI( p2, 4, columnEnds );
hb_arraySetNI( p2, 5, selectionMode );
hb_arraySetNI( p2, 6, selectionState );
hb_arraySetNI( p2, 7, k );
hb_vmEvalBlockV( block, 2, p1, p2 );
hb_itemRelease( p1 );
hb_itemRelease( p2 );
if( selectionMode == selectionMode_column ) //&& k == 0 )
columnEnds = columnBegins;
}
else
{
QPlainTextEdit::cut();
}
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbCopy()
{
if( block )
{
PHB_ITEM p1 = hb_itemPutNI( NULL, 21011 );
PHB_ITEM p2 = hb_itemNew( NULL );
hb_arrayNew( p2, 7 );
hb_arraySetNI( p2, 1, rowBegins );
hb_arraySetNI( p2, 2, columnBegins );
hb_arraySetNI( p2, 3, rowEnds );
hb_arraySetNI( p2, 4, columnEnds );
hb_arraySetNI( p2, 5, selectionMode );
hb_arraySetNI( p2, 6, selectionState );
hb_arraySetNI( p2, 7, 0 );
hb_vmEvalBlockV( block, 2, p1, p2 );
hb_itemRelease( p1 );
hb_itemRelease( p2 );
}
else
{
QPlainTextEdit::copy();
}
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbPaste()
{
if( block )
{
PHB_ITEM p1 = hb_itemPutNI( NULL, 21012 );
PHB_ITEM p2 = hb_itemPutNI( NULL, selectionMode );
hb_vmEvalBlockV( block, 1, p1, p2 );
hb_itemRelease( p1 );
hb_itemRelease( p2 );
if( ! isSelectionPersistent )
{
hbClearSelection();
}
}
else
{
QPlainTextEdit::paste();
}
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::mouseDoubleClickEvent( QMouseEvent *event )
{
QPlainTextEdit::mouseDoubleClickEvent( event );
QTextCursor c( textCursor() );
if( c.hasSelection() )
{
rowBegins = c.blockNumber();
rowEnds = rowBegins;
columnEnds = c.columnNumber();
columnBegins = columnEnds - ( c.selectionEnd() - c.selectionStart() );
selectionMode = selectionMode_stream;
emit selectionChanged();
repaint();
}
if( block )
{
PHB_ITEM p1 = hb_itemPutNI( NULL, QEvent::MouseButtonDblClick );
hb_vmEvalBlockV( block, 1, p1 );
hb_itemRelease( p1 );
}
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::mousePressEvent( QMouseEvent *event )
{
if( isSelectionByApplication )
{
if( isColumnSelectionON )
{
event->accept();
}
else
{
QPlainTextEdit::mousePressEvent( event );
}
return;
}
if( event->modifiers() & Qt::ShiftModifier )
{
QTextCursor c( textCursor() );
rowBegins = c.blockNumber();
columnBegins = c.columnNumber();
QPlainTextEdit::mousePressEvent( event );
c = textCursor();
rowEnds = c.blockNumber();
columnEnds = c.columnNumber();
selectionState = 1;
setCursorWidth( 1 );
selectionMode = selectionMode_stream;
emit selectionChanged();
repaint();
}
else
{
setCursorWidth( 1 );
if( ! isSelectionPersistent )
{
selectionState = 0;
hbClearSelection();
}
else
{
selectionState = 1;
}
QPlainTextEdit::mousePressEvent( event );
}
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::mouseReleaseEvent( QMouseEvent *event )
{
if( isSelectionByApplication )
{
if( isLineSelectionON )
{
QPlainTextEdit::mouseReleaseEvent( event );
rowEnds = textCursor().blockNumber();
}
else if( isColumnSelectionON )
{
event->accept();
hbHitTest( event->pos() );
rowEnds = hitTestRow;
columnEnds = hitTestColumn;
}
else if( isStreamSelectionON )
{
QPlainTextEdit::mouseReleaseEvent( event );
rowEnds = textCursor().blockNumber();
columnEnds = textCursor().columnNumber();
}
repaint();
return;
}
selectionState = 1;
setCursorWidth( 1 );
emit selectionChanged();
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::mouseMoveEvent( QMouseEvent *event )
{
if( isSelectionByApplication )
{
event->accept();
return;
}
if( selectionMode == selectionMode_line )
selectionMode = selectionMode_stream;
if( event->buttons() & Qt::LeftButton )
{
if( selectionState == 1 )
{
selectionState = 2;
hbClearSelection();
}
if( columnBegins == -1 )
{
if( selectionMode == selectionMode_column )
setCursorWidth( 0 );
QTextCursor c( textCursor() );
rowBegins = c.blockNumber();
columnBegins = c.columnNumber();
rowEnds = rowBegins;
columnEnds = columnBegins;
emit selectionChanged();
QPlainTextEdit::mouseMoveEvent( event );
}
else
{
if( selectionMode == selectionMode_column )
{
QTextCursor c( cursorForPosition( QPoint( 1,1 ) ) );
rowEnds = c.blockNumber() + ( event->y() / fontMetrics().height() );
columnEnds = c.columnNumber() + ( event->x() / fontMetrics().averageCharWidth() );
}
QPlainTextEdit::mouseMoveEvent( event );
QTextCursor c = textCursor();
if( selectionMode != selectionMode_column )
{
rowEnds = c.blockNumber();
columnEnds = c.columnNumber();
}
c.clearSelection();
setTextCursor( c );
repaint();
}
}
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::keyReleaseEvent( QKeyEvent * event )
{
QPlainTextEdit::keyReleaseEvent( event );
if( ( event->modifiers() & Qt::ControlModifier ) && event->text() == "" )
{
if( selectionState == 2 )
{
selectionState = 1;
emit selectionChanged();
}
}
}
/*----------------------------------------------------------------------*/
bool HBQPlainTextEdit::hbKeyPressSelectionByApplication( QKeyEvent * event )
{
bool shift = event->modifiers() & Qt::ShiftModifier;
int k = event->key();
if( isNavableKey( k ) && shift )
{
event->accept();
QTextCursor c( textCursor() );
c.clearSelection();
setTextCursor( c );
QKeyEvent * ev = new QKeyEvent( event->type(), event->key(), Qt::NoModifier, event->text() );
keyPressEvent( ev );
return true;
}
if( isNavableKey( k ) )
{
if( selectionMode == selectionMode_stream )
{
QPlainTextEdit::keyPressEvent( event );
QTextCursor c( textCursor() );
rowEnds = c.blockNumber();
columnEnds = c.columnNumber();
}
else if( selectionMode == selectionMode_column )
{
switch( k )
{
case Qt::Key_Right:
{
QTextCursor c( textCursor() );
c.movePosition( QTextCursor::EndOfLine );
if( c.columnNumber() <= columnEnds )
{
setTextCursor( c );
}
event->ignore();
columnEnds++;
break;
}
case Qt::Key_Left:
{
QTextCursor c( textCursor() );
int col = c.columnNumber();
if( col < columnEnds - 1 )
{
c.movePosition( QTextCursor::Left );
columnEnds--;
}
else if( columnEnds - 1 >= 0 )
{
columnEnds--;
}
event->ignore();
break;
}
case Qt::Key_Home:
{
QPlainTextEdit::keyPressEvent( event );
columnEnds = textCursor().columnNumber();
break;
}
case Qt::Key_End:
{
QTextCursor c( textCursor() );
c.movePosition( QTextCursor::EndOfLine, QTextCursor::MoveAnchor );
if( c.columnNumber() <= columnEnds )
{
QPlainTextEdit::keyPressEvent( event );
columnEnds = textCursor().columnNumber();;
}
else
{
event->ignore();
}
break;
}
case Qt::Key_Up:
case Qt::Key_PageUp:
case Qt::Key_Down:
case Qt::Key_PageDown:
QPlainTextEdit::keyPressEvent( event );
rowEnds = textCursor().blockNumber();
break;
default:
event->ignore();
break;
}
}
else if( selectionMode == selectionMode_line )
{
QPlainTextEdit::keyPressEvent( event );
QTextCursor c( textCursor() );
rowEnds = c.blockNumber();
}
repaint();
}
else
{
event->ignore();
}
return true;
}
/*----------------------------------------------------------------------*/
bool HBQPlainTextEdit::hbKeyPressSelection( QKeyEvent * event )
{
bool ctrl = event->modifiers() & Qt::ControlModifier;
bool shift = event->modifiers() & Qt::ShiftModifier;
if( ctrl && shift )
return false;
int k = event->key();
if( ctrl && event->text().isEmpty() )
{
#if 0
event->ignore();
return true;
#endif
return false;
}
if( ctrl && ( k == Qt::Key_C || k == Qt::Key_V || k == Qt::Key_X ||
k == Qt::Key_A || k == Qt::Key_Z || k == Qt::Key_Y ) )
{
event->ignore();
return true;
}
if( isSelectionByApplication )
{
return hbKeyPressSelectionByApplication( event );
}
bool bClear = false;
if( shift && isNavableKey( k ) )
{
if( selectionMode == selectionMode_line )
{
selectionMode = selectionMode_stream;
selectionState = 0;
}
if( selectionState == 0 )
{
hbClearSelection();
}
isShiftPressed = true;
event->accept();
QTextCursor c( textCursor() );
c.clearSelection();
setTextCursor( c );
if( columnBegins == -1 )
{
if( selectionMode == selectionMode_column )
setCursorWidth( 0 );
selectionState = 2;
rowBegins = c.blockNumber();
columnBegins = c.columnNumber();
rowEnds = rowBegins;
columnEnds = columnBegins;
emit selectionChanged();
repaint();
}
QKeyEvent * ev = new QKeyEvent( event->type(), event->key(), Qt::NoModifier, event->text() );
keyPressEvent( ev );
return true;
}
if( isShiftPressed && isNavableKey( k ) )
{
isShiftPressed = false;
if( selectionMode == selectionMode_stream )
{
QPlainTextEdit::keyPressEvent( event );
rowEnds = textCursor().blockNumber();
columnEnds = textCursor().columnNumber();
}
else if( selectionMode == selectionMode_column )
{
switch( k )
{
case Qt::Key_Right:
{
QTextCursor c( textCursor() );
c.movePosition( QTextCursor::EndOfLine );
if( c.columnNumber() <= columnEnds ){
setTextCursor( c );
ensureCursorVisible();
}
else
{
#if 0 /* Tobe Matured */
int v = horizontalScrollBar()->value();
int m = horizontalScrollBar()->maximum();
int w = fontMetrics().averageCharWidth();
if( ( ( columnEnds + 1 ) * w ) > m ){
if( v == m )
horizontalScrollBar()->setMaximum( m + w );
}
horizontalScrollBar()->setValue( v + w );
#endif
}
event->ignore();
columnEnds++;
break;
}
case Qt::Key_Left:
{
QTextCursor c( textCursor() );
int col = c.columnNumber();
if( col < columnEnds - 1 ){
c.movePosition( QTextCursor::Left );
columnEnds--;
}
else if( columnEnds - 1 >= 0 ){
columnEnds--;
}
event->ignore();
break;
}
case Qt::Key_Home:
{
QPlainTextEdit::keyPressEvent( event );
columnEnds = textCursor().columnNumber();
break;
}
case Qt::Key_End:
{
QTextCursor c( textCursor() );
c.movePosition( QTextCursor::EndOfLine, QTextCursor::MoveAnchor );
if( c.columnNumber() <= columnEnds ){
QPlainTextEdit::keyPressEvent( event );
columnEnds = textCursor().columnNumber();;
} else {
event->ignore();
}
break;
}
case Qt::Key_Up:
case Qt::Key_PageUp:
case Qt::Key_Down:
case Qt::Key_PageDown:
QPlainTextEdit::keyPressEvent( event );
rowEnds = textCursor().blockNumber();
break;
default:
event->ignore();
break;
}
}
emit selectionChanged();
repaint();
return true;
}
else if( ! ctrl && k >= ' ' && k < 127 && columnBegins >= 0 && selectionMode == selectionMode_column )
{
if( ( columnBegins == columnEnds && selectionState > 0 ) || isCursorInSelection() )
{
if( block )
{
PHB_ITEM p1 = hb_itemPutNI( NULL, 21013 );
PHB_ITEM p2 = hb_itemNew( NULL );
hb_arrayNew( p2, 7 );
hb_arraySetNI( p2, 1, rowBegins );
hb_arraySetNI( p2, 2, columnBegins );
hb_arraySetNI( p2, 3, rowEnds );
hb_arraySetNI( p2, 4, columnEnds );
hb_arraySetNI( p2, 5, selectionMode );
hb_arraySetNI( p2, 6, selectionState );
hb_arraySetPtr( p2, 7, event );
hb_vmEvalBlockV( block, 2, p1, p2 );
hb_itemRelease( p1 );
hb_itemRelease( p2 );
if( columnBegins == columnEnds ){
columnBegins++;
columnEnds++;
}
repaint();
event->accept();
return true;
}
}
else
bClear = true;
}
else if( ! ctrl && ( k == Qt::Key_Backspace || k == Qt::Key_Delete ) && columnBegins >= 0 && selectionState > 0 && selectionMode == selectionMode_column )
{
hbCut( k );
if( k == Qt::Key_Backspace ){
columnBegins--;
columnEnds--;
}
else {
columnEnds = columnBegins;
}
repaint();
event->accept();
return true;
}
else if( ! ctrl && k == Qt::Key_Delete && columnBegins >= 0 && selectionState > 0 && ( selectionMode == selectionMode_stream || selectionMode == selectionMode_line ) )
{
hbCut( k );
repaint();
selectionState = 0;
event->accept();
return true;
}
else if( isNavableKey( k ) || ( k >= ' ' && k < 127 ) )
{
bClear = true;
}
if( bClear )
{
if( isSelectionPersistent )
{
if( selectionState > 0 )
{
emit selectionChanged();
setCursorWidth( 1 );
selectionState = 0;
if( columnEnds == columnBegins ){
hbClearSelection();
}
}
}
else
{
if( selectionState > 0 )
{
emit selectionChanged();
setCursorWidth( 1 );
selectionState = 0;
hbClearSelection();
repaint();
}
}
}
return false;
#if 0
else if( selectionMode == selectionMode_line )
{
if( isLineSelectionON && isNavableKey( k ) )
{
QPlainTextEdit::keyPressEvent( event );
QTextCursor c( textCursor() );
rowEnds = c.blockNumber();
repaint();
return true;
}
else if( ! isSelectionPersistent )
{
if( selectionState > 0 )
{
emit selectionChanged();
setCursorWidth( 1 );
selectionState = 0;
hbClearSelection();
repaint();
}
}
}
#endif
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::keyPressEvent( QKeyEvent * event )
{
//HB_TRACE( HB_TR_ALWAYS, ( "keyPressEvent %i 000", event->key() ) );
if( hbKeyPressSelection( event ) )
{
QApplication::processEvents();
return;
}
//HB_TRACE( HB_TR_ALWAYS, ( "keyPressEvent %i", event->key() ) );
if( c && c->popup()->isVisible() )
{
// The following keys are forwarded by the completer to the widget
switch( event->key() )
{
case Qt::Key_Enter :
case Qt::Key_Return :
case Qt::Key_Escape :
case Qt::Key_Tab :
case Qt::Key_Backtab :
event->ignore();
return; // let the completer do default behavior
case Qt::Key_Space:
if( block ){
PHB_ITEM p1 = hb_itemPutNI( NULL, 21001 );
hb_vmEvalBlockV( block, 1, p1 );
hb_itemRelease( p1 );
}
break;
default:
break;
}
}
QPlainTextEdit::keyPressEvent( event );
if( ! c )
return;
if( ( event->modifiers() & ( Qt::ControlModifier | Qt::AltModifier ) ) )
{
c->popup()->hide();
return;
}
const bool ctrlOrShift = event->modifiers() & ( Qt::ControlModifier | Qt::ShiftModifier );
if( ( ctrlOrShift && event->text().isEmpty() ) )
return;
static QString eow( " ~!@#$%^&*()+{}|:\"<>?,./;'[]\\-=" ); /* end of word */
bool hasModifier = ( event->modifiers() != Qt::NoModifier ) && !ctrlOrShift;
QString completionPrefix = hbTextUnderCursor();
if( ( hasModifier ||
event->text().isEmpty() ||
completionPrefix.length() < 3 ||
eow.contains( event->text().right( 1 ) ) ) )
{
c->popup()->hide();
return;
}
if( completionPrefix != c->completionPrefix() )
{
c->setCompletionPrefix( completionPrefix );
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!
}
/*----------------------------------------------------------------------*/
QString HBQPlainTextEdit::hbTextUnderCursor()
{
QTextCursor tc = textCursor();
tc.select( QTextCursor::WordUnderCursor );
return tc.selectedText();
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::resizeEvent( QResizeEvent *e )
{
setContentsMargins( 0,0,0,0 );
viewport()->setContentsMargins( 0,0,0,0 );
QPlainTextEdit::resizeEvent( e );
QRect cr = contentsRect();
lineNumberArea->setGeometry( QRect( cr.left(), cr.top() + horzRulerHeight, hbLineNumberAreaWidth(), cr.height() ) );
horzRuler->setGeometry( QRect( cr.left(), cr.top(), cr.width(), horzRulerHeight ) );
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::focusInEvent( QFocusEvent * event )
{
if( c )
c->setWidget( this );
QPlainTextEdit::focusInEvent( event );
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::paintEvent( QPaintEvent * event )
{
QPainter painter( viewport() );
int curBlock = textCursor().blockNumber();
QTextBlock tblock = firstVisibleBlock();
int blockNumber = tblock.blockNumber();
int height = ( int ) blockBoundingRect( tblock ).height();
int top = ( int ) blockBoundingGeometry( tblock ).translated( contentOffset() ).top();
int bottom = top + height;
while( tblock.isValid() && top <= event->rect().bottom() )
{
if( tblock.isVisible() && bottom >= event->rect().top() )
{
int index = bookMarksGoto.indexOf( blockNumber + 1 );
if( index != -1 )
{
QRect r( 0, top, viewport()->width(), height );
painter.fillRect( r, brushForBookmark( index ) );
}
else if( curBlock == blockNumber && m_currentLineColor.isValid() )
{
if( highlightCurLine == true )
{
QRect r = HBQPlainTextEdit::cursorRect();
r.setX( 0 );
r.setWidth( viewport()->width() );
painter.fillRect( r, QBrush( m_currentLineColor ) );
}
}
}
tblock = tblock.next();
top = bottom;
bottom = top + height;
++blockNumber;
}
this->hbPaintSelection( event );
this->hbPaintHighlight( event );
#if 0
{
QPainter p( viewport() );
caretState = caretState == 0 ? 1 : 0;
QRect r( cursorRect() );
r.setX( r.x() + 100 );
r.setWidth( 1 );
p.fillRect( r, QBrush( QColor( caretState == 1 ? Qt::red : Qt::white ) ) );
}
#endif
painter.end();
QPlainTextEdit::paintEvent( event );
#if 0
QPainter * painter = new QPainter( viewport() );
int curBlock = textCursor().blockNumber();
QTextBlock tblock = firstVisibleBlock();
int blockNumber = tblock.blockNumber();
int height = ( int ) blockBoundingRect( tblock ).height();
int top = ( int ) blockBoundingGeometry( tblock ).translated( contentOffset() ).top();
int bottom = top + height;
this->hbPaintSelection( event );
while( tblock.isValid() && top <= event->rect().bottom() )
{
if( tblock.isVisible() && bottom >= event->rect().top() )
{
int index = bookMarksGoto.indexOf( blockNumber + 1 );
if( index != -1 )
{
QRect r( 0, top, viewport()->width(), height );
painter->fillRect( r, brushForBookmark( index ) );
}
else if( curBlock == blockNumber && m_currentLineColor.isValid() )
{
if( highlightCurLine == true )
{
QRect r = HBQPlainTextEdit::cursorRect();
r.setX( 0 );
r.setWidth( viewport()->width() );
painter->fillRect( r, QBrush( m_currentLineColor ) );
}
}
}
tblock = tblock.next();
top = bottom;
bottom = top + height;
++blockNumber;
}
#if 0 /* A day wasted - I could not find how I can execute paiting from within prg code */
if( block )
{
PHB_ITEM p1 = hb_itemPutNI( NULL, QEvent::Paint );
PHB_ITEM p2 = hb_itemPutPtr( NULL, painter );
hb_vmEvalBlockV( block, 2, p1, p2 );
hb_itemRelease( p1 );
hb_itemRelease( p2 );
}
#endif
painter->end();
delete ( ( QPainter * ) painter );
QPlainTextEdit::paintEvent( event );
#endif
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::horzRulerPaintEvent( QPaintEvent *event )
{
int fontWidth = fontMetrics().averageCharWidth();
QRect cr = event->rect();
QPainter painter( horzRuler );
painter.fillRect( cr, m_horzRulerBkColor );
painter.setPen( Qt::gray );
painter.drawLine( cr.left(), cr.bottom(), cr.width(), cr.bottom() );
painter.setPen( Qt::black );
int left = cr.left() + ( fontWidth / 2 ) + ( lineNumberArea->isVisible() ? lineNumberArea->width() : 0 );
QRect rc( cursorRect( textCursor() ) );
QTextCursor cursor( cursorForPosition( QPoint( 1, rc.top() + 1 ) ) );
int i;
for( i = hbFirstVisibleColumn(); left < cr.width(); i++ )
{
if( i % 10 == 0 )
{
painter.drawLine( left, cr.bottom()-3, left, cr.bottom()-5 );
QString number = QString::number( i );
painter.drawText( left - fontWidth, cr.top()-2, fontWidth * 2, 17, Qt::AlignCenter, number );
}
else if( i % 5 == 0 )
{
painter.drawLine( left, cr.bottom()-3, left, cr.bottom()-5 );
}
else
{
painter.drawLine( left, cr.bottom()-3, left, cr.bottom()-4 );
}
if( i == textCursor().columnNumber() )
{
painter.fillRect( QRect( left, cr.top() + 2, fontWidth, 11 ), QColor( 100,100,100 ) );
}
left += fontWidth;
}
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::lineNumberAreaPaintEvent( QPaintEvent *event )
{
QPainter painter( lineNumberArea );
painter.fillRect( event->rect(), m_lineAreaBkColor );
QTextBlock block = firstVisibleBlock();
int blockNumber = block.blockNumber();
int top = ( int ) blockBoundingGeometry( block ).translated( contentOffset() ).top();
int bottom = top +( int ) blockBoundingRect( block ).height();
int off = fontMetrics().height() / 4;
while( block.isValid() && top <= event->rect().bottom() )
{
if( block.isVisible() && bottom >= event->rect().top() )
{
QString number = QString::number( blockNumber + 1 );
painter.setPen( ( blockNumber + 1 ) % 10 == 0 ? Qt::red : Qt::black );
painter.drawText( 0, top, lineNumberArea->width()-2, fontMetrics().height(), Qt::AlignRight, number );
int index = bookMarksGoto.indexOf( number.toInt() );
if( index != -1 )
{
painter.setBrush( brushForBookmark( index ) );
painter.drawRect( 5, top + off, off * 2, off * 2 );
}
}
block = block.next();
top = bottom;
bottom = top +( int ) blockBoundingRect( block ).height();
++blockNumber;
}
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbPaintHighlight( QPaintEvent * event )
{
HB_SYMBOL_UNUSED( event );
if( highlight.top() > -1 )
{
int fontHeight = fontMetrics().height();
int t = firstVisibleBlock().blockNumber();
int b = t + ( viewport()->height() / fontHeight ) + 1;
int rb = highlight.top();
int re = highlight.bottom();
if( re >= t && rb < b )
{
QPainter p( viewport() );
int top = ( ( rb <= t ) ? 0 : ( ( rb - t ) * fontHeight ) );
int btm = ( ( re - t + 1 ) * fontHeight ) - top;
btm = btm > viewport()->height() ? viewport()->height() : btm;
QRect r( 0, top, viewport()->width(), btm );
p.fillRect( r, QBrush( QColor( 255,255,0 ) ) );
}
}
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbPaintSelection( QPaintEvent * event )
{
HB_SYMBOL_UNUSED( event );
if( rowBegins >= 0 && rowEnds >= 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;
int t = firstVisibleBlock().blockNumber();
int c = hbFirstVisibleColumn();
int fontHeight = fontMetrics().height();
int b = t + ( viewport()->height() / fontHeight ) + 1;
re = re > b ? b : re;
if( re >= t && rb < b )
{
QPainter p( viewport() );
int marginX = ( c > 0 ? 0 : contentsRect().left() ) + 2 ;
int fontWidth = fontMetrics().averageCharWidth();
int top = ( ( rb <= t ) ? 0 : ( ( rb - t ) * fontHeight ) );
int btm = ( ( re - t + 1 ) * fontHeight ) - top;
btm = btm > viewport()->height() ? viewport()->height() : btm;
if( selectionMode == selectionMode_column )
{
int x = ( ( cb - c ) * fontWidth ) + marginX;
int w = ( cb == ce ? 1 : ( ( ce - cb ) * fontWidth ) );
QRect r( x, top, w, btm );
p.fillRect( r, QBrush( m_selectionColor ) );
}
else if( selectionMode == selectionMode_stream )
{
int i;
int width = viewport()->width();
QRect r;
for( i = ( rb >= t ? rb : t ); i <= re; i++ )
{
if( rowBegins > rowEnds )
{
if( i == rowEnds )
{
if( rb == re )
{
int x = ( ( cb - c ) * fontWidth ) + marginX;
int w = ( ce - cb ) * fontWidth;
r = QRect( x, top, w, fontHeight );
}
else
{
int x = ( ( columnEnds - c ) * fontWidth ) + marginX;
r = QRect( x, top, width + abs( x ), fontHeight );
}
}
else if( i == rowBegins )
{
int x = ( ( columnBegins - c ) * fontWidth ) + marginX;
r = QRect( 0, top, x, fontHeight );
}
else
{
r = QRect( 0, top, width, fontHeight );
}
}
else
{
if( i == rowBegins )
{
if( rb == re )
{
int x = ( ( cb - c ) * fontWidth ) + marginX;
int w = ( ce - cb ) * fontWidth;
r = QRect( x, top, w, fontHeight );
}
else
{
int x = ( ( columnBegins - c ) * fontWidth ) + marginX;
r = QRect( x, top, width + abs( x ), fontHeight );
}
}
else if( i == rowEnds )
{
int x = ( ( columnEnds - c ) * fontWidth ) + marginX;
r = QRect( 0, top, x, fontHeight );
}
else
{
r = QRect( 0, top, width, fontHeight );
}
}
p.fillRect( r, QBrush( m_selectionColor ) );
top += fontHeight;
}
}
else if( selectionMode == selectionMode_line )
{
QRect r( 0, top, viewport()->width(), btm );
p.fillRect( r, QBrush( m_selectionColor ) );
}
}
}
}
/*----------------------------------------------------------------------*/
QBrush HBQPlainTextEdit::brushForBookmark( int index )
{
QBrush br;
if( index == 0 )
br = QBrush( QColor( 255, 255, 127 ) );
else if( index == 1 )
br = QBrush( QColor( 175, 175, 255 ) );
else if( index == 2 )
br = QBrush( QColor( 255, 175, 175 ) );
else if( index == 3 )
br = QBrush( QColor( 175, 255, 175 ) );
else if( index == 4 )
br = QBrush( QColor( 255, 190, 125 ) );
else if( index == 5 )
br = QBrush( QColor( 175, 255, 255 ) );
else
br = QBrush( m_currentLineColor );
return br;
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbBookmarks( int block )
{
int found = bookMark.indexOf( block );
if( found == -1 )
{
bookMark.push_back( block );
qSort( bookMark );
}
else
{
bookMark.remove( found );
}
found = -1;
int i = 0;
for( i = 0; i < bookMarksGoto.size(); i++ )
{
if( bookMarksGoto[ i ] == block )
{
bookMarksGoto.removeAt( i );
found = i;
break;
}
}
if( found == -1 )
{
bookMarksGoto.append( block );
}
hbUpdateLineNumberAreaWidth( 0 );
lineNumberArea->repaint();
update();
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbGotoBookmark( int block )
{
if( bookMarksGoto.size() > 0 )
{
int i;
for( i = 0; i < bookMarksGoto.size(); i++ )
{
if( bookMarksGoto[ i ] == block )
{
QTextCursor cursor( document()->findBlockByNumber( block - 1 ) );
setTextCursor( cursor );
break;
}
}
}
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbNextBookmark( int block )
{
if( bookMark.count() > 0 )
{
QVector<int>::iterator i = qUpperBound( bookMark.begin(), bookMark.end(), block );
if( i != bookMark.end() )
{
QTextCursor cursor( document()->findBlockByNumber( *i - 1 ) );
setTextCursor( cursor );
}
else
{
QTextCursor cursor( document()->findBlockByNumber( *bookMark.begin() - 1 ) );
setTextCursor( cursor );
}
}
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbPrevBookmark( int block )
{
if( bookMark.count() > 0 )
{
QVector<int>::iterator i = qUpperBound( bookMark.begin(), bookMark.end(), block );
i -= 2;
if( i >= bookMark.begin() )
{
QTextCursor cursor( document()->findBlockByNumber( *i - 1 ) );
setTextCursor( cursor );
}
else
{
QVector<int>::iterator it = bookMark.end();
--it;
QTextCursor cursor( document()->findBlockByNumber( *it - 1 ) );
setTextCursor( cursor );
}
}
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbNumberBlockVisible( bool b )
{
numberBlock = b;
if( b )
{
lineNumberArea->show();
hbUpdateLineNumberAreaWidth( hbLineNumberAreaWidth() );
}
else
{
lineNumberArea->hide();
hbUpdateLineNumberAreaWidth( 0 );
}
update();
}
/*----------------------------------------------------------------------*/
bool HBQPlainTextEdit::hbNumberBlockVisible()
{
return numberBlock;
}
/*----------------------------------------------------------------------*/
int HBQPlainTextEdit::hbLineNumberAreaWidth()
{
int digits = 1;
int max = qMax( 1, blockCount() );
while( max >= 10 )
{
max /= 10;
++digits;
}
int width = fontMetrics().width( QLatin1Char( '9' ) );
int iM = fontMetrics().height() / 2;
int iMark = bookMarksGoto.size() > 0 ? ( 5 + iM + 2 ) : 0;
int space = iMark + ( width * digits ) + 2;
return space;
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbUpdateHorzRulerHeight( int height )
{
horzRulerHeight = height;
setViewportMargins( hbLineNumberAreaWidth(), horzRulerHeight, 0, 0 );
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbUpdateLineNumberAreaWidth( int )
{
if( numberBlock )
{
setViewportMargins( hbLineNumberAreaWidth(), horzRulerHeight, 0, 0 );
}
else
{
setViewportMargins( 0, horzRulerHeight, 0, 0 );
}
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbUpdateHorzRuler( const QRect & rect, int dy )
{
HB_SYMBOL_UNUSED( rect );
setTabStopWidth( spaces * fontMetrics().averageCharWidth() );
if( dy == 0 )
horzRuler->update();
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbUpdateLineNumberArea( const QRect &rect, int dy )
{
if( dy )
lineNumberArea->scroll( 0, dy );
else
lineNumberArea->update( 0, rect.y(), lineNumberArea->width(), rect.height() );
if( rect.contains( viewport()->rect() ) )
{
hbUpdateLineNumberAreaWidth( 0 );
}
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbSetSpaces( int newSpaces )
{
spaces = newSpaces;
spacesTab = "";
if( spaces > 0 )
{
for( int i = 0; i < spaces; ++i )
spacesTab += " ";
}
else
{
if( spaces == -101 )
spacesTab = "\t";
}
}
/*----------------------------------------------------------------------*/
int HBQPlainTextEdit::hbGetIndex( const QTextCursor &crQTextCursor )
{
QTextBlock b;
int column = 1;
b = crQTextCursor.block();
column = crQTextCursor.position() - b.position();
return column;
}
/*----------------------------------------------------------------------*/
int HBQPlainTextEdit::hbGetLine( const QTextCursor &crQTextCursor )
{
QTextBlock b,cb;
int line = 1;
cb = crQTextCursor.block();
for( b = document()->begin();b!=document()->end();b = b.next() )
{
if( b==cb )
return line;
line++;
}
return line;
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbSlotCursorPositionChanged()
{
if( m_currentLineColor.isValid() )
viewport()->update();
if( styleHightlighter != "none" )
hbBraceHighlight();
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbSetStyleHightlighter( const QString &style )
{
styleHightlighter = style;
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbShowHighlighter( const QString &style, bool b )
{
if( b )
{
if( styleHightlighter != "none" )
{
delete highlighter;
highlighter = 0;
}
highlighter = new HBQSyntaxHighlighter( document() );
}
else
{
delete highlighter;
highlighter = 0;
}
styleHightlighter = style;
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbEscapeQuotes()
{
QTextCursor cursor( textCursor() );
QString selTxt( cursor.selectedText() );
if( selTxt.isEmpty() )
return;
QString txt = selTxt.replace( QString( "'" ), QString( "\\\'" ) );
insertPlainText( txt );
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbEscapeDQuotes()
{
QTextCursor cursor( textCursor() );
QString selTxt( cursor.selectedText() );
if( selTxt.isEmpty() )
return;
QString txt = selTxt.replace( QString( "\"" ), QString( "\\\"" ) );
insertPlainText( txt );
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbUnescapeQuotes()
{
QTextCursor cursor( textCursor() );
QString selTxt( cursor.selectedText() );
if( selTxt.isEmpty() )
return;
QString txt = selTxt.replace( QString( "\\\'" ), QString( "'" ) );
insertPlainText( txt );
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbUnescapeDQuotes()
{
QTextCursor cursor( textCursor() );
QString selTxt( cursor.selectedText() );
if( selTxt.isEmpty() )
return;
QString txt = selTxt.replace( QString( "\\\"" ), QString( "\"" ) );
insertPlainText( txt );
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbCaseUpper()
{
QTextCursor cursor = textCursor();
QString selTxt( cursor.selectedText() );
if( selTxt.isEmpty() )
return;
int b = cursor.selectionStart();
int e = cursor.selectionEnd();
cursor.beginEditBlock();
insertPlainText( selTxt.toUpper() );
cursor.setPosition( b );
cursor.movePosition( QTextCursor::NextCharacter, QTextCursor::KeepAnchor, e-b );
cursor.endEditBlock();
setTextCursor( cursor );
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbCaseLower()
{
QTextCursor cursor = textCursor();
QString selTxt( cursor.selectedText() );
if( selTxt.isEmpty() )
return;
int b = cursor.selectionStart();
int e = cursor.selectionEnd();
cursor.beginEditBlock();
insertPlainText( selTxt.toLower() );
cursor.setPosition( b );
cursor.movePosition( QTextCursor::NextCharacter, QTextCursor::KeepAnchor, e-b );
cursor.endEditBlock();
setTextCursor( cursor );
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbConvertQuotes()
{
QTextCursor cursor = textCursor();
QString selTxt( cursor.selectedText() );
if( selTxt.isEmpty() )
return;
int b = cursor.selectionStart();
int e = cursor.selectionEnd();
cursor.beginEditBlock();
insertPlainText( selTxt.replace( QString( "\"" ), QString( "\'" ) ) );
cursor.setPosition( b );
cursor.movePosition( QTextCursor::NextCharacter, QTextCursor::KeepAnchor, e-b );
cursor.endEditBlock();
setTextCursor( cursor );
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbConvertDQuotes()
{
QTextCursor cursor = textCursor();
QString selTxt( cursor.selectedText() );
if( selTxt.isEmpty() )
return;
int b = cursor.selectionStart();
int e = cursor.selectionEnd();
cursor.beginEditBlock();
insertPlainText( selTxt.replace( QString( "\'" ), QString( "\"" ) ) );
cursor.setPosition( b );
cursor.movePosition( QTextCursor::NextCharacter, QTextCursor::KeepAnchor, e-b );
cursor.endEditBlock();
setTextCursor( cursor );
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbReplaceSelection( const QString & txt )
{
QTextCursor cursor = textCursor();
QString selTxt( cursor.selectedText() );
if( selTxt.isEmpty() )
return;
int b = cursor.selectionStart();
cursor.beginEditBlock();
insertPlainText( txt );
cursor.setPosition( b );
cursor.movePosition( QTextCursor::NextCharacter, QTextCursor::KeepAnchor, txt.length() );
cursor.endEditBlock();
setTextCursor( cursor );
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbStreamComment()
{
QTextCursor cursor = textCursor();
QString selTxt( cursor.selectedText() );
if( selTxt.isEmpty() )
return;
int b = cursor.selectionStart();
int e = cursor.selectionEnd();
cursor.beginEditBlock();
insertPlainText( "/*" + selTxt + "*/" );
cursor.setPosition( b );
cursor.movePosition( QTextCursor::NextCharacter, QTextCursor::KeepAnchor, e-b+4 );
cursor.endEditBlock();
setTextCursor( cursor );
}
/*----------------------------------------------------------------------*/
QString HBQPlainTextEdit::hbGetSelectedText()
{
QTextCursor cursor( textCursor() );
QString selTxt( cursor.selectedText() );
if( selTxt.isEmpty() )
return "";
QString txt = selTxt.replace( 0x2029, QString( "\n" ) );
return txt;
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbInsertTab( int mode )
{
QTextCursor cursor = textCursor();
QTextCursor c( cursor );
c.setPosition( cursor.position() );
setTextCursor( c );
if( mode == 0 )
{
insertPlainText( spacesTab );
}
else
{
int icol = c.columnNumber();
int ioff = qMin( icol, spaces );
c.setPosition( c.position() - ioff );
}
setTextCursor( c );
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbMoveLine( int iDirection )
{
QTextCursor cursor = textCursor();
QTextCursor c = cursor;
cursor.beginEditBlock();
cursor.movePosition( QTextCursor::StartOfLine );
cursor.movePosition( QTextCursor::EndOfLine, QTextCursor::KeepAnchor );
QString textCurrentLine = cursor.selectedText();
if( iDirection == -1 && cursor.blockNumber() > 0 )
{
cursor.movePosition( QTextCursor::StartOfLine );
cursor.movePosition( QTextCursor::Up );
cursor.movePosition( QTextCursor::EndOfLine, QTextCursor::KeepAnchor );
QString textPrevLine = cursor.selectedText();
setTextCursor( cursor );
insertPlainText( textCurrentLine );
cursor.movePosition( QTextCursor::Down );
cursor.movePosition( QTextCursor::StartOfLine );
cursor.movePosition( QTextCursor::EndOfLine, QTextCursor::KeepAnchor );
setTextCursor( cursor );
insertPlainText( textPrevLine );
c.movePosition( QTextCursor::Up );
}
else if( iDirection == 1 && cursor.blockNumber() < cursor.document()->blockCount() - 1 )
{
cursor.movePosition( QTextCursor::StartOfLine );
cursor.movePosition( QTextCursor::Down );
cursor.movePosition( QTextCursor::EndOfLine, QTextCursor::KeepAnchor );
QString textPrevLine = cursor.selectedText();
setTextCursor( cursor );
insertPlainText( textCurrentLine );
cursor.movePosition( QTextCursor::Up );
cursor.movePosition( QTextCursor::StartOfLine );
cursor.movePosition( QTextCursor::EndOfLine, QTextCursor::KeepAnchor );
setTextCursor( cursor );
insertPlainText( textPrevLine );
c.movePosition( QTextCursor::Down );
}
cursor.endEditBlock();
setTextCursor( c );
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbDeleteLine()
{
QTextCursor cursor = textCursor();
QTextCursor c = cursor;
cursor.beginEditBlock();
cursor.movePosition( QTextCursor::StartOfLine );
cursor.movePosition( QTextCursor::EndOfLine, QTextCursor::KeepAnchor );
cursor.movePosition( QTextCursor::Down, QTextCursor::KeepAnchor );
QString textUnderCursor = cursor.selectedText();
setTextCursor( cursor );
insertPlainText( "" );
cursor.endEditBlock();
setTextCursor( c );
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbBlockIndent( int steps )
{
QTextCursor cursor = textCursor();
if( cursor.hasSelection() )
{
QTextCursor c = cursor;
QTextDocument * doc = c.document();
int bs = doc->findBlock( c.selectionStart() ).blockNumber();
int be = doc->findBlock( c.selectionEnd() ).blockNumber();
cursor.beginEditBlock();
cursor.movePosition( QTextCursor::Start );
cursor.movePosition( QTextCursor::NextBlock, QTextCursor::MoveAnchor, bs );
int s = abs( steps );
int i, j;
for( i = bs; i <= be; i++ )
{
setTextCursor( cursor );
for( j = 0; j < s; j++ )
{
cursor.movePosition( QTextCursor::StartOfLine );
if( steps < 0 )
{
cursor.movePosition( QTextCursor::NextCharacter, QTextCursor::KeepAnchor );
QString textUnderCursor = cursor.selectedText();
if( textUnderCursor == " " )
{
setTextCursor( cursor );
insertPlainText( "" );
}
}
else
{
setTextCursor( cursor );
insertPlainText( " " );
}
}
cursor.movePosition( QTextCursor::NextBlock, QTextCursor::MoveAnchor, 1 );
}
cursor.endEditBlock();
setTextCursor( c );
}
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbBlockComment()
{
QTextCursor cursor = textCursor();
QTextCursor c = cursor;
QTextDocument * doc = c.document();
int bs = doc->findBlock( c.selectionStart() ).blockNumber();
int be = doc->findBlock( c.selectionEnd() ).blockNumber();
cursor.beginEditBlock();
cursor.movePosition( QTextCursor::Start );
cursor.movePosition( QTextCursor::NextBlock, QTextCursor::MoveAnchor, bs );
int i;
for( i = bs; i <= be; i++ )
{
setTextCursor( cursor );
cursor.movePosition( QTextCursor::StartOfLine );
cursor.movePosition( QTextCursor::NextCharacter, QTextCursor::KeepAnchor );
cursor.movePosition( QTextCursor::NextCharacter, QTextCursor::KeepAnchor );
QString textUnderCursor = cursor.selectedText();
if( textUnderCursor == "//" )
{
setTextCursor( cursor );
insertPlainText( "" );
}
else
{
cursor.movePosition( QTextCursor::StartOfLine );
insertPlainText( "//" );
}
cursor.movePosition( QTextCursor::NextBlock, QTextCursor::MoveAnchor, 1 );
}
cursor.endEditBlock();
setTextCursor( c );
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbDuplicateLine()
{
QTextCursor cursor = textCursor();
QTextCursor c = cursor;
cursor.movePosition( QTextCursor::StartOfLine );
cursor.movePosition( QTextCursor::EndOfLine, QTextCursor::KeepAnchor );
QString textUnderCursor = cursor.selectedText();
cursor.movePosition( QTextCursor::EndOfLine );
setTextCursor( cursor );
insertPlainText( "\n" + textUnderCursor );
setTextCursor( c );
}
/*----------------------------------------------------------------------*/
void HBQPlainTextEdit::hbBraceHighlight()
{
QColor lineColor = QColor( Qt::yellow ).lighter( 160 );
QTextDocument *doc = document();
extraSelections.clear();
setExtraSelections( extraSelections );
selection.format.setBackground( lineColor );
QTextCursor cursor = textCursor();
cursor.movePosition( QTextCursor::NextCharacter, QTextCursor::KeepAnchor );
QString brace = cursor.selectedText();
if( ( brace != "{" ) && ( brace != "}" )
&& ( brace != "[" ) && ( brace != "]" )
&& ( brace != "(" ) && ( brace != ")" )
&& ( brace != "<" ) && ( brace != ">" ) )
{
return;
}
QString openBrace;
QString closeBrace;
if( ( brace == "{" ) || ( brace == "}" ) )
{
openBrace = "{";
closeBrace = "}";
}
if( ( brace == "[" ) || ( brace == "]" ) )
{
openBrace = "[";
closeBrace = "]";
}
if( ( brace == "(" ) || ( brace == ")" ) )
{
openBrace = "(";
closeBrace = ")";
}
if( ( brace == "<" ) || ( brace == ">" ) )
{
openBrace = "<";
closeBrace = ">";
}
QTextCursor cursor1;
QTextCursor cursor2;
QTextCursor matches;
if( brace == openBrace )
{
cursor1 = doc->find( closeBrace, cursor );
cursor2 = doc->find( openBrace, cursor );
if( cursor2.isNull() )
{
matches = cursor1;
}
else
{
while( cursor1.position() > cursor2.position() )
{
cursor1 = doc->find( closeBrace, cursor1 );
cursor2 = doc->find( openBrace, cursor2 );
if( cursor2.isNull() )
break;
}
matches = cursor1;
}
}
else
{
if( brace == closeBrace )
{
cursor1 = doc->find( openBrace, cursor, QTextDocument::FindBackward );
cursor2 = doc->find( closeBrace, cursor, QTextDocument::FindBackward );
if( cursor2.isNull() )
{
matches = cursor1;
}
else
{
while( cursor1.position() < cursor2.position() )
{
cursor1 = doc->find( openBrace, cursor1, QTextDocument::FindBackward );
cursor2 = doc->find( closeBrace, cursor2, QTextDocument::FindBackward );
if( cursor2.isNull() )
break;
}
matches = cursor1;
}
}
}
if( ! matches.isNull() )
{
if( m_matchBracesAll )
{
selection.cursor = cursor;
extraSelections.append( selection );
}
selection.cursor = cursor1;
extraSelections.append( selection );
setExtraSelections( extraSelections );
}
}
/*----------------------------------------------------------------------*/
#endif