--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#define QT_NO_MENU
+
+#include <QPainter>
+#include <QPaintEvent>
+#include <QStyle>
+#include <QStyleOptionFrame>
+
+#include "wellarray.h"
+
+void QWellArray::paintEvent(QPaintEvent *e)
+{
+ QRect r = e->rect();
+ int cx = r.x();
+ int cy = r.y();
+ int ch = r.height();
+ int cw = r.width();
+ int colfirst = columnAt(cx);
+ int collast = columnAt(cx + cw);
+ int rowfirst = rowAt(cy);
+ int rowlast = rowAt(cy + ch);
+
+ if (isRightToLeft()) {
+ int t = colfirst;
+ colfirst = collast;
+ collast = t;
+ }
+
+ QPainter painter(this);
+ QPainter *p = &painter;
+ QRect rect(0, 0, cellWidth(), cellHeight());
+
+
+ if (collast < 0 || collast >= ncols)
+ collast = ncols-1;
+ if (rowlast < 0 || rowlast >= nrows)
+ rowlast = nrows-1;
+
+ // Go through the rows
+ for (int r = rowfirst; r <= rowlast; ++r) {
+ // get row position and height
+ int rowp = rowY(r);
+
+ // Go through the columns in the row r
+ // if we know from where to where, go through [colfirst, collast],
+ // else go through all of them
+ for (int c = colfirst; c <= collast; ++c) {
+ // get position and width of column c
+ int colp = columnX(c);
+ // Translate painter and draw the cell
+ rect.translate(colp, rowp);
+ paintCell(p, r, c, rect);
+ rect.translate(-colp, -rowp);
+ }
+ }
+}
+
+struct QWellArrayData {
+ QBrush *brush;
+};
+
+QWellArray::QWellArray(int rows, int cols, QWidget *parent)
+ : QWidget(parent)
+ ,nrows(rows), ncols(cols)
+{
+ d = 0;
+ setFocusPolicy(Qt::StrongFocus);
+ cellw = 28;
+ cellh = 24;
+ curCol = 0;
+ curRow = 0;
+ selCol = -1;
+ selRow = -1;
+}
+
+QSize QWellArray::sizeHint() const
+{
+ ensurePolished();
+ return gridSize().boundedTo(QSize(640, 480));
+}
+
+
+void QWellArray::paintCell(QPainter* p, int row, int col, const QRect &rect)
+{
+ int b = 3; //margin
+
+ const QPalette & g = palette();
+ QStyleOptionFrame opt;
+ int dfw = style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
+ opt.lineWidth = dfw;
+ opt.midLineWidth = 1;
+ opt.rect = rect.adjusted(b, b, -b, -b);
+ opt.palette = g;
+ opt.state = QStyle::State_Enabled | QStyle::State_Sunken;
+ style()->drawPrimitive(QStyle::PE_Frame, &opt, p, this);
+ b += dfw;
+
+ if ((row == curRow) && (col == curCol)) {
+ if (hasFocus()) {
+ QStyleOptionFocusRect opt;
+ opt.palette = g;
+ opt.rect = rect;
+ opt.state = QStyle::State_None | QStyle::State_KeyboardFocusChange;
+ style()->drawPrimitive(QStyle::PE_FrameFocusRect, &opt, p, this);
+ }
+ }
+ paintCellContents(p, row, col, opt.rect.adjusted(dfw, dfw, -dfw, -dfw));
+}
+
+/*!
+ Reimplement this function to change the contents of the well array.
+ */
+void QWellArray::paintCellContents(QPainter *p, int row, int col, const QRect &r)
+{
+ if (d) {
+ p->fillRect(r, d->brush[row*numCols()+col]);
+ } else {
+ p->fillRect(r, Qt::white);
+ p->setPen(Qt::black);
+ p->drawLine(r.topLeft(), r.bottomRight());
+ p->drawLine(r.topRight(), r.bottomLeft());
+ }
+}
+
+void QWellArray::mousePressEvent(QMouseEvent *e)
+{
+ // The current cell marker is set to the cell the mouse is pressed in
+ QPoint pos = e->pos();
+ setCurrent(rowAt(pos.y()), columnAt(pos.x()));
+}
+
+void QWellArray::mouseReleaseEvent(QMouseEvent * /* event */)
+{
+ // The current cell marker is set to the cell the mouse is clicked in
+ setSelected(curRow, curCol);
+}
+
+
+/*
+ Sets the cell currently having the focus. This is not necessarily
+ the same as the currently selected cell.
+*/
+
+void QWellArray::setCurrent(int row, int col)
+{
+ if ((curRow == row) && (curCol == col))
+ return;
+
+ if (row < 0 || col < 0)
+ row = col = -1;
+
+ int oldRow = curRow;
+ int oldCol = curCol;
+
+ curRow = row;
+ curCol = col;
+
+ updateCell(oldRow, oldCol);
+ updateCell(curRow, curCol);
+}
+
+/*
+ Sets the currently selected cell to \a row, \a column. If \a row or
+ \a column are less than zero, the current cell is unselected.
+
+ Does not set the position of the focus indicator.
+*/
+void QWellArray::setSelected(int row, int col)
+{
+ int oldRow = selRow;
+ int oldCol = selCol;
+
+ if (row < 0 || col < 0)
+ row = col = -1;
+
+ selCol = col;
+ selRow = row;
+
+ updateCell(oldRow, oldCol);
+ updateCell(selRow, selCol);
+ if (row >= 0)
+ emit selected(row, col);
+
+#ifndef QT_NO_MENU
+ if (isVisible() && qobject_cast<QMenu*>(parentWidget()))
+ parentWidget()->close();
+#endif
+}
+
+void QWellArray::focusInEvent(QFocusEvent*)
+{
+ updateCell(curRow, curCol);
+}
+
+void QWellArray::setCellBrush(int row, int col, const QBrush &b)
+{
+ if (!d) {
+ d = new QWellArrayData;
+ int i = numRows()*numCols();
+ d->brush = new QBrush[i];
+ }
+ if (row >= 0 && row < numRows() && col >= 0 && col < numCols())
+ d->brush[row*numCols()+col] = b;
+}
+
+/*
+ Returns the brush set for the cell at \a row, \a column. If no brush is
+ set, Qt::NoBrush is returned.
+*/
+
+QBrush QWellArray::cellBrush(int row, int col)
+{
+ if (d && row >= 0 && row < numRows() && col >= 0 && col < numCols())
+ return d->brush[row*numCols()+col];
+ return Qt::NoBrush;
+}
+
+
+
+/*!\reimp
+*/
+
+void QWellArray::focusOutEvent(QFocusEvent*)
+{
+ updateCell(curRow, curCol);
+}
+
+/*\reimp
+*/
+void QWellArray::keyPressEvent(QKeyEvent* e)
+{
+ switch(e->key()) { // Look at the key code
+ case Qt::Key_Left: // If 'left arrow'-key,
+ if(curCol > 0) // and cr't not in leftmost col
+ setCurrent(curRow, curCol - 1); // set cr't to next left column
+ break;
+ case Qt::Key_Right: // Correspondingly...
+ if(curCol < numCols()-1)
+ setCurrent(curRow, curCol + 1);
+ break;
+ case Qt::Key_Up:
+ if(curRow > 0)
+ setCurrent(curRow - 1, curCol);
+ break;
+ case Qt::Key_Down:
+ if(curRow < numRows()-1)
+ setCurrent(curRow + 1, curCol);
+ break;
+#if 0
+ // bad idea that shouldn't have been implemented; very counterintuitive
+ case Qt::Key_Return:
+ case Qt::Key_Enter:
+ /*
+ ignore the key, so that the dialog get it, but still select
+ the current row/col
+ */
+ e->ignore();
+ // fallthrough intended
+#endif
+ case Qt::Key_Space:
+ setSelected(curRow, curCol);
+ break;
+ default: // If not an interesting key,
+ e->ignore(); // we don't accept the event
+ return;
+ }
+
+}
--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** 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, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, 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.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QWidget>
+
+struct QWellArrayData;
+
+class QWellArray : public QWidget
+{
+ Q_OBJECT
+ Q_PROPERTY(int selectedColumn READ selectedColumn)
+ Q_PROPERTY(int selectedRow READ selectedRow)
+
+public:
+ QWellArray(int rows, int cols, QWidget* parent=0);
+ ~QWellArray() {}
+ QString cellContent(int row, int col) const;
+
+ int selectedColumn() const { return selCol; }
+ int selectedRow() const { return selRow; }
+
+ virtual void setCurrent(int row, int col);
+ virtual void setSelected(int row, int col);
+
+ QSize sizeHint() const;
+
+ virtual void setCellBrush(int row, int col, const QBrush &);
+ QBrush cellBrush(int row, int col);
+
+ inline int cellWidth() const
+ { return cellw; }
+
+ inline int cellHeight() const
+ { return cellh; }
+
+ inline int rowAt(int y) const
+ { return y / cellh; }
+
+ inline int columnAt(int x) const
+ { if (isRightToLeft()) return ncols - (x / cellw) - 1; return x / cellw; }
+
+ inline int rowY(int row) const
+ { return cellh * row; }
+
+ inline int columnX(int column) const
+ { if (isRightToLeft()) return cellw * (ncols - column - 1); return cellw * column; }
+
+ inline int numRows() const
+ { return nrows; }
+
+ inline int numCols() const
+ {return ncols; }
+
+ inline QRect cellRect() const
+ { return QRect(0, 0, cellw, cellh); }
+
+ inline QSize gridSize() const
+ { return QSize(ncols * cellw, nrows * cellh); }
+
+ QRect cellGeometry(int row, int column)
+ {
+ QRect r;
+ if (row >= 0 && row < nrows && column >= 0 && column < ncols)
+ r.setRect(columnX(column), rowY(row), cellw, cellh);
+ return r;
+ }
+
+ inline void updateCell(int row, int column) { update(cellGeometry(row, column)); }
+
+signals:
+ void selected(int row, int col);
+
+protected:
+ virtual void paintCell(QPainter *, int row, int col, const QRect&);
+ virtual void paintCellContents(QPainter *, int row, int col, const QRect&);
+
+ void mousePressEvent(QMouseEvent*);
+ void mouseReleaseEvent(QMouseEvent*);
+ void keyPressEvent(QKeyEvent*);
+ void focusInEvent(QFocusEvent*);
+ void focusOutEvent(QFocusEvent*);
+ void paintEvent(QPaintEvent *);
+
+private:
+ Q_DISABLE_COPY(QWellArray)
+
+ int nrows;
+ int ncols;
+ int cellw;
+ int cellh;
+ int curRow;
+ int curCol;
+ int selRow;
+ int selCol;
+ QWellArrayData *d;
+};