~valavanisalex/ubuntu/maverick/qtiplot/qtiplot-fix-605025

« back to all changes in this revision

Viewing changes to qtiplot/src/lib/3rdparty/qtcolorpicker/src/qtcolorpicker.cpp

  • Committer: Alex Valavanis
  • Date: 2010-07-21 23:21:12 UTC
  • mfrom: (1.1.7 upstream)
  • Revision ID: valavanisalex@googlemail.com-20100721232112-p4o2jezjgutlj5x9
Merging shared upstream rev into target branch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/****************************************************************************
2
 
**
3
 
** This file is part of a Qt Solutions component.
4
 
** 
5
 
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
6
 
** 
7
 
** Contact:  Qt Software Information (qt-info@nokia.com)
8
 
** 
9
 
** Commercial Usage  
10
 
** Licensees holding valid Qt Commercial licenses may use this file in
11
 
** accordance with the Qt Solutions Commercial License Agreement provided
12
 
** with the Software or, alternatively, in accordance with the terms
13
 
** contained in a written agreement between you and Nokia.
14
 
** 
15
 
** GNU Lesser General Public License Usage
16
 
** Alternatively, this file may be used under the terms of the GNU Lesser
17
 
** General Public License version 2.1 as published by the Free Software
18
 
** Foundation and appearing in the file LICENSE.LGPL included in the
19
 
** packaging of this file.  Please review the following information to
20
 
** ensure the GNU Lesser General Public License version 2.1 requirements
21
 
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22
 
** 
23
 
** In addition, as a special exception, Nokia gives you certain
24
 
** additional rights. These rights are described in the Nokia Qt LGPL
25
 
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26
 
** package.
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
 
** 
36
 
** Please note Third Party Software included with Qt Solutions may impose
37
 
** additional restrictions and it is the user's responsibility to ensure
38
 
** that they have met the licensing requirements of the GPL, LGPL, or Qt
39
 
** Solutions Commercial license and the relevant license of the Third
40
 
** Party Software they are using.
41
 
** 
42
 
** If you are unsure which license is appropriate for your use, please
43
 
** contact the sales department at qt-sales@nokia.com.
44
 
** 
45
 
****************************************************************************/
46
 
 
47
 
#include <QtGui/QApplication>
48
 
#include <QtGui/QDesktopWidget>
49
 
#include <QtGui/QPainter>
50
 
#include <QtGui/QPushButton>
51
 
#include <QtGui/QColorDialog>
52
 
#include <QtCore/QMap>
53
 
#include <QtGui/QLayout>
54
 
#include <QtGui/QStyle>
55
 
#include <QtGui/QLabel>
56
 
#include <QtGui/QToolTip>
57
 
#include <QtGui/QPixmap>
58
 
#include <QtGui/QFocusEvent>
59
 
#include <QtGui/QPaintEvent>
60
 
#include <QtGui/QGridLayout>
61
 
#include <QtGui/QHideEvent>
62
 
#include <QtGui/QKeyEvent>
63
 
#include <QtGui/QShowEvent>
64
 
#include <QtGui/QMouseEvent>
65
 
#include <math.h>
66
 
 
67
 
#include "qtcolorpicker.h"
68
 
 
69
 
/*! \class QtColorPicker
70
 
 
71
 
    \brief The QtColorPicker class provides a widget for selecting
72
 
    colors from a popup color grid.
73
 
 
74
 
    Users can invoke the color picker by clicking on it, or by
75
 
    navigating to it and pressing Space. They can use the mouse or
76
 
    arrow keys to navigate between colors on the grid, and select a
77
 
    color by clicking or by pressing Enter or Space. The
78
 
    colorChanged() signal is emitted whenever the color picker's color
79
 
    changes.
80
 
 
81
 
    The widget also supports negative selection: Users can click and
82
 
    hold the mouse button on the QtColorPicker widget, then move the
83
 
    mouse over the color grid and release the mouse button over the
84
 
    color they wish to select.
85
 
 
86
 
    The color grid shows a customized selection of colors. An optional
87
 
    ellipsis "..." button (signifying "more") can be added at the
88
 
    bottom of the grid; if the user presses this, a QColorDialog pops
89
 
    up and lets them choose any color they like. This button is made
90
 
    available by using setColorDialogEnabled().
91
 
 
92
 
    When a color is selected, the QtColorPicker widget shows the color
93
 
    and its name. If the name cannot be determined, the translatable
94
 
    name "Custom" is used.
95
 
 
96
 
    The QtColorPicker object is optionally initialized with the number
97
 
    of columns in the color grid. Colors are then added left to right,
98
 
    top to bottom using insertColor(). If the number of columns is not
99
 
    set, QtColorPicker calculates the number of columns and rows that
100
 
    will make the grid as square as possible.
101
 
 
102
 
    \code
103
 
    DrawWidget::DrawWidget(QWidget *parent, const char *name)
104
 
    {
105
 
        QtColorPicker *picker = new QtColorPicker(this);
106
 
        picker->insertColor(red, "Red"));
107
 
        picker->insertColor(QColor("green"), "Green"));
108
 
        picker->insertColor(QColor(0, 0, 255), "Blue"));
109
 
        picker->insertColor(white);
110
 
 
111
 
        connect(colors, SIGNAL(colorChanged(const QColor &)), SLOT(setCurrentColor(const QColor &)));
112
 
    }
113
 
    \endcode
114
 
 
115
 
    An alternative to adding colors manually is to initialize the grid
116
 
    with QColorDialog's standard colors using setStandardColors().
117
 
 
118
 
    QtColorPicker also provides a the static function getColor(),
119
 
    which pops up the grid of standard colors at any given point.
120
 
 
121
 
    \img colorpicker1.png
122
 
    \img colorpicker2.png
123
 
 
124
 
    \sa QColorDialog
125
 
*/
126
 
 
127
 
