You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
qt3/tools/designer/editor/markerwidget.cpp

492 lines
13 KiB

/**********************************************************************
** Copyright (C) 2005-2008 Trolltech ASA. All rights reserved.
**
** This file is part of Qt Designer.
**
** This file may be used under the terms of the GNU General
** Public License versions 2.0 or 3.0 as published by the Free
** Software Foundation and appearing in the files LICENSE.GPL2
** and LICENSE.GPL3 included in the packaging of this file.
** Alternatively you may (at your option) use any later version
** of the GNU General Public License if such license has been
** publicly approved by Trolltech ASA (or its successors, if any)
** and the KDE Free Qt Foundation.
**
** Please review the following information to ensure GNU General
** Public Licensing requirements will be met:
** http://trolltech.com/products/qt/licenses/licensing/opensource/.
** If you are unsure which license is appropriate for your use, please
** review the following information:
** http://trolltech.com/products/qt/licenses/licensing/licensingoverview
** or contact the sales department at sales@trolltech.com.
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with
** the Software.
**
** This file is provided "AS IS" with NO WARRANTY OF ANY KIND,
** INCLUDING THE WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE. Trolltech reserves all rights not granted
** herein.
**
**********************************************************************/
#include "markerwidget.h"
#include "viewmanager.h"
#include <private/qrichtext_p.h>
#include "editor.h"
#include <qpainter.h>
#include <qpopupmenu.h>
#include "paragdata.h"
static const char * error_xpm[] = {
"15 15 35 1",
" c None",
". c #FF0000",
"+ c #F50F0F",
"@ c #BF5F5F",
"# c #FF1010",
"$ c #FF7878",
"% c #FF0A0A",
"& c #FF0606",
"* c #FF1414",
"= c #FFFFFF",
"- c #FFA3A3",
"; c #FF0707",
"> c #FF0202",
", c #FF9898",
"' c #FF8888",
") c #D04747",
"! c #FFA7A7",
"~ c #FF9D9D",
"{ c #FFB1B1",
"] c #FF0C0C",
"^ c #F90A0A",
"/ c #FFB5B5",
"( c #FF0909",
"_ c #A08F8F",
": c #FFACAC",
"< c #FF0303",
"[ c #9F8F8F",
"} c #FB0606",
"| c #9F9090",
"1 c #CE4949",
"2 c #999999",
"3 c #FF1919",
"4 c #F70C0C",
"5 c #A38A8A",
"6 c #B37272",
" .... ",
" ........ ",
" .........+@ ",
" ..#$%..&$*.+ ",
" ..$=-;>,='..) ",
"...%-=!~={]..^ ",
"....;!==/(...._",
"....>~==:<....[",
"...&,=/:=!;..}|",
" ..$={(<!='..12",
" ..*']..;'3.45 ",
" +........462 ",
" @+......462 ",
" )^..}152 ",
" _[|2 "};
static const char * breakpoint_xpm[] = {
"15 15 3 1",
" c None",
". c #8B0000",
"+ c #FFFFFF",
" ....... ",
" ......... ",
" ........... ",
" ............. ",
"..+.+++.+..++..",
".+.+.+.+.+.+.+.",
".+...+.+.+.+.+.",
"..+..+.+.+.++..",
"...+.+.+.+.+...",
".+.+.+.+.+.+...",
"..+..+..+..+...",
" ............. ",
" ........... ",
" ......... ",
" ....... " };
static const char * step_xpm[] = {
"16 16 128 2",
" c None",
". c #B4B6BF",
"+ c #7893D8",
"@ c #8D95BF",
"# c #B8BFC1",
"$ c #B6D1E6",
"% c #7193E6",
"& c #8893C2",
"* c #B3BDC4",
"= c #AAD2EC",
"- c #9AD0FF",
"; c #6690EF",
"> c #8894C8",
", c #AFBAC4",
"' c #95BFEC",
") c #99CBFF",
"! c #8EC3FF",
"~ c #6D95F0",
"{ c #8792CA",
"] c #9DA7C3",
"^ c #8BA2E3",
"/ c #809AE0",
"( c #8398D1",
"_ c #93A0CC",
": c #ACB3CB",
"< c #B4B9C4",
"[ c #B6BAC4",
"} c #93A4CC",
"| c #82B0F5",
"1 c #8BBCFF",
"2 c #8EC0FF",
"3 c #8FC1FF",
"4 c #6594F4",
"5 c #7381CC",
"6 c #81A7E9",
"7 c #D0F5FF",
"8 c #C1EBFF",
"9 c #AEDAFF",
"0 c #A2D1FC",
"a c #A3C8F3",
"b c #AACAE6",
"c c #B4CFE9",
"d c #ADCCF9",
"e c #84B2FF",
"f c #82B4FF",
"g c #86B7FF",
"h c #88B7FF",
"i c #83B4FF",
"j c #5F8AF3",
"k c #7585C8",
"l c #77A4F3",
"m c #ABDFFF",
"n c #9CCAFF",
"o c #96C7FF",
"p c #97C8FF",
"q c #95C5FF",
"r c #9DCCFF",
"s c #A0CDFF",
"t c #90C0FF",
"u c #82AFFF",
"v c #7FAFFF",
"w c #7DAEFF",
"x c #79AAFF",
"y c #6C9EFF",
"z c #4366EB",
"A c #6894F2",
"B c #93C6FF",
"C c #82B3FF",
"D c #7AABFF",
"E c #73A5FF",
"F c #71A3FF",
"G c #6C9DFF",
"H c #699BFF",
"I c #76A8FF",
"J c #7EB0FF",
"K c #7BADFF",
"L c #74A5FF",
"M c #608BFF",
"N c #3462FF",
"O c #2444E5",
"P c #577AE0",
"Q c #5D90FF",
"R c #4C7AFF",
"S c #3B66FF",
"T c #335CF9",
"U c #365AF1",
"V c #3858E5",
"W c #3959E0",
"X c #416CF9",
"Y c #75A5FF",
"Z c #78A9FF",
"` c #74A4FF",
" . c #6191FF",
".. c #3059FF",
"+. c #1B37F1",
"@. c #6A75C7",
"#. c #828BC1",
"$. c #4358D8",
"%. c #374BDA",
"&. c #4759CA",
"*. c #636CC4",
"=. c #8489C0",
"-. c #9DA1C1",
";. c #A3A6BF",
">. c #7486CB",
",. c #6E98F5",
"'. c #719EFF",
"). c #608DFF",
"!. c #315EFF",
"~. c #1432F4",
"{. c #5C63C8",
"]. c #B1B4B9",
"^. c #B3BABB",
"/. c #ABB4C3",
"(. c #7299E9",
"_. c #5486FF",
":. c #224EFF",
"<. c #1733F2",
"[. c #7079C5",
"}. c #5C7DE9",
"|. c #2450FF",
"1. c #1B39EC",
"2. c #7077C5",
"3. c #3A54E1",
"4. c #1E36EA",
"5. c #858CBF",
"6. c #525FCB",
"7. c #727CBC",
" ",
" . + @ ",
" # $ % & ",
" * = - ; > ",
" , ' ) ! ~ { ",
"] ^ / ( _ : < [ } | 1 2 3 4 5 ",
"6 7 8 9 0 a b c d e f g h i j k ",
"l m n o p q r s t u v u w x y z ",
"A B C D E F G H I J K D L M N O ",
"P Q R S T U V W X Y Z ` ...+.@.",
"#.$.%.&.*.=.-.;.>.,.'.).!.~.{. ",
" ].^. /.(._.:.<.[. ",
" }.|.1.2. ",
" 3.4.5. ",
" 6.7. ",
" "};
static const char *stack_frame_xpm[]={
"16 16 2 1",
". c None",
"# c #00c000",
"................",
".###............",
".#####..........",
".#######........",
".#########......",
".###########....",
".#############..",
".##############.",
".##############.",
".#############..",
".###########....",
".#########......",
".#######........",
".#####..........",
".###............",
"................"};
static QPixmap *errorPixmap = 0;
static QPixmap *breakpointPixmap = 0;
static QPixmap *stepPixmap = 0;
static QPixmap *stackFrame = 0;
MarkerWidget::MarkerWidget( ViewManager *parent, const char*name )
: QWidget( parent, name, WRepaintNoErase | WStaticContents | WResizeNoErase ), viewManager( parent )
{
if ( !errorPixmap ) {
errorPixmap = new QPixmap( error_xpm );
breakpointPixmap = new QPixmap( breakpoint_xpm );
stepPixmap = new QPixmap( step_xpm );
stackFrame = new QPixmap( stack_frame_xpm );
}
}
void MarkerWidget::paintEvent( QPaintEvent * )
{
buffer.fill( backgroundColor() );
QTextParagraph *p = ( (Editor*)viewManager->currentView() )->document()->firstParagraph();
QPainter painter( &buffer );
int yOffset = ( (Editor*)viewManager->currentView() )->contentsY();
while ( p ) {
if ( !p->isVisible() ) {
p = p->next();
continue;
}
if ( p->rect().y() + p->rect().height() - yOffset < 0 ) {
p = p->next();
continue;
}
if ( p->rect().y() - yOffset > height() )
break;
if ( !((p->paragId() + 1) % 10) ) {
painter.save();
painter.setPen( colorGroup().dark() );
painter.drawText( 0, p->rect().y() - yOffset, width() - 20, p->rect().height(),
Qt::AlignRight | Qt::AlignTop, QString::number( p->paragId() + 1 ) );
painter.restore();
}
ParagData *paragData = (ParagData*)p->extraData();
if ( paragData ) {
switch ( paragData->marker ) {
case ParagData::Error:
painter.drawPixmap( 3, p->rect().y() +
( p->rect().height() - errorPixmap->height() ) / 2 -
yOffset, *errorPixmap );
break;
case ParagData::Breakpoint:
painter.drawPixmap( 3, p->rect().y() +
( p->rect().height() - breakpointPixmap->height() ) / 2 -
yOffset, *breakpointPixmap );
break;
default:
break;
}
switch ( paragData->lineState ) {
case ParagData::FunctionStart:
painter.setPen( colorGroup().foreground() );
painter.setBrush( colorGroup().base() );
painter.drawLine( width() - 11, p->rect().y() - yOffset,
width() - 11, p->rect().y() + p->rect().height() - yOffset );
painter.drawRect( width() - 15, p->rect().y() + ( p->rect().height() - 9 ) / 2 - yOffset, 9, 9 );
painter.drawLine( width() - 13, p->rect().y() + ( p->rect().height() - 9 ) / 2 - yOffset + 4,
width() - 9, p->rect().y() +
( p->rect().height() - 9 ) / 2 - yOffset + 4 );
if ( !paragData->functionOpen )
painter.drawLine( width() - 11,
p->rect().y() + ( p->rect().height() - 9 ) / 2 - yOffset + 2,
width() - 11,
p->rect().y() +
( p->rect().height() - 9 ) / 2 - yOffset + 6 );
break;
case ParagData::InFunction:
painter.setPen( colorGroup().foreground() );
painter.drawLine( width() - 11, p->rect().y() - yOffset,
width() - 11, p->rect().y() + p->rect().height() - yOffset );
break;
case ParagData::FunctionEnd:
painter.setPen( colorGroup().foreground() );
painter.drawLine( width() - 11, p->rect().y() - yOffset,
width() - 11, p->rect().y() + p->rect().height() - yOffset );
painter.drawLine( width() - 11, p->rect().y() + p->rect().height() - yOffset,
width() - 7, p->rect().y() + p->rect().height() - yOffset );
break;
default:
break;
}
if ( paragData->step )
painter.drawPixmap( 3, p->rect().y() +
( p->rect().height() - stepPixmap->height() ) / 2 -
yOffset, *stepPixmap );
if ( paragData->stackFrame )
painter.drawPixmap( 3, p->rect().y() +
( p->rect().height() - stackFrame->height() ) / 2 -
yOffset, *stackFrame );
}
p = p->next();
}
painter.end();
bitBlt( this, 0, 0, &buffer );
}
void MarkerWidget::resizeEvent( QResizeEvent *e )
{
buffer.resize( e->size() );
QWidget::resizeEvent( e );
}
void MarkerWidget::mousePressEvent( QMouseEvent *e )
{
if ( e->button() != LeftButton )
return;
bool supports = ( (Editor*)viewManager->currentView() )->supportsBreakPoints();
QTextParagraph *p = ( (Editor*)viewManager->currentView() )->document()->firstParagraph();
int yOffset = ( (Editor*)viewManager->currentView() )->contentsY();
while ( p ) {
if ( e->y() >= p->rect().y() - yOffset && e->y() <= p->rect().y() + p->rect().height() - yOffset ) {
QTextParagraphData *d = p->extraData();
if ( !d )
return;
ParagData *data = (ParagData*)d;
if ( supports && ( e->x() < width() - 15 ) ) {
if ( data->marker == ParagData::Breakpoint ) {
data->marker = ParagData::NoMarker;
} else {
bool ok = TRUE;
isBreakpointPossible( ok, ( (Editor*)viewManager->currentView() )->text(), p->paragId() );
if ( ok )
data->marker = ParagData::Breakpoint;
else
emit showMessage( tr( "<font color=red>Can't set breakpoint here!</font>" ) );
}
} else {
if ( data->lineState == ParagData::FunctionStart ) {
if ( data->functionOpen )
emit collapseFunction( p );
else
emit expandFunction( p );
}
}
break;
}
p = p->next();
}
doRepaint();
emit markersChanged();
}
void MarkerWidget::contextMenuEvent( QContextMenuEvent *e )
{
QPopupMenu m( 0, "editor_breakpointsmenu" );
int toggleBreakPoint = 0;
// int editBreakpoints = 0;
QTextParagraph *p = ( (Editor*)viewManager->currentView() )->document()->firstParagraph();
int yOffset = ( (Editor*)viewManager->currentView() )->contentsY();
bool supports = ( (Editor*)viewManager->currentView() )->supportsBreakPoints();
while ( p && supports ) {
if ( e->y() >= p->rect().y() - yOffset && e->y() <= p->rect().y() + p->rect().height() - yOffset ) {
if ( ( (ParagData*)p->extraData() )->marker == ParagData::Breakpoint )
toggleBreakPoint = m.insertItem( tr( "Clear Breakpoint\tF9" ) );
else
toggleBreakPoint = m.insertItem( tr( "Set Breakpoint\tF9" ) );
// editBreakpoints = m.insertItem( tr( "Edit Breakpoints..." ) );
m.insertSeparator();
break;
}
p = p->next();
}
const int collapseAll = m.insertItem( tr( "Collapse All" ) );
const int expandAll = m.insertItem( tr( "Expand All" ) );
const int collapseFunctions = m.insertItem( tr( "Collapse all Functions" ) );
const int expandFunctions = m.insertItem( tr( "Expand all Functions" ) );
int res = m.exec( e->globalPos() );
if ( res == -1)
return;
if ( res == collapseAll ) {
emit collapse( TRUE );
} else if ( res == collapseFunctions ) {
emit collapse( FALSE );
} else if ( res == expandAll ) {
emit expand( TRUE );
} else if ( res == expandFunctions ) {
emit expand( FALSE );
} else if ( res == toggleBreakPoint ) {
if ( ( (ParagData*)p->extraData() )->marker == ParagData::Breakpoint ) {
( (ParagData*)p->extraData() )->marker = ParagData::NoMarker;
} else {
bool ok;
isBreakpointPossible( ok, ( (Editor*)viewManager->currentView() )->text(), p->paragId() );
if ( ok )
( (ParagData*)p->extraData() )->marker = ParagData::Breakpoint;
else
emit showMessage( tr( "<font color=red>Can't set breakpoint here!</font>" ) );
}
// } else if ( res == editBreakpoints ) {
// emit editBreakPoints();
}
doRepaint();
emit markersChanged();
}