mirror of
https://github.com/RetroShare/RetroShare.git
synced 2025-01-11 23:49:38 -05:00
Merge pull request #61 from PhenomRetroShare/Improve_ElidedLabel_Alignment_HTML
Improve ElidedLabel
This commit is contained in:
commit
ef292faa22
@ -40,23 +40,30 @@
|
|||||||
|
|
||||||
#include "ElidedLabel.h"
|
#include "ElidedLabel.h"
|
||||||
|
|
||||||
#include <QPainter>
|
|
||||||
#include <QTextLayout>
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <QPainter>
|
||||||
#include <QStyleOption>
|
#include <QStyleOption>
|
||||||
|
#include <QTextDocument>
|
||||||
|
#include <QTextLayout>
|
||||||
|
#include <QToolTip>
|
||||||
|
|
||||||
ElidedLabel::ElidedLabel(const QString &text, QWidget *parent)
|
ElidedLabel::ElidedLabel(const QString &text, QWidget *parent)
|
||||||
: QLabel(parent)
|
: QLabel(parent)
|
||||||
, mElided(false)
|
, mElided(false)
|
||||||
|
, mOnlyPlainText(false)
|
||||||
, mContent(text)
|
, mContent(text)
|
||||||
{
|
{
|
||||||
|
mRectElision = QRect();
|
||||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||||
}
|
}
|
||||||
|
|
||||||
ElidedLabel::ElidedLabel(QWidget *parent)
|
ElidedLabel::ElidedLabel(QWidget *parent)
|
||||||
: QLabel(parent)
|
: QLabel(parent)
|
||||||
, mElided(false)
|
, mElided(false)
|
||||||
|
, mOnlyPlainText(false)
|
||||||
|
, mContent("")
|
||||||
{
|
{
|
||||||
|
mRectElision = QRect();
|
||||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,6 +73,12 @@ void ElidedLabel::setText(const QString &newText)
|
|||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ElidedLabel::setOnlyPlainText(const bool &value)
|
||||||
|
{
|
||||||
|
mOnlyPlainText = value;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
void ElidedLabel::clear()
|
void ElidedLabel::clear()
|
||||||
{
|
{
|
||||||
mContent.clear();
|
mContent.clear();
|
||||||
@ -75,43 +88,138 @@ void ElidedLabel::clear()
|
|||||||
void ElidedLabel::paintEvent(QPaintEvent *event)
|
void ElidedLabel::paintEvent(QPaintEvent *event)
|
||||||
{
|
{
|
||||||
QLabel::paintEvent(event);
|
QLabel::paintEvent(event);
|
||||||
|
QList<QPair<QTextLine,QPoint> > lLines;
|
||||||
|
QString elidedLastLine = "";
|
||||||
QPainter painter(this);
|
QPainter painter(this);
|
||||||
QFontMetrics fontMetrics = painter.fontMetrics();
|
QFontMetrics fontMetrics = painter.fontMetrics();
|
||||||
QRect cr = contentsRect();
|
QRect cr = contentsRect();
|
||||||
cr.adjust(margin(), margin(), -margin(), -margin());
|
cr.adjust(margin(), margin(), -margin(), -margin());
|
||||||
|
|
||||||
bool didElide = false;
|
bool didElide = false;
|
||||||
|
QChar ellipsisChar(0x2026);//= "…"
|
||||||
int lineSpacing = fontMetrics.lineSpacing();
|
int lineSpacing = fontMetrics.lineSpacing();
|
||||||
int x, y = x =cr.top()+(cr.height()-lineSpacing)/2;
|
int y = 0;
|
||||||
|
|
||||||
|
QString plainText = "";
|
||||||
|
if (mOnlyPlainText)
|
||||||
|
{
|
||||||
|
plainText = mContent;
|
||||||
|
} else {
|
||||||
|
QTextDocument td;
|
||||||
|
td.setHtml(mContent);
|
||||||
|
plainText = td.toPlainText();
|
||||||
|
}
|
||||||
|
plainText = plainText.replace("\n",QChar(QChar::LineSeparator));
|
||||||
|
plainText = plainText.replace("\r",QChar(QChar::LineSeparator));
|
||||||
|
|
||||||
|
QTextLayout textLayout(plainText, painter.font());
|
||||||
|
QTextOption to = textLayout.textOption();
|
||||||
|
to.setAlignment(alignment());
|
||||||
|
to.setWrapMode(wordWrap() ? QTextOption::WrapAtWordBoundaryOrAnywhere : QTextOption::NoWrap);
|
||||||
|
textLayout.setTextOption(to);
|
||||||
|
|
||||||
QTextLayout textLayout(mContent, painter.font());
|
|
||||||
textLayout.beginLayout();
|
textLayout.beginLayout();
|
||||||
forever {
|
forever {
|
||||||
|
//Get new line for text.
|
||||||
QTextLine line = textLayout.createLine();
|
QTextLine line = textLayout.createLine();
|
||||||
|
|
||||||
if (!line.isValid())
|
if (!line.isValid())
|
||||||
break;
|
break;// No more line to write
|
||||||
|
|
||||||
line.setLineWidth(cr.width()+2*x);
|
line.setLineWidth(cr.width());
|
||||||
int nextLineY = y + lineSpacing;
|
int nextLineY = y + lineSpacing;
|
||||||
|
|
||||||
if (cr.height() >= nextLineY + lineSpacing) {
|
if ((cr.height() >= nextLineY + lineSpacing) && wordWrap()) {
|
||||||
line.draw(&painter, QPoint(x, y));
|
//Line written normaly, next line will too
|
||||||
|
lLines.append(QPair<QTextLine, QPoint>(line, QPoint(0, y)));
|
||||||
y = nextLineY;
|
y = nextLineY;
|
||||||
} else {
|
} else {
|
||||||
QString lastLine = mContent.mid(line.textStart());
|
//The next line can't be written.
|
||||||
QString elidedLastLine = fontMetrics.elidedText(lastLine, Qt::ElideRight, cr.width());
|
QString lastLine = plainText.mid(line.textStart()).split(QChar(QChar::LineSeparator)).at(0);
|
||||||
painter.drawText(QPoint(x, y + fontMetrics.ascent()), elidedLastLine);
|
QTextLine lineEnd = textLayout.createLine();
|
||||||
line = textLayout.createLine();
|
if (!lineEnd.isValid() && (wordWrap()
|
||||||
didElide = line.isValid();
|
|| (fontMetrics.width(lastLine) < cr.width()))) {
|
||||||
|
//No more text for next line so this one is OK
|
||||||
|
lLines.append(QPair<QTextLine, QPoint>(line, QPoint(0, y)));
|
||||||
|
elidedLastLine="";
|
||||||
|
didElide = false;
|
||||||
|
} else {
|
||||||
|
//Text is left, so get elided text
|
||||||
|
if (lastLine == "") {
|
||||||
|
elidedLastLine = ellipsisChar;
|
||||||
|
} else {
|
||||||
|
elidedLastLine = fontMetrics.elidedText(lastLine, Qt::ElideRight, cr.width()-1);
|
||||||
|
if (elidedLastLine.right(1) != ellipsisChar)
|
||||||
|
elidedLastLine.append(ellipsisChar);//New line at end
|
||||||
|
}
|
||||||
|
didElide = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
textLayout.endLayout();
|
textLayout.endLayout();
|
||||||
|
|
||||||
|
int iTransX, iTransY = iTransX = 0;
|
||||||
|
int iHeight = lLines.count() * lineSpacing;
|
||||||
|
if (didElide) iHeight += lineSpacing;
|
||||||
|
|
||||||
|
//Compute lines translation with alignment
|
||||||
|
if (alignment() & Qt::AlignTop)
|
||||||
|
iTransY = 0;
|
||||||
|
if (alignment() & Qt::AlignBottom)
|
||||||
|
iTransY = cr.height() - iHeight;
|
||||||
|
if (alignment() & Qt::AlignVCenter)
|
||||||
|
iTransY = (cr.height() - iHeight) / 2;
|
||||||
|
|
||||||
|
QPair<QTextLine,QPoint> pair;
|
||||||
|
QPoint lastPos(-1,-1);
|
||||||
|
//Now we know how many lines to redraw at good position
|
||||||
|
foreach (pair, lLines){
|
||||||
|
lastPos = pair.second + QPoint(0, iTransY);
|
||||||
|
pair.first.draw(&painter, lastPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Print last elided line
|
||||||
|
if (didElide) {
|
||||||
|
int width = fontMetrics.width(elidedLastLine);
|
||||||
|
if (lastPos.y() == -1){
|
||||||
|
y = iTransY;// Only one line
|
||||||
|
} else {
|
||||||
|
y = lastPos.y() + lineSpacing;
|
||||||
|
}
|
||||||
|
if (width < cr.width()){
|
||||||
|
//Text don't taking all line (with line break), so align it
|
||||||
|
if (alignment() & Qt::AlignLeft)
|
||||||
|
iTransX = 0;
|
||||||
|
if (alignment() & Qt::AlignRight)
|
||||||
|
iTransX = cr.width() - width;
|
||||||
|
if (alignment() & Qt::AlignHCenter)
|
||||||
|
iTransX = (cr.width() - width) / 2;
|
||||||
|
if (alignment() & Qt::AlignJustify)
|
||||||
|
iTransX = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
painter.drawText(QPoint(iTransX, y + fontMetrics.ascent()), elidedLastLine);
|
||||||
|
//Draw button to get ToolTip
|
||||||
|
mRectElision = QRect(iTransX + width - fontMetrics.width(ellipsisChar)
|
||||||
|
, y
|
||||||
|
, fontMetrics.width(ellipsisChar)
|
||||||
|
, fontMetrics.height() - 1);
|
||||||
|
painter.drawRoundRect(mRectElision);
|
||||||
|
} else {
|
||||||
|
mRectElision = QRect();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Send signal if changed
|
||||||
if (didElide != mElided) {
|
if (didElide != mElided) {
|
||||||
mElided = didElide;
|
mElided = didElide;
|
||||||
emit elisionChanged(didElide);
|
emit elisionChanged(didElide);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ElidedLabel::mousePressEvent(QMouseEvent *ev)
|
||||||
|
{
|
||||||
|
if (mElided && (ev->buttons()==Qt::LeftButton) && (mRectElision.contains(ev->pos()))){
|
||||||
|
QToolTip::showText(mapToGlobal(QPoint(0, 0)),QString("<FONT>") + mContent + QString("</FONT>"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -52,6 +52,7 @@ class ElidedLabel : public QLabel
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(QString text READ text WRITE setText)
|
Q_PROPERTY(QString text READ text WRITE setText)
|
||||||
Q_PROPERTY(bool isElided READ isElided)
|
Q_PROPERTY(bool isElided READ isElided)
|
||||||
|
Q_PROPERTY(bool isOnlyPlainText READ isOnlyPlainText WRITE setOnlyPlainText)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ElidedLabel(const QString &text, QWidget *parent = 0);
|
ElidedLabel(const QString &text, QWidget *parent = 0);
|
||||||
@ -59,20 +60,25 @@ public:
|
|||||||
|
|
||||||
const QString & text() const { return mContent; }
|
const QString & text() const { return mContent; }
|
||||||
bool isElided() const { return mElided; }
|
bool isElided() const { return mElided; }
|
||||||
|
bool isOnlyPlainText() const { return mOnlyPlainText; }
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void setText(const QString &text);
|
void setText(const QString &text);
|
||||||
|
void setOnlyPlainText(const bool &value);
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void paintEvent(QPaintEvent *event);
|
void paintEvent(QPaintEvent *event);
|
||||||
|
void mousePressEvent(QMouseEvent *ev);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void elisionChanged(bool elided);
|
void elisionChanged(bool elided);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool mElided;
|
bool mElided;
|
||||||
|
bool mOnlyPlainText;
|
||||||
QString mContent;
|
QString mContent;
|
||||||
|
QRect mRectElision;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // ELIDEDLABEL_H
|
#endif // ELIDEDLABEL_H
|
||||||
|
Loading…
Reference in New Issue
Block a user