/*! \fn QtColorPicker::colorChanged(const QColor &color)
128
 
 
129
 
    This signal is emitted when the QtColorPicker's color is changed.
130
 
    \a color is the new color.
131
 
 
132
 
    To obtain the color's name, use text().
133
 
*/
134
 
 
135
 
/*
136
 
    A class  that acts very much  like a QPushButton. It's not styled,
137
 
    so we  can  expect  the  exact  same    look,  feel and   geometry
138
 
    everywhere.     Also,  this  button     always emits   clicked  on
139
 
    mouseRelease, even if the mouse button was  not pressed inside the
140
 
    widget.
141
 
*/
142
 
class ColorPickerButton : public QFrame
143
 
{
144
 
    Q_OBJECT
145
 
 
146
 
public:
147
 
    ColorPickerButton(QWidget *parent);
148
 
 
149
 
signals:
150
 
    void clicked();
151
 
 
152
 
protected:
153
 
    void mousePressEvent(QMouseEvent *e);
154
 
    void mouseMoveEvent(QMouseEvent *e);
155
 
    void mouseReleaseEvent(QMouseEvent *e);
156
 
    void keyPressEvent(QKeyEvent *e);
157
 
    void keyReleaseEvent(QKeyEvent *e);
158
 
    void paintEvent(QPaintEvent *e);
159
 
    void focusInEvent(QFocusEvent *e);
160
 
    void focusOutEvent(QFocusEvent *e);
161
 
};
162
 
 
163
 
/*
164
 
    This class represents each "color" or item in the color grid.
165
 
*/
166
 
class ColorPickerItem : public QFrame
167
 
{
168
 
    Q_OBJECT
169
 
 
170
 
public:
171
 
    ColorPickerItem(const QColor &color = Qt::white, const QString &text = QString::null,
172
 
                      QWidget *parent = 0);
173
 
    ~ColorPickerItem();
174
 
 
175
 
    QColor color() const;
176
 
    QString text() const;
177
 
 
178
 
    void setSelected(bool);
179
 
    bool isSelected() const;
180
 
signals:
181
 
    void clicked();
182
 
    void selected();
183
 
 
184
 
public slots:
185
 
    void setColor(const QColor &color, const QString &text = QString());
186
 
 
187
 
protected:
188
 
    void mousePressEvent(QMouseEvent *e);
189
 
    void mouseReleaseEvent(QMouseEvent *e);
190
 
    void mouseMoveEvent(QMouseEvent *e);
191
 
    void paintEvent(QPaintEvent *e);
192
 
 
193
 
private:
194
 
    QColor c;
195
 
    QString t;
196
 
    bool sel;
197
 
};
198
 
 
199
 
/*
200
 
 
201
 
*/
202
 
class ColorPickerPopup : public QFrame
203
 
{
204
 
    Q_OBJECT
205
 
 
206
 
public:
207
 
    ColorPickerPopup(int width, bool withColorDialog,
208
 
                       QWidget *parent = 0);
209
 
    ~ColorPickerPopup();
210
 
 
211
 
    void insertColor(const QColor &col, const QString &text, int index);
212
 
    void exec();
213
 
 
214
 
    void setExecFlag();
215
 
 
216
 
    QColor lastSelected() const;
217
 
 
218
 
    ColorPickerItem *find(const QColor &col) const;
219
 
    QColor color(int index) const;
220
 
 
221
 
signals:
222
 
    void selected(const QColor &);
223
 
    void hid();
224
 
 
225
 
public slots:
226
 
    void getColorFromDialog();
227
 
 
228
 
protected slots:
229
 
    void updateSelected();
230
 
 
231
 
protected:
232
 
    void keyPressEvent(QKeyEvent *e);
233
 
    void showEvent(QShowEvent *e);
234
 
    void hideEvent(QHideEvent *e);
235
 
    void mouseReleaseEvent(QMouseEvent *e);
236
 
 
237
 
    void regenerateGrid();
238
 
 
239
 
private:
240
 
    QMap<int, QMap<int, QWidget *> > widgetAt;
241
 
    QList<ColorPickerItem *> items;
242
 
    QGridLayout *grid;
243
 
    ColorPickerButton *moreButton;
244
 
    QEventLoop *eventLoop;
245
 
 
246
 
    int lastPos;
247
 
    int cols;
248
 
    QColor lastSel;
249
 
};
250
 
 
251
 
/*!
252
 
    Constructs a QtColorPicker widget. The popup will display a grid
253
 
    with \a cols columns, or if \a cols is -1, the number of columns
254
 
    will be calculated automatically.
255
 
 
256
 
    If \a enableColorDialog is true, the popup will also have a "More"
257
 
    button (signified by an ellipsis "...") that presents a
258
 
    QColorDialog when clicked.
259
 
 
260
 
    After constructing a QtColorPicker, call insertColor() to add
261
 
    individual colors to the popup grid, or call setStandardColors()
262
 
    to add all the standard colors in one go.
263
 
 
264
 
    The \a parent argument is passed to QFrame's constructor.
265
 
 
266
 
    \sa QFrame
267
 
*/
268
 
