WingHexExplorer2/3rdparty/qcodeedit2/lib/widgets/qlinenumberpanel.cpp

233 lines
5.8 KiB
C++

/****************************************************************************
**
** Copyright (C) 2006-2009 fullmetalcoder <fullmetalcoder@hotmail.fr>
**
** This file is part of the Edyuk project <http://edyuk.org>
**
** This file may be used under the terms of the GNU General Public License
** version 3 as published by the Free Software Foundation and appearing in the
** file GPL.txt included in the packaging of this file.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/
#include "qlinenumberpanel.h"
/*!
\file qlinenumberpanel.cpp
\brief Implementation of the QLineNumberPanel class
\see QLineNumberPanel
*/
#include <QPainter>
#include <QScrollBar>
#include "qdocument.h"
#include "qdocument_p.h"
#include "qdocumentline.h"
#include "qeditor.h"
/*!
\ingroup widgets
@{
*/
/*!
\class QLineNumberPanel
\brief A specific panel in charge of drawing line numbers of an editor
*/
QCE_AUTO_REGISTER(QLineNumberPanel)
/*!
\brief Constructor
*/
QLineNumberPanel::QLineNumberPanel(QWidget *p) : QPanel(p), m_verbose(false) {
setFixedWidth(20);
}
/*!
\brief Empty destructor
*/
QLineNumberPanel::~QLineNumberPanel() {}
/*!
*/
QString QLineNumberPanel::type() const { return "Line numbers"; }
/*!
*/
bool QLineNumberPanel::isVerboseMode() const { return m_verbose; }
/*!
*/
void QLineNumberPanel::setVerboseMode(bool y) {
m_verbose = y;
update();
}
/*!
*/
void QLineNumberPanel::editorChange(QEditor *e) {
if (editor()) {
disconnect(editor(), SIGNAL(cursorPositionChanged()), this,
SLOT(update()));
}
if (e) {
_fixWidth =
QFontMetrics(e->document()->font())
.horizontalAdvance(QString::number(e->document()->lines())) +
5;
connect(e, SIGNAL(cursorPositionChanged()), this, SLOT(update()));
connect(e, &QEditor::zoomed, this, [=] {
_fixWidth = QFontMetrics(e->document()->font())
.horizontalAdvance(
QString::number(e->document()->lines())) +
5;
});
}
}
/*!
*/
void QLineNumberPanel::paint(QPainter *p, QEditor *e) {
/*
possible Unicode caracter for wrapping arrow :
0x21B3
0x2937
*/
QFont f(font());
f.setWeight(QFont::Bold);
const QFontMetrics sfm(f);
#ifndef WIN32
static const QChar wrappingArrow(0x2937);
const QFontMetrics specialSfm(sfm);
#else
// 0xC4 gives a decent wrapping arrow in Wingdings fonts, availables on all
// windows systems this is a hackish fallback to workaround Windows issues
// with Unicode...
static const QChar wrappingArrow(0xC4);
QFont specialFont(font());
specialFont.setFamily("Wingdings");
const QFontMetrics specialSfm(specialFont);
#endif
const int max = e->document()->lines();
const int panelWidth = sfm.horizontalAdvance(QString::number(max)) + 5;
setFixedWidth(panelWidth);
const QFontMetrics fm(e->document()->font());
int n, posY, as = fm.ascent(), ls = fm.lineSpacing(),
pageBottom = e->viewport()->height(),
contentsY = e->verticalOffset();
QString txt;
QDocument *d = e->document();
const int cursorLine = e->cursor().lineNumber();
n = d->lineNumber(contentsY);
posY = as + 2 + d->y(n) - contentsY;
// qDebug("first = %i; last = %i", first, last);
// qDebug("beg pos : %i", posY);
p->save();
f = p->font();
f.setPointSize(d->font().pointSize());
p->setFont(f);
for (;; ++n) {
// qDebug("n = %i; pos = %i", n, posY);
QDocumentLine line = d->line(n);
if (line.isNull() || ((posY - as) > pageBottom))
break;
if (line.isHidden())
continue;
bool draw = true;
if (!m_verbose) {
draw = !((n + 1) % 10) || !n || line.marks().count();
}
txt = QString::number(n + 1);
if (n == cursorLine) {
draw = true;
p->save();
auto f = p->font();
f.setBold(true);
p->setFont(f);
}
if (draw) {
p->drawText(width() - 2 - sfm.horizontalAdvance(txt), posY, txt);
} else {
int yOff = posY - (as + 1) + ls / 2;
if ((n + 1) % 5)
p->drawPoint(width() - 5, yOff);
else
p->drawLine(width() - 7, yOff, width() - 2, yOff);
}
if (line.lineSpan() > 1) {
#ifdef Q_OS_WIN32
p->save();
specialFont.setBold(
n ==
cursorLine); // todo: only get bold on the current wrapped line
specialFont.setPointSize(d->font().pointSize());
p->setFont(specialFont);
#endif
for (int i = 1; i < line.lineSpan(); ++i) {
// draw line wrapping indicators
// p->drawText(width() - 2 - sfm.width(wrappingArrow), posY + i
// * ls, wrappingArrow);
p->drawText(width() - 1 -
specialSfm.horizontalAdvance(wrappingArrow),
posY + i * ls, wrappingArrow);
}
#ifdef Q_OS_WIN32
p->restore();
#endif
}
if (n == cursorLine) {
p->restore();
}
posY += ls * line.lineSpan();
}
p->restore();
// p->setPen(Qt::DotLine);
// p->drawLine(width()-1, 0, width()-1, pageBottom);
// setFixedWidth(sfm.width(txt) + 5);
}
/*! @} */
QSize QLineNumberPanel::sizeHint() const { return QSize(_fixWidth, 0); }