Exemple #1
0
QPixmap QDeclarativeTextPrivate::wrappedTextImage(bool drawStyle)
{
    //do layout
    QSize size = cachedLayoutSize;

    int x = 0;
    for (int i = 0; i < layout.lineCount(); ++i) {
        QTextLine line = layout.lineAt(i);
        if (hAlign == QDeclarativeText::AlignLeft) {
            x = 0;
        } else if (hAlign == QDeclarativeText::AlignRight) {
            x = size.width() - (int)line.naturalTextWidth();
        } else if (hAlign == QDeclarativeText::AlignHCenter) {
            x = (size.width() - (int)line.naturalTextWidth()) / 2;
        }
        line.setPosition(QPoint(x, (int)line.y()));
    }

    //paint text
    QPixmap img(size);
    if (!size.isEmpty()) {
        img.fill(Qt::transparent);
        QPainter p(&img);
        drawWrappedText(&p, QPointF(0,0), drawStyle);
    }
    return img;
}
void TextLabel::drawTextLayout(QPainter *painter, const QTextLayout &layout, const QRect &rect)
{
    if (rect.width() < 1 || rect.height() < 1) {
        return;
    }

    QPixmap pixmap(rect.size());
    pixmap.fill(Qt::transparent);

    QPainter p(&pixmap);
    p.setPen(painter->pen());

    // Create the alpha gradient for the fade out effect
    QLinearGradient alphaGradient(0, 0, 1, 0);
    alphaGradient.setCoordinateMode(QGradient::ObjectBoundingMode);
    if (layout.textOption().textDirection() == Qt::LeftToRight) {
        alphaGradient.setColorAt(0, QColor(0, 0, 0, 255));
        alphaGradient.setColorAt(1, QColor(0, 0, 0, 0));
    } else {
        alphaGradient.setColorAt(0, QColor(0, 0, 0, 0));
        alphaGradient.setColorAt(1, QColor(0, 0, 0, 255));
    }

    QFontMetrics fm(layout.font());
    int textHeight = layout.lineCount() * fm.lineSpacing();

    QPointF position(0, (rect.height() - textHeight) / 2);
    QList<QRect> fadeRects;
    int fadeWidth = 30;

    // Draw each line in the layout
    for (int i = 0; i < layout.lineCount(); i++) {
        QTextLine line = layout.lineAt(i);
        line.draw(&p, position);

        // Add a fade out rect to the list if the line is too long
        if (line.naturalTextWidth() > rect.width())
        {
            int x = int(qMin(line.naturalTextWidth(), (qreal)pixmap.width())) - fadeWidth;
            int y = int(line.position().y() + position.y());
            QRect r = QStyle::visualRect(layout.textOption().textDirection(), pixmap.rect(),
                                         QRect(x, y, fadeWidth, int(line.height())));
            fadeRects.append(r);
        }
    }

    // Reduce the alpha in each fade out rect using the alpha gradient
    if (!fadeRects.isEmpty()) {
        p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
        foreach (const QRect &rect, fadeRects) {
            p.fillRect(rect, alphaGradient);
        }
void TextLabel::layoutText(QTextLayout &layout, const QString &text, const QSize &constraints)
{
    QFontMetrics metrics(layout.font());
    int leading = metrics.leading();
    int height = 0;
    int maxWidth = constraints.width();
    int widthUsed = 0;
    int lineSpacing = metrics.lineSpacing();
    QTextLine line;

    layout.setText(text);

    layout.beginLayout();
    while ((line = layout.createLine()).isValid()) {
        height += leading;

        // Make the last line that will fit infinitely long.
        // drawTextLayout() will handle this by fading the line out
        // if it won't fit in the constraints.
        if (height + 2 * lineSpacing > constraints.height()) {
            line.setPosition(QPoint(0, height));
            break;
        }

        line.setLineWidth(maxWidth);
        line.setPosition(QPoint(0, height));

        height += int(line.height());
        widthUsed = int(qMax(qreal(widthUsed), line.naturalTextWidth()));
    }
    layout.endLayout();
}
Exemple #4
0
    void setContent(const ToolTipContent &data)
    {
        QString html;
        if (!data.mainText().isEmpty()) {
            html.append("<div><b>" + data.mainText() + "</b></div>");
        }
        html.append(data.subText());

        m_anchor.clear();
        m_document->clear();
        data.registerResources(m_document);
        if (!html.isEmpty()) {
            m_document->setHtml("<p>" + html + "</p>");
        }
        m_document->adjustSize();

        m_haloRects.clear();
        QTextLayout *layout = m_document->begin().layout();
        //layout->setPosition(QPointF(textRect.x(), textBoundingRect->y()));
        QTextLine line;
        for (int i = 0; i < layout->lineCount(); ++i) {
            line = layout->lineAt(i);

            // Add halo rect only when a non empty line is found
            if (line.naturalTextWidth()) {
                m_haloRects.append(line.naturalTextRect().translated(layout->position().toPoint()).toRect().translated(m_margin, m_margin));
            }
        }

        update();
    }
Exemple #5
0
void KTextDocumentLayout::Private::adjustSize()
{
    if (parent->resizeMethod() == KTextDocument::NoResize)
        return;

    if (parent->shapes().isEmpty())
        return;
    // Limit auto-resizing to the first shape only (there won't be more
    // with auto-resizing turned on, unless specifically set)
    KShape *shape = parent->shapes().first();

    // Determine the maximum width of all text lines
    qreal width = 0;
    for (QTextBlock block = parent->document()->begin(); block.isValid(); block = block.next()) {
        // The block layout's wrap mode must be QTextOption::NoWrap, thus the line count
        // of a valid block must be 1 (otherwise this resizing scheme wouldn't work)
        Q_ASSERT(block.layout()->lineCount() == 1);
        QTextLine line = block.layout()->lineAt(0);
        width = qMax(width, line.naturalTextWidth());
    }

    // Use position and height of last text line to calculate height
    QTextLine line = parent->document()->lastBlock().layout()->lineAt(0);
    qreal height = line.position().y() + line.height();

    shape->setSize(QSizeF(width, height));
}
int JobItem::descriptionHeight(const QStyleOptionViewItem & option)
{
    int textTotalWidth = 0;
    int lineWidth = option.rect.width() - 2 * m_itemPadding;
    QString description = m_job->description().simplified();
    QTextLayout descriptionLayout(description, m_descriptionFont, m_paintDevice);
    descriptionLayout.beginLayout();
    for (int i = 0; i < m_descriptionLineCount - 1; ++i)
    {
        QTextLine line = descriptionLayout.createLine();
        if (!line.isValid())
        {
            // There is no text left to be inserted into the layout.
            break;
        }
        line.setLineWidth(lineWidth);
        textTotalWidth += line.naturalTextWidth();
    }
    descriptionLayout.endLayout();

    // Add space for last visible line.
    textTotalWidth += lineWidth;

    m_descriptionText = m_descriptionFontMetrics.elidedText(description,
                                                            Qt::ElideRight,
                                                            textTotalWidth);
    m_descriptionRect =
        m_descriptionFontMetrics.boundingRect(0,
                                              0,
                                              option.rect.width() - 2 * m_itemPadding,
                                              0,
                                              descriptionFlags(),
                                              m_descriptionText);
    return m_descriptionRect.height();
}
Exemple #7
0
void paint_QTextLayout(QPainter &p, bool useCache)
{
    static bool first = true;
    static QTextLayout *textLayout[lines];
    if (first) {
        for (int i = 0; i < lines; ++i) {
            textLayout[i] = new QTextLayout(strings[i]);
            int leading = p.fontMetrics().leading();
            qreal height = 0;
            qreal widthUsed = 0;
            textLayout[i]->setCacheEnabled(useCache);
            textLayout[i]->beginLayout();
            while (1) {
                QTextLine line = textLayout[i]->createLine();
                if (!line.isValid())
                    break;

                line.setLineWidth(lineWidth);
                height += leading;
                line.setPosition(QPointF(0, height));
                height += line.height();
                widthUsed = qMax(widthUsed, line.naturalTextWidth());
            }
            textLayout[i]->endLayout();
        }
        first = false;
    }
    for (int i = 0; i < count; ++i) {
        for (int j = 0; j < lines; ++j) {
            textLayout[j]->draw(&p, QPoint(0, j*spacing));
        }
    }
}
Exemple #8
0
QSize QDeclarativeTextPrivate::setupTextLayout(QTextLayout *layout)
{
    Q_Q(QDeclarativeText);
    layout->setCacheEnabled(true);

    int height = 0;
    qreal widthUsed = 0;
    qreal lineWidth = 0;

    //set manual width
    if ((wrap || elideMode != QDeclarativeText::ElideNone) && q->widthValid())
        lineWidth = q->width();

    layout->beginLayout();

    while (1) {
        QTextLine line = layout->createLine();
        if (!line.isValid())
            break;

        if ((wrap || elideMode != QDeclarativeText::ElideNone) && q->widthValid())
            line.setLineWidth(lineWidth);
    }
    layout->endLayout();

    int x = 0;
    for (int i = 0; i < layout->lineCount(); ++i) {
        QTextLine line = layout->lineAt(i);
        widthUsed = qMax(widthUsed, line.naturalTextWidth());
        line.setPosition(QPointF(0, height));
        height += int(line.height());

        if (!cache) {
            if (hAlign == QDeclarativeText::AlignLeft) {
                x = 0;
            } else if (hAlign == QDeclarativeText::AlignRight) {
                x = q->width() - (int)line.naturalTextWidth();
            } else if (hAlign == QDeclarativeText::AlignHCenter) {
                x = (q->width() - (int)line.naturalTextWidth()) / 2;
            }
            line.setPosition(QPoint(x, (int)line.y()));
        }
    }

    return QSize(qCeil(widthUsed), height);
}
qreal TextDocumentLayout::blockWidth(const QTextBlock &block)
{
    QTextLayout *layout = block.layout();
    if (!layout->lineCount())
        return 0; // only for layouted blocks
    qreal blockWidth = 0;
    for (int i = 0; i < layout->lineCount(); ++i) {
        QTextLine line = layout->lineAt(i);
        blockWidth = qMax(line.naturalTextWidth() + 8, blockWidth);
    }
    return blockWidth;
}
float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>*) const
{
    if (!run.length())
        return 0;
    const QString string = fixSpacing(qstring(run));
    QTextLayout layout(string, font());
    QTextLine line = setupLayout(&layout, run);
    int w = int(line.naturalTextWidth());
    // WebKit expects us to ignore word spacing on the first character (as opposed to what Qt does)
    if (treatAsSpace(run[0]))
        w -= m_wordSpacing;

    return w + run.padding();
}
static QTextLine setupLayout(QTextLayout* layout, const TextRun& style)
{
    int flags = style.rtl() ? Qt::TextForceRightToLeft : Qt::TextForceLeftToRight;
    if (style.padding())
        flags |= Qt::TextJustificationForced;
    layout->setFlags(flags);
    layout->beginLayout();
    QTextLine line = layout->createLine();
    line.setLineWidth(INT_MAX/256);
    if (style.padding())
        line.setLineWidth(line.naturalTextWidth() + style.padding());
    layout->endLayout();
    return line;
}
// Origin: Qt
static void viewItemTextLayout ( QTextLayout &textLayout, int lineWidth, qreal &height, qreal &widthUsed )
{
	height = 0;
	widthUsed = 0;
	textLayout.beginLayout();
	while ( true )
	{
		QTextLine line = textLayout.createLine();
		if ( !line.isValid() )
			break;
		line.setLineWidth ( lineWidth );
		line.setPosition ( QPointF ( 0, height ) );
		height += line.height();
		widthUsed = qMax ( widthUsed, line.naturalTextWidth() );
	}
	textLayout.endLayout();
}
// copied from QItemDelegate for drawDisplay
QSizeF doTextLayout(QTextLayout *textLayout, int lineWidth)
{
    qreal height = 0;
    qreal widthUsed = 0;
    textLayout->beginLayout();
    while (true) {
        QTextLine line = textLayout->createLine();
        if (!line.isValid())
            break;
        line.setLineWidth(lineWidth);
        line.setPosition(QPointF(0, height));
        height += line.height();
        widthUsed = qMax(widthUsed, line.naturalTextWidth());
    }
    textLayout->endLayout();
    return QSizeF(widthUsed, height);
}
Exemple #14
0
void CodeEditor::paintEvent(QPaintEvent* event)
{
    QPlainTextEdit::paintEvent(event);

    QPainter painter(viewport());
    painter.setPen(Qt::darkGray);

    QTextBlock block = firstVisibleBlock();

    QRectF rect;

    do {

        if (!block.isVisible())
            continue;

        rect = blockBoundingGeometry(block).translated(contentOffset());

        QTextLine line = block.layout()->lineAt(0);

        if (config->whitespaces) {
            QString txt = block.text();

            for (int i = 0; i < txt.length(); i++) {
                // rect.x() <- учитывая горизонтальный скролинг
                QPoint point(rect.x() + line.cursorToX(i), rect.y() + line.ascent());

                if (txt[i] == ' ')
                    painter.drawText(point, QChar(0x00b7));
                else if (txt[i] == '\t')
                    painter.drawText(point, QChar(0x21b9));
            }
        }

        int state = block.userState();

        if (!(state & Error) && state & Folded) {
            QRect collapseRect(rect.x() + line.rect().x() + line.naturalTextWidth() + FONTWIDTH * 2,
                               rect.y() + 2, FONTWIDTH * 6, line.height() - 4);

            painter.drawText(collapseRect, Qt::AlignCenter, state & Comment ? "...;" : "...)");
            painter.drawRoundedRect(collapseRect, 4, 6);
        }

    } while ((block = block.next()).isValid() && rect.y() < viewport()->height());
}
Exemple #15
0
static int layoutText(QTextLayout *layout, int maxWidth) {
    qreal height = 0;
    int textWidth = 0;
    layout->beginLayout();
    while (true) {
        QTextLine line = layout->createLine();
        if (!line.isValid()) {
            break;
        }
        line.setLineWidth(maxWidth);
        line.setPosition(QPointF(0, height));
        height += line.height();
        textWidth = qMax(textWidth, qRound(line.naturalTextWidth() + 0.5));
    }
    layout->endLayout();
    return textWidth;
}
Exemple #16
0
QSizeF QItemDelegatePrivate::doTextLayout(int lineWidth) const
{
    qreal height = 0;
    qreal widthUsed = 0;
    textLayout.beginLayout();
    while (true) {
        QTextLine line = textLayout.createLine();
        if (!line.isValid())
            break;
        line.setLineWidth(lineWidth);
        line.setPosition(QPointF(0, height));
        height += line.height();
        widthUsed = qMax(widthUsed, line.naturalTextWidth());
    }
    textLayout.endLayout();
    return QSizeF(widthUsed, height);
}
Exemple #17
0
void CodeEditor::mouseMoveEvent(QMouseEvent* event)
{
    QTextBlock block = findBlockByY(event->pos().y());

    QRect collapseRect;

    if (block.isValid()) {
        QRectF    rect = blockBoundingGeometry(block).translated(contentOffset());
        QTextLine line = block.layout()->lineAt(0);

        collapseRect = QRect(rect.x() + line.rect().x() + line.naturalTextWidth() + FONTWIDTH * 2,
                             rect.y() + 2, FONTWIDTH * 6, line.height() - 4);
    }

    int state = block.userState();

    if (!(state & Error) && state & Folded && collapseRect.contains(event->pos())) {
        pointedBlock = block;

        viewport()->setCursor(Qt::PointingHandCursor);

        QString str;

        while ((block = block.next()).isValid() && !block.isVisible()) {

            if (str.count() > 1)
                str += "\n";

            if (block.blockNumber() - pointedBlock.blockNumber() > 50) {
                str += "..."; // "\n...";
                break;
            }

            str += block.text();
        }

        QToolTip::showText(event->globalPos(), str, this);
    } else {
        pointedBlock = QTextBlock();
        viewport()->setCursor(Qt::IBeamCursor);
    }

    QPlainTextEdit::mouseMoveEvent(event);
}
qreal QmlConsoleItemDelegate::layoutText(QTextLayout &tl, int width,
                                         bool *showFileLineInfo) const
{
    qreal height = 0;
    tl.beginLayout();
    while (true) {
        QTextLine line = tl.createLine();

        if (!line.isValid())
            break;
        line.setLeadingIncluded(true);
        line.setLineWidth(width);
        if (width < line.naturalTextWidth() && showFileLineInfo)
            *showFileLineInfo = false;
        line.setPosition(QPoint(0, height));
        height += line.height();
    }
    tl.endLayout();
    return height;
}
Exemple #19
0
void
ElidedLabel::paintEvent( QPaintEvent* event )
{
    QFrame::paintEvent( event );
    QPainter p( this );
    QRect r = contentsRect();
    r.adjust( m_margin, m_margin, -m_margin, -m_margin );

    if ( m_multiLine )
    {
        QTextLayout textLayout( m_text );
        textLayout.setFont( p.font() );
        int widthUsed = 0;
        int lineCount = 0;
        int lineLimit = r.height() / fontMetrics().height();

        textLayout.beginLayout();
        while ( ++lineCount < lineLimit )
        {
            QTextLine line = textLayout.createLine();
            if ( !line.isValid() )
                break;

            line.setLineWidth( r.width() );
            widthUsed += line.naturalTextWidth();
        }
        textLayout.endLayout();
        widthUsed += r.width();

        const QString elidedText = fontMetrics().elidedText( m_text, Qt::ElideRight, widthUsed );
        p.drawText( r, Qt::AlignLeft | Qt::AlignTop | Qt::TextWordWrap, elidedText );
    }
    else
    {
        const QString elidedText = fontMetrics().elidedText( m_text, m_mode, r.width() );
        p.drawText( r, m_align, elidedText );
    }
}
void FadingMultilineLabel::positionLayouts()
{
	QFontMetricsF fm = fontMetrics();
	qreal lineHeight = fm.height();

	delete textLayout_;
	textLayout_ = 0;

	textLayout_ = new QTextLayout(text_, font());
	textLayout_->setTextOption(textOption_);
	// textLayout_->setAdditionalFormats(formats[p]);
	textLayout_->beginLayout();

	qreal x = 0.0;
	qreal y = 0.0;
	qreal ymax = 0.0;

	fadeOuts_.clear();
	QTextLine line = textLayout_->createLine();

	while (line.isValid()) {
		line.setPosition(QPointF(x, y));
		line.setLineWidth(width());

		if (line.naturalTextWidth() > width()) {
			fadeOuts_ << QRect(x, y, width(), lineHeight);
		}

		y += line.height();
		line = textLayout_->createLine();
	}

	textLayout_->endLayout();

	sizeHint_ = QSize(width(), y);
	updateGeometry();
}
Exemple #21
0
void Msg::ShowMsg(const QString str)
{
    mUpdateRect = boundingRect();

    mLay->setText(str);
    int leading = -3;
    qreal h = 0;
    qreal maxw = 0;
    qreal maxh = 0;
    mLay->beginLayout();

    while (1)
    {
        QTextLine line = mLay->createLine();
        if (!line.isValid())
        {
            break;
        }

        line.setLineWidth(280);
        h += leading;
        line.setPosition(QPointF(0, h));
        h += line.height();
        maxw = qMax(maxw, line.naturalTextWidth());
    }
    mLay->endLayout();

    float ypos = 4 + (70 - mLay->boundingRect().height()) / 2;

    maxw = qMax(mUpdateRect.width(), mLay->boundingRect().width());
    maxh = qMax(mUpdateRect.height(), mLay->boundingRect().height() + ypos);

    mUpdateRect = QRectF(0, 0, maxw, maxh + ypos);

    update(boundingRect());
}
Exemple #22
0
int main(int argc, char* argv[])
{
#if defined(_MSC_VER) && defined(_DEBUG)
    // Enable leak detection for MSVC debug builds.
    {
        // Check for a debugger and prompt if one is not attached.
        while (!IsDebuggerPresent()
               && IDYES == MessageBox(0,
                                      "You are starting debug mudlet without a debugger attached. If you wish to attach one and verify that it worked, click yes. To continue without a debugger, click no.",
                                      "Mudlet Debug",
                                      MB_ICONINFORMATION | MB_YESNO | MB_DEFBUTTON2))
            ;

        // _CRTDBG_ALLOC_MEM_DF: Enable heap debugging.
        // _CRTDBG_LEAK_CHECK_DF: Check for leaks at program exit.
        _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);

        // Create a log file for writing leaks.
        HANDLE hLogFile = CreateFile("stderr.txt", GENERIC_WRITE,
            FILE_SHARE_WRITE, NULL, CREATE_ALWAYS,
            FILE_ATTRIBUTE_NORMAL, NULL);
        _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
        _CrtSetReportFile(_CRT_WARN, hLogFile);

        // Set this to break on the allocation number shown in the debug output above.
        // _crtBreakAlloc = 0;

        pcre_malloc = pcre_malloc_dbg;
        pcre_free = pcre_free_dbg;
        pcre_stack_malloc = pcre_malloc_dbg;
        pcre_stack_free = pcre_free_dbg;
    }
#endif // _MSC_VER && _DEBUG
    spDebugConsole = 0;
    unsigned int startupAction = 0;

    Q_INIT_RESOURCE(mudlet_alpha);

    QScopedPointer<QCoreApplication> initApp(createApplication(argc, argv, startupAction));

    QApplication* app = qobject_cast<QApplication*>(initApp.data());

    // Non-GUI actions --help and --version as suggested by GNU coding standards,
    // section 4.7: http://www.gnu.org/prep/standards/standards.html#Command_002dLine-Interfaces
    if (app == 0) {
        if (startupAction & 2) {
            // Do "version" action - wording and format is quite tightly specified by the coding standards
            std::cout << APP_TARGET << " " << APP_VERSION << APP_BUILD << std::endl;
            std::cout << "Qt libraries " << QT_VERSION_STR << "(compilation) " << qVersion() << "(runtime)" << std::endl;
            std::cout << "Copyright (C) 2008-" << std::string(__DATE__).substr(7, 4) << " Mudlet devs." << std::endl;
            std::cout << "Licence GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>" << std::endl;
            std::cout << "This is free software: you are free to change and redistribute it." << std::endl;
            std::cout << "There is NO WARRANTY, to the extent permitted by law." << std::endl;
        }
        if (startupAction & 1) {
            // Do "help" action -
            std::cout << "Usage: " << std::string(APP_TARGET) << "[OPTION...]" << std::endl;
#if defined(Q_OS_WIN32)
            std::cout << "   /h, /help           displays this message." << std::endl;
            std::cout << "   /v, /version        displays version information." << std::endl;
            std::cout << "   /q, /quiet          no splash screen on startup." << std::endl;
#define OPT_PREFIX '/'
#else
            std::cout << "   -h, --help          displays this message." << std::endl;
            std::cout << "   -v, --version       displays version information." << std::endl;
            std::cout << "   -q, --quiet         no splash screen on startup." << std::endl;
#define OPT_PREFIX '-'
#endif
            std::cout << "There are other inherited options that arise from the Qt Libraries which" << std::endl;
            std::cout << "are not likely to be useful for normal use of this application:" << std::endl;
            // From documentation and from http://qt-project.org/doc/qt-5/qapplication.html:
            std::cout << "       " << OPT_PREFIX << "dograb         ignore any implicit or explicit -nograb." << std::endl;
            std::cout << "                       " << OPT_PREFIX << "dograb wins over " << OPT_PREFIX << "nograb even when" << std::endl;
            std::cout << "                       " << OPT_PREFIX << "nograb is last on the command line." << std::endl;
            std::cout << "       " << OPT_PREFIX << "nograb         the application should never grab the mouse or the" << std::endl;
#if defined(Q_OS_LINUX)
            std::cout << "                       keyboard. This option is set by default when Mudlet is" << std::endl;
            std::cout << "                       running in the gdb debugger under Linux." << std::endl;
#else
            std::cout << "                       keyboard." << std::endl;
#endif
            std::cout << "        " << OPT_PREFIX << "reverse       sets the application's layout direction to" << std::endl;
            std::cout << "                       right to left." << std::endl;
            std::cout << "        " << OPT_PREFIX << "style= style  sets the application GUI style. Possible values depend" << std::endl;
            std::cout << "                       on your system configuration. If Qt was compiled with" << std::endl;
            std::cout << "                       additional styles or has additional styles as plugins" << std::endl;
            std::cout << "                       these will be available to the -style command line" << std::endl;
            std::cout << "                       option. You can also set the style for all Qt" << std::endl;
            std::cout << "                       applications by setting the QT_STYLE_OVERRIDE environment" << std::endl;
            std::cout << "                       variable." << std::endl;
            std::cout << "        " << OPT_PREFIX << "style style   is the same as listed above." << std::endl;
            std::cout << "        " << OPT_PREFIX << "stylesheet= stylesheet" << std::endl;
            std::cout << "                       sets the application styleSheet." << std::endl;
            std::cout << "                       The value must be a path to a file that contains the" << std::endl;
            std::cout << "                       Style Sheet. Note: Relative URLs in the Style Sheet" << std::endl;
            std::cout << "                       file are relative to the Style Sheet file's path." << std::endl;
            std::cout << "        " << OPT_PREFIX << "stylesheet stylesheet" << std::endl;
            std::cout << "                       is the same as listed above." << std::endl;
#if defined(Q_OS_UNIX)
            std::cout << "        " << OPT_PREFIX << "sync          runs Mudlet in X synchronous mode. Synchronous mode" << std::endl;
            std::cout << "                       forces the X server to perform each X client request" << std::endl;
            std::cout << "                       immediately and not use buffer optimization. It makes" << std::endl;
            std::cout << "                       the program easier to debug and often much slower. The" << std::endl;
            std::cout << "                       -sync option is only valid for the X11 version of Qt." << std::endl;
#endif
            std::cout << "        " << OPT_PREFIX << "widgetcount   prints debug message at the end about number of widgets" << std::endl;
            std::cout << "                       left undestroyed and maximum number of widgets existing" << std::endl;
            std::cout << "                       at the same time." << std::endl;
            std::cout << "        " << OPT_PREFIX << "qmljsdebugger=1234[,block]" << std::endl;
            std::cout << "                       activates the QML/JS debugger with a specified port." << std::endl;
            std::cout << "                       The number is the port value and block is optional" << std::endl;
            std::cout << "                       and will make the application wait until a debugger" << std::endl;
            std::cout << "                       connects to it." << std::endl;
            std::cout << std::endl;
            std::cout << "Report bugs to: <https://github.com/Mudlet/Mudlet/issues>" << std::endl;
            std::cout << "pkg home page: <http://www.mudlet.org/>" << std::endl;
        }
        return 0;
    }

    // Turn the cursor into the waiting one during startup, so something shows
    // activity even if the quiet, no splashscreen startup has been used
    app->setOverrideCursor(QCursor(Qt::WaitCursor));
    app->setOrganizationName("Mudlet");
    app->setApplicationName("Mudlet");
    app->setApplicationVersion(APP_VERSION);

    bool show_splash = !(startupAction & 4); // Not --quiet.

    QImage splashImage(":/Mudlet_splashscreen_main.png");
    if (show_splash) {
        QPainter painter(&splashImage);
        unsigned fontSize = 16;
        QString sourceVersionText = QString("Version: " APP_VERSION APP_BUILD);

        bool isWithinSpace = false;
        while (!isWithinSpace) {
            QFont font("DejaVu Serif", fontSize, QFont::Bold | QFont::Serif | QFont::PreferMatch | QFont::PreferAntialias);
            QTextLayout versionTextLayout(sourceVersionText, font, painter.device());
            versionTextLayout.beginLayout();
            // Start work in this text item
            QTextLine versionTextline = versionTextLayout.createLine();
            // First draw (one line from) the text we have put in on the layout to
            // see how wide it is..., assuming accutally that it will only take one
            // line of text
            versionTextline.setLineWidth(280);
            //Splashscreen bitmap is (now) 320x360 - hopefully entire line will all fit into 280
            versionTextline.setPosition(QPointF(0, 0));
            // Only pretend, so we can see how much space it will take
            QTextLine dummy = versionTextLayout.createLine();
            if (!dummy.isValid()) {
                // No second line so have got all text in first so can do it
                isWithinSpace = true;
                qreal versionTextWidth = versionTextline.naturalTextWidth();
                // This is the ACTUAL width of the created text
                versionTextline.setPosition(QPointF((320 - versionTextWidth) / 2.0, 270));
                // And now we can place it centred horizontally
                versionTextLayout.endLayout();
                // end the layout process and paint it out
                painter.setPen(QColor(176, 64, 0, 255)); // #b04000
                versionTextLayout.draw(&painter, QPointF(0, 0));
            } else {
                // Too big - text has spilled over onto a second line - so try again
                fontSize--;
                versionTextLayout.clearLayout();
                versionTextLayout.endLayout();
            }
        }

        // Repeat for other text, but we know it will fit at given size
        QString sourceCopyrightText = QChar(169) % QString(" Mudlet makers 2008-") % QString(__DATE__).mid(7);
        QFont font("DejaVu Serif", 16, QFont::Bold | QFont::Serif | QFont::PreferMatch | QFont::PreferAntialias);
        QTextLayout copyrightTextLayout(sourceCopyrightText, font, painter.device());
        copyrightTextLayout.beginLayout();
        QTextLine copyrightTextline = copyrightTextLayout.createLine();
        copyrightTextline.setLineWidth(280);
        copyrightTextline.setPosition(QPointF(1, 1));
        qreal copyrightTextWidth = copyrightTextline.naturalTextWidth();
        copyrightTextline.setPosition(QPointF((320 - copyrightTextWidth) / 2.0, 340));
        copyrightTextLayout.endLayout();
        painter.setPen(QColor(112, 16, 0, 255)); // #701000
        copyrightTextLayout.draw(&painter, QPointF(0, 0));
    }
    QPixmap pixmap = QPixmap::fromImage(splashImage);
    QSplashScreen splash(pixmap);
    if (show_splash) {
        splash.show();
    }
    app->processEvents();

    QString splash_message;
    if (show_splash) {
        splash_message.append("\n\nMudlet comes with\n"
                              "ABSOLUTELY NO WARRANTY!\n"
                              "This is free software, and you are\n"
                              "welcome to redistribute it under\n"
                              "certain conditions; select the\n"
                              "'About' item for details.\n\n");
        splash_message.append("Locating profiles... ");
        splash.showMessage(splash_message, Qt::AlignHCenter | Qt::AlignTop);
        app->processEvents();
    }

    QString directory = QDir::homePath() + "/.config/mudlet";
    QDir dir;
    if (!dir.exists(directory)) {
        dir.mkpath(directory);
    }

    if (show_splash) {
        splash_message.append("Done.\n\nLoading font files... ");
        splash.showMessage(splash_message, Qt::AlignHCenter | Qt::AlignTop);
        app->processEvents();
    }

    if (!QFile::exists(directory + "/COPYRIGHT.TXT")) {
        QFile file_f1(":/fonts/ttf-bitstream-vera-1.10/COPYRIGHT.TXT");
        file_f1.copy(directory + "/COPYRIGHT.TXT");
    }

    if (!QFile::exists(directory + "/RELEASENOTES.TXT")) {
        QFile file_f2(":/fonts/ttf-bitstream-vera-1.10/RELEASENOTES.TXT");
        file_f2.copy(directory + "/RELEASENOTES.TXT");
    }

    if (!QFile::exists(directory + "/VeraMoIt.ttf")) {
        QFile file_f3(":/fonts/ttf-bitstream-vera-1.10/VeraMoIt.ttf");
        file_f3.copy(directory + "/VeraMoIt.ttf");
    }

    if (!QFile::exists(directory + "/local.conf")) {
        QFile file_f4(":/fonts/ttf-bitstream-vera-1.10/local.conf");
        file_f4.copy(directory + "/local.conf");
    }

    if (!QFile::exists(directory + "/VeraMoBd.ttf")) {
        QFile file_f5(":/fonts/ttf-bitstream-vera-1.10/VeraMoBd.ttf");
        file_f5.copy(directory + "/VeraMoBd.ttf");
    }

    if (!QFile::exists(directory + "/VeraMoBd.ttf")) {
        QFile file_f6(":/fonts/ttf-bitstream-vera-1.10/VeraMoBd.ttf");
        file_f6.copy(directory + "/VeraMoBd.ttf");
    }

    if (!QFile::exists(directory + "/README.TXT")) {
        QFile file_f7(":/fonts/ttf-bitstream-vera-1.10/README.TXT");
        file_f7.copy(directory + "/README.TXT");
    }

    if (!QFile::exists(directory + "/VeraMoBI.ttf")) {
        QFile file_f8(":/fonts/ttf-bitstream-vera-1.10/VeraMoBI.ttf");
        file_f8.copy(directory + "/VeraMoBI.ttf");
    }

    if (!QFile::exists(directory + "/VeraMono.ttf")) {
        QFile file_f9(":/fonts/ttf-bitstream-vera-1.10/VeraMono.ttf");
        file_f9.copy(directory + "/VeraMono.ttf");
    }

    if (show_splash) {
        splash_message.append("Done.\n\n"
                              "All data has been loaded successfully.\n\n"
                              "Starting... Have fun!\n\n");
        splash.showMessage(splash_message, Qt::AlignHCenter | Qt::AlignTop);
        app->processEvents();
    }

    mudlet::debugMode = false;
    FontManager fm;
    fm.addFonts();
    QString home = QDir::homePath() + "/.config/mudlet";
    QString homeLink = QDir::homePath() + "/mudlet-data";
    QFile::link(home, homeLink);
    mudlet::start();
    mudlet::self()->show();
    if (show_splash) {
        splash.finish(mudlet::self());
    }
    app->restoreOverrideCursor();
    // NOTE: Must restore cursor - BEWARE DEBUGGERS if you terminate application
    // without doing/reaching this restore - it can be quite hard to accurately
    // click something in a parent process to the application when you are stuck
    // with some OS's choice of wait cursor - you might wish to temparily disable
    // the earlier setOverrideCursor() line and this one.
    return app->exec();
}
ReportItem::PrintResult ReportItemPara::printMetaPaintChildren(ReportItemMetaPaint *out, const ReportItem::Rect &bounding_rect)
{
	qfLogFuncFrame() << this << bounding_rect.toString();
	PrintResult res = PR_PrintedOk;
	if(m_indexToPrint == 0) {
		printedText = paraText();
	}
	//qfInfo() << printedText;
	QString text = printedText.mid(m_indexToPrint);
	int initial_index_to_print = m_indexToPrint;

	QString sql_id = sqlId();
	/// tiskne se prazdny text
	bool omit_empty_text = isOmitEmptyText();
	if(text.isEmpty() && omit_empty_text) {
	}
	else {
		QString text_to_layout = text;
		//qfWarning() << "length: " << text.length() << " text: [" << text << "]\n" << text.toUtf8().toHex();
		bool text_item_should_be_created = true;
		style::CompiledTextStyle style;
		style::Text *p_text_style = effectiveTextStyle();
		if(p_text_style) {
			style = p_text_style->textStyle();
		}
		QFontMetricsF font_metrics = processor()->fontMetrics(style.font());
		QTextOption text_option;
		{
			if(isTextWrap())
				text_option.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
			//alignment_flags |= Qt::TextWordWrap;
			int al = textHAlign() | textVAlign();
			Qt::Alignment alignment_flags = (Qt::Alignment)al;
			text_option.setAlignment(alignment_flags);
		}
		Rect rendered_bounding_rect;
		/// velikost boundingRect je v mm, tak to prepocitej na body vystupniho zarizeni
		rendered_bounding_rect = qmlwidgets::graphics::mm2device(bounding_rect, processor()->paintDevice());

		bool render_check_mark = false;
		QRegExp rx = ReportItemMetaPaint::checkReportSubstitutionRegExp;
		if(rx.exactMatch(text_to_layout)) {
			//bool check_on = rx.capturedTexts().value(1) == "1";
			rendered_bounding_rect = font_metrics.boundingRect('X');
			render_check_mark = true;
			m_indexToPrint += text_to_layout.length();
		}
		else {
			if(text_to_layout.isEmpty()) {
				/// neni omitEmptyString, takze i prazdnej text vyrendruj alespon jako mezeru aby se na to dalo treba kliknout
				text_to_layout = ' ';
			}

			//text.replace(ReportItemMetaPaint::checkOnReportSubstitution, "X");
			//text.replace(ReportItemMetaPaint::checkOffReportSubstitution, "X");
			//qfInfo().noSpace().color(QFLog::Green) << "index to print: " << indexToPrint << " text: '" << text << "'";
			//qfInfo() << "bounding rect:" << bounding_rect.toString();
			//qfWarning() << "device physical DPI:" << processor()->paintDevice()->physicalDpiX() << processor()->paintDevice()->physicalDpiY();
			//qfWarning().noSpace() << "'" << text << "' font metrics: " << br.toString();

			//QString text = element.text().simplified().replace("\\n", "\n");
			//qfInfo() << "br:" << br.toString();
			//Rect br_debug = br;
			//bool splitted = false;
			/// do layout
			{
				qreal leading = font_metrics.leading();
				qreal height = 0;
				qreal width = 0;
				textLayout.setFont(style.font());
				textLayout.setTextOption(text_option);
				textLayout.setText(text_to_layout);
				textLayout.beginLayout();
				bool finished = false;
				while (!finished) {
					QTextLine line = textLayout.createLine();
					finished = !line.isValid();
					if(!finished) {
						line.setLineWidth(rendered_bounding_rect.width()); /// setWidth() nastavi spravne line.height(), proto musi byt pred merenim popsane vysky.

						if((line.textLength() == 0) && (line.textStart() + line.textLength() == text_to_layout.length())) {
							/// nevim kde je chyba, pri vicerakovych textech mi to pridava jeden prazdnej radek na konec, takhle se tomu snazim zabranit (Qt 4.6.3)
							finished = true;
						}
						else {
							qreal interline_space = (height > 0)? leading: 0;
							if(height + interline_space + line.height() > rendered_bounding_rect.height()) {
								res = PR_PrintAgainOnNextPage;
								if(height == 0) {
									/// nevejde se ani jeden radek
									text_item_should_be_created = false;
									break;
								}
								else {
									/// neco se preci jenom veslo
									int pos = line.textStart();
									m_indexToPrint += pos;
									break;
								}
							}
							height += interline_space;
							line.setPosition(QPointF(0., height));
							height += line.height();
							width = qMax(width, line.naturalTextWidth());
						}
					}
					if(finished) {
						m_indexToPrint = printedText.length();
					}
				}
				textLayout.endLayout();
				rendered_bounding_rect.setWidth(width);
				rendered_bounding_rect.setHeight(height);
			}
		}
		/// velikost boundingRect je v bodech vystupniho zarizeni, tak to prepocitej na mm
		rendered_bounding_rect = qmlwidgets::graphics::device2mm(rendered_bounding_rect, processor()->paintDevice());
		/// rendered rect is left aligned, if text is reight aligned or centered, the ReportItemMetaPaintText::paint() does it
		if(text_item_should_be_created ) {
			ReportItemMetaPaintText *mt;
			if(render_check_mark )
				mt = new ReportItemMetaPaintCheck(out, this);
			else {
				mt = new ReportItemMetaPaintText(out, this);
				mt->sqlId = sql_id;
				//--mt->editGrants = elementAttribute("editGrants");
			}
			//qfInfo() << "creating item:" << mt;
			mt->pen = style.pen();
			mt->font = style.font();
			mt->text = text.mid(0, m_indexToPrint - initial_index_to_print);
			//qfWarning() << "text:" << text;
			mt->textOption = text_option;
			mt->renderedRect = rendered_bounding_rect;
			mt->renderedRect.flags = designedRect.flags;
		}
		//qfDebug().color(QFLog::Green, QFLog::Red) << "\tleading:" << processor()->fontMetrics(style.font).leading() << "\theight:" << processor()->fontMetrics(style.font).height();
		qfDebug() << "\tchild rendered rect:" << rendered_bounding_rect.toString();
	}
	qfDebug() << "\t<<< CHILDREN paraText return:" << res.toString();
	return res;
}
Exemple #24
0
void QSvgText::draw(QPainter *p, QSvgExtraStates &states)
{
    applyStyle(p, states);
    qreal oldOpacity = p->opacity();
    p->setOpacity(oldOpacity * states.fillOpacity);

    // Force the font to have a size of 100 pixels to avoid truncation problems
    // when the font is very small.
    qreal scale = 100.0 / p->font().pointSizeF();
    Qt::Alignment alignment = states.textAnchor;

    QTransform oldTransform = p->worldTransform();
    p->scale(1 / scale, 1 / scale);

    qreal y = 0;
    bool initial = true;
    qreal px = m_coord.x() * scale;
    qreal py = m_coord.y() * scale;
    QSizeF scaledSize = m_size * scale;

    if (m_type == TEXTAREA) {
        if (alignment == Qt::AlignHCenter)
            px += scaledSize.width() / 2;
        else if (alignment == Qt::AlignRight)
            px += scaledSize.width();
    }

    QRectF bounds;
    if (m_size.height() != 0)
        bounds = QRectF(0, py, 1, scaledSize.height()); // x and width are not used.

    bool appendSpace = false;
    QVector<QString> paragraphs;
    QStack<QTextCharFormat> formats;
    QVector<QList<QTextLayout::FormatRange> > formatRanges;
    paragraphs.push_back(QString());
    formatRanges.push_back(QList<QTextLayout::FormatRange>());

    for (int i = 0; i < m_tspans.size(); ++i) {
        if (m_tspans[i] == LINEBREAK) {
            if (m_type == TEXTAREA) {
                if (paragraphs.back().isEmpty()) {
                    QFont font = p->font();
                    font.setPixelSize(font.pointSizeF() * scale);

                    QTextLayout::FormatRange range;
                    range.start = 0;
                    range.length = 1;
                    range.format.setFont(font);
                    formatRanges.back().append(range);

                    paragraphs.back().append(QLatin1Char(' '));;
                }
                appendSpace = false;
                paragraphs.push_back(QString());
                formatRanges.push_back(QList<QTextLayout::FormatRange>());
            }
        } else {
            WhitespaceMode mode = m_tspans[i]->whitespaceMode();
            m_tspans[i]->applyStyle(p, states);

            QFont font = p->font();
            font.setPixelSize(font.pointSizeF() * scale);

            QString newText(m_tspans[i]->text());
            newText.replace(QLatin1Char('\t'), QLatin1Char(' '));
            newText.replace(QLatin1Char('\n'), QLatin1Char(' '));

            bool prependSpace = !appendSpace && !m_tspans[i]->isTspan() && (mode == Default) && !paragraphs.back().isEmpty() && newText.startsWith(QLatin1Char(' '));
            if (appendSpace || prependSpace)
                paragraphs.back().append(QLatin1Char(' '));

            bool appendSpaceNext = (!m_tspans[i]->isTspan() && (mode == Default) && newText.endsWith(QLatin1Char(' ')));

            if (mode == Default) {
                newText = newText.simplified();
                if (newText.isEmpty())
                    appendSpaceNext = false;
            }

            QTextLayout::FormatRange range;
            range.start = paragraphs.back().length();
            range.length = newText.length();
            range.format.setFont(font);
            range.format.setTextOutline(p->pen());
            range.format.setForeground(p->brush());

            if (appendSpace) {
                Q_ASSERT(!formatRanges.back().isEmpty());
                ++formatRanges.back().back().length;
            } else if (prependSpace) {
                --range.start;
                ++range.length;
            }
            formatRanges.back().append(range);

            appendSpace = appendSpaceNext;
            paragraphs.back() += newText;

            m_tspans[i]->revertStyle(p, states);
        }
    }

    if (states.svgFont) {
        // SVG fonts not fully supported...
        QString text = paragraphs.front();
        for (int i = 1; i < paragraphs.size(); ++i) {
            text.append(QLatin1Char('\n'));
            text.append(paragraphs[i]);
        }
        states.svgFont->draw(p, m_coord * scale, text, p->font().pointSizeF() * scale, states.textAnchor);
    } else {
        for (int i = 0; i < paragraphs.size(); ++i) {
            QTextLayout tl(paragraphs[i]);
            QTextOption op = tl.textOption();
            op.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
            tl.setTextOption(op);
            tl.setAdditionalFormats(formatRanges[i]);
            tl.beginLayout();

            forever {
                QTextLine line = tl.createLine();
                if (!line.isValid())
                    break;
                if (m_size.width() != 0)
                    line.setLineWidth(scaledSize.width());
            }
            tl.endLayout();

            bool endOfBoundsReached = false;
            for (int i = 0; i < tl.lineCount(); ++i) {
                QTextLine line = tl.lineAt(i);

                qreal x = 0;
                if (alignment == Qt::AlignHCenter)
                    x -= 0.5 * line.naturalTextWidth();
                else if (alignment == Qt::AlignRight)
                    x -= line.naturalTextWidth();

                if (initial && m_type == TEXT)
                    y -= line.ascent();
                initial = false;

                line.setPosition(QPointF(x, y));

                // Check if the current line fits into the bounding rectangle.
                if ((m_size.width() != 0 && line.naturalTextWidth() > scaledSize.width())
                    || (m_size.height() != 0 && y + line.height() > scaledSize.height())) {
                    // I need to set the bounds height to 'y-epsilon' to avoid drawing the current
                    // line. Since the font is scaled to 100 units, 1 should be a safe epsilon.
                    bounds.setHeight(y - 1);
                    endOfBoundsReached = true;
                    break;
                }

                y += 1.1 * line.height();
            }
            tl.draw(p, QPointF(px, py), QVector<QTextLayout::FormatRange>(), bounds);

            if (endOfBoundsReached)
                break;
        }
    }

    p->setWorldTransform(oldTransform, false);
    p->setOpacity(oldOpacity);
    revertStyle(p, states);
}
// FIXME: we need to figure out a way to derive from Fm::FolderItemDelegate to avoid code duplication.
void DesktopItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const {
  Q_ASSERT(index.isValid());
  QStyleOptionViewItemV4 opt = option;
  initStyleOption(&opt, index);

  painter->save();
  painter->setClipRect(option.rect);

  opt.decorationAlignment = Qt::AlignHCenter | Qt::AlignTop;
  opt.displayAlignment = Qt::AlignTop | Qt::AlignHCenter;

  // draw the icon
  QIcon::Mode iconMode;
  if(opt.state & QStyle::State_Enabled) {
    if(opt.state & QStyle::State_Selected)
      iconMode = QIcon::Selected;
    else {
      iconMode = QIcon::Normal;
    }
  }
  else
    iconMode = QIcon::Disabled;
  QPoint iconPos(opt.rect.x() + (opt.rect.width() - opt.decorationSize.width()) / 2, opt.rect.y());
  QPixmap pixmap = opt.icon.pixmap(opt.decorationSize, iconMode);
  painter->drawPixmap(iconPos, pixmap);

  // draw some emblems for the item if needed
  // we only support symlink emblem at the moment
  FmFileInfo* file = static_cast<FmFileInfo*>(index.data(Fm::FolderModel::FileInfoRole).value<void*>());
  if(file) {
    if(fm_file_info_is_symlink(file)) {
      painter->drawPixmap(iconPos, symlinkIcon_.pixmap(opt.decorationSize / 2, iconMode));
    }
  }

  // draw text
  QRectF textRect(opt.rect.x(), opt.rect.y() + opt.decorationSize.height(), opt.rect.width(), opt.rect.height() - opt.decorationSize.height());
  QTextLayout layout(opt.text, opt.font);

  QTextOption textOption;
  textOption.setAlignment(opt.displayAlignment);
  textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
  textOption.setTextDirection(opt.direction);
  layout.setTextOption(textOption);
  qreal height = 0;
  qreal width = 0;
  int visibleLines = 0;
  layout.beginLayout();
  QString elidedText;

  for(;;) {
    QTextLine line = layout.createLine();
    if(!line.isValid())
      break;
    line.setLineWidth(textRect.width());
    height += opt.fontMetrics.leading();
    line.setPosition(QPointF(0, height));
    if((height + line.height() + textRect.y()) > textRect.bottom()) {
      // if part of this line falls outside the textRect, ignore it and quit.
      QTextLine lastLine = layout.lineAt(visibleLines - 1);
      elidedText = opt.text.mid(lastLine.textStart());
      elidedText = opt.fontMetrics.elidedText(elidedText, opt.textElideMode, textRect.width());
      break;
    }
    height += line.height();
    width = qMax(width, line.naturalTextWidth());
    ++ visibleLines;
  }
  layout.endLayout();
  QRectF boundRect = layout.boundingRect();
  boundRect.setWidth(width);
  boundRect.moveTo(textRect.x() + (textRect.width() - width)/2, textRect.y());
  if((opt.state & QStyle::State_Selected) && opt.widget) {
    QPalette palette = opt.widget->palette();
    // qDebug("w: %f, h:%f, m:%f", boundRect.width(), boundRect.height(), layout.minimumWidth());
    painter->fillRect(boundRect, palette.highlight());
  }
  else { // only draw shadow for non-selected items
    // draw shadow, FIXME: is it possible to use QGraphicsDropShadowEffect here?
    QPen prevPen = painter->pen();
    painter->setPen(QPen(shadowColor_));
    for(int i = 0; i < visibleLines; ++i) {
      QTextLine line = layout.lineAt(i);
      if(i == (visibleLines - 1) && !elidedText.isEmpty()) { // the last line, draw elided text
        QPointF pos(textRect.x() + line.position().x() + 1, textRect.y() + line.y() + line.ascent() + 1);
        painter->drawText(pos, elidedText);
      }
      else {
        line.draw(painter, textRect.topLeft() + QPointF(1, 1));
      }
    }
    painter->setPen(prevPen);
  }

  // draw text
  for(int i = 0; i < visibleLines; ++i) {
    QTextLine line = layout.lineAt(i);
    if(i == (visibleLines - 1) && !elidedText.isEmpty()) { // the last line, draw elided text
      QPointF pos(textRect.x() + line.position().x(), textRect.y() + line.y() + line.ascent());
      painter->drawText(pos, elidedText);
    }
    else {
      line.draw(painter, textRect.topLeft());
    }
  }

  if(opt.state & QStyle::State_HasFocus) {
    // FIXME: draw focus rect
  }
  painter->restore();
}
Exemple #26
0
void QSvgText::draw(QPainter *p, QSvgExtraStates &states)
{
    applyStyle(p, states);

    QSvgFontStyle *fontStyle = static_cast<QSvgFontStyle*>(
        styleProperty(QSvgStyleProperty::FONT));
    if (fontStyle && fontStyle->svgFont()) {
        // SVG fonts not fully supported...
        QString text = m_paragraphs.front();
        for (int i = 1; i < m_paragraphs.size(); ++i) {
            text.append(QLatin1Char('\n'));
            text.append(m_paragraphs[i]);
        }
        fontStyle->svgFont()->draw(p, m_coord, text, fontStyle->pointSize(), m_textAlignment);
        revertStyle(p, states);
        return;
    }

    // Scale the font to its correct size.
    QTransform oldTransform = p->worldTransform();
    p->scale(1 / m_scale, 1 / m_scale);

    qreal y = 0;
    bool initial = true;
    qreal px = m_coord.x() * m_scale;
    qreal py = m_coord.y() * m_scale;
    QSizeF scaledSize = m_size * m_scale;

    if (m_type == TEXTAREA) {
        if (m_textAlignment == Qt::AlignHCenter)
            px += scaledSize.width() / 2;
        else if (m_textAlignment == Qt::AlignRight)
            px += scaledSize.width();
    }

    QRectF bounds;
    if (m_size.height() != 0)
        bounds = QRectF(0, 0, 1, scaledSize.height());

    for (int i = 0; i < m_paragraphs.size(); ++i) {
        QTextLayout tl(m_paragraphs[i]);
        QTextOption op = tl.textOption();
        op.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
        tl.setTextOption(op);
        tl.setAdditionalFormats(m_formatRanges[i]);
        tl.beginLayout();
        forever {
            QTextLine line = tl.createLine();
            if (!line.isValid())
                break;

            if (m_size.width() != 0)
                line.setLineWidth(scaledSize.width());
        }
        tl.endLayout();

        bool endOfBoundsReached = false;
        for (int i = 0; i < tl.lineCount(); ++i) {
            QTextLine line = tl.lineAt(i);

            qreal x = 0;
            if (m_textAlignment == Qt::AlignHCenter)
                x -= line.naturalTextWidth() / 2;
            else if (m_textAlignment == Qt::AlignRight)
                x -= line.naturalTextWidth();

            if (initial && m_type == TEXT)
                y -= line.ascent();
            initial = false;

            line.setPosition(QPointF(x, y));
            if ((m_size.width() != 0 && line.naturalTextWidth() > scaledSize.width())
                || (m_size.height() != 0 && y + line.height() > scaledSize.height())) {
                bounds.setHeight(y);
                endOfBoundsReached = true;
                break;
            }

            y += 1.1 * line.height();
        }
        tl.draw(p, QPointF(px, py), QVector<QTextLayout::FormatRange>(), bounds);

        if (endOfBoundsReached)
            break;
    }

    p->setWorldTransform(oldTransform, false);
    revertStyle(p, states);
}
void KStandardItemListWidget::updateIconsLayoutTextCache()
{
    //      +------+
    //      | Icon |
    //      +------+
    //
    //    Name role that
    // might get wrapped above
    //    several lines.
    //  Additional role 1
    //  Additional role 2

    const QHash<QByteArray, QVariant> values = data();

    const KItemListStyleOption& option = styleOption();
    const qreal padding = option.padding;
    const qreal maxWidth = size().width() - 2 * padding;
    const qreal widgetHeight = size().height();
    const qreal lineSpacing = m_customizedFontMetrics.lineSpacing();

    // Initialize properties for the "text" role. It will be used as anchor
    // for initializing the position of the other roles.
    TextInfo* nameTextInfo = m_textInfo.value("text");
    const QString nameText = KStringHandler::preProcessWrap(values["text"].toString());
    nameTextInfo->staticText.setText(nameText);

    // Calculate the number of lines required for the name and the required width
    qreal nameWidth = 0;
    qreal nameHeight = 0;
    QTextLine line;

    const int additionalRolesCount = qMax(visibleRoles().count() - 1, 0);
    const int maxNameLines = (option.maxTextSize.height() / int(lineSpacing)) - additionalRolesCount;

    QTextLayout layout(nameTextInfo->staticText.text(), m_customizedFont);
    layout.setTextOption(nameTextInfo->staticText.textOption());
    layout.beginLayout();
    int nameLineIndex = 0;
    while ((line = layout.createLine()).isValid()) {
        line.setLineWidth(maxWidth);
        nameWidth = qMax(nameWidth, line.naturalTextWidth());
        nameHeight += line.height();

        ++nameLineIndex;
        if (nameLineIndex == maxNameLines) {
            // The maximum number of textlines has been reached. If this is
            // the case provide an elided text if necessary.
            const int textLength = line.textStart() + line.textLength();
            if (textLength < nameText.length()) {
                // Elide the last line of the text
                QString lastTextLine = nameText.mid(line.textStart(), line.textLength());
                lastTextLine = m_customizedFontMetrics.elidedText(lastTextLine,
                                                                  Qt::ElideRight,
                                                                  line.naturalTextWidth() - 1);
                const QString elidedText = nameText.left(line.textStart()) + lastTextLine;
                nameTextInfo->staticText.setText(elidedText);
            }
            break;
        }
    }
    layout.endLayout();

    // Use one line for each additional information
    nameTextInfo->staticText.setTextWidth(maxWidth);
    nameTextInfo->pos = QPointF(padding, widgetHeight -
                                         nameHeight -
                                         additionalRolesCount * lineSpacing -
                                         padding);
    m_textRect = QRectF(padding + (maxWidth - nameWidth) / 2,
                        nameTextInfo->pos.y(),
                        nameWidth,
                        nameHeight);

    // Calculate the position for each additional information
    qreal y = nameTextInfo->pos.y() + nameHeight;
    foreach (const QByteArray& role, m_sortedVisibleRoles) {
        if (role == "text") {
            continue;
        }

        const QString text = roleText(role, values);
        TextInfo* textInfo = m_textInfo.value(role);
        textInfo->staticText.setText(text);

        qreal requiredWidth = 0;

        QTextLayout layout(text, m_customizedFont);
        QTextOption textOption;
        textOption.setWrapMode(QTextOption::NoWrap);
        layout.setTextOption(textOption);

        layout.beginLayout();
        QTextLine textLine = layout.createLine();
        if (textLine.isValid()) {
            textLine.setLineWidth(maxWidth);
            requiredWidth = textLine.naturalTextWidth();
            if (requiredWidth > maxWidth) {
                const QString elidedText = m_customizedFontMetrics.elidedText(text, Qt::ElideRight, maxWidth);
                textInfo->staticText.setText(elidedText);
                requiredWidth = m_customizedFontMetrics.width(elidedText);
            } else if (role == "rating") {
		// Use the width of the rating pixmap, because the rating text is empty.
                requiredWidth = m_rating.width();
            }
        }
        layout.endLayout();

        textInfo->pos = QPointF(padding, y);
        textInfo->staticText.setTextWidth(maxWidth);

        const QRectF textRect(padding + (maxWidth - requiredWidth) / 2, y, requiredWidth, lineSpacing);
        m_textRect |= textRect;

        y += lineSpacing;
    }

    // Add a padding to the text rectangle
    m_textRect.adjust(-padding, -padding, padding, padding);
}
QSizeF KStandardItemListWidgetInformant::itemSizeHint(int index, const KItemListView* view) const
{
    const QHash<QByteArray, QVariant> values = view->model()->data(index);
    const KItemListStyleOption& option = view->styleOption();
    const int additionalRolesCount = qMax(view->visibleRoles().count() - 1, 0);

    switch (static_cast<const KStandardItemListView*>(view)->itemLayout()) {
    case KStandardItemListWidget::IconsLayout: {
        const QString text = KStringHandler::preProcessWrap(values["text"].toString());

        const qreal itemWidth = view->itemSize().width();
        const qreal maxWidth = itemWidth - 2 * option.padding;
        QTextLine line;

        // Calculate the number of lines required for wrapping the name
        QTextOption textOption(Qt::AlignHCenter);
        textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);

        qreal textHeight = 0;
        QTextLayout layout(text, option.font);
        layout.setTextOption(textOption);
        layout.beginLayout();
        while ((line = layout.createLine()).isValid()) {
            line.setLineWidth(maxWidth);
            line.naturalTextWidth();
            textHeight += line.height();
        }
        layout.endLayout();

        // Add one line for each additional information
        textHeight += additionalRolesCount * option.fontMetrics.lineSpacing();

        const qreal maxTextHeight = option.maxTextSize.height();
        if (maxTextHeight > 0 && textHeight > maxTextHeight) {
            textHeight = maxTextHeight;
        }

        return QSizeF(itemWidth, textHeight + option.iconSize + option.padding * 3);
    }

    case KStandardItemListWidget::CompactLayout: {
        // For each row exactly one role is shown. Calculate the maximum required width that is necessary
        // to show all roles without horizontal clipping.
        qreal maximumRequiredWidth = 0.0;

        foreach (const QByteArray& role, view->visibleRoles()) {
            const QString text = roleText(role, values);
            const qreal requiredWidth = option.fontMetrics.width(text);
            maximumRequiredWidth = qMax(maximumRequiredWidth, requiredWidth);
        }

        qreal width = option.padding * 4 + option.iconSize + maximumRequiredWidth;
        const qreal maxWidth = option.maxTextSize.width();
        if (maxWidth > 0 && width > maxWidth) {
            width = maxWidth;
        }
        const qreal height = option.padding * 2 + qMax(option.iconSize, (1 + additionalRolesCount) * option.fontMetrics.lineSpacing());
        return QSizeF(width, height);
    }

    case KStandardItemListWidget::DetailsLayout: {
        const qreal height = option.padding * 2 + qMax(option.iconSize, option.fontMetrics.height());
        return QSizeF(-1, height);
    }

    default:
        Q_ASSERT(false);
        break;
    }

    return QSize();
}
// if painter is nullptr, the method calculate the bounding rectangle of the text and save it to textRect
void FolderItemDelegate::drawText(QPainter* painter, QStyleOptionViewItemV4& opt, QRectF& textRect) const {
  QTextLayout layout(opt.text, opt.font);
  QTextOption textOption;
  textOption.setAlignment(opt.displayAlignment);
  textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
  textOption.setTextDirection(opt.direction);
  layout.setTextOption(textOption);
  qreal height = 0;
  qreal width = 0;
  int visibleLines = 0;
  layout.beginLayout();
  QString elidedText;
  for(;;) {
    QTextLine line = layout.createLine();
    if(!line.isValid())
      break;
    line.setLineWidth(textRect.width());
    height += opt.fontMetrics.leading();
    line.setPosition(QPointF(0, height));
    if((height + line.height() + textRect.y()) > textRect.bottom()) {
      // if part of this line falls outside the textRect, ignore it and quit.
      QTextLine lastLine = layout.lineAt(visibleLines - 1);
      elidedText = opt.text.mid(lastLine.textStart());
      elidedText = opt.fontMetrics.elidedText(elidedText, opt.textElideMode, textRect.width());
      if(visibleLines == 1) // this is the only visible line
        width = textRect.width();
      break;
    }
    height += line.height();
    width = qMax(width, line.naturalTextWidth());
    ++ visibleLines;
  }
  layout.endLayout();

  // draw background for selected item
  QRectF boundRect = layout.boundingRect();
  //qDebug() << "bound rect: " << boundRect << "width: " << width;
  boundRect.setWidth(width);
  boundRect.moveTo(textRect.x() + (textRect.width() - width)/2, textRect.y());

  if(!painter) { // no painter, calculate the bounding rect only
    textRect = boundRect;
    return;
  }

  QPalette::ColorGroup cg = opt.state & QStyle::State_Enabled ? QPalette::Normal : QPalette::Disabled;
  if(opt.state & QStyle::State_Selected) {
    painter->fillRect(boundRect, opt.palette.highlight());
    painter->setPen(opt.palette.color(cg, QPalette::HighlightedText));
  }
  else
    painter->setPen(opt.palette.color(cg, QPalette::Text));

  // draw text
  for(int i = 0; i < visibleLines; ++i) {
    QTextLine line = layout.lineAt(i);
    if(i == (visibleLines - 1) && !elidedText.isEmpty()) { // the last line, draw elided text
      QPointF pos(textRect.x() + line.position().x(), textRect.y() + line.y() + line.ascent());
      painter->drawText(pos, elidedText);
    }
    else {
      line.draw(painter, textRect.topLeft());
    }
  }

  if(opt.state & QStyle::State_HasFocus) {
    // draw focus rect
    QStyleOptionFocusRect o;
    o.QStyleOption::operator=(opt);
    o.rect = boundRect.toRect(); // subElementRect(SE_ItemViewItemFocusRect, vopt, widget);
    o.state |= QStyle::State_KeyboardFocusChange;
    o.state |= QStyle::State_Item;
    QPalette::ColorGroup cg = (opt.state & QStyle::State_Enabled)
                  ? QPalette::Normal : QPalette::Disabled;
    o.backgroundColor = opt.palette.color(cg, (opt.state & QStyle::State_Selected)
                                  ? QPalette::Highlight : QPalette::Window);
    if (const QWidget* widget = opt.widget) {
      QStyle* style = widget->style() ? widget->style() : qApp->style();
      style->drawPrimitive(QStyle::PE_FrameFocusRect, &o, painter, widget);
    }
  }
}
void TextDocumentLayout::layoutBlock(const QTextBlock &block)
{
    QTextDocument *doc = document();
    qreal margin = doc->documentMargin();
    qreal blockMaximumWidth = 0;

    qreal height = 0;
    QTextLayout *tl = block.layout();
    QTextOption option = doc->defaultTextOption();
    tl->setTextOption(option);

    int extraMargin = 0;
    if (option.flags() & QTextOption::AddSpaceForLineAndParagraphSeparators) {
        QFontMetrics fm(block.charFormat().font());
        extraMargin += fm.width(QChar(0x21B5));
    }
    tl->beginLayout();
    qreal availableWidth = d->width;
    if (availableWidth <= 0) {
        availableWidth = qreal(INT_MAX); // similar to text edit with pageSize.width == 0
    }
    availableWidth -= 2*margin + extraMargin;
    qreal indentMargin = 0;
    while (1) {
        QTextLine line = tl->createLine();
        if (!line.isValid())
            break;
        line.setLeadingIncluded(true);
        line.setLineWidth(availableWidth - indentMargin);
        line.setPosition(QPointF(margin + indentMargin, height));
        if(!height) //enter only in the first iteration
        {
            indentMargin = indentWidth(block);
        }
        height += line.height();
        blockMaximumWidth = qMax(blockMaximumWidth, line.naturalTextWidth() + 2*margin);
    }
    tl->endLayout();

    int previousLineCount = doc->lineCount();
    const_cast<QTextBlock&>(block).setLineCount(block.isVisible() ? tl->lineCount() : 0);
    int lineCount = doc->lineCount();

    bool emitDocumentSizeChanged = previousLineCount != lineCount;
    if (blockMaximumWidth > d->maximumWidth) {
        // new longest line
        d->maximumWidth = blockMaximumWidth;
        d->maximumWidthBlockNumber = block.blockNumber();
        emitDocumentSizeChanged = true;
    } else if (block.blockNumber() == d->maximumWidthBlockNumber && blockMaximumWidth < d->maximumWidth) {
        // longest line shrinking
        QTextBlock b = doc->firstBlock();
        d->maximumWidth = 0;
        QTextBlock maximumBlock;
        while (b.isValid()) {
            qreal blockMaximumWidth = blockWidth(b);
            if (blockMaximumWidth > d->maximumWidth) {
                d->maximumWidth = blockMaximumWidth;
                maximumBlock = b;
            }
            b = b.next();
        }
        if (maximumBlock.isValid()) {
            d->maximumWidthBlockNumber = maximumBlock.blockNumber();
            emitDocumentSizeChanged = true;
        }
    }
    if (emitDocumentSizeChanged)// && !d->blockDocumentSizeChanged)
        emit documentSizeChanged(documentSize());

    emit updateBlock(block);
}