QtColorPicker::QtColorPicker(QWidget *parent,
269
 
                             int cols, bool enableColorDialog)
270
 
    : QPushButton(parent), popup(0), withColorDialog(enableColorDialog)
271
 
{
272
 
    setFocusPolicy(Qt::StrongFocus);
273
 
    setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
274
 
    setAutoDefault(false);
275
 
    setAutoFillBackground(true);
276
 
    setCheckable(true);
277
 
 
278
 
    // Set text
279
 
    setText(tr("Black"));
280
 
    firstInserted = false;
281
 
 
282
 
    // Create and set icon
283
 
    col = Qt::black;
284
 
    dirty = true;
285
 
 
286
 
    // Create color grid popup and connect to it.
287
 
    popup = new ColorPickerPopup(cols, withColorDialog, this);
288
 
    connect(popup, SIGNAL(selected(const QColor &)),
289
 
            SLOT(setCurrentColor(const QColor &)));
290
 
    connect(popup, SIGNAL(hid()), SLOT(popupClosed()));
291
 
 
292
 
    // Connect this push button's pressed() signal.
293
 
    connect(this, SIGNAL(toggled(bool)), SLOT(buttonPressed(bool)));
294
 
}
295
 
 
296
 
/*!
297
 
    Destructs the QtColorPicker.
298
 
*/
299
 
QtColorPicker::~QtColorPicker()
300
 
{
301
 
}
302
 
 
303
 
/*! \internal
304
 
 
305
 
    Pops up the color grid, and makes sure the status of
306
 
    QtColorPicker's button is right.
307
 
*/
308
 
void QtColorPicker::buttonPressed(bool toggled)
309
 
{
310
 
    if (!toggled)
311
 
        return;
312
 
 
313
 
    const QRect desktop = QApplication::desktop()->geometry();
314
 
    // Make sure the popup is inside the desktop.
315
 
    QPoint pos = mapToGlobal(rect().bottomLeft());
316
 
    if (pos.x() < desktop.left())
317
 
       pos.setX(desktop.left());
318
 
    if (pos.y() < desktop.top())
319
 
       pos.setY(desktop.top());
320
 
 
321
 
    if ((pos.x() + popup->sizeHint().width()) > desktop.width())
322
 
       pos.setX(desktop.width() - popup->sizeHint().width());
323
 
    if ((pos.y() + popup->sizeHint().height()) > desktop.bottom())
324
 
       pos.setY(desktop.bottom() - popup->sizeHint().height());
325
 
    popup->move(pos);
326
 
 
327
 
    if (ColorPickerItem *item = popup->find(col))
328
 
        item->setSelected(true);
329
 
 
330
 
    // Remove focus from this widget, preventing the focus rect
331
 
    // from showing when the popup is shown. Order an update to
332
 
    // make sure the focus rect is cleared.
333
 
    clearFocus();
334
 
    update();
335
 
 
336
 
    // Allow keyboard navigation as soon as the popup shows.
337
 
    popup->setFocus();
338
 
 
339
 
    // Execute the popup. The popup will enter the event loop.
340
 
    popup->show();
341
 
}
342
 
 
343
 
/*!
344
 
    \internal
345
 
*/
346
 
void QtColorPicker::paintEvent(QPaintEvent *e)
347
 
{
348
 
    if (dirty) {
349
 
        int iconSize = style()->pixelMetric(QStyle::PM_SmallIconSize);
350
 
        QPixmap pix(iconSize, iconSize);
351
 
        pix.fill(palette().button().color());
352
 
 
353
 
        QPainter p(&pix);
354
 
 
355
 
        int w = pix.width();                    // width of cell in pixels
356
 
        int h = pix.height();                   // height of cell in pixels
357
 
        p.setPen(QPen(Qt::gray));
358
 
        p.setBrush(col);
359
 
        p.drawRect(2, 2, w - 5, h - 5);
360
 
        setIcon(QIcon(pix));
361
 
 
362
 
        dirty = false;
363
 
    }
364
 
    QPushButton::paintEvent(e);
365
 
}
366
 
 
367
 
/*! \internal
368
 
 
369
 
    Makes sure the button isn't pressed when the popup hides.
370
 
*/
371
 
void QtColorPicker::popupClosed()
372
 
{
373
 
    setChecked(false);
374
 
    setFocus();
375
 
}
376
 
 
377
 
/*!
378
 
    Returns the currently selected color.
379
 
 
380
 
    \sa text()
381
 
*/
382
 
QColor QtColorPicker::currentColor() const
383
 
{
384
 
    return col;
385
 
}
386
 
 
387
 
/*!
388
 
    Returns the color at position \a index.
389
 
*/
390
 
QColor QtColorPicker::color(int index) const
391
 
{
392
 
    return popup->color(index);
393
 
}
394
 
 
395
 
/*!
396
 
    Adds the 17 predefined colors from the Qt namespace.
397
 
 
398
 
    (The names given to the colors, "Black", "White", "Red", etc., are
399
 
    all translatable.)
400
 
 
401
 
    \sa insertColor()
402
 
*/
403
 
void QtColorPicker::setStandardColors()
404
 
