浏览代码

New class Fb2CodeEdit

Kandrashin Denis 13 年之前
父节点
当前提交
a2e8b45dd3
共有 4 个文件被更改,包括 189 次插入8 次删除
  1. 111 3
      source/fb2code.cpp
  2. 75 2
      source/fb2code.hpp
  3. 1 1
      source/fb2main.cpp
  4. 2 2
      source/fb2main.hpp

+ 111 - 3
source/fb2code.cpp

@@ -1,5 +1,7 @@
 #include "fb2code.hpp"
 
+#ifdef USE_SCINTILLA
+
 /////////////////////////////////////////////////////////////////////////////
 //
 //  http://qtcoder.blogspot.com/2010/10/qscintills.html
@@ -10,7 +12,7 @@
 #include <Qsci/qscilexerxml.h>
 #include <QtDebug>
 
-Fb2Scintilla::Fb2Scintilla(QWidget *parent) :
+Fb2CodeEdit::Fb2CodeEdit(QWidget *parent) :
     QsciScintilla(parent)
 {
     zoomTo(1);
@@ -67,13 +69,13 @@ Fb2Scintilla::Fb2Scintilla(QWidget *parent) :
     connect(this, SIGNAL(linesChanged()), SLOT(linesChanged()));
 }
 
-void Fb2Scintilla::linesChanged()
+void Fb2CodeEdit::linesChanged()
 {
     QString width = QString().setNum(lines() * 10);
     setMarginWidth(0, width);
 }
 
-void Fb2Scintilla::load(const QByteArray &array, const QList<int> &folds)
+void Fb2CodeEdit::load(const QByteArray &array, const QList<int> &folds)
 {
     SendScintilla(SCI_SETTEXT, array.constData());
     SendScintilla(SCI_EMPTYUNDOBUFFER);
@@ -83,3 +85,109 @@ void Fb2Scintilla::load(const QByteArray &array, const QList<int> &folds)
         foldLine(*it);
     }
 }
+
+#else // USE_SCINTILLA
+
+#include <QtGui>
+
+Fb2CodeEdit::Fb2CodeEdit(QWidget *parent) : QPlainTextEdit(parent)
+{
+    lineNumberArea = new LineNumberArea(this);
+
+    connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateLineNumberAreaWidth(int)));
+    connect(this, SIGNAL(updateRequest(QRect,int)), this, SLOT(updateLineNumberArea(QRect,int)));
+    connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(highlightCurrentLine()));
+
+    #ifdef Q_WS_WIN
+    setFont(QFont("Courier New", 8));
+    #else
+    setFont(QFont("Monospace", 8));
+    #endif
+
+    updateLineNumberAreaWidth(0);
+    highlightCurrentLine();
+}
+
+int Fb2CodeEdit::lineNumberAreaWidth()
+{
+    int digits = 1;
+    int max = qMax(1, blockCount());
+    while (max >= 10) {
+        max /= 10;
+        ++digits;
+    }
+
+    int space = 3 + fontMetrics().width(QLatin1Char('9')) * digits;
+
+    return space;
+}
+
+void Fb2CodeEdit::updateLineNumberAreaWidth(int /* newBlockCount */)
+{
+    setViewportMargins(lineNumberAreaWidth(), 0, 0, 0);
+}
+
+void Fb2CodeEdit::updateLineNumberArea(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()))
+        updateLineNumberAreaWidth(0);
+}
+
+void Fb2CodeEdit::resizeEvent(QResizeEvent *e)
+{
+    QPlainTextEdit::resizeEvent(e);
+
+    QRect cr = contentsRect();
+    lineNumberArea->setGeometry(QRect(cr.left(), cr.top(), lineNumberAreaWidth(), cr.height()));
+}
+
+void Fb2CodeEdit::highlightCurrentLine()
+{
+    QList<QTextEdit::ExtraSelection> extraSelections;
+
+    if (!isReadOnly()) {
+        QTextEdit::ExtraSelection selection;
+
+        QColor lineColor = QColor(Qt::yellow).lighter(160);
+
+        selection.format.setBackground(lineColor);
+        selection.format.setProperty(QTextFormat::FullWidthSelection, true);
+        selection.cursor = textCursor();
+        selection.cursor.clearSelection();
+        extraSelections.append(selection);
+    }
+
+    setExtraSelections(extraSelections);
+}
+
+void Fb2CodeEdit::lineNumberAreaPaintEvent(QPaintEvent *event)
+{
+    QPainter painter(lineNumberArea);
+    painter.fillRect(event->rect(), Qt::lightGray);
+
+    QTextBlock block = firstVisibleBlock();
+    int blockNumber = block.blockNumber();
+    int top = (int) blockBoundingGeometry(block).translated(contentOffset()).top();
+    int bottom = top + (int) blockBoundingRect(block).height();
+
+    while (block.isValid() && top <= event->rect().bottom()) {
+        if (block.isVisible() && bottom >= event->rect().top()) {
+            QString number = QString::number(blockNumber + 1);
+            painter.setPen(Qt::black);
+            painter.drawText(0, top, lineNumberArea->width(), fontMetrics().height(),
+                             Qt::AlignRight, number);
+        }
+
+        block = block.next();
+        top = bottom;
+        bottom = top + (int) blockBoundingRect(block).height();
+        ++blockNumber;
+    }
+}
+
+#endif // USE_SCINTILLA

