demos/shared/arthurwidgets.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/shared/arthurwidgets.cpp	Mon Jan 11 14:00:40 2010 +0000
@@ -0,0 +1,371 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the demonstration applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file.  Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights.  These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "arthurwidgets.h"
+#include <QApplication>
+#include <QPainter>
+#include <QPainterPath>
+#include <QPixmapCache>
+#include <QtEvents>
+#include <QTextDocument>
+#include <QAbstractTextDocumentLayout>
+#include <QFile>
+#include <QTextBrowser>
+#include <QBoxLayout>
+
+#include <private/qpixmapdata_p.h>
+
+extern QPixmap cached(const QString &img);
+
+ArthurFrame::ArthurFrame(QWidget *parent)
+    : QWidget(parent)
+    , m_prefer_image(false)
+{
+#ifdef QT_OPENGL_SUPPORT
+    glw = 0;
+    m_use_opengl = false;
+    QGLFormat f = QGLFormat::defaultFormat();
+    f.setSampleBuffers(true);
+    f.setStencil(true);
+    f.setAlpha(true);
+    f.setAlphaBufferSize(8);
+    QGLFormat::setDefaultFormat(f);
+#endif
+    m_document = 0;
+    m_show_doc = false;
+
+    m_tile = QPixmap(128, 128);
+    m_tile.fill(Qt::white);
+    QPainter pt(&m_tile);
+    QColor color(230, 230, 230);
+    pt.fillRect(0, 0, 64, 64, color);
+    pt.fillRect(64, 64, 64, 64, color);
+    pt.end();
+
+//     QPalette pal = palette();
+//     pal.setBrush(backgroundRole(), m_tile);
+//     setPalette(pal);
+
+#ifdef Q_WS_X11
+    QPixmap xRenderPixmap(1, 1);
+    m_prefer_image = xRenderPixmap.pixmapData()->classId() == QPixmapData::X11Class && !xRenderPixmap.x11PictureHandle();
+#endif
+}
+
+
+#ifdef QT_OPENGL_SUPPORT
+void ArthurFrame::enableOpenGL(bool use_opengl)
+{
+    m_use_opengl = use_opengl;
+
+    if (!glw) {
+        glw = new GLWidget(this);
+        glw->setAutoFillBackground(false);
+        glw->disableAutoBufferSwap();
+        QApplication::postEvent(this, new QResizeEvent(size(), size()));
+    }
+
+    if (use_opengl) {
+        glw->show();
+    } else {
+        glw->hide();
+    }
+
+    update();
+}
+#endif
+
+void ArthurFrame::paintEvent(QPaintEvent *e)
+{
+#ifdef Q_WS_QWS
+    static QPixmap *static_image = 0;
+#else
+    static QImage *static_image = 0;
+#endif
+    QPainter painter;
+    if (preferImage()
+#ifdef QT_OPENGL_SUPPORT
+        && !m_use_opengl
+#endif
+        ) {
+        if (!static_image || static_image->size() != size()) {
+            delete static_image;
+#ifdef Q_WS_QWS
+            static_image = new QPixmap(size());
+#else
+            static_image = new QImage(size(), QImage::Format_RGB32);
+#endif
+        }
+        painter.begin(static_image);
+
+        int o = 10;
+
+        QBrush bg = palette().brush(QPalette::Background);
+        painter.fillRect(0, 0, o, o, bg);
+        painter.fillRect(width() - o, 0, o, o, bg);
+        painter.fillRect(0, height() - o, o, o, bg);
+        painter.fillRect(width() - o, height() - o, o, o, bg);
+    } else {
+#ifdef QT_OPENGL_SUPPORT
+        if (m_use_opengl) {
+            painter.begin(glw);
+            painter.fillRect(QRectF(0, 0, glw->width(), glw->height()), palette().color(backgroundRole()));
+        } else {
+            painter.begin(this);
+        }
+#else
+        painter.begin(this);
+#endif
+    }
+
+    painter.setClipRect(e->rect());
+
+    painter.setRenderHint(QPainter::Antialiasing);
+
+    QPainterPath clipPath;
+
+    QRect r = rect();
+    qreal left = r.x() + 1;
+    qreal top = r.y() + 1;
+    qreal right = r.right();
+    qreal bottom = r.bottom();
+    qreal radius2 = 8 * 2;
+
+    clipPath.moveTo(right - radius2, top);
+    clipPath.arcTo(right - radius2, top, radius2, radius2, 90, -90);
+    clipPath.arcTo(right - radius2, bottom - radius2, radius2, radius2, 0, -90);
+    clipPath.arcTo(left, bottom - radius2, radius2, radius2, 270, -90);
+    clipPath.arcTo(left, top, radius2, radius2, 180, -90);
+    clipPath.closeSubpath();
+
+    painter.save();
+    painter.setClipPath(clipPath, Qt::IntersectClip);
+
+    painter.drawTiledPixmap(rect(), m_tile);
+
+    // client painting
+
+    paint(&painter);
+
+    painter.restore();
+
+    painter.save();
+    if (m_show_doc)
+        paintDescription(&painter);
+    painter.restore();
+
+    int level = 180;
+    painter.setPen(QPen(QColor(level, level, level), 2));
+    painter.setBrush(Qt::NoBrush);
+    painter.drawPath(clipPath);
+
+    if (preferImage()
+#ifdef QT_OPENGL_SUPPORT
+        && !m_use_opengl
+#endif
+        ) {
+        painter.end();
+        painter.begin(this);
+#ifdef Q_WS_QWS
+        painter.drawPixmap(e->rect(), *static_image, e->rect());
+#else
+        painter.drawImage(e->rect(), *static_image, e->rect());
+#endif
+    }
+
+#ifdef QT_OPENGL_SUPPORT
+    if (m_use_opengl && (inherits("PathDeformRenderer") || inherits("PathStrokeRenderer") || inherits("CompositionRenderer") || m_show_doc))
+        glw->swapBuffers();
+#endif
+}
+
+void ArthurFrame::resizeEvent(QResizeEvent *e)
+{
+#ifdef QT_OPENGL_SUPPORT
+    if (glw)
+        glw->setGeometry(0, 0, e->size().width()-1, e->size().height()-1);
+#endif
+    QWidget::resizeEvent(e);
+}
+
+void ArthurFrame::setDescriptionEnabled(bool enabled)
+{
+    if (m_show_doc != enabled) {
+        m_show_doc = enabled;
+        emit descriptionEnabledChanged(m_show_doc);
+        update();
+    }
+}
+
+void ArthurFrame::loadDescription(const QString &fileName)
+{
+    QFile textFile(fileName);
+    QString text;
+    if (!textFile.open(QFile::ReadOnly))
+        text = QString("Unable to load resource file: '%1'").arg(fileName);
+    else
+        text = textFile.readAll();
+    setDescription(text);
+}
+
+
+void ArthurFrame::setDescription(const QString &text)
+{
+    m_document = new QTextDocument(this);
+    m_document->setHtml(text);
+}
+
+void ArthurFrame::paintDescription(QPainter *painter)
+{
+    if (!m_document)
+        return;
+
+    int pageWidth = qMax(width() - 100, 100);
+    int pageHeight = qMax(height() - 100, 100);
+    if (pageWidth != m_document->pageSize().width()) {
+        m_document->setPageSize(QSize(pageWidth, pageHeight));
+    }
+
+    QRect textRect(width() / 2 - pageWidth / 2,
+                   height() / 2 - pageHeight / 2,
+                   pageWidth,
+                   pageHeight);
+    int pad = 10;
+    QRect clearRect = textRect.adjusted(-pad, -pad, pad, pad);
+    painter->setPen(Qt::NoPen);
+    painter->setBrush(QColor(0, 0, 0, 63));
+    int shade = 10;
+    painter->drawRect(clearRect.x() + clearRect.width() + 1,
+                      clearRect.y() + shade,
+                      shade,
+                      clearRect.height() + 1);
+    painter->drawRect(clearRect.x() + shade,
+                      clearRect.y() + clearRect.height() + 1,
+                      clearRect.width() - shade + 1,
+                      shade);
+
+    painter->setRenderHint(QPainter::Antialiasing, false);
+    painter->setBrush(QColor(255, 255, 255, 220));
+    painter->setPen(Qt::black);
+    painter->drawRect(clearRect);
+
+    painter->setClipRegion(textRect, Qt::IntersectClip);
+    painter->translate(textRect.topLeft());
+
+    QAbstractTextDocumentLayout::PaintContext ctx;
+
+    QLinearGradient g(0, 0, 0, textRect.height());
+    g.setColorAt(0, Qt::black);
+    g.setColorAt(0.9, Qt::black);
+    g.setColorAt(1, Qt::transparent);
+
+    QPalette pal = palette();
+    pal.setBrush(QPalette::Text, g);
+
+    ctx.palette = pal;
+    ctx.clip = QRect(0, 0, textRect.width(), textRect.height());
+    m_document->documentLayout()->draw(painter, ctx);
+}
+
+void ArthurFrame::loadSourceFile(const QString &sourceFile)
+{
+    m_sourceFileName = sourceFile;
+}
+
+void ArthurFrame::showSource()
+{
+    // Check for existing source
+    if (qFindChild<QTextBrowser *>(this))
+        return;
+
+    QString contents;
+    if (m_sourceFileName.isEmpty()) {
+        contents = QString("No source for widget: '%1'").arg(objectName());
+    } else {
+        QFile f(m_sourceFileName);
+        if (!f.open(QFile::ReadOnly))
+            contents = QString("Could not open file: '%1'").arg(m_sourceFileName);
+        else
+            contents = f.readAll();
+    }
+
+    contents.replace('&', "&amp;");
+    contents.replace('<', "&lt;");
+    contents.replace('>', "&gt;");
+
+    QStringList keywords;
+    keywords << "for " << "if " << "switch " << " int " << "#include " << "const"
+             << "void " << "uint " << "case " << "double " << "#define " << "static"
+             << "new" << "this";
+
+    foreach (QString keyword, keywords)
+        contents.replace(keyword, QLatin1String("<font color=olive>") + keyword + QLatin1String("</font>"));
+    contents.replace("(int ", "(<font color=olive><b>int </b></font>");
+
+    QStringList ppKeywords;
+    ppKeywords << "#ifdef" << "#ifndef" << "#if" << "#endif" << "#else";
+
+    foreach (QString keyword, ppKeywords)
+        contents.replace(keyword, QLatin1String("<font color=navy>") + keyword + QLatin1String("</font>"));
+
+    contents.replace(QRegExp("(\\d\\d?)"), QLatin1String("<font color=navy>\\1</font>"));
+
+    QRegExp commentRe("(//.+)\\n");
+    commentRe.setMinimal(true);
+    contents.replace(commentRe, QLatin1String("<font color=red>\\1</font>\n"));
+
+    QRegExp stringLiteralRe("(\".+\")");
+    stringLiteralRe.setMinimal(true);
+    contents.replace(stringLiteralRe, QLatin1String("<font color=green>\\1</font>"));
+
+    QString html = contents;
+    html.prepend("<html><pre>");
+    html.append("</pre></html>");
+
+    QTextBrowser *sourceViewer = new QTextBrowser(0);
+    sourceViewer->setWindowTitle("Source: " + m_sourceFileName.mid(5));
+    sourceViewer->setParent(this, Qt::Dialog);
+    sourceViewer->setAttribute(Qt::WA_DeleteOnClose);
+    sourceViewer->setLineWrapMode(QTextEdit::NoWrap);
+    sourceViewer->setHtml(html);
+    sourceViewer->resize(600, 600);
+    sourceViewer->show();
+}