{
405
 
    insertColor(Qt::black, tr("Black"));
406
 
    insertColor(Qt::white, tr("White"));
407
 
    insertColor(Qt::red, tr("Red"));
408
 
    insertColor(Qt::darkRed, tr("Dark red"));
409
 
    insertColor(Qt::green, tr("Green"));
410
 
    insertColor(Qt::darkGreen, tr("Dark green"));
411
 
    insertColor(Qt::blue, tr("Blue"));
412
 
    insertColor(Qt::darkBlue, tr("Dark blue"));
413
 
    insertColor(Qt::cyan, tr("Cyan"));
414
 
    insertColor(Qt::darkCyan, tr("Dark cyan"));
415
 
    insertColor(Qt::magenta, tr("Magenta"));
416
 
    insertColor(Qt::darkMagenta, tr("Dark magenta"));
417
 
    insertColor(Qt::yellow, tr("Yellow"));
418
 
    insertColor(Qt::darkYellow, tr("Dark yellow"));
419
 
    insertColor(Qt::gray, tr("Gray"));
420
 
    insertColor(Qt::darkGray, tr("Dark gray"));
421
 
    insertColor(Qt::lightGray, tr("Light gray"));
422
 
}
423
 
 
424
 
 
425
 
/*!
426
 
    Makes \a color current. If \a color is not already in the color grid, it
427
 
    is inserted with the text "Custom".
428
 
 
429
 
    This function emits the colorChanged() signal if the new color is
430
 
    valid, and different from the old one.
431
 
*/
432
 
void QtColorPicker::setCurrentColor(const QColor &color)
433
 
{
434
 
    if (col == color || !color.isValid())
435
 
        return;
436
 
 
437
 
    ColorPickerItem *item = popup->find(color);
438
 
    if (!item) {
439
 
        insertColor(color, tr("Custom"));
440
 
        item = popup->find(color);
441
 
    }
442
 
 
443
 
    col = color;
444
 
    setText(item->text());
445
 
 
446
 
    dirty = true;
447
 
 
448
 
    popup->hide();
449
 
    repaint();
450
 
 
451
 
    item->setSelected(true);
452
 
    emit colorChanged(color);
453
 
}
454
 
 
455
 
/*!
456
 
    Adds the color \a color with the name \a text to the color grid,
457
 
    at position \a index. If index is -1, the color is assigned
458
 
    automatically assigned a position, starting from left to right,
459
 
    top to bottom.
460
 
*/
461
 
void QtColorPicker::insertColor(const QColor &color, const QString &text, int index)
462
 
{
463
 
    popup->insertColor(color, text, index);
464
 
    if (!firstInserted) {
465
 
        col = color;
466
 
        setText(text);
467
 
        firstInserted = true;
468
 
    }
469
 
}
470
 
 
471
 
/*! \property QtColorPicker::colorDialog
472
 
    \brief Whether the ellipsis "..." (more) button is available.
473
 
 
474
 
    If this property is set to TRUE, the color grid popup will include
475
 
    a "More" button (signified by an ellipsis, "...") which pops up a
476
 
    QColorDialog when clicked. The user will then be able to select
477
 
    any custom color they like.
478
 
*/
479
 
void QtColorPicker::setColorDialogEnabled(bool enabled)
480
 
{
481
 
    withColorDialog = enabled;
482
 
}
483
 
bool QtColorPicker::colorDialogEnabled() const
484
 
{
485
 
    return withColorDialog;
486
 
}
487
 
 
488
 
/*!
489
 
    Pops up a color grid with Qt default colors at \a point, using
490
 
    global coordinates. If \a allowCustomColors is true, there will
491
 
    also be a button on the popup that invokes QColorDialog.
492
 
 
493
 
    For example:
494
 
 
495
 
    \code
496
 
        void Drawer::mouseReleaseEvent(QMouseEvent *e)
497
 
        {
498
 
            if (e->button() & RightButton) {
499
 
                QColor color = QtColorPicker::getColor(mapToGlobal(e->pos()));
500
 
            }
501
 
        }
502
 
    \endcode
503
 
*/
504
 
QColor QtColorPicker::getColor(const QPoint &point, bool allowCustomColors)
505
 
{
506
 
    ColorPickerPopup popup(-1, allowCustomColors);
507
 
 
508
 
    popup.insertColor(Qt::black, tr("Black"), 0);
509
 
    popup.insertColor(Qt::white, tr("White"), 1);
510
 
    popup.insertColor(Qt::red, tr("Red"), 2);
511
 
    popup.insertColor(Qt::darkRed, tr("Dark red"), 3);
512
 
    popup.insertColor(Qt::green, tr("Green"), 4);
513
 
    popup.insertColor(Qt::darkGreen, tr("Dark green"), 5);
514
 
    popup.insertColor(Qt::blue, tr("Blue"), 6);
515
 
    popup.insertColor(Qt::darkBlue, tr("Dark blue"), 7);
516
 
    popup.insertColor(Qt::cyan, tr("Cyan"), 8);
517
 
    popup.insertColor(Qt::darkCyan, tr("Dark cyan"), 9);
518
 
    popup.insertColor(Qt::magenta, tr("Magenta"), 10);
519
 
    popup.insertColor(Qt::darkMagenta, tr("Dark magenta"), 11);
520
 
    popup.insertColor(Qt::yellow, tr("Yellow"), 12);
521
 
    popup.insertColor(Qt::darkYellow, tr("Dark yellow"), 13);
522
 
    popup.insertColor(Qt::gray, tr("Gray"), 14);
523
 
    popup.insertColor(Qt::darkGray, tr("Dark gray"), 15);
524
 
    popup.insertColor(Qt::lightGray, tr("Light gray"), 16);
525
 
 
526
 
    popup.move(point);
527
 
    popup.exec();
528
 
    return popup.lastSelected();
529
 
}
530
 
 
531
 