+ 75 - 2
source/fb2code.hpp

@@ -1,14 +1,16 @@
 #ifndef FB2CODE_H
 #define FB2CODE_H
 
+#ifdef USE_SCINTILLA
+
 #include <Qsci/qsciscintilla.h>
 #include <QList>
 
-class Fb2Scintilla : public QsciScintilla
+class Fb2CodeEdit : public QsciScintilla
 {
     Q_OBJECT
 public:
-    explicit Fb2Scintilla(QWidget *parent = 0);
+    explicit Fb2CodeEdit(QWidget *parent = 0);
     void load(const QByteArray &array, const QList<int> &folds);
     
 signals:
@@ -20,4 +22,75 @@ private slots:
 
 };
 
+#else // USE_SCINTILLA
+
+#include <QByteArray>
+#include <QList>
+#include <QPlainTextEdit>
+#include <QObject>
+
+QT_BEGIN_NAMESPACE
+class QPaintEvent;
+class QResizeEvent;
+class QSize;
+class QWidget;
+QT_END_NAMESPACE
+
+class LineNumberArea;
+
+class Fb2CodeEdit : public QPlainTextEdit
+{
+    Q_OBJECT
+
+public:
+    Fb2CodeEdit(QWidget *parent = 0);
+
+    QString text() const { return toPlainText(); }
+
+    bool read(QIODevice *device) { return true; }
+
+    void zoomTo ( int size ) {}
+
+    void load(const QByteArray data, const QList<int> folds)
+        { setPlainText(QString::fromUtf8(data.data())); }
+
+    bool isUndoAvailable() { return false; }
+
+    bool isRedoAvailable() { return false; }
+
+public slots:
+    void zoomIn() {}
+    void zoomOut() {}
+
+protected:
+    void resizeEvent(QResizeEvent *event);
+
+private slots:
+    void updateLineNumberAreaWidth(int newBlockCount);
+    void highlightCurrentLine();
+    void updateLineNumberArea(const QRect &, int);
+
+private:
+    class LineNumberArea : public QWidget
+    {
+    public:
+        LineNumberArea(Fb2CodeEdit *parent) : QWidget(parent) { editor = parent; }
+        QSize sizeHint() const { return QSize(editor->lineNumberAreaWidth(), 0); }
+    protected:
+        void paintEvent(QPaintEvent *event) { editor->lineNumberAreaPaintEvent(event); }
+    private:
+        Fb2CodeEdit *editor;
+    };
+
+private:
+    void lineNumberAreaPaintEvent(QPaintEvent *event);
+    int lineNumberAreaWidth();
+    QWidget *lineNumberArea;
+    friend class Fb2CodeEdit::LineNumberArea;
+};
+
+typedef Fb2CodeEdit Fb2CodeEdit;
+
+#endif // USE_SCINTILLA
+
 #endif // FB2CODE_H

+ 1 - 1
source/fb2main.cpp

@@ -597,7 +597,7 @@ void Fb2MainWindow::viewCode()
     FB2DELETE(headTree);
 
     if (!codeEdit) {
-        codeEdit = new Fb2Scintilla;
+        codeEdit = new Fb2CodeEdit;
     }
     if (load) codeEdit->load(xml, folds);
     setCentralWidget(codeEdit);

+ 2 - 2
source/fb2main.hpp

@@ -14,7 +14,7 @@ class QTreeView;
 class QWebInspector;
 QT_END_NAMESPACE
 
-class Fb2Scintilla;
+class Fb2CodeEdit;
 class Fb2WebView;
 
 class Fb2MainWindow : public QMainWindow
@@ -80,7 +80,7 @@ private:
     QTextEdit *noteEdit;
     QTextEdit *messageEdit;
     QDockWidget *dockTree;
-    Fb2Scintilla *codeEdit;
+    Fb2CodeEdit *codeEdit;
     QTreeView *treeView;
     QString curFile;
     bool isUntitled;