How to disable the dragging feature of tableview. I have attached the code file below.
#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(); }
#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)); } }
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() } }
#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
#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(); }
#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
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" } } ] }
#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
#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); }
_______________________________________________ Interest mailing list Interest@qt-project.org https://lists.qt-project.org/listinfo/interest