Use QDoubleSpinBox for partial 64-bit int support. Closes #1952

* Actually creating a 64-bit spinbox is not feasible without constructing it
  almost from scratch due to how much QAbstractSpinBox depends on private
  internals that can't be overridden. Instead use a QDoubleSpinBox with no
  decimals since we don't need the full 64-bit range, and the mantissa of a
  double is enough.
This commit is contained in:
baldurk
2020-06-30 12:34:52 +01:00
parent f238428d81
commit e5e9a9c94b
4 changed files with 67 additions and 17 deletions
+37
View File
@@ -27,6 +27,7 @@
#include <QCheckBox>
#include <QCoreApplication>
#include <QDebug>
#include <QDoubleSpinBox>
#include <QFileDialog>
#include <QMessageBox>
#include <QProcess>
@@ -575,6 +576,42 @@ private:
QAbstractItemView *m_widget;
};
// helper functions for using a double spinbox for 64-bit integers. We do this because it's
// infeasible in Qt to actually derive and create a real 64-bit integer spinbox because critical
// functionality depends on deriving QAbstractSpinBoxPrivate which is unavailable. So instead we use
// a QDoubleSpinBox and restrict ourselves to the 53 bits of mantissa. This struct only has inline
// helpers so we can cast a QDoubleSpinBox to one of these and use it as-is.
class RDSpinBox64 : public QDoubleSpinBox
{
private:
static const qlonglong mask = (1ULL << 53U) - 1;
public:
void configure() { QDoubleSpinBox::setDecimals(0); }
void setSingleStep(qlonglong val) { QDoubleSpinBox::setSingleStep(makeValue(val)); }
void setMinimum(qlonglong min) { QDoubleSpinBox::setMinimum(makeValue(min)); }
void setMaximum(qlonglong max) { QDoubleSpinBox::setMaximum(makeValue(max)); }
void setRange(qlonglong min, qlonglong max)
{
RDSpinBox64::setMinimum(min);
RDSpinBox64::setMaximum(max);
}
void setSingleStep(qulonglong val) { QDoubleSpinBox::setSingleStep(makeValue(val)); }
void setMinimum(qulonglong min) { QDoubleSpinBox::setMinimum(makeValue(min)); }
void setMaximum(qulonglong max) { QDoubleSpinBox::setMaximum(makeValue(max)); }
void setRange(qulonglong min, qulonglong max)
{
RDSpinBox64::setMinimum(min);
RDSpinBox64::setMaximum(max);
}
static qlonglong getValue(double d) { return qlonglong(d); }
static qulonglong getUValue(double d) { return qulonglong(d); }
static double makeValue(qlonglong l) { return l < 0 ? -double((-l) & mask) : double(l & mask); }
static double makeValue(qulonglong l) { return double(l & mask); }
};
class QMenu;
// helper for doing a manual blocking invoke of a dialog
+22 -13
View File
@@ -1913,6 +1913,15 @@ BufferViewer::BufferViewer(ICaptureContext &ctx, bool meshview, QWidget *parent)
{
ui->setupUi(this);
byteRangeStart = (RDSpinBox64 *)ui->byteRangeStart;
byteRangeLength = (RDSpinBox64 *)ui->byteRangeLength;
byteRangeStart->configure();
byteRangeLength->configure();
byteRangeStart->setMinimum(0ULL);
byteRangeLength->setMinimum(0ULL);
m_ModelVSIn = new BufferItemModel(ui->vsinData, true, meshview, this);
m_ModelVSOut = new BufferItemModel(ui->vsoutData, false, meshview, this);
m_ModelGSOut = new BufferItemModel(ui->gsoutData, false, meshview, this);
@@ -2129,9 +2138,9 @@ void BufferViewer::SetupMeshView()
// hide buttons we don't want in the toolbar
ui->byteRangeLine->setVisible(false);
ui->byteRangeStartLabel->setVisible(false);
ui->byteRangeStart->setVisible(false);
byteRangeStart->setVisible(false);
ui->byteRangeLengthLabel->setVisible(false);
ui->byteRangeLength->setVisible(false);
byteRangeLength->setVisible(false);
ui->resourceDetails->setVisible(false);
ui->formatSpecifier->setVisible(false);
@@ -3848,34 +3857,34 @@ void BufferViewer::processFormat(const QString &format)
ui->formatSpecifier->setFormat(format);
uint32_t stride = qMax(1U, cols.type.descriptor.arrayByteStride);
qulonglong stride = qMax(1U, cols.type.descriptor.arrayByteStride);
ui->byteRangeStart->setSingleStep((int)stride);
ui->byteRangeLength->setSingleStep((int)stride);
byteRangeStart->setSingleStep(stride);
byteRangeLength->setSingleStep(stride);
ui->byteRangeStart->setMaximum((int)m_ObjectByteSize);
ui->byteRangeLength->setMaximum((int)m_ObjectByteSize);
byteRangeStart->setMaximum(m_ObjectByteSize);
byteRangeLength->setMaximum(m_ObjectByteSize);
ui->byteRangeStart->setValue((int)m_ByteOffset);
ui->byteRangeLength->setValue((int)m_ByteSize);
byteRangeStart->setValue(m_ByteOffset);
byteRangeLength->setValue(m_ByteSize);
ui->formatSpecifier->setErrors(errors);
OnEventChanged(m_Ctx.CurEvent());
}
void BufferViewer::on_byteRangeStart_valueChanged(int value)
void BufferViewer::on_byteRangeStart_valueChanged(double value)
{
m_ByteOffset = value;
m_ByteOffset = RDSpinBox64::getUValue(value);
m_PagingByteOffset = 0;
processFormat(m_Format);
}
void BufferViewer::on_byteRangeLength_valueChanged(int value)
void BufferViewer::on_byteRangeLength_valueChanged(double value)
{
m_ByteSize = value;
m_ByteSize = RDSpinBox64::getUValue(value);
m_PagingByteOffset = 0;
+6 -2
View File
@@ -34,6 +34,7 @@ namespace Ui
class BufferViewer;
}
class RDSpinBox64;
class QItemSelection;
class QMenu;
class QPushButton;
@@ -112,8 +113,8 @@ private slots:
void on_instance_valueChanged(int value);
void on_viewIndex_valueChanged(int value);
void on_rowOffset_valueChanged(int value);
void on_byteRangeStart_valueChanged(int value);
void on_byteRangeLength_valueChanged(int value);
void on_byteRangeStart_valueChanged(double value);
void on_byteRangeLength_valueChanged(double value);
// manual slots
void render_mouseMove(QMouseEvent *e);
@@ -226,6 +227,9 @@ private:
QAction *m_ExportBytes = NULL;
QAction *m_DebugVert = NULL;
RDSpinBox64 *byteRangeStart = NULL;
RDSpinBox64 *byteRangeLength = NULL;
RDTableView *tableForStage(MeshDataStage stage);
BufferItemModel *modelForStage(MeshDataStage stage);
+2 -2
View File
@@ -916,7 +916,7 @@ Enter 0.0 to use automatic/guessed value derived from data.</string>
</widget>
</item>
<item>
<widget class="QSpinBox" name="byteRangeStart">
<widget class="QDoubleSpinBox" name="byteRangeStart">
<property name="maximum">
<number>999123456</number>
</property>
@@ -930,7 +930,7 @@ Enter 0.0 to use automatic/guessed value derived from data.</string>
</widget>
</item>
<item>
<widget class="QSpinBox" name="byteRangeLength">
<widget class="QDoubleSpinBox" name="byteRangeLength">
<property name="maximum">
<number>999123456</number>
</property>