|
@@ -27,13 +27,47 @@
|
|
|
#include <QVariant>
|
|
|
#include <QTableWidgetItem>
|
|
|
#include <QResizeEvent>
|
|
|
+#include <QDoubleSpinBox>
|
|
|
+#include <QItemEditorFactory>
|
|
|
+#include <QStyledItemDelegate>
|
|
|
#include <QDebug>
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
+// Custom item editors
|
|
|
+
|
|
|
+namespace
|
|
|
+{
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
+ class CustomDoubleSpinBox : public QDoubleSpinBox
|
|
|
+ {
|
|
|
+ public:
|
|
|
+ CustomDoubleSpinBox(QWidget * newParent):QDoubleSpinBox(newParent)
|
|
|
+ {
|
|
|
+ // We know that the parentWidget of newParent will be a ctkMatrixWidget because this object is
|
|
|
+ // created by the QItemEditorFactory
|
|
|
+ ctkMatrixWidget* matrixWidget = qobject_cast<ctkMatrixWidget*>(newParent->parentWidget());
|
|
|
+ Q_ASSERT(matrixWidget);
|
|
|
+
|
|
|
+ this->setMinimum(matrixWidget->minimum());
|
|
|
+ this->setMaximum(matrixWidget->maximum());
|
|
|
+ this->setDecimals(matrixWidget->decimals());
|
|
|
+ this->setSingleStep(matrixWidget->singleStep());
|
|
|
+ }
|
|
|
+ };
|
|
|
+}
|
|
|
+
|
|
|
+//-----------------------------------------------------------------------------
|
|
|
class ctkMatrixWidgetPrivate: public ctkPrivate<ctkMatrixWidget>
|
|
|
{
|
|
|
public:
|
|
|
void init();
|
|
|
+ void validateElements();
|
|
|
+
|
|
|
+ // Parameters for the spinbox used to change the value of matrix elements
|
|
|
+ double Minimum;
|
|
|
+ double Maximum;
|
|
|
+ int Decimals;
|
|
|
+ double SingleStep;
|
|
|
};
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
@@ -41,7 +75,13 @@ void ctkMatrixWidgetPrivate::init()
|
|
|
{
|
|
|
CTK_P(ctkMatrixWidget);
|
|
|
// Set Read-only
|
|
|
- p->setEditTriggers(ctkMatrixWidget::NoEditTriggers);
|
|
|
+ p->setEditable(false);
|
|
|
+
|
|
|
+ // Set parameters for the spinbox
|
|
|
+ this->Minimum = -100;
|
|
|
+ this->Maximum = 100;
|
|
|
+ this->Decimals = 2;
|
|
|
+ this->SingleStep = 0.01;
|
|
|
|
|
|
// Hide headers
|
|
|
p->verticalHeader()->hide();
|
|
@@ -57,6 +97,15 @@ void ctkMatrixWidgetPrivate::init()
|
|
|
// Disable the frame by default
|
|
|
p->setFrameStyle(QFrame::NoFrame);
|
|
|
|
|
|
+ // Register custom editors
|
|
|
+ QItemEditorFactory *editorFactory = new QItemEditorFactory;
|
|
|
+ editorFactory->registerEditor(QVariant::Double, new QStandardItemEditorCreator<CustomDoubleSpinBox>);
|
|
|
+
|
|
|
+ QStyledItemDelegate* defaultItemDelegate =
|
|
|
+ qobject_cast<QStyledItemDelegate*>(p->itemDelegate());
|
|
|
+ Q_ASSERT(defaultItemDelegate);
|
|
|
+ defaultItemDelegate->setItemEditorFactory(editorFactory);
|
|
|
+
|
|
|
// Define prototype item
|
|
|
QTableWidgetItem* _item = new QTableWidgetItem();
|
|
|
_item->setData(Qt::DisplayRole, QVariant(0.0));
|
|
@@ -70,6 +119,27 @@ void ctkMatrixWidgetPrivate::init()
|
|
|
}
|
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
+void ctkMatrixWidgetPrivate::validateElements()
|
|
|
+{
|
|
|
+ CTK_P(ctkMatrixWidget);
|
|
|
+ for (int i=0; i < p->rowCount(); i++)
|
|
|
+ {
|
|
|
+ for (int j=0; j < p->columnCount(); j++)
|
|
|
+ {
|
|
|
+ double value = p->item(i, j)->data(Qt::DisplayRole).toDouble();
|
|
|
+ if (value < this->Minimum)
|
|
|
+ {
|
|
|
+ p->item(i,j)->setData(Qt::DisplayRole, QVariant(this->Minimum));
|
|
|
+ }
|
|
|
+ if (value > this->Maximum)
|
|
|
+ {
|
|
|
+ p->item(i,j)->setData(Qt::DisplayRole, QVariant(this->Maximum));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// --------------------------------------------------------------------------
|
|
|
ctkMatrixWidget::ctkMatrixWidget(QWidget* _parent) : Superclass(4, 4, _parent)
|
|
|
{
|
|
|
CTK_INIT_PRIVATE(ctkMatrixWidget);
|
|
@@ -87,7 +157,59 @@ ctkMatrixWidget::ctkMatrixWidget(int rows, int columns, QWidget* _parent)
|
|
|
}
|
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
-QSize ctkMatrixWidget::minimumSizeHint () const
|
|
|
+bool ctkMatrixWidget::editable()const
|
|
|
+{
|
|
|
+ return this->editTriggers();
|
|
|
+}
|
|
|
+
|
|
|
+// --------------------------------------------------------------------------
|
|
|
+void ctkMatrixWidget::setEditable(bool newEditable)
|
|
|
+{
|
|
|
+ if (newEditable)
|
|
|
+ {
|
|
|
+ this->setEditTriggers(ctkMatrixWidget::DoubleClicked);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ this->setEditTriggers(ctkMatrixWidget::NoEditTriggers);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// --------------------------------------------------------------------------
|
|
|
+CTK_GET_CXX(ctkMatrixWidget, double, minimum, Minimum);
|
|
|
+CTK_GET_CXX(ctkMatrixWidget, double, maximum, Maximum);
|
|
|
+CTK_GET_CXX(ctkMatrixWidget, double, singleStep, SingleStep);
|
|
|
+CTK_SET_CXX(ctkMatrixWidget, double, setSingleStep, SingleStep);
|
|
|
+CTK_GET_CXX(ctkMatrixWidget, int, decimals, Decimals);
|
|
|
+CTK_SET_CXX(ctkMatrixWidget, int, setDecimals, Decimals);
|
|
|
+
|
|
|
+// --------------------------------------------------------------------------
|
|
|
+void ctkMatrixWidget::setMinimum(double newMinimum)
|
|
|
+{
|
|
|
+ CTK_D(ctkMatrixWidget);
|
|
|
+ d->Minimum = newMinimum;
|
|
|
+ d->validateElements();
|
|
|
+}
|
|
|
+
|
|
|
+// --------------------------------------------------------------------------
|
|
|
+void ctkMatrixWidget::setMaximum(double newMaximum)
|
|
|
+{
|
|
|
+ CTK_D(ctkMatrixWidget);
|
|
|
+ d->Maximum = newMaximum;
|
|
|
+ d->validateElements();
|
|
|
+}
|
|
|
+
|
|
|
+// --------------------------------------------------------------------------
|
|
|
+void ctkMatrixWidget::setRange(double newMinimum, double newMaximum)
|
|
|
+{
|
|
|
+ CTK_D(ctkMatrixWidget);
|
|
|
+ d->Minimum = newMinimum;
|
|
|
+ d->Maximum = newMaximum;
|
|
|
+ d->validateElements();
|
|
|
+}
|
|
|
+
|
|
|
+// --------------------------------------------------------------------------
|
|
|
+QSize ctkMatrixWidget::minimumSizeHint() const
|
|
|
{
|
|
|
int maxWidth = this->sizeHintForColumn(0);
|
|
|
for (int j = 1; j < this->columnCount(); ++j)
|
|
@@ -103,7 +225,7 @@ QSize ctkMatrixWidget::minimumSizeHint () const
|
|
|
}
|
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
-QSize ctkMatrixWidget::sizeHint () const
|
|
|
+QSize ctkMatrixWidget::sizeHint() const
|
|
|
{
|
|
|
return this->minimumSizeHint();
|
|
|
}
|
|
@@ -142,6 +264,7 @@ void ctkMatrixWidget::updateGeometries()
|
|
|
// --------------------------------------------------------------------------
|
|
|
void ctkMatrixWidget::reset()
|
|
|
{
|
|
|
+ CTK_D(ctkMatrixWidget);
|
|
|
// Initialize 4x4 matrix
|
|
|
for (int i=0; i < this->rowCount(); i++)
|
|
|
{
|
|
@@ -150,7 +273,18 @@ void ctkMatrixWidget::reset()
|
|
|
this->setItem(i, j, this->itemPrototype()->clone());
|
|
|
if (i == j)
|
|
|
{
|
|
|
- this->setValue(i, j, 1);
|
|
|
+ if (d->Maximum < 1.0)
|
|
|
+ {
|
|
|
+ this->setValue(i, j, d->Maximum);
|
|
|
+ }
|
|
|
+ else if (d->Minimum > 1.0)
|
|
|
+ {
|
|
|
+ this->setValue(i, j, d->Minimum);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ this->setValue(i, j, 1.0);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -168,20 +302,29 @@ double ctkMatrixWidget::value(int i, int j)const
|
|
|
// --------------------------------------------------------------------------
|
|
|
void ctkMatrixWidget::setValue(int i, int j, double _value)
|
|
|
{
|
|
|
+ CTK_D(ctkMatrixWidget);
|
|
|
Q_ASSERT( i>=0 && i<this->rowCount() &&
|
|
|
j>=0 && j<this->columnCount());
|
|
|
|
|
|
- this->item(i, j)->setData(Qt::DisplayRole, QVariant(_value));
|
|
|
+ if (_value >= d->Minimum && _value <= d->Maximum)
|
|
|
+ {
|
|
|
+ this->item(i, j)->setData(Qt::DisplayRole, QVariant(_value));
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
// --------------------------------------------------------------------------
|
|
|
void ctkMatrixWidget::setVector(const QVector<double> & vector)
|
|
|
{
|
|
|
+ CTK_D(ctkMatrixWidget);
|
|
|
for (int i=0; i < this->rowCount(); i++)
|
|
|
{
|
|
|
for (int j=0; j < this->columnCount(); j++)
|
|
|
{
|
|
|
- this->item(i,j)->setData(Qt::DisplayRole, QVariant(vector.at(i * this->columnCount() + j)));
|
|
|
+ double value = vector.at(i * this->columnCount() + j);
|
|
|
+ if (value >= d->Minimum && value <= d->Maximum)
|
|
|
+ {
|
|
|
+ this->item(i,j)->setData(Qt::DisplayRole, QVariant(value));
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|