[2] | 1 | /****************************************************************************
|
---|
| 2 | **
|
---|
[846] | 3 | ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
|
---|
[561] | 4 | ** All rights reserved.
|
---|
| 5 | ** Contact: Nokia Corporation ([email protected])
|
---|
[2] | 6 | **
|
---|
| 7 | ** This file is part of the demonstration applications of the Qt Toolkit.
|
---|
| 8 | **
|
---|
| 9 | ** $QT_BEGIN_LICENSE:LGPL$
|
---|
| 10 | ** Commercial Usage
|
---|
| 11 | ** Licensees holding valid Qt Commercial licenses may use this file in
|
---|
| 12 | ** accordance with the Qt Commercial License Agreement provided with the
|
---|
| 13 | ** Software or, alternatively, in accordance with the terms contained in
|
---|
| 14 | ** a written agreement between you and Nokia.
|
---|
| 15 | **
|
---|
| 16 | ** GNU Lesser General Public License Usage
|
---|
| 17 | ** Alternatively, this file may be used under the terms of the GNU Lesser
|
---|
| 18 | ** General Public License version 2.1 as published by the Free Software
|
---|
| 19 | ** Foundation and appearing in the file LICENSE.LGPL included in the
|
---|
| 20 | ** packaging of this file. Please review the following information to
|
---|
| 21 | ** ensure the GNU Lesser General Public License version 2.1 requirements
|
---|
| 22 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
---|
| 23 | **
|
---|
[561] | 24 | ** In addition, as a special exception, Nokia gives you certain additional
|
---|
| 25 | ** rights. These rights are described in the Nokia Qt LGPL Exception
|
---|
| 26 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
---|
[2] | 27 | **
|
---|
| 28 | ** GNU General Public License Usage
|
---|
| 29 | ** Alternatively, this file may be used under the terms of the GNU
|
---|
| 30 | ** General Public License version 3.0 as published by the Free Software
|
---|
| 31 | ** Foundation and appearing in the file LICENSE.GPL included in the
|
---|
| 32 | ** packaging of this file. Please review the following information to
|
---|
| 33 | ** ensure the GNU General Public License version 3.0 requirements will be
|
---|
| 34 | ** met: http://www.gnu.org/copyleft/gpl.html.
|
---|
| 35 | **
|
---|
[561] | 36 | ** If you have questions regarding the use of this file, please contact
|
---|
| 37 | ** Nokia at [email protected].
|
---|
[2] | 38 | ** $QT_END_LICENSE$
|
---|
| 39 | **
|
---|
| 40 | ****************************************************************************/
|
---|
| 41 |
|
---|
| 42 | #include "arthurwidgets.h"
|
---|
| 43 | #include <QApplication>
|
---|
| 44 | #include <QPainter>
|
---|
| 45 | #include <QPainterPath>
|
---|
| 46 | #include <QPixmapCache>
|
---|
| 47 | #include <QtEvents>
|
---|
| 48 | #include <QTextDocument>
|
---|
| 49 | #include <QAbstractTextDocumentLayout>
|
---|
| 50 | #include <QFile>
|
---|
| 51 | #include <QTextBrowser>
|
---|
| 52 | #include <QBoxLayout>
|
---|
| 53 |
|
---|
[514] | 54 | #ifdef Q_WS_X11
|
---|
[2] | 55 | #include <private/qpixmapdata_p.h>
|
---|
[514] | 56 | #endif
|
---|
[2] | 57 |
|
---|
| 58 | extern QPixmap cached(const QString &img);
|
---|
| 59 |
|
---|
| 60 | ArthurFrame::ArthurFrame(QWidget *parent)
|
---|
| 61 | : QWidget(parent)
|
---|
| 62 | , m_prefer_image(false)
|
---|
| 63 | {
|
---|
| 64 | #ifdef QT_OPENGL_SUPPORT
|
---|
| 65 | glw = 0;
|
---|
| 66 | m_use_opengl = false;
|
---|
| 67 | QGLFormat f = QGLFormat::defaultFormat();
|
---|
| 68 | f.setSampleBuffers(true);
|
---|
| 69 | f.setStencil(true);
|
---|
| 70 | f.setAlpha(true);
|
---|
| 71 | f.setAlphaBufferSize(8);
|
---|
| 72 | QGLFormat::setDefaultFormat(f);
|
---|
| 73 | #endif
|
---|
| 74 | m_document = 0;
|
---|
| 75 | m_show_doc = false;
|
---|
| 76 |
|
---|
| 77 | m_tile = QPixmap(128, 128);
|
---|
| 78 | m_tile.fill(Qt::white);
|
---|
| 79 | QPainter pt(&m_tile);
|
---|
| 80 | QColor color(230, 230, 230);
|
---|
| 81 | pt.fillRect(0, 0, 64, 64, color);
|
---|
| 82 | pt.fillRect(64, 64, 64, 64, color);
|
---|
| 83 | pt.end();
|
---|
| 84 |
|
---|
| 85 | // QPalette pal = palette();
|
---|
| 86 | // pal.setBrush(backgroundRole(), m_tile);
|
---|
| 87 | // setPalette(pal);
|
---|
| 88 |
|
---|
| 89 | #ifdef Q_WS_X11
|
---|
| 90 | QPixmap xRenderPixmap(1, 1);
|
---|
| 91 | m_prefer_image = xRenderPixmap.pixmapData()->classId() == QPixmapData::X11Class && !xRenderPixmap.x11PictureHandle();
|
---|
| 92 | #endif
|
---|
| 93 | }
|
---|
| 94 |
|
---|
| 95 |
|
---|
| 96 | #ifdef QT_OPENGL_SUPPORT
|
---|
| 97 | void ArthurFrame::enableOpenGL(bool use_opengl)
|
---|
| 98 | {
|
---|
| 99 | m_use_opengl = use_opengl;
|
---|
| 100 |
|
---|
| 101 | if (!glw) {
|
---|
| 102 | glw = new GLWidget(this);
|
---|
| 103 | glw->setAutoFillBackground(false);
|
---|
| 104 | glw->disableAutoBufferSwap();
|
---|
| 105 | QApplication::postEvent(this, new QResizeEvent(size(), size()));
|
---|
| 106 | }
|
---|
| 107 |
|
---|
| 108 | if (use_opengl) {
|
---|
| 109 | glw->show();
|
---|
| 110 | } else {
|
---|
| 111 | glw->hide();
|
---|
| 112 | }
|
---|
| 113 |
|
---|
| 114 | update();
|
---|
| 115 | }
|
---|
| 116 | #endif
|
---|
| 117 |
|
---|
| 118 | void ArthurFrame::paintEvent(QPaintEvent *e)
|
---|
| 119 | {
|
---|
| 120 | #ifdef Q_WS_QWS
|
---|
| 121 | static QPixmap *static_image = 0;
|
---|
| 122 | #else
|
---|
| 123 | static QImage *static_image = 0;
|
---|
| 124 | #endif
|
---|
| 125 | QPainter painter;
|
---|
| 126 | if (preferImage()
|
---|
| 127 | #ifdef QT_OPENGL_SUPPORT
|
---|
| 128 | && !m_use_opengl
|
---|
| 129 | #endif
|
---|
| 130 | ) {
|
---|
| 131 | if (!static_image || static_image->size() != size()) {
|
---|
| 132 | delete static_image;
|
---|
| 133 | #ifdef Q_WS_QWS
|
---|
| 134 | static_image = new QPixmap(size());
|
---|
| 135 | #else
|
---|
| 136 | static_image = new QImage(size(), QImage::Format_RGB32);
|
---|
| 137 | #endif
|
---|
| 138 | }
|
---|
| 139 | painter.begin(static_image);
|
---|
| 140 |
|
---|
| 141 | int o = 10;
|
---|
| 142 |
|
---|
| 143 | QBrush bg = palette().brush(QPalette::Background);
|
---|
| 144 | painter.fillRect(0, 0, o, o, bg);
|
---|
| 145 | painter.fillRect(width() - o, 0, o, o, bg);
|
---|
| 146 | painter.fillRect(0, height() - o, o, o, bg);
|
---|
| 147 | painter.fillRect(width() - o, height() - o, o, o, bg);
|
---|
| 148 | } else {
|
---|
| 149 | #ifdef QT_OPENGL_SUPPORT
|
---|
| 150 | if (m_use_opengl) {
|
---|
| 151 | painter.begin(glw);
|
---|
| 152 | painter.fillRect(QRectF(0, 0, glw->width(), glw->height()), palette().color(backgroundRole()));
|
---|
| 153 | } else {
|
---|
| 154 | painter.begin(this);
|
---|
| 155 | }
|
---|
| 156 | #else
|
---|
| 157 | painter.begin(this);
|
---|
| 158 | #endif
|
---|
| 159 | }
|
---|
| 160 |
|
---|
| 161 | painter.setClipRect(e->rect());
|
---|
| 162 |
|
---|
| 163 | painter.setRenderHint(QPainter::Antialiasing);
|
---|
| 164 |
|
---|
| 165 | QPainterPath clipPath;
|
---|
| 166 |
|
---|
| 167 | QRect r = rect();
|
---|
| 168 | qreal left = r.x() + 1;
|
---|
| 169 | qreal top = r.y() + 1;
|
---|
| 170 | qreal right = r.right();
|
---|
| 171 | qreal bottom = r.bottom();
|
---|
| 172 | qreal radius2 = 8 * 2;
|
---|
| 173 |
|
---|
| 174 | clipPath.moveTo(right - radius2, top);
|
---|
| 175 | clipPath.arcTo(right - radius2, top, radius2, radius2, 90, -90);
|
---|
| 176 | clipPath.arcTo(right - radius2, bottom - radius2, radius2, radius2, 0, -90);
|
---|
| 177 | clipPath.arcTo(left, bottom - radius2, radius2, radius2, 270, -90);
|
---|
| 178 | clipPath.arcTo(left, top, radius2, radius2, 180, -90);
|
---|
| 179 | clipPath.closeSubpath();
|
---|
| 180 |
|
---|
| 181 | painter.save();
|
---|
| 182 | painter.setClipPath(clipPath, Qt::IntersectClip);
|
---|
| 183 |
|
---|
| 184 | painter.drawTiledPixmap(rect(), m_tile);
|
---|
| 185 |
|
---|
| 186 | // client painting
|
---|
| 187 |
|
---|
| 188 | paint(&painter);
|
---|
| 189 |
|
---|
| 190 | painter.restore();
|
---|
| 191 |
|
---|
| 192 | painter.save();
|
---|
| 193 | if (m_show_doc)
|
---|
| 194 | paintDescription(&painter);
|
---|
| 195 | painter.restore();
|
---|
| 196 |
|
---|
| 197 | int level = 180;
|
---|
| 198 | painter.setPen(QPen(QColor(level, level, level), 2));
|
---|
| 199 | painter.setBrush(Qt::NoBrush);
|
---|
| 200 | painter.drawPath(clipPath);
|
---|
| 201 |
|
---|
| 202 | if (preferImage()
|
---|
| 203 | #ifdef QT_OPENGL_SUPPORT
|
---|
| 204 | && !m_use_opengl
|
---|
| 205 | #endif
|
---|
| 206 | ) {
|
---|
| 207 | painter.end();
|
---|
| 208 | painter.begin(this);
|
---|
| 209 | #ifdef Q_WS_QWS
|
---|
| 210 | painter.drawPixmap(e->rect(), *static_image, e->rect());
|
---|
| 211 | #else
|
---|
| 212 | painter.drawImage(e->rect(), *static_image, e->rect());
|
---|
| 213 | #endif
|
---|
| 214 | }
|
---|
| 215 |
|
---|
| 216 | #ifdef QT_OPENGL_SUPPORT
|
---|
| 217 | if (m_use_opengl && (inherits("PathDeformRenderer") || inherits("PathStrokeRenderer") || inherits("CompositionRenderer") || m_show_doc))
|
---|
| 218 | glw->swapBuffers();
|
---|
| 219 | #endif
|
---|
| 220 | }
|
---|
| 221 |
|
---|
| 222 | void ArthurFrame::resizeEvent(QResizeEvent *e)
|
---|
| 223 | {
|
---|
| 224 | #ifdef QT_OPENGL_SUPPORT
|
---|
| 225 | if (glw)
|
---|
| 226 | glw->setGeometry(0, 0, e->size().width()-1, e->size().height()-1);
|
---|
| 227 | #endif
|
---|
| 228 | QWidget::resizeEvent(e);
|
---|
| 229 | }
|
---|
| 230 |
|
---|
| 231 | void ArthurFrame::setDescriptionEnabled(bool enabled)
|
---|
| 232 | {
|
---|
| 233 | if (m_show_doc != enabled) {
|
---|
| 234 | m_show_doc = enabled;
|
---|
| 235 | emit descriptionEnabledChanged(m_show_doc);
|
---|
| 236 | update();
|
---|
| 237 | }
|
---|
| 238 | }
|
---|
| 239 |
|
---|
| 240 | void ArthurFrame::loadDescription(const QString &fileName)
|
---|
| 241 | {
|
---|
| 242 | QFile textFile(fileName);
|
---|
| 243 | QString text;
|
---|
| 244 | if (!textFile.open(QFile::ReadOnly))
|
---|
| 245 | text = QString("Unable to load resource file: '%1'").arg(fileName);
|
---|
| 246 | else
|
---|
| 247 | text = textFile.readAll();
|
---|
| 248 | setDescription(text);
|
---|
| 249 | }
|
---|
| 250 |
|
---|
| 251 |
|
---|
| 252 | void ArthurFrame::setDescription(const QString &text)
|
---|
| 253 | {
|
---|
| 254 | m_document = new QTextDocument(this);
|
---|
| 255 | m_document->setHtml(text);
|
---|
| 256 | }
|
---|
| 257 |
|
---|
| 258 | void ArthurFrame::paintDescription(QPainter *painter)
|
---|
| 259 | {
|
---|
| 260 | if (!m_document)
|
---|
| 261 | return;
|
---|
| 262 |
|
---|
| 263 | int pageWidth = qMax(width() - 100, 100);
|
---|
| 264 | int pageHeight = qMax(height() - 100, 100);
|
---|
| 265 | if (pageWidth != m_document->pageSize().width()) {
|
---|
| 266 | m_document->setPageSize(QSize(pageWidth, pageHeight));
|
---|
| 267 | }
|
---|
| 268 |
|
---|
| 269 | QRect textRect(width() / 2 - pageWidth / 2,
|
---|
| 270 | height() / 2 - pageHeight / 2,
|
---|
| 271 | pageWidth,
|
---|
| 272 | pageHeight);
|
---|
| 273 | int pad = 10;
|
---|
| 274 | QRect clearRect = textRect.adjusted(-pad, -pad, pad, pad);
|
---|
| 275 | painter->setPen(Qt::NoPen);
|
---|
| 276 | painter->setBrush(QColor(0, 0, 0, 63));
|
---|
| 277 | int shade = 10;
|
---|
| 278 | painter->drawRect(clearRect.x() + clearRect.width() + 1,
|
---|
| 279 | clearRect.y() + shade,
|
---|
| 280 | shade,
|
---|
| 281 | clearRect.height() + 1);
|
---|
| 282 | painter->drawRect(clearRect.x() + shade,
|
---|
| 283 | clearRect.y() + clearRect.height() + 1,
|
---|
| 284 | clearRect.width() - shade + 1,
|
---|
| 285 | shade);
|
---|
| 286 |
|
---|
| 287 | painter->setRenderHint(QPainter::Antialiasing, false);
|
---|
| 288 | painter->setBrush(QColor(255, 255, 255, 220));
|
---|
| 289 | painter->setPen(Qt::black);
|
---|
| 290 | painter->drawRect(clearRect);
|
---|
| 291 |
|
---|
| 292 | painter->setClipRegion(textRect, Qt::IntersectClip);
|
---|
| 293 | painter->translate(textRect.topLeft());
|
---|
| 294 |
|
---|
| 295 | QAbstractTextDocumentLayout::PaintContext ctx;
|
---|
| 296 |
|
---|
| 297 | QLinearGradient g(0, 0, 0, textRect.height());
|
---|
| 298 | g.setColorAt(0, Qt::black);
|
---|
| 299 | g.setColorAt(0.9, Qt::black);
|
---|
| 300 | g.setColorAt(1, Qt::transparent);
|
---|
| 301 |
|
---|
| 302 | QPalette pal = palette();
|
---|
| 303 | pal.setBrush(QPalette::Text, g);
|
---|
| 304 |
|
---|
| 305 | ctx.palette = pal;
|
---|
| 306 | ctx.clip = QRect(0, 0, textRect.width(), textRect.height());
|
---|
| 307 | m_document->documentLayout()->draw(painter, ctx);
|
---|
| 308 | }
|
---|
| 309 |
|
---|
| 310 | void ArthurFrame::loadSourceFile(const QString &sourceFile)
|
---|
| 311 | {
|
---|
| 312 | m_sourceFileName = sourceFile;
|
---|
| 313 | }
|
---|
| 314 |
|
---|
| 315 | void ArthurFrame::showSource()
|
---|
| 316 | {
|
---|
| 317 | // Check for existing source
|
---|
| 318 | if (qFindChild<QTextBrowser *>(this))
|
---|
| 319 | return;
|
---|
| 320 |
|
---|
| 321 | QString contents;
|
---|
| 322 | if (m_sourceFileName.isEmpty()) {
|
---|
| 323 | contents = QString("No source for widget: '%1'").arg(objectName());
|
---|
| 324 | } else {
|
---|
| 325 | QFile f(m_sourceFileName);
|
---|
| 326 | if (!f.open(QFile::ReadOnly))
|
---|
| 327 | contents = QString("Could not open file: '%1'").arg(m_sourceFileName);
|
---|
| 328 | else
|
---|
| 329 | contents = f.readAll();
|
---|
| 330 | }
|
---|
| 331 |
|
---|
| 332 | contents.replace('&', "&");
|
---|
| 333 | contents.replace('<', "<");
|
---|
| 334 | contents.replace('>', ">");
|
---|
| 335 |
|
---|
| 336 | QStringList keywords;
|
---|
| 337 | keywords << "for " << "if " << "switch " << " int " << "#include " << "const"
|
---|
| 338 | << "void " << "uint " << "case " << "double " << "#define " << "static"
|
---|
| 339 | << "new" << "this";
|
---|
| 340 |
|
---|
| 341 | foreach (QString keyword, keywords)
|
---|
| 342 | contents.replace(keyword, QLatin1String("<font color=olive>") + keyword + QLatin1String("</font>"));
|
---|
| 343 | contents.replace("(int ", "(<font color=olive><b>int </b></font>");
|
---|
| 344 |
|
---|
| 345 | QStringList ppKeywords;
|
---|
| 346 | ppKeywords << "#ifdef" << "#ifndef" << "#if" << "#endif" << "#else";
|
---|
| 347 |
|
---|
| 348 | foreach (QString keyword, ppKeywords)
|
---|
| 349 | contents.replace(keyword, QLatin1String("<font color=navy>") + keyword + QLatin1String("</font>"));
|
---|
| 350 |
|
---|
| 351 | contents.replace(QRegExp("(\\d\\d?)"), QLatin1String("<font color=navy>\\1</font>"));
|
---|
| 352 |
|
---|
| 353 | QRegExp commentRe("(//.+)\\n");
|
---|
| 354 | commentRe.setMinimal(true);
|
---|
| 355 | contents.replace(commentRe, QLatin1String("<font color=red>\\1</font>\n"));
|
---|
| 356 |
|
---|
| 357 | QRegExp stringLiteralRe("(\".+\")");
|
---|
| 358 | stringLiteralRe.setMinimal(true);
|
---|
| 359 | contents.replace(stringLiteralRe, QLatin1String("<font color=green>\\1</font>"));
|
---|
| 360 |
|
---|
| 361 | QString html = contents;
|
---|
| 362 | html.prepend("<html><pre>");
|
---|
| 363 | html.append("</pre></html>");
|
---|
| 364 |
|
---|
| 365 | QTextBrowser *sourceViewer = new QTextBrowser(0);
|
---|
| 366 | sourceViewer->setWindowTitle("Source: " + m_sourceFileName.mid(5));
|
---|
| 367 | sourceViewer->setParent(this, Qt::Dialog);
|
---|
| 368 | sourceViewer->setAttribute(Qt::WA_DeleteOnClose);
|
---|
| 369 | sourceViewer->setLineWrapMode(QTextEdit::NoWrap);
|
---|
| 370 | sourceViewer->setHtml(html);
|
---|
| 371 | sourceViewer->resize(600, 600);
|
---|
| 372 | sourceViewer->show();
|
---|
| 373 | }
|
---|