/*! \internal
532
 
 
533
 
    Constructs the popup widget.
534
 
*/
535
 
ColorPickerPopup::ColorPickerPopup(int width, bool withColorDialog,
536
 
                                       QWidget *parent)
537
 
    : QFrame(parent, Qt::Popup)
538
 
{
539
 
    setFrameStyle(QFrame::StyledPanel);
540
 
    setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
541
 
 
542
 
    setFocusPolicy(Qt::StrongFocus);
543
 
    setMouseTracking(true);
544
 
    cols = width;
545
 
 
546
 
    if (withColorDialog) {
547
 
        moreButton = new ColorPickerButton(this);
548
 
        moreButton->setFixedWidth(24);
549
 
        moreButton->setFixedHeight(21);
550
 
        moreButton->setFrameRect(QRect(2, 2, 20, 17));
551
 
        connect(moreButton, SIGNAL(clicked()), SLOT(getColorFromDialog()));
552
 
    } else {
553
 
        moreButton = 0;
554
 
    }
555
 
 
556
 
    eventLoop = 0;
557
 
    grid = 0;
558
 
    regenerateGrid();
559
 
}
560
 
 
561
 
 
562
 
/*! \internal
563
 
 
564
 
    Destructs the popup widget.
565
 
*/
566
 
ColorPickerPopup::~ColorPickerPopup()
567
 
{
568
 
    if (eventLoop)
569
 
        eventLoop->exit();
570
 
}
571
 
 
572
 
/*! \internal
573
 
 
574
 
    If there is an item whole color is equal to \a col, returns a
575
 
    pointer to this item; otherwise returns 0.
576
 
*/
577
 
ColorPickerItem *ColorPickerPopup::find(const QColor &col) const
578
 
{
579
 
    for (int i = 0; i < items.size(); ++i) {
580
 
        if (items.at(i) && items.at(i)->color() == col)
581
 
            return items.at(i);
582
 
    }
583
 
 
584
 
    return 0;
585
 
}
586
 
 
587
 
/*! \internal
588
 
 
589
 
    Adds \a item to the grid. The items are added from top-left to
590
 
    bottom-right.
591
 
*/
592
 
void ColorPickerPopup::insertColor(const QColor &col, const QString &text, int index)
593
 
{
594
 
    // Don't add colors that we have already.
595
 
    ColorPickerItem *existingItem = find(col);
596
 
    ColorPickerItem *lastSelectedItem = find(lastSelected());
597
 
 
598
 
    if (existingItem) {
599
 
        if (lastSelectedItem && existingItem != lastSelectedItem)
600
 
            lastSelectedItem->setSelected(false);
601
 
        existingItem->setFocus();
602
 
        existingItem->setSelected(true);
603
 
        return;
604
 
    }
605
 
 
606
 
    ColorPickerItem *item = new ColorPickerItem(col, text, this);
607
 
 
608
 
    if (lastSelectedItem) {
609
 
        lastSelectedItem->setSelected(false);
610
 
    }
611
 
    else {
612
 
        item->setSelected(true);
613
 
        lastSel = col;
614
 
    }
615
 
    item->setFocus();
616
 
 
617
 
    connect(item, SIGNAL(selected()), SLOT(updateSelected()));
618
 
 
619
 
    if (index == -1)
620
 
        index = items.count();
621
 
 
622
 
    items.insert((unsigned int)index, item);
623
 
    regenerateGrid();
624
 
 
625
 
    update();
626
 
}
627
 
 
628
 
/*! \internal
629
 
 
630
 
*/
631
 
QColor ColorPickerPopup::color(int index) const
632
 
{
633
 
    if (index < 0 || index > (int) items.count() - 1)
634
 
        return QColor();
635
 
 
636
 
    ColorPickerPopup *that = (ColorPickerPopup *)this;
637
 
    return that->items.at(index)->color();
638
 
}
639
 
 
640
 
/*! \internal
641
 
 
642
 
*/
643
 
void ColorPickerPopup::exec()
644
 
{
645
 
    show();
646
 
 
647
 
    QEventLoop e;
648
 
    eventLoop = &e;
649
 
    (void) e.exec();
650
 
    eventLoop = 0;
651
 
}
652
 
 
653
 
/*! \internal
654
 
 
655
 
*/
656
 
void ColorPickerPopup::updateSelected()
657
 
{
658
 
    QLayoutItem *layoutItem;
659
 
    int i = 0;
660
 
    while ((layoutItem = grid->itemAt(i)) != 0) {
661
 
        QWidget *w = layoutItem->widget();
662
 
        if (w && w->inherits("ColorPickerItem")) {
663
 
            ColorPickerItem *litem = reinterpret_cast<ColorPickerItem *>(layoutItem->widget());
664
 
            if (litem != sender())
665
 
                litem->setSelected(false);
666
 
        }
667
 
        ++i;
668
 
    }
669
 
 
670
 
    if (sender() && sender()->inherits("ColorPickerItem")) {
671
 
        ColorPickerItem *item = (ColorPickerItem *)sender();
672
 
        lastSel = item->color();
673
 
        emit selected(item->color());
674
 
    }
675
 
 
676
 
    hide();
677
 
}
678
 
 
679
 
/*! \internal
680
 
 
681
 
*/
682
 
void ColorPickerPopup::mouseReleaseEvent(QMouseEvent *e)
683
 
