summaryrefslogtreecommitdiff
path: root/src/utils/colorpicker/qtcolorpicker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/utils/colorpicker/qtcolorpicker.cpp')
-rw-r--r--src/utils/colorpicker/qtcolorpicker.cpp1144
1 files changed, 1144 insertions, 0 deletions
diff --git a/src/utils/colorpicker/qtcolorpicker.cpp b/src/utils/colorpicker/qtcolorpicker.cpp
new file mode 100644
index 0000000..2a4fff1
--- /dev/null
+++ b/src/utils/colorpicker/qtcolorpicker.cpp
@@ -0,0 +1,1144 @@
+/****************************************************************************
+**
+** This file is part of a Qt Solutions component.
+**
+** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+**
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Solutions Commercial License Agreement provided
+** with the Software or, alternatively, in accordance with the terms
+** contained in a written agreement between you and Nokia.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** Please note Third Party Software included with Qt Solutions may impose
+** additional restrictions and it is the user's responsibility to ensure
+** that they have met the licensing requirements of the GPL, LGPL, or Qt
+** Solutions Commercial license and the relevant license of the Third
+** Party Software they are using.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+**
+****************************************************************************/
+
+#include <QtGui/QApplication>
+#include <QtGui/QDesktopWidget>
+#include <QtGui/QPainter>
+#include <QtGui/QPushButton>
+#include <QtGui/QColorDialog>
+#include <QtCore/QMap>
+#include <QtGui/QLayout>
+#include <QtGui/QStyle>
+#include <QtGui/QLabel>
+#include <QtGui/QToolTip>
+#include <QtGui/QPixmap>
+#include <QtGui/QFocusEvent>
+#include <QtGui/QPaintEvent>
+#include <QtGui/QGridLayout>
+#include <QtGui/QHideEvent>
+#include <QtGui/QKeyEvent>
+#include <QtGui/QShowEvent>
+#include <QtGui/QMouseEvent>
+#include <math.h>
+
+#include "qtcolorpicker.h"
+
+/*! \class QtColorPicker
+
+ \brief The QtColorPicker class provides a widget for selecting
+ colors from a popup color grid.
+
+ Users can invoke the color picker by clicking on it, or by
+ navigating to it and pressing Space. They can use the mouse or
+ arrow keys to navigate between colors on the grid, and select a
+ color by clicking or by pressing Enter or Space. The
+ colorChanged() signal is emitted whenever the color picker's color
+ changes.
+
+ The widget also supports negative selection: Users can click and
+ hold the mouse button on the QtColorPicker widget, then move the
+ mouse over the color grid and release the mouse button over the
+ color they wish to select.
+
+ The color grid shows a customized selection of colors. An optional
+ ellipsis "..." button (signifying "more") can be added at the
+ bottom of the grid; if the user presses this, a QColorDialog pops
+ up and lets them choose any color they like. This button is made
+ available by using setColorDialogEnabled().
+
+ When a color is selected, the QtColorPicker widget shows the color
+ and its name. If the name cannot be determined, the translatable
+ name "Custom" is used.
+
+ The QtColorPicker object is optionally initialized with the number
+ of columns in the color grid. Colors are then added left to right,
+ top to bottom using insertColor(). If the number of columns is not
+ set, QtColorPicker calculates the number of columns and rows that
+ will make the grid as square as possible.
+
+ \code
+ DrawWidget::DrawWidget(QWidget *parent, const char *name)
+ {
+ QtColorPicker *picker = new QtColorPicker(this);
+ picker->insertColor(red, "Red"));
+ picker->insertColor(QColor("green"), "Green"));
+ picker->insertColor(QColor(0, 0, 255), "Blue"));
+ picker->insertColor(white);
+
+ connect(colors, SIGNAL(colorChanged(const QColor &)), SLOT(setCurrentColor(const QColor &)));
+ }
+ \endcode
+
+ An alternative to adding colors manually is to initialize the grid
+ with QColorDialog's standard colors using setStandardColors().
+
+ QtColorPicker also provides a the static function getColor(),
+ which pops up the grid of standard colors at any given point.
+
+ \img colorpicker1.png
+ \img colorpicker2.png
+
+ \sa QColorDialog
+*/
+
+/*! \fn QtColorPicker::colorChanged(const QColor &color)
+
+ This signal is emitted when the QtColorPicker's color is changed.
+ \a color is the new color.
+
+ To obtain the color's name, use text().
+*/
+
+/*
+ A class that acts very much like a QPushButton. It's not styled,
+ so we can expect the exact same look, feel and geometry
+ everywhere. Also, this button always emits clicked on
+ mouseRelease, even if the mouse button was not pressed inside the
+ widget.
+*/
+class ColorPickerButton : public QFrame
+{
+ Q_OBJECT
+
+public:
+ ColorPickerButton(QWidget *parent);
+
+signals:
+ void clicked();
+
+protected:
+ void mousePressEvent(QMouseEvent *e);
+ void mouseMoveEvent(QMouseEvent *e);
+ void mouseReleaseEvent(QMouseEvent *e);
+ void keyPressEvent(QKeyEvent *e);
+ void keyReleaseEvent(QKeyEvent *e);
+ void paintEvent(QPaintEvent *e);
+ void focusInEvent(QFocusEvent *e);
+ void focusOutEvent(QFocusEvent *e);
+};
+
+/*
+ This class represents each "color" or item in the color grid.
+*/
+class ColorPickerItem : public QFrame
+{
+ Q_OBJECT
+
+public:
+ ColorPickerItem(const QColor &color = Qt::white, const QString &text = QString::null,
+ QWidget *parent = 0);
+ ~ColorPickerItem();
+
+ QColor color() const;
+ QString text() const;
+
+ void setSelected(bool);
+ bool isSelected() const;
+signals:
+ void clicked();
+ void selected();
+
+public slots:
+ void setColor(const QColor &color, const QString &text = QString());
+
+protected:
+ void mousePressEvent(QMouseEvent *e);
+ void mouseReleaseEvent(QMouseEvent *e);
+ void mouseMoveEvent(QMouseEvent *e);
+ void paintEvent(QPaintEvent *e);
+
+private:
+ QColor c;
+ QString t;
+ bool sel;
+};
+
+/*
+
+*/
+class ColorPickerPopup : public QFrame
+{
+ Q_OBJECT
+
+public:
+ ColorPickerPopup(int width, bool withColorDialog,
+ QWidget *parent = 0);
+ ~ColorPickerPopup();
+
+ void insertColor(const QColor &col, const QString &text, int index);
+ void exec();
+
+ void setExecFlag();
+
+ QColor lastSelected() const;
+
+ ColorPickerItem *find(const QColor &col) const;
+ QColor color(int index) const;
+
+signals:
+ void selected(const QColor &);
+ void hid();
+
+public slots:
+ void getColorFromDialog();
+
+protected slots:
+ void updateSelected();
+
+protected:
+ void keyPressEvent(QKeyEvent *e);
+ void showEvent(QShowEvent *e);
+ void hideEvent(QHideEvent *e);
+ void mouseReleaseEvent(QMouseEvent *e);
+
+ void regenerateGrid();
+
+private:
+ QMap<int, QMap<int, QWidget *> > widgetAt;
+ QList<ColorPickerItem *> items;
+ QGridLayout *grid;
+ ColorPickerButton *moreButton;
+ QEventLoop *eventLoop;
+
+ int lastPos;
+ int cols;
+ QColor lastSel;
+};
+
+/*!
+ Constructs a QtColorPicker widget. The popup will display a grid
+ with \a cols columns, or if \a cols is -1, the number of columns
+ will be calculated automatically.
+
+ If \a enableColorDialog is true, the popup will also have a "More"
+ button (signified by an ellipsis "...") that presents a
+ QColorDialog when clicked.
+
+ After constructing a QtColorPicker, call insertColor() to add
+ individual colors to the popup grid, or call setStandardColors()
+ to add all the standard colors in one go.
+
+ The \a parent argument is passed to QFrame's constructor.
+
+ \sa QFrame
+*/
+QtColorPicker::QtColorPicker(QWidget *parent,
+ int cols, bool enableColorDialog)
+ : QPushButton(parent), popup(0), withColorDialog(enableColorDialog)
+{
+ setFocusPolicy(Qt::StrongFocus);
+ setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
+ setAutoDefault(false);
+ setAutoFillBackground(true);
+ setCheckable(true);
+
+ // Set text
+ setText(tr("Black"));
+ firstInserted = false;
+
+ // Create and set icon
+ col = Qt::black;
+ dirty = true;
+
+ // Create color grid popup and connect to it.
+ popup = new ColorPickerPopup(cols, withColorDialog, this);
+ connect(popup, SIGNAL(selected(const QColor &)),
+ SLOT(setCurrentColor(const QColor &)));
+ connect(popup, SIGNAL(hid()), SLOT(popupClosed()));
+
+ // Connect this push button's pressed() signal.
+ connect(this, SIGNAL(toggled(bool)), SLOT(buttonPressed(bool)));
+}
+
+/*!
+ Destructs the QtColorPicker.
+*/
+QtColorPicker::~QtColorPicker()
+{
+}
+
+/*! \internal
+
+ Pops up the color grid, and makes sure the status of
+ QtColorPicker's button is right.
+*/
+void QtColorPicker::buttonPressed(bool toggled)
+{
+ if (!toggled)
+ return;
+
+ const QRect desktop = QApplication::desktop()->geometry();
+ // Make sure the popup is inside the desktop.
+ QPoint pos = mapToGlobal(rect().bottomLeft());
+ if (pos.x() < desktop.left())
+ pos.setX(desktop.left());
+ if (pos.y() < desktop.top())
+ pos.setY(desktop.top());
+
+ if ((pos.x() + popup->sizeHint().width()) > desktop.width())
+ pos.setX(desktop.width() - popup->sizeHint().width());
+ if ((pos.y() + popup->sizeHint().height()) > desktop.bottom())
+ pos.setY(desktop.bottom() - popup->sizeHint().height());
+ popup->move(pos);
+
+ if (ColorPickerItem *item = popup->find(col))
+ item->setSelected(true);
+
+ // Remove focus from this widget, preventing the focus rect
+ // from showing when the popup is shown. Order an update to
+ // make sure the focus rect is cleared.
+ clearFocus();
+ update();
+
+ // Allow keyboard navigation as soon as the popup shows.
+ popup->setFocus();
+
+ // Execute the popup. The popup will enter the event loop.
+ popup->show();
+}
+
+/*!
+ \internal
+*/
+void QtColorPicker::paintEvent(QPaintEvent *e)
+{
+ if (dirty) {
+ int iconSize = style()->pixelMetric(QStyle::PM_SmallIconSize);
+ QPixmap pix(iconSize, iconSize);
+ pix.fill(palette().button().color());
+
+ QPainter p(&pix);
+
+ int w = pix.width(); // width of cell in pixels
+ int h = pix.height(); // height of cell in pixels
+ p.setPen(QPen(Qt::gray));
+ p.setBrush(col);
+ p.drawRect(2, 2, w - 5, h - 5);
+ setIcon(QIcon(pix));
+
+ dirty = false;
+ }
+ QPushButton::paintEvent(e);
+}
+
+/*! \internal
+
+ Makes sure the button isn't pressed when the popup hides.
+*/
+void QtColorPicker::popupClosed()
+{
+ setChecked(false);
+ setFocus();
+}
+
+/*!
+ Returns the currently selected color.
+
+ \sa text()
+*/
+QColor QtColorPicker::currentColor() const
+{
+ return col;
+}
+
+/*!
+ Returns the color at position \a index.
+*/
+QColor QtColorPicker::color(int index) const
+{
+ return popup->color(index);
+}
+
+/*!
+ Adds the 17 predefined colors from the Qt namespace.
+
+ (The names given to the colors, "Black", "White", "Red", etc., are
+ all translatable.)
+
+ \sa insertColor()
+*/
+void QtColorPicker::setStandardColors()
+{
+ insertColor(Qt::black, tr("Black"));
+ insertColor(Qt::white, tr("White"));
+ insertColor(Qt::red, tr("Red"));
+ insertColor(Qt::darkRed, tr("Dark red"));
+ insertColor(Qt::green, tr("Green"));
+ insertColor(Qt::darkGreen, tr("Dark green"));
+ insertColor(Qt::blue, tr("Blue"));
+ insertColor(Qt::darkBlue, tr("Dark blue"));
+ insertColor(Qt::cyan, tr("Cyan"));
+ insertColor(Qt::darkCyan, tr("Dark cyan"));
+ insertColor(Qt::magenta, tr("Magenta"));
+ insertColor(Qt::darkMagenta, tr("Dark magenta"));
+ insertColor(Qt::yellow, tr("Yellow"));
+ insertColor(Qt::darkYellow, tr("Dark yellow"));
+ insertColor(Qt::gray, tr("Gray"));
+ insertColor(Qt::darkGray, tr("Dark gray"));
+ insertColor(Qt::lightGray, tr("Light gray"));
+}
+
+
+/*!
+ Makes \a color current. If \a color is not already in the color grid, it
+ is inserted with the text "Custom".
+
+ This function emits the colorChanged() signal if the new color is
+ valid, and different from the old one.
+*/
+void QtColorPicker::setCurrentColor(const QColor &color)
+{
+ if (col == color || !color.isValid())
+ return;
+
+ ColorPickerItem *item = popup->find(color);
+ if (!item) {
+ insertColor(color, tr("Custom"));
+ item = popup->find(color);
+ }
+
+ col = color;
+ setText(item->text());
+
+ dirty = true;
+
+ popup->hide();
+ repaint();
+
+ item->setSelected(true);
+ emit colorChanged(color);
+}
+
+/*!
+ Adds the color \a color with the name \a text to the color grid,
+ at position \a index. If index is -1, the color is assigned
+ automatically assigned a position, starting from left to right,
+ top to bottom.
+*/
+void QtColorPicker::insertColor(const QColor &color, const QString &text, int index)
+{
+ popup->insertColor(color, text, index);
+ if (!firstInserted) {
+ col = color;
+ setText(text);
+ firstInserted = true;
+ }
+}
+
+/*! \property QtColorPicker::colorDialog
+ \brief Whether the ellipsis "..." (more) button is available.
+
+ If this property is set to TRUE, the color grid popup will include
+ a "More" button (signified by an ellipsis, "...") which pops up a
+ QColorDialog when clicked. The user will then be able to select
+ any custom color they like.
+*/
+void QtColorPicker::setColorDialogEnabled(bool enabled)
+{
+ withColorDialog = enabled;
+}
+bool QtColorPicker::colorDialogEnabled() const
+{
+ return withColorDialog;
+}
+
+/*!
+ Pops up a color grid with Qt default colors at \a point, using
+ global coordinates. If \a allowCustomColors is true, there will
+ also be a button on the popup that invokes QColorDialog.
+
+ For example:
+
+ \code
+ void Drawer::mouseReleaseEvent(QMouseEvent *e)
+ {
+ if (e->button() & RightButton) {
+ QColor color = QtColorPicker::getColor(mapToGlobal(e->pos()));
+ }
+ }
+ \endcode
+*/
+QColor QtColorPicker::getColor(const QPoint &point, bool allowCustomColors)
+{
+ ColorPickerPopup popup(-1, allowCustomColors);
+
+ popup.insertColor(Qt::black, tr("Black"), 0);
+ popup.insertColor(Qt::white, tr("White"), 1);
+ popup.insertColor(Qt::red, tr("Red"), 2);
+ popup.insertColor(Qt::darkRed, tr("Dark red"), 3);
+ popup.insertColor(Qt::green, tr("Green"), 4);
+ popup.insertColor(Qt::darkGreen, tr("Dark green"), 5);
+ popup.insertColor(Qt::blue, tr("Blue"), 6);
+ popup.insertColor(Qt::darkBlue, tr("Dark blue"), 7);
+ popup.insertColor(Qt::cyan, tr("Cyan"), 8);
+ popup.insertColor(Qt::darkCyan, tr("Dark cyan"), 9);
+ popup.insertColor(Qt::magenta, tr("Magenta"), 10);
+ popup.insertColor(Qt::darkMagenta, tr("Dark magenta"), 11);
+ popup.insertColor(Qt::yellow, tr("Yellow"), 12);
+ popup.insertColor(Qt::darkYellow, tr("Dark yellow"), 13);
+ popup.insertColor(Qt::gray, tr("Gray"), 14);
+ popup.insertColor(Qt::darkGray, tr("Dark gray"), 15);
+ popup.insertColor(Qt::lightGray, tr("Light gray"), 16);
+
+ popup.move(point);
+ popup.exec();
+ return popup.lastSelected();
+}
+
+/*! \internal
+
+ Constructs the popup widget.
+*/
+ColorPickerPopup::ColorPickerPopup(int width, bool withColorDialog,
+ QWidget *parent)
+ : QFrame(parent, Qt::Popup)
+{
+ setFrameStyle(QFrame::StyledPanel);
+ setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
+
+ setFocusPolicy(Qt::StrongFocus);
+ setMouseTracking(true);
+ cols = width;
+
+ if (withColorDialog) {
+ moreButton = new ColorPickerButton(this);
+ moreButton->setFixedWidth(24);
+ moreButton->setFixedHeight(21);
+ moreButton->setFrameRect(QRect(2, 2, 20, 17));
+ connect(moreButton, SIGNAL(clicked()), SLOT(getColorFromDialog()));
+ } else {
+ moreButton = 0;
+ }
+
+ eventLoop = 0;
+ grid = 0;
+ regenerateGrid();
+}
+
+
+/*! \internal
+
+ Destructs the popup widget.
+*/
+ColorPickerPopup::~ColorPickerPopup()
+{
+ if (eventLoop)
+ eventLoop->exit();
+}
+
+/*! \internal
+
+ If there is an item whole color is equal to \a col, returns a
+ pointer to this item; otherwise returns 0.
+*/
+ColorPickerItem *ColorPickerPopup::find(const QColor &col) const
+{
+ for (int i = 0; i < items.size(); ++i) {
+ if (items.at(i) && items.at(i)->color() == col)
+ return items.at(i);
+ }
+
+ return 0;
+}
+
+/*! \internal
+
+ Adds \a item to the grid. The items are added from top-left to
+ bottom-right.
+*/
+void ColorPickerPopup::insertColor(const QColor &col, const QString &text, int index)
+{
+ // Don't add colors that we have already.
+ ColorPickerItem *existingItem = find(col);
+ ColorPickerItem *lastSelectedItem = find(lastSelected());
+
+ if (existingItem) {
+ if (lastSelectedItem && existingItem != lastSelectedItem)
+ lastSelectedItem->setSelected(false);
+ existingItem->setFocus();
+ existingItem->setSelected(true);
+ return;
+ }
+
+ ColorPickerItem *item = new ColorPickerItem(col, text, this);
+
+ if (lastSelectedItem) {
+ lastSelectedItem->setSelected(false);
+ }
+ else {
+ item->setSelected(true);
+ lastSel = col;
+ }
+ item->setFocus();
+
+ connect(item, SIGNAL(selected()), SLOT(updateSelected()));
+
+ if (index == -1)
+ index = items.count();
+
+ items.insert((unsigned int)index, item);
+ regenerateGrid();
+
+ update();
+}
+
+/*! \internal
+
+*/
+QColor ColorPickerPopup::color(int index) const
+{
+ if (index < 0 || index > (int) items.count() - 1)
+ return QColor();
+
+ ColorPickerPopup *that = (ColorPickerPopup *)this;
+ return that->items.at(index)->color();
+}
+
+/*! \internal
+
+*/
+void ColorPickerPopup::exec()
+{
+ show();
+
+ QEventLoop e;
+ eventLoop = &e;
+ (void) e.exec();
+ eventLoop = 0;
+}
+
+/*! \internal
+
+*/
+void ColorPickerPopup::updateSelected()
+{
+ QLayoutItem *layoutItem;
+ int i = 0;
+ while ((layoutItem = grid->itemAt(i)) != 0) {
+ QWidget *w = layoutItem->widget();
+ if (w && w->inherits("ColorPickerItem")) {
+ ColorPickerItem *litem = reinterpret_cast<ColorPickerItem *>(layoutItem->widget());
+ if (litem != sender())
+ litem->setSelected(false);
+ }
+ ++i;
+ }
+
+ if (sender() && sender()->inherits("ColorPickerItem")) {
+ ColorPickerItem *item = (ColorPickerItem *)sender();
+ lastSel = item->color();
+ emit selected(item->color());
+ }
+
+ hide();
+}
+
+/*! \internal
+
+*/
+void ColorPickerPopup::mouseReleaseEvent(QMouseEvent *e)
+{
+ if (!rect().contains(e->pos()))
+ hide();
+}
+
+/*! \internal
+
+ Controls keyboard navigation and selection on the color grid.
+*/
+void ColorPickerPopup::keyPressEvent(QKeyEvent *e)
+{
+ int curRow = 0;
+ int curCol = 0;
+
+ bool foundFocus = false;
+ for (int j = 0; !foundFocus && j < grid->rowCount(); ++j) {
+ for (int i = 0; !foundFocus && i < grid->columnCount(); ++i) {
+ if (widgetAt[j][i] && widgetAt[j][i]->hasFocus()) {
+ curRow = j;
+ curCol = i;
+ foundFocus = true;
+ break;
+ }
+ }
+ }
+
+ switch (e->key()) {
+ case Qt::Key_Left:
+ if (curCol > 0) --curCol;
+ else if (curRow > 0) { --curRow; curCol = grid->columnCount() - 1; }
+ break;
+ case Qt::Key_Right:
+ if (curCol < grid->columnCount() - 1 && widgetAt[curRow][curCol + 1]) ++curCol;
+ else if (curRow < grid->rowCount() - 1) { ++curRow; curCol = 0; }
+ break;
+ case Qt::Key_Up:
+ if (curRow > 0) --curRow;
+ else curCol = 0;
+ break;
+ case Qt::Key_Down:
+ if (curRow < grid->rowCount() - 1) {
+ QWidget *w = widgetAt[curRow + 1][curCol];
+ if (w) {
+ ++curRow;
+ } else for (int i = 1; i < grid->columnCount(); ++i) {
+ if (!widgetAt[curRow + 1][i]) {
+ curCol = i - 1;
+ ++curRow;
+ break;
+ }
+ }
+ }
+ break;
+ case Qt::Key_Space:
+ case Qt::Key_Return:
+ case Qt::Key_Enter: {
+ QWidget *w = widgetAt[curRow][curCol];
+ if (w && w->inherits("ColorPickerItem")) {
+ ColorPickerItem *wi = reinterpret_cast<ColorPickerItem *>(w);
+ wi->setSelected(true);
+
+ QLayoutItem *layoutItem;
+ int i = 0;
+ while ((layoutItem = grid->itemAt(i)) != 0) {
+ QWidget *w = layoutItem->widget();
+ if (w && w->inherits("ColorPickerItem")) {
+ ColorPickerItem *litem
+ = reinterpret_cast<ColorPickerItem *>(layoutItem->widget());
+ if (litem != wi)
+ litem->setSelected(false);
+ }
+ ++i;
+ }
+
+ lastSel = wi->color();
+ emit selected(wi->color());
+ hide();
+ } else if (w && w->inherits("QPushButton")) {
+ ColorPickerItem *wi = reinterpret_cast<ColorPickerItem *>(w);
+ wi->setSelected(true);
+
+ QLayoutItem *layoutItem;
+ int i = 0;
+ while ((layoutItem = grid->itemAt(i)) != 0) {
+ QWidget *w = layoutItem->widget();
+ if (w && w->inherits("ColorPickerItem")) {
+ ColorPickerItem *litem
+ = reinterpret_cast<ColorPickerItem *>(layoutItem->widget());
+ if (litem != wi)
+ litem->setSelected(false);
+ }
+ ++i;
+ }
+
+ lastSel = wi->color();
+ emit selected(wi->color());
+ hide();
+ }
+ }
+ break;
+ case Qt::Key_Escape:
+ hide();
+ break;
+ default:
+ e->ignore();
+ break;
+ }
+
+ widgetAt[curRow][curCol]->setFocus();
+}
+
+/*! \internal
+
+*/
+void ColorPickerPopup::hideEvent(QHideEvent *e)
+{
+ if (eventLoop) {
+ eventLoop->exit();
+ }
+
+ setFocus();
+
+ emit hid();
+ QFrame::hideEvent(e);
+}
+
+/*! \internal
+
+*/
+QColor ColorPickerPopup::lastSelected() const
+{
+ return lastSel;
+}
+
+/*! \internal
+
+ Sets focus on the popup to enable keyboard navigation. Draws
+ focusRect and selection rect.
+*/
+void ColorPickerPopup::showEvent(QShowEvent *)
+{
+ bool foundSelected = false;
+ for (int i = 0; i < grid->columnCount(); ++i) {
+ for (int j = 0; j < grid->rowCount(); ++j) {
+ QWidget *w = widgetAt[j][i];
+ if (w && w->inherits("ColorPickerItem")) {
+ if (((ColorPickerItem *)w)->isSelected()) {
+ w->setFocus();
+ foundSelected = true;
+ break;
+ }
+ }
+ }
+ }
+
+ if (!foundSelected) {
+ if (items.count() == 0)
+ setFocus();
+ else
+ widgetAt[0][0]->setFocus();
+ }
+}
+
+/*!
+
+*/
+void ColorPickerPopup::regenerateGrid()
+{
+ widgetAt.clear();
+
+ int columns = cols;
+ if (columns == -1)
+ columns = (int) ceil(sqrt((float) items.count()));
+
+ // When the number of columns grows, the number of rows will
+ // fall. There's no way to shrink a grid, so we create a new
+ // one.
+ if (grid) delete grid;
+ grid = new QGridLayout(this);
+ grid->setMargin(1);
+ grid->setSpacing(0);
+
+ int ccol = 0, crow = 0;
+ for (int i = 0; i < items.size(); ++i) {
+ if (items.at(i)) {
+ widgetAt[crow][ccol] = items.at(i);
+ grid->addWidget(items.at(i), crow, ccol++);
+ if (ccol == columns) {
+ ++crow;
+ ccol = 0;
+ }
+ }
+ }
+
+ if (moreButton) {
+ grid->addWidget(moreButton, crow, ccol);
+ widgetAt[crow][ccol] = moreButton;
+ }
+ updateGeometry();
+}
+
+/*! \internal
+
+ Copies the color dialog's currently selected item and emits
+ itemSelected().
+*/
+void ColorPickerPopup::getColorFromDialog()
+{
+ bool ok;
+ QRgb rgb = QColorDialog::getRgba(lastSel.rgba(), &ok, parentWidget());
+ if (!ok)
+ return;
+
+ QColor col = QColor::fromRgba(rgb);
+ insertColor(col, tr("Custom"), -1);
+ lastSel = col;
+ emit selected(col);
+}
+
+/*!
+ Constructs a ColorPickerItem whose color is set to \a color, and
+ whose name is set to \a text.
+*/
+ColorPickerItem::ColorPickerItem(const QColor &color, const QString &text,
+ QWidget *parent)
+ : QFrame(parent), c(color), t(text), sel(false)
+{
+ setToolTip(t);
+ setFixedWidth(24);
+ setFixedHeight(21);
+}
+
+/*!
+ Destructs a ColorPickerItem.
+ */
+ColorPickerItem::~ColorPickerItem()
+{
+}
+
+/*!
+ Returns the item's color.
+
+ \sa text()
+*/
+QColor ColorPickerItem::color() const
+{
+ return c;
+}
+
+/*!
+ Returns the item's text.
+
+ \sa color()
+*/
+QString ColorPickerItem::text() const
+{
+ return t;
+}
+
+/*!
+
+*/
+bool ColorPickerItem::isSelected() const
+{
+ return sel;
+}
+
+/*!
+
+*/
+void ColorPickerItem::setSelected(bool selected)
+{
+ sel = selected;
+ update();
+}
+
+/*!
+ Sets the item's color to \a color, and its name to \a text.
+*/
+void ColorPickerItem::setColor(const QColor &color, const QString &text)
+{
+ c = color;
+ t = text;
+ setToolTip(t);
+ update();
+}
+
+/*!
+
+*/
+void ColorPickerItem::mouseMoveEvent(QMouseEvent *)
+{
+ setFocus();
+ update();
+}
+
+/*!
+
+*/
+void ColorPickerItem::mouseReleaseEvent(QMouseEvent *)
+{
+ sel = true;
+ emit selected();
+}
+
+/*!
+
+*/
+void ColorPickerItem::mousePressEvent(QMouseEvent *)
+{
+ setFocus();
+ update();
+}
+
+/*!
+
+*/
+void ColorPickerItem::paintEvent(QPaintEvent *)
+{
+ QPainter p(this);
+ int w = width(); // width of cell in pixels
+ int h = height(); // height of cell in pixels
+
+ p.setPen( QPen( Qt::gray, 0, Qt::SolidLine ) );
+
+ if (sel)
+ p.drawRect(1, 1, w - 3, h - 3);
+
+ p.setPen( QPen( Qt::black, 0, Qt::SolidLine ) );
+ p.drawRect(3, 3, w - 7, h - 7);
+ p.fillRect(QRect(4, 4, w - 8, h - 8), QBrush(c));
+
+ if (hasFocus())
+ p.drawRect(0, 0, w - 1, h - 1);
+}
+
+/*!
+
+*/
+ColorPickerButton::ColorPickerButton(QWidget *parent)
+ : QFrame(parent)
+{
+ setFrameStyle(StyledPanel);
+}
+
+/*!
+
+*/
+void ColorPickerButton::mousePressEvent(QMouseEvent *)
+{
+ setFrameShadow(Sunken);
+ update();
+}
+
+/*!
+
+*/
+void ColorPickerButton::mouseMoveEvent(QMouseEvent *)
+{
+ setFocus();
+ update();
+}
+
+/*!
+
+*/
+void ColorPickerButton::mouseReleaseEvent(QMouseEvent *)
+{
+ setFrameShadow(Raised);
+ repaint();
+ emit clicked();
+}
+
+/*!
+
+*/
+void ColorPickerButton::keyPressEvent(QKeyEvent *e)
+{
+ if (e->key() == Qt::Key_Up
+ || e->key() == Qt::Key_Down
+ || e->key() == Qt::Key_Left
+ || e->key() == Qt::Key_Right) {
+ qApp->sendEvent(parent(), e);
+ } else if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Space || e->key() == Qt::Key_Return) {
+ setFrameShadow(Sunken);
+ update();
+ } else {
+ QFrame::keyPressEvent(e);
+ }
+}
+
+/*!
+
+*/
+void ColorPickerButton::keyReleaseEvent(QKeyEvent *e)
+{
+ if (e->key() == Qt::Key_Up
+ || e->key() == Qt::Key_Down
+ || e->key() == Qt::Key_Left
+ || e->key() == Qt::Key_Right) {
+ qApp->sendEvent(parent(), e);
+ } else if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Space || e->key() == Qt::Key_Return) {
+ setFrameShadow(Raised);
+ repaint();
+ emit clicked();
+ } else {
+ QFrame::keyReleaseEvent(e);
+ }
+
+}
+
+/*!
+
+*/
+void ColorPickerButton::focusInEvent(QFocusEvent *e)
+{
+ setFrameShadow(Raised);
+ update();
+ QFrame::focusOutEvent(e);
+}
+
+/*!
+
+*/
+void ColorPickerButton::focusOutEvent(QFocusEvent *e)
+{
+ setFrameShadow(Raised);
+ update();
+ QFrame::focusOutEvent(e);
+}
+
+/*!
+
+*/
+void ColorPickerButton::paintEvent(QPaintEvent *e)
+{
+ QFrame::paintEvent(e);
+
+ QPainter p(this);
+ p.fillRect(contentsRect(), palette().button());
+
+ QRect r = rect();
+
+ int offset = frameShadow() == Sunken ? 1 : 0;
+
+ QPen pen(palette().buttonText(), 1);
+ p.setPen(pen);
+
+ p.drawRect(r.center().x() + offset - 4, r.center().y() + offset, 1, 1);
+ p.drawRect(r.center().x() + offset , r.center().y() + offset, 1, 1);
+ p.drawRect(r.center().x() + offset + 4, r.center().y() + offset, 1, 1);
+ if (hasFocus()) {
+ p.setPen( QPen( Qt::black, 0, Qt::SolidLine ) );
+ p.drawRect(0, 0, width() - 1, height() - 1);
+ }
+
+ p.end();
+
+}
+
+#include "qtcolorpicker.moc"
+