[Interest] How to disable dragging feature of Tableview
Poonam Sangale
sanglepoonam123 at gmail.com
Fri Apr 7 13:33:08 CEST 2023
How to disable the dragging feature of tableview. I have attached the code
file below.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/interest/attachments/20230407/9d6d7065/attachment.htm>
-------------- next part --------------
#include "ProcessModel.h"
#include <QDebug>
#include <QFontMetrics>
#include <QGuiApplication>
ProcessModel::ProcessModel(QObject *parent) : QAbstractTableModel (parent)
{
m_roleNames = QAbstractTableModel::roleNames();
// TODO loop over the QMetaEnum
m_roleNames.insert(int(Role::Sort), QByteArray("sort"));
m_roleNames.insert(int(Role::Number), QByteArray("number"));
m_roleNames.insert(int(Role::Type), QByteArray("type"));
update();
}
ProcessModel::~ProcessModel()
{
}
QHash<int, QByteArray> ProcessModel::roleNames() const
{
return m_roleNames;
}
int ProcessModel::rowCount(const QModelIndex &) const
{
return m_pids.count();
}
int ProcessModel::columnCount(const QModelIndex &) const
{
return F_CMDLINE + 1;
}
QVariant ProcessModel::data(const QModelIndex &index, int role) const
{
fields field = fields(index.column());
int pid = m_pids[index.row()];
ProcInfo pi = m_proc.procs.value(pid);
switch (role) {
case Qt::DisplayRole:
return pi.toVariant(field);
case Qt::InitialSortOrderRole: {
bool numeric = false;
pi.toVariant(field).toFloat(&numeric);
if (numeric)
return Qt::DescendingOrder;
return Qt::AscendingOrder;
}
case int(ProcessModel::Role::Sort):
return pi.toVariant(field);
case int(ProcessModel::Role::Number):
return pi.toVariant(field).toDouble();
case int(ProcessModel::Role::Type):
// TODO this is silly: make a virtual in the Category perhaps?
switch (field) {
case F_PID:
case F_PPID:
return QLatin1String("readonly");
case F_PGID:
case F_SID:
return QLatin1String("id");
case F_STAT1:
case F_STAT2:
case F_STAT3:
case F_STAT4:
return QLatin1String("stat");
case F_CMD:
case F_CMDLINE:
return QLatin1String("string");
default:
return QLatin1String("string");
}
default:
return QVariant();
}
return pi.toVariant(field);
}
QVariant ProcessModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role != Qt::DisplayRole)
return QVariant();
if (orientation == Qt::Horizontal) {
// section is interpreted as column
return m_proc.Header_Info.value(static_cast<fields>(section));
} else {
return QString();
}
}
int ProcessModel::columnWidth(int c, const QFont *font)
{
if (!m_columnWidths[c]) {
QString header = m_proc.Header_Info.value(static_cast<fields>(c));
QFontMetrics defaultFontMetrics = QFontMetrics(QGuiApplication::font());
QFontMetrics fm = (font ? QFontMetrics(*font) : defaultFontMetrics);
int ret = fm.horizontalAdvance(headerData(c, Qt::Horizontal).toString() + QLatin1String(" ^")) + 8;
for (int r = 0; r < m_pids.count(); ++r) {
ProcInfo pi = m_proc.procs.value(m_pids[r]);
ret = qMax(ret, fm.horizontalAdvance(pi.toVariant(fields(c)).toString()));
}
m_columnWidths[c] = ret;
}
return m_columnWidths[c];
}
void ProcessModel::update()
{
qDebug() << __FUNCTION__;
beginResetModel();
m_proc.refresh();
m_pids = m_proc.procs.keys().toVector();
std::sort(m_pids.begin(), m_pids.end());
endResetModel();
}
-------------- next part --------------
#include "Proc.h"
#include <QRandomGenerator>
#include <QTime>
#include <random>
std::random_device dev;
std::mt19937 rng(dev());
const QMap<fields, QString> Proc::Header_Info = {
{F_PID, {"PID"}},
{F_PPID, {"PPID"}},
{F_PGID, {"PGID"}},
{F_SID, {"SID"}},
{F_STAT1, {"STAT1"}},
{F_STAT2, {"STAT2"}},
{F_STAT3, {"STAT3"}},
{F_STAT4, {"STAT4"}},
{F_CMD, {"CMD"}},
{F_CMDLINE, {"CMDLINE"}}
};
QString random_string(int length=32, QString allow_symbols=QString("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")) {
QString result;
QRandomGenerator(QTime::currentTime().msec());
for (int i = 0; i < length; ++i) {
std::uniform_int_distribution<std::mt19937::result_type> dist1(0,allow_symbols.length());
result.append(allow_symbols.at(dist1(rng)));
}
return result;
}
ProcInfo::ProcInfo()
{
}
ProcInfo::ProcInfo(int pid)
{
mpid = pid;
std::uniform_int_distribution<std::mt19937::result_type> dist1(1,6);
ppid = dist1(rng);
std::uniform_int_distribution<std::mt19937::result_type> dist2(0,100);
pgid = dist2(rng);
std::uniform_int_distribution<std::mt19937::result_type> dist3(100,1000);
sid = dist3(rng);
stat1 = QString("%1%").arg(pgid);
stat2 = QString("%1 bytes be or not to be is the question.").arg(pgid + sid);
stat3 = QString("%1 bytes").arg(pgid - sid);
stat4 = QString("%1 bytes").arg(pgid * sid);
cmd = random_string();
cmdline = random_string();
}
ProcInfo::~ProcInfo()
{
}
QVariant ProcInfo::toVariant(fields f)
{
switch (f) {
case F_PID: return mpid;
case F_PPID: return ppid;
case F_PGID: return pgid;
case F_SID: return sid;
case F_STAT1: return stat1;
case F_STAT2: return stat2;
case F_STAT3: return stat3;
case F_STAT4: return stat4;
case F_CMD: return cmd;
case F_CMDLINE: return cmdline;
default: return "";
}
}
Proc::Proc()
{
}
void Proc::refresh()
{
procs.clear();
std::uniform_int_distribution<std::mt19937::result_type> dist(1000,2500);
const int numOfPids = dist(rng);
for (int i = 0; i < numOfPids; ++i)
{
procs.insert(i, ProcInfo(i));
}
}
-------------- next part --------------
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Layouts 1.12
import ProcessModel 0.1
import SortFilterTableModel 0.1
import QtQuick.Controls 2.4
import Qt.labs.qmlmodels 1.0
ApplicationWindow {
id: window
visible: true
width: 1024
height: 800
//title: qsTr("05-TableView-DelegateChooser")
header: ToolBar {
RowLayout {
anchors.fill: parent
anchors.rightMargin: 6
Switch {
id: cbUpdate
checked: true
text: qsTr("Update every")
}
SpinBox {
id: sbUpdate
from: 1
to: 60
value: 2
enabled: cbUpdate.checked
}
Label {
text: "sec"
}
Button {
id: resizeCols
text: qsTr("Resize cols")
onClicked: {
//console.log(table.model.columnCount())
for ( var index = 0; index < table.model.columnCount(); ++index) {
var width = Math.min(600, table.model.columnWidth(index))
//console.log(index + " " + width)
headerRepeater.itemAt(index).setWidth(width)
}
table.forceLayout()
}
}
Item {
Layout.fillWidth: true
}
TextField {
id: tfFilter
implicitWidth: parent.width / 4
onTextEdited: table.contentY = 0
}
}
}
Row {
id: header
width: table.contentWidth
height: cbUpdate.height
x: -table.contentX
z: 1
spacing: 4
Repeater {
id: headerRepeater
model: table.model.columnCount()
SortableColumnHeading {
initialWidth: Math.min(600, table.model.columnWidth(index)); height: parent.height
text: table.model.headerData(index, Qt.Horizontal)
initialSortOrder: table.model.initialSortOrder(index)
onSorting: {
for (var i = 0; i < headerRepeater.model; ++i)
if (i !== index)
headerRepeater.itemAt(i).stopSorting()
table.model.sort(index, state == "up" ? Qt.AscendingOrder : Qt.DescendingOrder)
}
}
}
}
TableView {
id: table
anchors.fill: parent
anchors.topMargin: header.height
columnSpacing: 4; rowSpacing: 4
model: SortFilterTableModel {
filterText: tfFilter.text
}
Timer {
interval: sbUpdate.value * 1000
repeat: true
running: cbUpdate.checked
onTriggered: table.model.processModel.update()
}
columnWidthProvider: function(column) { return headerRepeater.itemAt(column).width }
delegate: DelegateChooser {
role: "type"
DelegateChoice {
roleValue: "readonly"
Rectangle {
color: "grey"
implicitHeight: readonlyText.implicitHeight
Text {
id: readonlyText
text: model.display
width: parent.width
elide: Text.ElideRight
font.preferShaping: false
}
}
}
DelegateChoice {
roleValue: "id"
Rectangle {
color: "yellow"
implicitHeight: idText.implicitHeight
Text {
id: idText
text: model.display
width: parent.width
elide: Text.ElideRight
font.preferShaping: false
}
}
}
DelegateChoice {
roleValue: "string"
Rectangle {
color: "#0048BA"
implicitHeight: stringText.implicitHeight *1.5
Text {
id: stringText
color: "white"
text: model.display
width: parent.width
elide: Text.ElideRight
font.preferShaping: false
}
}
}
DelegateChoice {
Rectangle {
color: "#EEE"
implicitHeight: defaultText.implicitHeight
Text {
id: defaultText
text: model.display
width: parent.width
elide: Text.ElideRight
horizontalAlignment: Text.AlignRight
font.preferShaping: false
}
}
}
}
ScrollBar.horizontal: ScrollBar { }
ScrollBar.vertical: ScrollBar { }
}
Shortcut { sequence: StandardKey.Quit; onActivated: Qt.quit() }
}
-------------- next part --------------
#ifndef PROC_H
#define PROC_H
#include <QMap>
#include <QVariant>
#include <QVector>
enum fields
{
F_PID = 0,
F_PPID,
F_PGID,
F_SID,
F_STAT1,
F_STAT2,
F_STAT3,
F_STAT4,
F_CMD,
F_CMDLINE,
F_END = -1
};
class ProcInfo
{
public:
ProcInfo();
ProcInfo(int pid);
~ProcInfo();
int mpid;
int ppid;
int pgid;
int sid;
QString stat1;
QString stat2;
QString stat3;
QString stat4;
QString cmd;
QString cmdline;
QVariant toVariant(fields f);
};
using ProcList = QMap<int, ProcInfo>;
class Proc
{
public:
Proc();
void refresh();
ProcList procs; // processes indexed by pid
static const QMap<fields, QString> Header_Info;
};
#endif // PROC_H
-------------- next part --------------
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QAbstractTableModel>
#include <QQmlContext>
#include "ProcessModel.h"
#include "SortFilterTableModel.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
qmlRegisterType<ProcessModel>("ProcessModel", 0, 1, "ProcessModel");
qmlRegisterType<SortFilterTableModel>("SortFilterTableModel", 0, 1, "SortFilterTableModel");
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
-------------- next part --------------
#ifndef ProcessModel_H
#define ProcessModel_H
#include "Proc.h"
#include <QAbstractTableModel>
#include <QTimer>
class ProcessModel : public QAbstractTableModel
{
Q_OBJECT
public:
// supplemental roles beyond Qt::ItemDataRole
enum class Role {
Sort = Qt::UserRole,
Number,
Type
};
Q_ENUM(Role)
explicit ProcessModel(QObject *parent= nullptr);
~ProcessModel();
QHash<int, QByteArray> roleNames() const override;
int rowCount(const QModelIndex & = QModelIndex()) const override;
int columnCount(const QModelIndex & = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role) const override;
QVariant headerData(int section, Qt::Orientation orientation,
int role = Qt::DisplayRole) const override;
Q_INVOKABLE int columnWidth(int c, const QFont *font = nullptr);
Q_INVOKABLE void update();
private:
Proc m_proc;
QVector<int> m_pids;
QVector<int> m_columnWidths = QVector<int>(F_CMDLINE + 1);
QHash<int, QByteArray> m_roleNames;
};
#endif
-------------- next part --------------
import QtQuick 2.12
Rectangle {
id: root
color: "wheat"
property int initialSortOrder: Qt.AscendingOrder
property alias text: label.text
property real initialWidth: 100
signal sorting
width: splitter.x + 6
function setWidth(newWidth) {
splitter.x = newWidth -6
}
function stopSorting() {
state = ""
}
Text {
id: label
anchors.verticalCenter: parent.verticalCenter
x: 4
width: parent.width - 4
text: table.model.headerData(index, Qt.Horizontal)
}
Text {
id: upDownIndicator
anchors.right: parent.right
anchors.margins: 8
anchors.verticalCenter: parent.verticalCenter
text: "^"
visible: false
}
TapHandler { id: tap; onTapped: nextState() }
Item {
id: splitter
x: root.initialWidth - 6
width: 12
height: parent.height
DragHandler {
yAxis.enabled: false
onActiveChanged: {
if (!active) {
if (splitter.x <= 5 ) {
splitter.x = 6
}
table.forceLayout()
}
}
}
Rectangle {
anchors.fill: parent
id: splitterRect
color: "grey"
visible: false
}
MouseArea {
hoverEnabled: true
anchors.fill: parent
onEntered: splitterRect.visible = true
onExited: splitterRect.visible = false
}
}
function nextState() {
if (state == "")
state = (initialSortOrder == Qt.DescendingOrder ? "down" : "up")
else if (state == "up")
state = "down"
else
state = "up"
root.sorting()
}
states: [
State {
name: "up"
PropertyChanges { target: upDownIndicator; visible: true; rotation: 0 }
PropertyChanges { target: root; color: "orange" }
},
State {
name: "down"
PropertyChanges { target: upDownIndicator; visible: true; rotation: 180 }
PropertyChanges { target: root; color: "orange" }
}
]
}
-------------- next part --------------
#ifndef SortFilterTableModel_H
#define SortFilterTableModel_H
#include <QObject>
#include <QSortFilterProxyModel>
#include "ProcessModel.h"
class SortFilterTableModel : public QSortFilterProxyModel
{
Q_OBJECT
Q_PROPERTY(ProcessModel *processModel READ processModel CONSTANT)
Q_PROPERTY(QString filterText READ filterText WRITE setFilterText NOTIFY filterTextChanged)
Q_CLASSINFO("DefaultProperty", "data")
public:
SortFilterTableModel(QObject *parent = nullptr);
ProcessModel *processModel() { return &m_ProcessModel; }
QString filterText() const {return m_filterText;}
void setFilterText(QString filterText);
Q_INVOKABLE void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) override;
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
Q_INVOKABLE int columnWidth(int c, const QFont *font = nullptr);
Q_INVOKABLE Qt::SortOrder initialSortOrder(int column) const;
QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override;
QModelIndex mapToSource(const QModelIndex &proxyIndex) const override;
signals:
void filterTextChanged(QString filterText);
private:
ProcessModel m_ProcessModel;
QVector<fields> m_fields;
QString m_filterText;
};
#endif // SortFilterTableModel_H
-------------- next part --------------
#include "SortFilterTableModel.h"
#include <QDebug>
SortFilterTableModel::SortFilterTableModel(QObject *parent)
: QSortFilterProxyModel (parent)
{
setSourceModel(&m_ProcessModel);
setSortRole(int(ProcessModel::Role::Sort));
// default fields that "top" displays
m_fields << F_PID
<< F_PPID
<< F_PGID
<< F_SID
<< F_STAT1
<< F_STAT2
<< F_STAT3
<< F_STAT4
<< F_CMD
<< F_CMDLINE;
setFilterKeyColumn(-1); //With -1: Include all columns to filter
}
void SortFilterTableModel::setFilterText(QString filterText)
{
if (m_filterText == filterText)
return;
m_filterText = filterText;
setFilterRegularExpression(filterText);
emit filterTextChanged(m_filterText);
}
void SortFilterTableModel::sort(int column, Qt::SortOrder order)
{
qDebug() << column << m_fields[column] << order;
QSortFilterProxyModel::sort(m_fields[column], order);
}
int SortFilterTableModel::columnCount(const QModelIndex &parent) const
{
Q_UNUSED(parent)
return m_fields.count();
}
int SortFilterTableModel::columnWidth(int c, const QFont *font)
{
if (c < 0 || c >= m_fields.count())
return 0;
return m_ProcessModel.columnWidth(m_fields[c], font);
}
Qt::SortOrder SortFilterTableModel::initialSortOrder(int column) const
{
bool ok = false;
if (column < 0 || column >= m_fields.count())
return Qt::AscendingOrder;
int ret = m_ProcessModel.data(m_ProcessModel.index(0, m_fields[column]), Qt::InitialSortOrderRole).toInt(&ok);
if (ok)
return Qt::SortOrder(ret);
else
return Qt::AscendingOrder;
}
QModelIndex SortFilterTableModel::mapFromSource(const QModelIndex &sourceIndex) const
{
int row = QSortFilterProxyModel::mapFromSource(sourceIndex).row();
fields field = fields(sourceIndex.column());
return m_ProcessModel.index(row, m_fields.indexOf(field));
}
QModelIndex SortFilterTableModel::mapToSource(const QModelIndex &proxyIndex) const
{
QModelIndex rowIndex = QSortFilterProxyModel::mapToSource(proxyIndex);
int col = -1;
if (proxyIndex.column() >= 0 && proxyIndex.column() < m_fields.count())
col = m_fields[proxyIndex.column()];
return m_ProcessModel.index(rowIndex.row(), col);
}
More information about the Interest
mailing list