{
684
 
    if (!rect().contains(e->pos()))
685
 
        hide();
686
 
}
687
 
 
688
 
/*! \internal
689
 
 
690
 
    Controls keyboard navigation and selection on the color grid.
691
 
*/
692
 
void ColorPickerPopup::keyPressEvent(QKeyEvent *e)
693
 
{
694
 
    int curRow = 0;
695
 
    int curCol = 0;
696
 
 
697
 
    bool foundFocus = false;
698
 
    for (int j = 0; !foundFocus && j < grid->rowCount(); ++j) {
699
 
        for (int i = 0; !foundFocus && i < grid->columnCount(); ++i) {
700
 
            if (widgetAt[j][i] && widgetAt[j][i]->hasFocus()) {
701
 
                curRow = j;
702
 
                curCol = i;
703
 
                foundFocus = true;
704
 
                break;
705
 
            }
706
 
        }
707
 
    }
708
 
 
709
 
    switch (e->key()) {
710
 
        case Qt::Key_Left:
711
 
            if (curCol > 0) --curCol;
712
 
            else if (curRow > 0) { --curRow; curCol = grid->columnCount() - 1; }
713
 
            break;
714
 
        case Qt::Key_Right:
715
 
            if (curCol < grid->columnCount() - 1 && widgetAt[curRow][curCol + 1]) ++curCol;
716
 
            else if (curRow < grid->rowCount() - 1) { ++curRow; curCol = 0; }
717
 
            break;
718
 
        case Qt::Key_Up:
719
 
            if (curRow > 0) --curRow;
720
 
            else curCol = 0;
721
 
            break;
722
 
        case Qt::Key_Down:
723
 
            if (curRow < grid->rowCount() - 1) {
724
 
                QWidget *w = widgetAt[curRow + 1][curCol];
725
 
                if (w) {
726
 
                    ++curRow;
727
 
                } else for (int i = 1; i < grid->columnCount(); ++i) {
728
 
                    if (!widgetAt[curRow + 1][i]) {
729
 
                        curCol = i - 1;
730
 
                        ++curRow;
731
 
                        break;
732
 
                    }
733
 
                }
734
 
            }
735
 
            break;
736
 
        case Qt::Key_Space:
737
 
        case Qt::Key_Return:
738
 
        case Qt::Key_Enter: {
739
 
            QWidget *w = widgetAt[curRow][curCol];
740
 
            if (w && w->inherits("ColorPickerItem")) {
741
 
                ColorPickerItem *wi = reinterpret_cast<ColorPickerItem *>(w);
742
 
                wi->setSelected(true);
743
 
 
744
 
                QLayoutItem *layoutItem;
745
 
                int i = 0;
746
 
                while ((layoutItem = grid->itemAt(i)) != 0) {
747
 
                    QWidget *w = layoutItem->widget();
748
 
                    if (w && w->inherits("ColorPickerItem")) {
749
 
                        ColorPickerItem *litem
750
 
                            = reinterpret_cast<ColorPickerItem *>(layoutItem->widget());
751
 
                        if (litem != wi)
752
 
                            litem->setSelected(false);
753
 
                    }
754
 
                    ++i;
755
 
                }
756
 
 
757
 
                lastSel = wi->color();
758
 
                emit selected(wi->color());
759
 
                hide();
760
 
            } else if (w && w->inherits("QPushButton")) {
761
 
                ColorPickerItem *wi = reinterpret_cast<ColorPickerItem *>(w);
762
 
                wi->setSelected(true);
763
 
 
764
 
                QLayoutItem *layoutItem;
765
 
                int i = 0;
766
 
                while ((layoutItem = grid->itemAt(i)) != 0) {
767
 
                    QWidget *w = layoutItem->widget();
768
 
                    if (w && w->inherits("ColorPickerItem")) {
769
 
                        ColorPickerItem *litem
770
 
                            = reinterpret_cast<ColorPickerItem *>(layoutItem->widget());
771
 
                        if (litem != wi)
772
 
                            litem->setSelected(false);
773
 
                    }
774
 
                    ++i;
775
 
                }
776
 
 
777
 
                lastSel = wi->color();
778
 
                emit selected(wi->color());
779
 
                hide();
780
 
            }
781
 
        }
782
 
        break;
783
 
        case Qt::Key_Escape:
784
 
            hide();
785
 
        break;
786
 
        default:
787
 
            e->ignore();
788
 
            break;
789
 
    }
790
 
 
791
 
    widgetAt[curRow][curCol]->setFocus();
792
 
}
793
 
 
794
 
/*! \internal
795
 
 
796
 
*/
797
 
void ColorPickerPopup::hideEvent(QHideEvent *e)
798
 
{
799
 
    if (eventLoop) {
800
 
        eventLoop->exit();
801
 
    }
802
 
 
803
 
    setFocus();
804
 
 
805
 
    emit hid();
806
 
    QFrame::hideEvent(e);
807
 
}
808
 
 
809
 
/*! \internal
810
 
 
811
 
*/
812
 
QColor ColorPickerPopup::lastSelected() const
813
 
{
814
 
    return lastSel;
815
 
}
816
 
 
817
 
/*! \internal
818
 
 
819
 
    Sets focus on the popup to enable keyboard navigation. Draws
820
 
    focusRect and selection rect.
821
 
*/
822
 
void ColorPickerPopup::showEvent(QShowEvent *)
823
 
