demos/gradients/gradients.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 ** Copyright (C) 2005-2006 Trolltech ASA. All rights reserved.
00004 **
00005 ** This file is part of the demonstration applications of the Qt Toolkit.
00006 **
00007 ** This file may be used under the terms of the GNU General Public
00008 ** License version 2.0 as published by the Free Software Foundation
00009 ** and appearing in the file LICENSE.GPL included in the packaging of
00010 ** this file.  Please review the following information to ensure GNU
00011 ** General Public Licensing requirements will be met:
00012 ** http://www.trolltech.com/products/qt/opensource.html
00013 **
00014 ** If you are unsure which license is appropriate for your use, please
00015 ** review the following information:
00016 ** http://www.trolltech.com/products/qt/licensing.html or contact the
00017 ** sales department at sales@trolltech.com.
00018 **
00019 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00020 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00021 **
00022 ****************************************************************************/
00023 
00024 #include "gradients.h"
00025 #include "hoverpoints.h"
00026 
00027 ShadeWidget::ShadeWidget(ShadeType type, QWidget *parent)
00028     : QWidget(parent), m_shade_type(type), m_alpha_gradient(QLinearGradient(0, 0, 0, 0))
00029 {
00030 
00031     // Checkers background
00032     if (m_shade_type == ARGBShade) {
00033         QPixmap pm(20, 20);
00034         QPainter pmp(&pm);
00035         pmp.fillRect(0, 0, 10, 10, Qt::lightGray);
00036         pmp.fillRect(10, 10, 10, 10, Qt::lightGray);
00037         pmp.fillRect(0, 10, 10, 10, Qt::darkGray);
00038         pmp.fillRect(10, 0, 10, 10, Qt::darkGray);
00039         pmp.end();
00040         QPalette pal = palette();
00041         pal.setBrush(backgroundRole(), QBrush(pm));
00042         setAutoFillBackground(true);
00043         setPalette(pal);
00044 
00045     } else {
00046         setAttribute(Qt::WA_NoBackground);
00047 
00048     }
00049 
00050     QPolygonF points;
00051     points << QPointF(0, sizeHint().height())
00052            << QPointF(sizeHint().width(), 0);
00053 
00054     m_hoverPoints = new HoverPoints(this, HoverPoints::CircleShape);
00055 //     m_hoverPoints->setConnectionType(HoverPoints::LineConnection);
00056     m_hoverPoints->setPoints(points);
00057     m_hoverPoints->setPointLock(0, HoverPoints::LockToLeft);
00058     m_hoverPoints->setPointLock(1, HoverPoints::LockToRight);
00059     m_hoverPoints->setSortType(HoverPoints::XSort);
00060 
00061     setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
00062 
00063     connect(m_hoverPoints, SIGNAL(pointsChanged(const QPolygonF &)), this, SIGNAL(colorsChanged()));
00064 }
00065 
00066 
00067 QPolygonF ShadeWidget::points() const
00068 {
00069     return m_hoverPoints->points();
00070 }
00071 
00072 
00073 uint ShadeWidget::colorAt(int x)
00074 {
00075     generateShade();
00076 
00077     QPolygonF pts = m_hoverPoints->points();
00078     for (int i=1; i < pts.size(); ++i) {
00079         if (pts.at(i-1).x() <= x && pts.at(i).x() >= x) {
00080             QLineF l(pts.at(i-1), pts.at(i));
00081             l.setLength(l.length() * ((x - l.x1()) / l.dx()));
00082             return m_shade.pixel(qRound(qMin(l.x2(), (qreal(m_shade.width() - 1)))),
00083                                  qRound(qMin(l.y2(), qreal(m_shade.height() - 1))));
00084         }
00085     }
00086     return 0;
00087 }
00088 
00089 
00090 void ShadeWidget::setGradientStops(const QGradientStops &stops)
00091 {
00092     if (m_shade_type == ARGBShade) {
00093         m_alpha_gradient = QLinearGradient(0, 0, width(), 0);
00094 
00095         for (int i=0; i<stops.size(); ++i) {
00096             QColor c = stops.at(i).second;
00097             m_alpha_gradient.setColorAt(stops.at(i).first, QColor(c.red(), c.green(), c.blue()));
00098         }
00099 
00100         m_shade = QImage();
00101         generateShade();
00102         update();
00103     }
00104 }
00105 
00106 
00107 void ShadeWidget::paintEvent(QPaintEvent *)
00108 {
00109     generateShade();
00110 
00111     QPainter p(this);
00112     p.drawImage(0, 0, m_shade);
00113 
00114     p.setPen(QColor(146, 146, 146));
00115     p.drawRect(0, 0, width() - 1, height() - 1);
00116 }
00117 
00118 
00119 void ShadeWidget::generateShade()
00120 {
00121     if (m_shade.isNull() || m_shade.size() != size()) {
00122 
00123         if (m_shade_type == ARGBShade) {
00124             m_shade = QImage(size(), QImage::Format_ARGB32_Premultiplied);
00125             m_shade.fill(0);
00126 
00127             QPainter p(&m_shade);
00128             p.fillRect(rect(), m_alpha_gradient);
00129 
00130             p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
00131             QLinearGradient fade(0, 0, 0, height());
00132             fade.setColorAt(0, QColor(0, 0, 0, 255));
00133             fade.setColorAt(1, QColor(0, 0, 0, 0));
00134             p.fillRect(rect(), fade);
00135 
00136         } else {
00137             m_shade = QImage(size(), QImage::Format_RGB32);
00138             QLinearGradient shade(0, 0, 0, height());
00139             shade.setColorAt(1, Qt::black);
00140 
00141             if (m_shade_type == RedShade)
00142                 shade.setColorAt(0, Qt::red);
00143             else if (m_shade_type == GreenShade)
00144                 shade.setColorAt(0, Qt::green);
00145             else
00146                 shade.setColorAt(0, Qt::blue);
00147 
00148             QPainter p(&m_shade);
00149             p.fillRect(rect(), shade);
00150         }
00151     }
00152 
00153 
00154 }
00155 
00156 
00157 GradientEditor::GradientEditor(QWidget *parent)
00158     : QWidget(parent)
00159 {
00160     QVBoxLayout *vbox = new QVBoxLayout(this);
00161     vbox->setSpacing(1);
00162     vbox->setMargin(1);
00163 
00164     m_red_shade = new ShadeWidget(ShadeWidget::RedShade, this);
00165     m_green_shade = new ShadeWidget(ShadeWidget::GreenShade, this);
00166     m_blue_shade = new ShadeWidget(ShadeWidget::BlueShade, this);
00167     m_alpha_shade = new ShadeWidget(ShadeWidget::ARGBShade, this);
00168 
00169     vbox->addWidget(m_red_shade);
00170     vbox->addWidget(m_green_shade);
00171     vbox->addWidget(m_blue_shade);
00172     vbox->addWidget(m_alpha_shade);
00173 
00174     connect(m_red_shade, SIGNAL(colorsChanged()), this, SLOT(pointsUpdated()));
00175     connect(m_green_shade, SIGNAL(colorsChanged()), this, SLOT(pointsUpdated()));
00176     connect(m_blue_shade, SIGNAL(colorsChanged()), this, SLOT(pointsUpdated()));
00177     connect(m_alpha_shade, SIGNAL(colorsChanged()), this, SLOT(pointsUpdated()));
00178 }
00179 
00180 
00181 inline static bool x_less_than(const QPointF &p1, const QPointF &p2)
00182 {
00183     return p1.x() < p2.x();
00184 }
00185 
00186 
00187 void GradientEditor::pointsUpdated()
00188 {
00189     double w = m_alpha_shade->width();
00190 
00191     QGradientStops stops;
00192 
00193     QPolygonF points;
00194 
00195     points += m_red_shade->points();
00196     points += m_green_shade->points();
00197     points += m_blue_shade->points();
00198     points += m_alpha_shade->points();
00199 
00200     qSort(points.begin(), points.end(), x_less_than);
00201 
00202     for (int i=0; i<points.size(); ++i) {
00203         double x = int(points.at(i).x());
00204         if (i < points.size() - 1 && x == points.at(i+1).x())
00205             continue;
00206         QColor color((0x00ff0000 & m_red_shade->colorAt(int(x))) >> 16,
00207                      (0x0000ff00 & m_green_shade->colorAt(int(x))) >> 8,
00208                      (0x000000ff & m_blue_shade->colorAt(int(x))),
00209                      (0xff000000 & m_alpha_shade->colorAt(int(x))) >> 24);
00210 
00211         if (x / w > 1)
00212             return;
00213 
00214         stops << QGradientStop(x / w, color);
00215     }
00216 
00217     m_alpha_shade->setGradientStops(stops);
00218 
00219     emit gradientStopsChanged(stops);
00220 }
00221 
00222 
00223 static void set_shade_points(const QPolygonF &points, ShadeWidget *shade)
00224 {
00225     shade->hoverPoints()->setPoints(points);
00226     shade->hoverPoints()->setPointLock(0, HoverPoints::LockToLeft);
00227     shade->hoverPoints()->setPointLock(points.size() - 1, HoverPoints::LockToRight);
00228     shade->update();
00229 }
00230 
00231 void GradientEditor::setGradientStops(const QGradientStops &stops)
00232 {
00233     QPolygonF pts_red, pts_green, pts_blue, pts_alpha;
00234 
00235     double h_red = m_red_shade->height();
00236     double h_green = m_green_shade->height();
00237     double h_blue = m_blue_shade->height();
00238     double h_alpha = m_alpha_shade->height();
00239 
00240     for (int i=0; i<stops.size(); ++i) {
00241         double pos = stops.at(i).first;
00242         QRgb color = stops.at(i).second.rgba();
00243         pts_red << QPointF(pos * m_red_shade->width(), h_red - qRed(color) * h_red / 255);
00244         pts_green << QPointF(pos * m_green_shade->width(), h_green - qGreen(color) * h_green / 255);
00245         pts_blue << QPointF(pos * m_blue_shade->width(), h_blue - qBlue(color) * h_blue / 255);
00246         pts_alpha << QPointF(pos * m_alpha_shade->width(), h_alpha - qAlpha(color) * h_alpha / 255);
00247     }
00248 
00249     set_shade_points(pts_red, m_red_shade);
00250     set_shade_points(pts_green, m_green_shade);
00251     set_shade_points(pts_blue, m_blue_shade);
00252     set_shade_points(pts_alpha, m_alpha_shade);
00253 
00254 }
00255 
00256 GradientWidget::GradientWidget(QWidget *parent)
00257     : QWidget(parent)
00258 {
00259     setWindowTitle("Gradients");
00260 
00261     m_renderer = new GradientRenderer(this);
00262 
00263     QGroupBox *mainGroup = new QGroupBox(this);
00264     mainGroup->setTitle("Gradients");
00265 
00266     QGroupBox *editorGroup = new QGroupBox(mainGroup);
00267     editorGroup->setAttribute(Qt::WA_ContentsPropagated);
00268     editorGroup->setTitle("Color Editor");
00269     m_editor = new GradientEditor(editorGroup);
00270 
00271     QGroupBox *typeGroup = new QGroupBox(mainGroup);
00272     typeGroup->setAttribute(Qt::WA_ContentsPropagated);
00273     typeGroup->setTitle("Gradient Type");
00274     m_linearButton = new QRadioButton("Linear Gradient", typeGroup);
00275     m_radialButton = new QRadioButton("Radial Gradient", typeGroup);
00276     m_conicalButton = new QRadioButton("Conical Gradient", typeGroup);
00277 
00278     QGroupBox *spreadGroup = new QGroupBox(mainGroup);
00279     spreadGroup->setAttribute(Qt::WA_ContentsPropagated);
00280     spreadGroup->setTitle("Spread Method");
00281     m_padSpreadButton = new QRadioButton("Pad Spread", spreadGroup);
00282     m_reflectSpreadButton = new QRadioButton("Reflect Spread", spreadGroup);
00283     m_repeatSpreadButton = new QRadioButton("Repeat Spread", spreadGroup);
00284 
00285     QGroupBox *defaultsGroup = new QGroupBox(mainGroup);
00286     defaultsGroup->setAttribute(Qt::WA_ContentsPropagated);
00287     defaultsGroup->setTitle("Defaults");
00288     QPushButton *default1Button = new QPushButton("1", defaultsGroup);
00289     QPushButton *default2Button = new QPushButton("2", defaultsGroup);
00290     QPushButton *default3Button = new QPushButton("3", defaultsGroup);
00291     QPushButton *default4Button = new QPushButton("Reset", editorGroup);
00292 
00293     QPushButton *showSourceButton = new QPushButton(mainGroup);
00294     showSourceButton->setText("Show Source");
00295 #ifdef QT_OPENGL_SUPPORT
00296     QPushButton *enableOpenGLButton = new QPushButton(mainGroup);
00297     enableOpenGLButton->setText("Use OpenGL");
00298     enableOpenGLButton->setCheckable(true);
00299     enableOpenGLButton->setChecked(m_renderer->usesOpenGL());
00300     if (!QGLFormat::hasOpenGL())
00301         enableOpenGLButton->hide();
00302 #endif
00303     QPushButton *whatsThisButton = new QPushButton(mainGroup);
00304     whatsThisButton->setText("What's This?");
00305     whatsThisButton->setCheckable(true);
00306 
00307     // Layouts
00308     QHBoxLayout *mainLayout = new QHBoxLayout(this);
00309     mainLayout->addWidget(m_renderer);
00310     mainLayout->addWidget(mainGroup);
00311 
00312     mainGroup->setFixedWidth(180);
00313     QVBoxLayout *mainGroupLayout = new QVBoxLayout(mainGroup);
00314     mainGroupLayout->addWidget(editorGroup);
00315     mainGroupLayout->addWidget(typeGroup);
00316     mainGroupLayout->addWidget(spreadGroup);
00317     mainGroupLayout->addWidget(defaultsGroup);
00318     mainGroupLayout->addStretch(1);
00319     mainGroupLayout->addWidget(showSourceButton);
00320 #ifdef QT_OPENGL_SUPPORT
00321     mainGroupLayout->addWidget(enableOpenGLButton);
00322 #endif
00323     mainGroupLayout->addWidget(whatsThisButton);
00324 
00325     QVBoxLayout *editorGroupLayout = new QVBoxLayout(editorGroup);
00326     editorGroupLayout->addWidget(m_editor);
00327 
00328     QVBoxLayout *typeGroupLayout = new QVBoxLayout(typeGroup);
00329     typeGroupLayout->addWidget(m_linearButton);
00330     typeGroupLayout->addWidget(m_radialButton);
00331     typeGroupLayout->addWidget(m_conicalButton);
00332 
00333     QVBoxLayout *spreadGroupLayout = new QVBoxLayout(spreadGroup);
00334     spreadGroupLayout->addWidget(m_padSpreadButton);
00335     spreadGroupLayout->addWidget(m_repeatSpreadButton);
00336     spreadGroupLayout->addWidget(m_reflectSpreadButton);
00337 
00338     QHBoxLayout *defaultsGroupLayout = new QHBoxLayout(defaultsGroup);
00339     defaultsGroupLayout->addWidget(default1Button);
00340     defaultsGroupLayout->addWidget(default2Button);
00341     defaultsGroupLayout->addWidget(default3Button);
00342     editorGroupLayout->addWidget(default4Button);
00343 
00344     connect(m_editor, SIGNAL(gradientStopsChanged(const QGradientStops &)),
00345             m_renderer, SLOT(setGradientStops(const QGradientStops &)));
00346 
00347     connect(m_linearButton, SIGNAL(clicked()), m_renderer, SLOT(setLinearGradient()));
00348     connect(m_radialButton, SIGNAL(clicked()), m_renderer, SLOT(setRadialGradient()));
00349     connect(m_conicalButton, SIGNAL(clicked()), m_renderer, SLOT(setConicalGradient()));
00350 
00351     connect(m_padSpreadButton, SIGNAL(clicked()), m_renderer, SLOT(setPadSpread()));
00352     connect(m_reflectSpreadButton, SIGNAL(clicked()), m_renderer, SLOT(setReflectSpread()));
00353     connect(m_repeatSpreadButton, SIGNAL(clicked()), m_renderer, SLOT(setRepeatSpread()));
00354 
00355     connect(default1Button, SIGNAL(clicked()), this, SLOT(setDefault1()));
00356     connect(default2Button, SIGNAL(clicked()), this, SLOT(setDefault2()));
00357     connect(default3Button, SIGNAL(clicked()), this, SLOT(setDefault3()));
00358     connect(default4Button, SIGNAL(clicked()), this, SLOT(setDefault4()));
00359 
00360     connect(showSourceButton, SIGNAL(clicked()), m_renderer, SLOT(showSource()));
00361 #ifdef QT_OPENGL_SUPPORT
00362     connect(enableOpenGLButton, SIGNAL(clicked(bool)), m_renderer, SLOT(enableOpenGL(bool)));
00363 #endif
00364     connect(whatsThisButton, SIGNAL(clicked(bool)), m_renderer, SLOT(setDescriptionEnabled(bool)));
00365     connect(whatsThisButton, SIGNAL(clicked(bool)),
00366             m_renderer->hoverPoints(), SLOT(setDisabled(bool)));
00367     connect(m_renderer, SIGNAL(descriptionEnabledChanged(bool)),
00368             whatsThisButton, SLOT(setChecked(bool)));
00369     connect(m_renderer, SIGNAL(descriptionEnabledChanged(bool)),
00370             m_renderer->hoverPoints(), SLOT(setDisabled(bool)));
00371 
00372     m_renderer->loadSourceFile(":res/gradients.cpp");
00373     m_renderer->loadDescription(":res/gradients.html");
00374 
00375     QTimer::singleShot(50, this, SLOT(setDefault1()));
00376 }
00377 
00378 void GradientWidget::setDefault(int config)
00379 {
00380     QGradientStops stops;
00381     QPolygonF points;
00382     switch (config) {
00383     case 1:
00384         stops << QGradientStop(0.00, QColor::fromRgba(0));
00385         stops << QGradientStop(0.04, QColor::fromRgba(0xff131360));
00386         stops << QGradientStop(0.08, QColor::fromRgba(0xff202ccc));
00387         stops << QGradientStop(0.42, QColor::fromRgba(0xff93d3f9));
00388         stops << QGradientStop(0.51, QColor::fromRgba(0xffb3e6ff));
00389         stops << QGradientStop(0.73, QColor::fromRgba(0xffffffec));
00390         stops << QGradientStop(0.92, QColor::fromRgba(0xff5353d9));
00391         stops << QGradientStop(0.96, QColor::fromRgba(0xff262666));
00392         stops << QGradientStop(1.00, QColor::fromRgba(0));
00393         m_linearButton->animateClick();
00394         m_repeatSpreadButton->animateClick();
00395         break;
00396 
00397     case 2:
00398         stops << QGradientStop(0.00, QColor::fromRgba(0xffffffff));
00399         stops << QGradientStop(0.11, QColor::fromRgba(0xfff9ffa0));
00400         stops << QGradientStop(0.13, QColor::fromRgba(0xfff9ff99));
00401         stops << QGradientStop(0.14, QColor::fromRgba(0xfff3ff86));
00402         stops << QGradientStop(0.49, QColor::fromRgba(0xff93b353));
00403         stops << QGradientStop(0.87, QColor::fromRgba(0xff264619));
00404         stops << QGradientStop(0.96, QColor::fromRgba(0xff0c1306));
00405         stops << QGradientStop(1.00, QColor::fromRgba(0));
00406         m_radialButton->animateClick();
00407         m_padSpreadButton->animateClick();
00408         break;
00409 
00410     case 3:
00411         stops << QGradientStop(0.00, QColor::fromRgba(0));
00412         stops << QGradientStop(0.10, QColor::fromRgba(0xffe0cc73));
00413         stops << QGradientStop(0.17, QColor::fromRgba(0xffc6a006));
00414         stops << QGradientStop(0.46, QColor::fromRgba(0xff600659));
00415         stops << QGradientStop(0.72, QColor::fromRgba(0xff0680ac));
00416         stops << QGradientStop(0.92, QColor::fromRgba(0xffb9d9e6));
00417         stops << QGradientStop(1.00, QColor::fromRgba(0));
00418         m_conicalButton->animateClick();
00419         m_padSpreadButton->animateClick();
00420         break;
00421 
00422     case 4:
00423         stops << QGradientStop(0.00, QColor::fromRgba(0xff000000));
00424         stops << QGradientStop(1.00, QColor::fromRgba(0xffffffff));
00425         break;
00426 
00427     default:
00428         qWarning("bad default: %d\n", config);
00429         break;
00430     }
00431 
00432     QPolygonF pts;
00433     int h_off = m_renderer->width() / 10;
00434     int v_off = m_renderer->height() / 8;
00435     pts << QPointF(m_renderer->width() / 2, m_renderer->height() / 2)
00436         << QPointF(m_renderer->width() / 2 - h_off, m_renderer->height() / 2 - v_off);
00437 
00438     m_editor->setGradientStops(stops);
00439     m_renderer->hoverPoints()->setPoints(pts);
00440     m_renderer->setGradientStops(stops);
00441 }
00442 
00443 
00444 GradientRenderer::GradientRenderer(QWidget *parent)
00445     : ArthurFrame(parent)
00446 {
00447     m_hoverPoints = new HoverPoints(this, HoverPoints::CircleShape);
00448     m_hoverPoints->setPointSize(QSize(20, 20));
00449     m_hoverPoints->setConnectionType(HoverPoints::NoConnection);
00450     m_hoverPoints->setEditable(false);
00451 
00452     QVector<QPointF> points;
00453     points << QPointF(100, 100) << QPointF(200, 200);
00454     m_hoverPoints->setPoints(points);
00455 
00456     m_spread = QGradient::PadSpread;
00457     m_gradientType = Qt::LinearGradientPattern;
00458 }
00459 
00460 void GradientRenderer::setGradientStops(const QGradientStops &stops)
00461 {
00462     m_stops = stops;
00463     update();
00464 }
00465 
00466 
00467 void GradientRenderer::mousePressEvent(QMouseEvent *)
00468 {
00469     setDescriptionEnabled(false);
00470 }
00471 
00472 void GradientRenderer::paint(QPainter *p)
00473 {
00474     QPolygonF pts = m_hoverPoints->points();
00475 
00476     QGradient g;
00477 
00478     if (m_gradientType == Qt::LinearGradientPattern) {
00479         g = QLinearGradient(pts.at(0), pts.at(1));
00480 
00481     } else if (m_gradientType == Qt::RadialGradientPattern) {
00482         QLineF line(pts.at(0), pts.at(1));
00483         if (line.length() > 132)
00484             line.setLength(132);
00485         g = QRadialGradient(line.p1(), qMin(width(), height()) / 3.0, line.p2());
00486     } else {
00487         QLineF l(pts.at(0), pts.at(1));
00488         double angle = l.angle(QLineF(0, 0, 1, 0));
00489         if (l.dy() > 0)
00490             angle = 360 - angle;
00491         g = QConicalGradient(pts.at(0), angle);
00492     }
00493 
00494     for (int i=0; i<m_stops.size(); ++i)
00495         g.setColorAt(m_stops.at(i).first, m_stops.at(i).second);
00496 
00497     g.setSpread(m_spread);
00498 
00499     p->setBrush(g);
00500     p->setPen(Qt::NoPen);
00501 
00502     p->drawRect(rect());
00503 
00504 }

Generated on Thu Mar 15 11:52:32 2007 for Qt 4.2 User's Guide by  doxygen 1.5.1