]> sigrok.org Git - pulseview.git/blobdiff - pv/widgets/wellarray.cpp
Added QWellArray from Qt
[pulseview.git] / pv / widgets / wellarray.cpp
diff --git a/pv/widgets/wellarray.cpp b/pv/widgets/wellarray.cpp
new file mode 100644 (file)
index 0000000..6776e34
--- /dev/null
@@ -0,0 +1,308 @@
+/****************************************************************************
+**
+** 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;
+    }
+
+}