{
824
 
    bool foundSelected = false;
825
 
    for (int i = 0; i < grid->columnCount(); ++i) {
826
 
        for (int j = 0; j < grid->rowCount(); ++j) {
827
 
            QWidget *w = widgetAt[j][i];
828
 
            if (w && w->inherits("ColorPickerItem")) {
829
 
                if (((ColorPickerItem *)w)->isSelected()) {
830
 
                    w->setFocus();
831
 
                    foundSelected = true;
832
 
                    break;
833
 
                }
834
 
            }
835
 
        }
836
 
    }
837
 
 
838
 
    if (!foundSelected) {
839
 
        if (items.count() == 0)
840
 
            setFocus();
841
 
        else
842
 
            widgetAt[0][0]->setFocus();
843
 
    }
844
 
}
845
 
 
846
 
/*!
847
 
 
848
 
*/
849
 
void ColorPickerPopup::regenerateGrid()
850
 
{
851
 
    widgetAt.clear();
852
 
 
853
 
    int columns = cols;
854
 
    if (columns == -1)
855
 
        columns = (int) ceil(sqrt((float) items.count()));
856
 
 
857
 
    // When the number of columns grows, the number of rows will
858
 
    // fall. There's no way to shrink a grid, so we create a new
859
 
    // one.
860
 
    if (grid) delete grid;
861
 
    grid = new QGridLayout(this);
862
 
    grid->setMargin(1);
863
 
    grid->setSpacing(0);
864
 
 
865
 
    int ccol = 0, crow = 0;
866
 
    for (int i = 0; i < items.size(); ++i) {
867
 
        if (items.at(i)) {
868
 
            widgetAt[crow][ccol] = items.at(i);
869
 
            grid->addWidget(items.at(i), crow, ccol++);
870
 
            if (ccol == columns) {
871
 
                ++crow;
872
 
                ccol = 0;
873
 
            }
874
 
        }
875
 
    }
876
 
 
877
 
    if (moreButton) {
878
 
        grid->addWidget(moreButton, crow, ccol);
879
 
        widgetAt[crow][ccol] = moreButton;
880
 
    }
881
 
    updateGeometry();
882
 
}
883
 
 
884
 
/*! \internal
885
 
 
886
 
    Copies the color dialog's currently selected item and emits
887
 
    itemSelected().
888
 
*/
889
 
void ColorPickerPopup::getColorFromDialog()
890
 
{
891
 
    bool ok;
892
 
    QRgb rgb = QColorDialog::getRgba(lastSel.rgba(), &ok, parentWidget());
893
 
    if (!ok)
894
 
        return;
895
 
 
896
 
    QColor col = QColor::fromRgba(rgb);
897
 
    insertColor(col, tr("Custom"), -1);
898
 
    lastSel = col;
899
 
    emit selected(col);
900
 
}
901
 
 
902
 
/*!
903
 
    Constructs a ColorPickerItem whose color is set to \a color, and
904
 
    whose name is set to \a text.
905
 
*/
906
 
ColorPickerItem::ColorPickerItem(const QColor &color, const QString &text,
907
 
                                     QWidget *parent)
908
 
    : QFrame(parent), c(color), t(text), sel(false)
909
 
{
910
 
    setToolTip(t);
911
 
    setFixedWidth(24);
912
 
    setFixedHeight(21);
913
 
}
914
 
 
915
 
/*!
916
 
    Destructs a ColorPickerItem.
917
 
 */
918
 
ColorPickerItem::~ColorPickerItem()
919
 
{
920
 
}
921
 
 
922
 
/*!
923
 
    Returns the item's color.
924
 
 
925
 
    \sa text()
926
 
*/
927
 
QColor ColorPickerItem::color() const
928
 
{
929
 
    return c;
930
 
}
931
 
 
932
 
/*!
933
 
    Returns the item's text.
934
 
 
935
 
    \sa color()
936
 
*/
937
 
QString ColorPickerItem::text() const
938
 
{
939
 
    return t;
940
 
}
941
 
 
942
 
/*!
943
 
 
944
 
*/
945
 
bool ColorPickerItem::isSelected() const
946
 
{
947
 
    return sel;
948
 
}
949
 
 
950
 
/*!
951
 
 
952
 
*/
953
 
void ColorPickerItem::setSelected(bool selected)
954
 
{
955
 
    sel = selected;
956
 
    update();
957
 
}
958
 
 
959
 
/*!
960
 
    Sets the item's color to \a color, and its name to \a text.
961
 
*/
962
 
void ColorPickerItem::setColor(const QColor &color, const QString &text)
963
 
{
964
 
    c = color;
965
 
    t = text;
966
 
    setToolTip(t);
967
 
    update();
968
 
}
969
 
 
970
 
/*!
971
 
 
972
 
*/
973
 
void ColorPickerItem::mouseMoveEvent(QMouseEvent *)
974
 
{
975
 
    setFocus();
976
 
    update();
977
 
}
978
 
 
979
 
/*!
980
 
 
981
 
*/
982
 
void ColorPickerItem::mouseReleaseEvent(QMouseEvent *)
983
 
{
984
 
    sel = true;
985
 
    emit selected();
986
 
}
987
 
 
988
 
/*!
989
 
 
990
 
*/
991
 
void ColorPickerItem::mousePressEvent(QMouseEvent *)
992
 
{
993
 
    setFocus();
994
 
    update();
995
 
}
996
 
 
997
 
/*!
998
 
 
999
 
*/
1000
 
void ColorPickerItem::paintEvent(QPaintEvent *)
1001
 
