# HG changeset patch # User Jacob Dawid # Date 1302641030 -7200 # Node ID 9a0e32b207437fb39c0010ca36067b9e858d45c8 # Parent d4e0d8f925111af057f1f0db60dd050317fca91d Incorporated NumberedTextView class from QtOctave. diff --git a/gui//Quint.pro b/gui//Quint.pro --- a/gui//Quint.pro +++ b/gui//Quint.pro @@ -46,7 +46,8 @@ src/CodeEdit.cpp \ src/FileEditorMdiSubWindow.cpp \ src/SyntaxHighlighter.cpp \ - src/BrowserWidget.cpp + src/BrowserWidget.cpp \ + src/NumberedCodeEdit.cpp HEADERS += \ src/TerminalCharacterDecoder.h \ @@ -89,7 +90,8 @@ src/CodeEdit.h \ src/FileEditorMdiSubWindow.h \ src/SyntaxHighlighter.h \ - src/BrowserWidget.h + src/BrowserWidget.h \ + src/NumberedCodeEdit.h INCFLAGS = -g3 $$system(mkoctfile -p INCFLAGS) LFLAGS = $$system(mkoctfile -p LFLAGS) \ diff --git a/gui//src/BrowserWidget.cpp b/gui//src/BrowserWidget.cpp --- a/gui//src/BrowserWidget.cpp +++ b/gui//src/BrowserWidget.cpp @@ -54,7 +54,7 @@ connect(forwardAction, SIGNAL(triggered()), m_webView, SLOT(forward())); connect(m_webView, SIGNAL(urlChanged(QUrl)), this, SLOT(setUrl(QUrl))); connect(m_urlLineEdit, SIGNAL(returnPressed()), this, SLOT(jumpToWebsite())); - connect(m_webView, SIGNAL(statusBarMessage(QString)), m_statusBar, SLOT(showMessage(QString))); + connect(m_webView, SIGNAL(statusBarMessage(QString)), this, SLOT(showMessage(QString))); } void BrowserWidget::setUrl(QUrl url) { @@ -68,6 +68,10 @@ load(url); } +void BrowserWidget::showStatusMessage(QString message) { + m_statusBar->showMessage(message, 1000); +} + void BrowserWidget::load(QUrl url) { m_webView->load(url); } diff --git a/gui//src/BrowserWidget.h b/gui//src/BrowserWidget.h --- a/gui//src/BrowserWidget.h +++ b/gui//src/BrowserWidget.h @@ -34,6 +34,7 @@ public slots: void setUrl(QUrl url); void jumpToWebsite(); + void showStatusMessage(QString message); private: void construct(); diff --git a/gui//src/FileEditorMdiSubWindow.cpp b/gui//src/FileEditorMdiSubWindow.cpp --- a/gui//src/FileEditorMdiSubWindow.cpp +++ b/gui//src/FileEditorMdiSubWindow.cpp @@ -64,6 +64,7 @@ m_toolBar = new QToolBar(this); m_codeEdit = new CodeEdit(this); m_statusBar = new QStatusBar(this); + m_numberedTextView = new NumberedTextView(this, m_codeEdit); m_codeEdit->setFontFamily("Courier"); m_codeEdit->setLineWrapMode(QTextEdit::NoWrap); @@ -84,7 +85,7 @@ QVBoxLayout *layout = new QVBoxLayout(); layout->addWidget(m_toolBar); - layout->addWidget(m_codeEdit); + layout->addWidget(m_numberedTextView); layout->addWidget(m_statusBar); layout->setMargin(2); widget()->setLayout(layout); diff --git a/gui//src/FileEditorMdiSubWindow.h b/gui//src/FileEditorMdiSubWindow.h --- a/gui//src/FileEditorMdiSubWindow.h +++ b/gui//src/FileEditorMdiSubWindow.h @@ -23,6 +23,7 @@ #include #include #include "CodeEdit.h" +#include "NumberedCodeEdit.h" class FileEditorMdiSubWindow : public QMdiSubWindow { Q_OBJECT @@ -40,6 +41,7 @@ void construct(); QToolBar *m_toolBar; CodeEdit *m_codeEdit; + NumberedTextView *m_numberedTextView; QStatusBar *m_statusBar; QString m_fileName; }; diff --git a/gui//src/NumberedCodeEdit.cpp b/gui//src/NumberedCodeEdit.cpp new file mode 100644 --- /dev/null +++ b/gui//src/NumberedCodeEdit.cpp @@ -0,0 +1,580 @@ +/* This file is part of the KDE libraries + Copyright (C) 2005, 2006 KJSEmbed Authors + See included AUTHORS file. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "NumberedCodeEdit.h" +#include "config.h" + +NumberBar::NumberBar( QWidget *parent ) + : QWidget( parent ), edit(0), currentLine(-1), bugLine(-1) +{ + // Make room for 4 digits and the breakpoint icon + setFixedWidth( fontMetrics().width( QString("0000") + 10 + 32 ) ); + stopMarker = QPixmap(); //QString(ICON_PATH) + "/stop.png" ); + currentMarker = QPixmap(); // QString(ICON_PATH) + "/bookmark.png" ); + bugMarker = QPixmap(); // QString(ICON_PATH) + "/bug.png" ); +} + +NumberBar::~NumberBar() +{ +} + +void NumberBar::setCurrentLine( int lineno ) +{ + currentLine = lineno; + update(); +} + +void NumberBar::setBugLine( int lineno ) +{ + bugLine = lineno; +} + +void NumberBar::toggleBreakpoint( int lineno ) +{ + if(lineno > 0) + { + int i = breakpoints.indexOf(lineno); + + if(i > -1) + breakpoints.removeAt(i); + else + breakpoints.push_back(lineno); + } + update(); +} + +void NumberBar::setTextEdit( CodeEdit *edit ) +{ + this->edit = edit; + setFixedWidth( edit->fontMetrics().width( QString("0000") + 10 + 32 ) ); + connect( edit->document()->documentLayout(), SIGNAL( update(const QRectF &) ), + this, SLOT( update() ) ); + connect( edit->verticalScrollBar(), SIGNAL(valueChanged(int) ), + this, SLOT( update() ) ); +} + +void NumberBar::paintEvent( QPaintEvent * ) +{ + QVector lines_list; + int first_line_no; + edit->publicBlockBoundingRectList(lines_list, first_line_no); + + const QFontMetrics fm = edit->fontMetrics(); + const int ascent = fontMetrics().ascent() + 1; // height = ascent + descent + 1 + + QPainter p(this); + p.setPen(palette().windowText().color()); + + bugRect = QRect(); + stopRect = QRect(); + currentRect = QRect(); + + int position_y; + int lineCount; + + const int lines_list_size=lines_list.size(); + + for(int i=0;iverticalScrollBar()->value(); + qreal pageBottom = contentsY + edit->viewport()->height(); + const QFontMetrics fm = fontMetrics(); + const int ascent = fontMetrics().ascent() + 1; // height = ascent + descent + 1 + int lineCount = 1; + + QPainter p(this); + p.setPen(palette().windowText().color()); + + bugRect = QRect(); + stopRect = QRect(); + currentRect = QRect(); + + for ( QTextBlock block = edit->document()->begin(); + block.isValid(); block = block.next(), ++lineCount ) { + + const QRectF boundingRect = edit->publicBlockBoundingRect( block ); + + QPointF position = boundingRect.topLeft(); + if ( position.y() + boundingRect.height() < contentsY ) + continue; + if ( position.y() > pageBottom ) + break; + + const QString txt = QString::number( lineCount ); + p.drawText( width() - fm.width(txt), qRound( position.y() ) - contentsY + ascent, txt ); + + // Bug marker + if ( bugLine == lineCount ) { + p.drawPixmap( 1, qRound( position.y() ) - contentsY, bugMarker ); + bugRect = QRect( 1, qRound( position.y() ) - contentsY, bugMarker.width(), bugMarker.height() ); + } + + // Stop marker + if ( breakpoints.contains(lineCount) ) { + p.drawPixmap( 19, qRound( position.y() ) - contentsY, stopMarker ); + stopRect = QRect( 19, qRound( position.y() ) - contentsY, stopMarker.width(), stopMarker.height() ); + } + + // Current line marker + if ( currentLine == lineCount ) { + p.drawPixmap( 19, qRound( position.y() ) - contentsY, currentMarker ); + currentRect = QRect( 19, qRound( position.y() ) - contentsY, currentMarker.width(), currentMarker.height() ); + } + } + */ +} + +bool NumberBar::event( QEvent *event ) +{ + if ( event->type() == QEvent::ToolTip ) { + QHelpEvent *helpEvent = static_cast(event); + + if ( stopRect.contains( helpEvent->pos() ) ) { + QToolTip::showText( helpEvent->globalPos(), tr("Stop Here")); + } + else if ( currentRect.contains( helpEvent->pos() ) ) { + QToolTip::showText( helpEvent->globalPos(), tr("Current Line")); + } + else if ( bugRect.contains( helpEvent->pos() ) ) { + QToolTip::showText( helpEvent->globalPos(), tr("Error Line" )); + } + } + + return QWidget::event(event); +} + +QList *NumberBar::getBreakpoints() +{ + return &breakpoints; +} + + + +NumberedTextView::NumberedTextView( QWidget *parent, CodeEdit *textEdit ) + : QFrame( parent ) +{ + setFrameStyle( QFrame::StyledPanel | QFrame::Sunken ); + setLineWidth( 2 ); + + view=textEdit; + view->installEventFilter( this ); + + connect( view->document(), SIGNAL(contentsChange(int,int,int)), this, SLOT(textChanged(int,int,int)) ); + + connect( view, SIGNAL(cursorPositionChanged()), this, SLOT(cursor_moved_cb()) ); + + // Setup the line number pane + + numbers = new NumberBar( this ); + numbers->setTextEdit( view ); + //numbers=NULL; + + + vbox = new QVBoxLayout(this); + vbox->setSpacing( 0 ); + vbox->setMargin( 0 ); + + hbox = new QHBoxLayout; + vbox->addLayout(hbox); + + hbox->setSpacing( 0 ); + hbox->setMargin( 0 ); + hbox->addWidget( numbers ); + hbox->addWidget( view ); + + textModifiedOk=false; + + QHBoxLayout *messages_layout= new QHBoxLayout; + vbox->addLayout(messages_layout); + messages_layout->setSpacing( 0 ); + messages_layout->setMargin( 0 ); + + line_column_label=new QLabel("Line: 1 Col: 1", this); + messages_layout->addWidget(line_column_label); + line_column_label->show(); +} + + +NumberedTextView::~NumberedTextView() +{ + hide(); + //printf("Borrado ntv\n"); +} + +void NumberedTextView::setCurrentLine( int lineno ) +{ + currentLine = lineno; + if(numbers!=NULL) numbers->setCurrentLine( lineno ); + + //Move cursor to lineno + if(lineno>-1) + { + QTextCursor cursor=textEdit()->textCursor(); + + cursor.movePosition(QTextCursor::Start); + + for(int i=1;isetTextCursor(cursor); + } + + textChanged( 0, 0, 1 ); +} + +void NumberedTextView::toggleBreakpoint( int lineno ) +{ + if(numbers!=NULL) numbers->toggleBreakpoint( lineno ); +} + +void NumberedTextView::setBugLine( int lineno ) +{ + if(numbers!=NULL) numbers->setBugLine( lineno ); +} + +void NumberedTextView::textChanged( int /*pos*/, int removed, int added ) +{ + //Q_UNUSED( pos ); + + if ( removed == 0 && added == 0 ) + return; + + //QTextBlock block = highlight.block(); + //QTextBlock block = view->document()->begin(); + //QTextBlockFormat fmt = block.blockFormat(); + //QColor bg = view->palette().base().color(); + //fmt.setBackground( bg ); + //highlight.setBlockFormat( fmt ); + /* + QTextBlockFormat fmt; + + int lineCount = 1; + for ( QTextBlock block = view->document()->begin(); + block.isValid() && block!=view->document()->end(); block = block.next(), ++lineCount ) { + + if ( lineCount == currentLine ) + { + fmt = block.blockFormat(); + QColor bg = view->palette().highlight().color(); + fmt.setBackground( bg ); + + highlight = QTextCursor( block ); + highlight.movePosition( QTextCursor::EndOfBlock, QTextCursor::KeepAnchor ); + highlight.setBlockFormat( fmt ); + + break; + } + } + */ + + if( !textModifiedOk && view->document()->isModified() ) + { + textModifiedOk=true; + emit textModified(); + } +} + +bool NumberedTextView::eventFilter( QObject *obj, QEvent *event ) +{ + if ( obj != view ) + return QFrame::eventFilter(obj, event); + + if ( event->type() == QEvent::ToolTip ) { + QHelpEvent *helpEvent = static_cast(event); + + QTextCursor cursor = view->cursorForPosition( helpEvent->pos() ); + cursor.movePosition( QTextCursor::StartOfWord, QTextCursor::MoveAnchor ); + cursor.movePosition( QTextCursor::EndOfWord, QTextCursor::KeepAnchor ); + + QString word = cursor.selectedText(); + emit mouseHover( word ); + emit mouseHover( helpEvent->pos(), word ); + + // QToolTip::showText( helpEvent->globalPos(), word ); // For testing + } + + return false; +} + +QList *NumberedTextView::getBreakpoints() +{ + QList *br=NULL; + if(numbers!=NULL) br=numbers->getBreakpoints(); + return br; +} + +void NumberedTextView::open(QString path) +{ + FILE *fl; + + fl = fopen(path.toLocal8Bit().constData(), "rt"); + if(fl) + { + filePath = path; + QTextStream stream(fl); + textEdit()->document()->setPlainText(stream.readAll()); + fclose(fl); + textModifiedOk=false; + textEdit()->document()->setModified(false); + }else{ + throw path; + } +} + +void NumberedTextView::save(QString path) +{ + FILE *fl; + + if(path.isEmpty()) + path = filePath; + else + filePath = path; + + fl = fopen(path.toLocal8Bit().constData(), "wt"); + if(fl) + { + QTextStream *stream = new QTextStream(fl); + (*stream) << textEdit()->document()->toPlainText(); + delete stream; + fclose(fl); + textModifiedOk=false; + view->document()->setModified(false); + }else{ + throw path; + } + + + QString repository=path+"~~"; + QString command("simplercs \""+repository+"\" \""+path+"\""); + QProcess::startDetached(command); + //QProcess::execute(command); + +} + +QString NumberedTextView::path() +{ + return filePath; +} + +void NumberedTextView::setPath(QString path) +{ + filePath=path; +} + +void NumberedTextView::setModified(bool modify) +{ + textModifiedOk=modify; +} + +bool NumberedTextView::modified() +{ + return textModifiedOk; +} + +void NumberedTextView::cursor_moved_cb() +{ + QTextCursor cursor=view->textCursor(); + QTextBlock actual_block=cursor.block(); + int lineCount=1; + QTextBlock block = view->document()->begin(); + + for ( ;block.isValid() && actual_block!=block; block = block.next()) lineCount++ ; + + int col= cursor.position() - block.position() + 1; + + line_column_label->setText("Line: "+QString::number(lineCount)+" Col: "+QString::number(col) ); +} + +static QString startLineInsertText(QString str, QString textToInsert) +{ + str.replace(QChar(0x2029), "\n"); + //printf("str=%s\n", str.toLocal8Bit().data() ); + + QStringList list = str.split("\n"); + + for(int i=0;idocument(); + + QTextCursor cursor(textEdit()->textCursor()); + + if( !cursor.hasSelection() ) return; + + QString str=cursor.selectedText(); + + str=startLineInsertText(str, "\t"); + + cursor.insertText(str); + cursor.setPosition(cursor.position()-str.size(), QTextCursor::KeepAnchor); + textEdit()->setTextCursor(cursor); +} + +void NumberedTextView::unindent() +{ + //QTextDocument *doc=textEdit()->document(); + + QTextCursor cursor(textEdit()->textCursor()); + + if( !cursor.hasSelection() ) return; + + QString str=cursor.selectedText(); + + QStringList textToRemove; + textToRemove << "\t" << " "; + str=startLineRemoveText(str, textToRemove); + + cursor.insertText(str); + cursor.setPosition(cursor.position()-str.size(), QTextCursor::KeepAnchor); + textEdit()->setTextCursor(cursor); +} + +void NumberedTextView::comment() +{ + //QTextDocument *doc=textEdit()->document(); + + QTextCursor cursor(textEdit()->textCursor()); + + if( !cursor.hasSelection() ) return; + + QString str=cursor.selectedText(); + + str=startLineInsertText(str, "%"); + + cursor.insertText(str); + cursor.setPosition(cursor.position()-str.size(), QTextCursor::KeepAnchor); + textEdit()->setTextCursor(cursor); +} + +void NumberedTextView::uncomment() +{ + //QTextDocument *doc=textEdit()->document(); + + QTextCursor cursor(textEdit()->textCursor()); + + if( !cursor.hasSelection() ) return; + + QString str=cursor.selectedText(); + + QStringList textToRemove; + textToRemove << "%" << "#"; + str=startLineRemoveText(str, textToRemove); + + cursor.insertText(str); + cursor.setPosition(cursor.position()-str.size(), QTextCursor::KeepAnchor); + textEdit()->setTextCursor(cursor); +} diff --git a/gui//src/NumberedCodeEdit.h b/gui//src/NumberedCodeEdit.h new file mode 100644 --- /dev/null +++ b/gui//src/NumberedCodeEdit.h @@ -0,0 +1,167 @@ +/* This file is part of the KDE libraries + Copyright (C) 2005, 2006 KJSEmbed Authors + See included AUTHORS file. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +// -*- c++ -*- +#ifndef NUMBERED_TEXT_VIEW_H +#define NUMBERED_TEXT_VIEW_H + +#include +#include +#include +#include +#include +#include +#include "CodeEdit.h" + +class CodeEdit; +class QHBoxLayout; + +/** + * @internal Used to display the numbers. + */ +class NumberBar : public QWidget +{ + Q_OBJECT + +public: + NumberBar( QWidget *parent ); + ~NumberBar(); + + void setCurrentLine( int lineno ); + void setBugLine( int lineno ); + void toggleBreakpoint( int lineno ); + QList *getBreakpoints(); + + void setTextEdit( CodeEdit *edit ); + void paintEvent( QPaintEvent *ev ); + +protected: + bool event( QEvent *ev ); + +private: + CodeEdit *edit; + QPixmap stopMarker; + QPixmap currentMarker; + QPixmap bugMarker; + QList breakpoints; + int currentLine; + int bugLine; + QRect stopRect; + QRect currentRect; + QRect bugRect; +}; + +/** + * Displays a CodeEdit with line numbers. + */ +class NumberedTextView : public QFrame +{ + Q_OBJECT + +public: + NumberedTextView( QWidget *parent = 0 , CodeEdit *textEdit=new CodeEdit() ); + ~NumberedTextView(); + + QList *getBreakpoints(); + + void open(QString path); + void save(QString path = QString()); + + QString path(); + void setPath(QString path); + + bool modified(); + void setModified(bool modify); + + /** Returns the CodeEdit of the main view. */ + CodeEdit *textEdit() const { return view; } + + /** + * Sets the line that should have the current line indicator. + * A value of -1 indicates no line should show the indicator. + */ + void setCurrentLine( int lineno ); + + /** + * Toggle breakpoint + */ + void toggleBreakpoint( int lineno ); + + /** + * Sets the line that should have the bug line indicator. + * A value of -1 indicates no line should show the indicator. + */ + void setBugLine( int lineno ); + + /** @internal Used to get tooltip events from the view for the hover signal. */ + bool eventFilter( QObject *obj, QEvent *event ); + + /**Indent selected text.*/ + void indent(); + + /**UnIndent selected text.*/ + void unindent(); + + /**Comment selected text.*/ + void comment(); + + /**UnComment selected text.*/ + void uncomment(); + +signals: + /** + * Emitted when the mouse is hovered over the text edit component. + * @param word The word under the mouse pointer + */ + void mouseHover( const QString &word ); + + /** + * Emitted when the mouse is hovered over the text edit component. + * @param pos The position of the mouse pointer. + * @param word The word under the mouse pointer + */ + void mouseHover( const QPoint &pos, const QString &word ); + + /** + * Emitted when file is changed. + */ + void textModified(); + +protected slots: + /** @internal Used to update the highlight on the current line. */ + void textChanged( int pos, int added, int removed ); +public slots: + void cursor_moved_cb(); + +private: + QString filePath; + QLabel *line_column_label; + CodeEdit *view; + NumberBar *numbers; + QHBoxLayout *hbox; + QVBoxLayout *vbox; + int currentLine; + QTextCursor highlight; + bool textModifiedOk; +}; + + +#endif // NUMBERED_TEXT_VIEW_H + +