From: Joel Holdsworth Date: Wed, 2 Oct 2013 21:04:46 +0000 (+0100) Subject: Added QWellArray from Qt X-Git-Tag: pulseview-0.2.0~267 X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=0c0e1888d11fd2135e439f82993b56b2323703ec;p=pulseview.git Added QWellArray from Qt This class orginates from a private class used inside QColorDialog. It is licensed under the LGPL v2.1 + GPL v3.0 --- diff --git a/CMakeLists.txt b/CMakeLists.txt index c2e9001b..469cb5e2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -142,6 +142,7 @@ set(pulseview_SOURCES pv/view/viewport.cpp pv/view/decode/annotation.cpp pv/widgets/popup.cpp + pv/widgets/wellarray.cpp ) # This list includes only QObject derrived class headers @@ -165,6 +166,7 @@ set(pulseview_HEADERS pv/view/trace.h pv/view/view.h pv/view/viewport.h + pv/widgets/wellarray.h ) set(pulseview_FORMS diff --git a/pv/widgets/wellarray.cpp b/pv/widgets/wellarray.cpp new file mode 100644 index 00000000..6776e34f --- /dev/null +++ b/pv/widgets/wellarray.cpp @@ -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 +#include +#include +#include + +#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(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; + } + +} diff --git a/pv/widgets/wellarray.h b/pv/widgets/wellarray.h new file mode 100644 index 00000000..0195b5d7 --- /dev/null +++ b/pv/widgets/wellarray.h @@ -0,0 +1,134 @@ +/**************************************************************************** +** +** 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 + +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; +};