{
1002
 
    QPainter p(this);
1003
 
    int w = width();                    // width of cell in pixels
1004
 
    int h = height();                   // height of cell in pixels
1005
 
 
1006
 
    p.setPen( QPen( Qt::gray, 0, Qt::SolidLine ) );
1007
 
 
1008
 
    if (sel)
1009
 
        p.drawRect(1, 1, w - 3, h - 3);
1010
 
 
1011
 
    p.setPen( QPen( Qt::black, 0, Qt::SolidLine ) );
1012
 
    p.drawRect(3, 3, w - 7, h - 7);
1013
 
    p.fillRect(QRect(4, 4, w - 8, h - 8), QBrush(c));
1014
 
 
1015
 
    if (hasFocus())
1016
 
        p.drawRect(0, 0, w - 1, h - 1);
1017
 
}
1018
 
 
1019
 
/*!
1020
 
 
1021
 
*/
1022
 
ColorPickerButton::ColorPickerButton(QWidget *parent)
1023
 
    : QFrame(parent)
1024
 
{
1025
 
    setFrameStyle(StyledPanel);
1026
 
}
1027
 
 
1028
 
/*!
1029
 
 
1030
 
*/
1031
 
void ColorPickerButton::mousePressEvent(QMouseEvent *)
1032
 
{
1033
 
    setFrameShadow(Sunken);
1034
 
    update();
1035
 
}
1036
 
 
1037
 
/*!
1038
 
 
1039
 
*/
1040
 
void ColorPickerButton::mouseMoveEvent(QMouseEvent *)
1041
 
{
1042
 
    setFocus();
1043
 
    update();
1044
 
}
1045
 
 
1046
 
/*!
1047
 
 
1048
 
*/
1049
 
void ColorPickerButton::mouseReleaseEvent(QMouseEvent *)
1050
 
{
1051
 
    setFrameShadow(Raised);
1052
 
    repaint();
1053
 
    emit clicked();
1054
 
}
1055
 
 
1056
 
/*!
1057
 
 
1058
 
*/
1059
 
void ColorPickerButton::keyPressEvent(QKeyEvent *e)
1060
 
{
1061
 
    if (e->key() == Qt::Key_Up
1062
 
        || e->key() == Qt::Key_Down
1063
 
        || e->key() == Qt::Key_Left
1064
 
        || e->key() == Qt::Key_Right) {
1065
 
        qApp->sendEvent(parent(), e);
1066
 
    } else if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Space || e->key() == Qt::Key_Return) {
1067
 
        setFrameShadow(Sunken);
1068
 
        update();
1069
 
    } else {
1070
 
        QFrame::keyPressEvent(e);
1071
 
    }
1072
 
}
1073
 
 
1074
 
/*!
1075
 
 
1076
 
*/
1077
 
void ColorPickerButton::keyReleaseEvent(QKeyEvent *e)
1078
 
{
1079
 
    if (e->key() == Qt::Key_Up
1080
 
        || e->key() == Qt::Key_Down
1081
 
        || e->key() == Qt::Key_Left
1082
 
        || e->key() == Qt::Key_Right) {
1083
 
        qApp->sendEvent(parent(), e);
1084
 
    } else if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Space || e->key() == Qt::Key_Return) {
1085
 
        setFrameShadow(Raised);
1086
 
        repaint();
1087
 
        emit clicked();
1088
 
    } else {
1089
 
        QFrame::keyReleaseEvent(e);
1090
 
    }
1091
 
 
1092
 
}
1093
 
 
1094
 
/*!
1095
 
 
1096
 
*/
1097
 
void ColorPickerButton::focusInEvent(QFocusEvent *e)
1098
 
{
1099
 
    setFrameShadow(Raised);
1100
 
    update();
1101
 
    QFrame::focusOutEvent(e);
1102
 
}
1103
 
 
1104
 
/*!
1105
 
 
1106
 
*/
1107
 
void ColorPickerButton::focusOutEvent(QFocusEvent *e)
1108
 
{
1109
 
    setFrameShadow(Raised);
1110
 
    update();
1111
 
    QFrame::focusOutEvent(e);
1112
 
}
1113
 
 
1114
 
/*!
1115
 
 
1116
 
*/
1117
 
void ColorPickerButton::paintEvent(QPaintEvent *e)
1118
 
{
1119
 
    QFrame::paintEvent(e);
1120
 
 
1121
 
    QPainter p(this);
1122
 
    p.fillRect(contentsRect(), palette().button());
1123
 
 
1124
 
    QRect r = rect();
1125
 
 
1126
 
    int offset = frameShadow() == Sunken ? 1 : 0;
1127
 
 
1128
 
    QPen pen(palette().buttonText(), 1);
1129
 
    p.setPen(pen);
1130
 
 
1131
 
    p.drawRect(r.center().x() + offset - 4, r.center().y() + offset, 1, 1);
1132
 
    p.drawRect(r.center().x() + offset    , r.center().y() + offset, 1, 1);
1133
 
    p.drawRect(r.center().x() + offset + 4, r.center().y() + offset, 1, 1);
1134
 
    if (hasFocus()) {
1135
 
        p.setPen( QPen( Qt::black, 0, Qt::SolidLine ) );
1136
 
        p.drawRect(0, 0, width() - 1, height() - 1);
1137
 
    }
1138
 
 
1139
 
    p.end();
1140
 
 
1141
 
}
1142
 
 
1143
 
#include "qtcolorpicker.moc"
1144