我正在开发一个名为“配置管理器”的窗口,它允许用户:
ListView
组件中具有特定扩展名的文件夹中的所有文件,TextEdit
组件,列表视图显示过滤/排序的项目。当用户单击列表视图的一项时,我会更改该项的颜色。如果他单击另一个项目,前一个项目的颜色会恢复为默认颜色,并且新项目的颜色也会发生变化。
数据存储在后端的一个继承自
QAsbtractListModel
的类中,我正在使用另一个继承自QSortFilterProxyModel
的类来仅显示过滤和排序的元素。
列表视图最多可以显示 100 个元素,因此我添加了一个滚动条以便能够选择其上显示的任何委托。
如果我选择第一个项目,颜色会正常更新。如果我单击第一个项目旁边的另一个项目,这两个项目(前一个和新的)的颜色变化也可以。如果选择顶部的一个项目,滚动列表视图的底部并选择另一个项目,我会遇到问题。这样,前一项就不会更新,并且仍然具有所选的颜色。在后端,通过一些 qDebug,我可以确认上一个项目没有更新,因为 setData 方法没有像我选择一个项目时那样被调用(以更新 GUI 上的颜色和模型上该元素后端的布尔值) ).
我这里不是说用键盘的CTRL或SHIFT键进行多重选择,但问题是一样的。仅更新部分项目。
我认为我缺少列表视图的一些属性,因为似乎并非所有委托都在缓存中(因此在滚动并选择新项目时不会更新)。
我添加了下面的代码,我现在不能做得更短。预先感谢您的帮助。
主要文件
#include <QGuiApplication>
#include <QQuickView>
#include <QQmlContext>
#include <QQmlApplicationEngine>
#include "FilenameListModel.h"
#include "FilterProxyModel.h"
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
FilenameListModel model;
FilterProxyModel filterModel;
filterModel.setSourceModel(&model);
engine.rootContext()->setContextProperty("_FilteredRunwayConfigurationFilesModel", &filterModel);
engine.load(QUrl("qrc:/main.qml"));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.5
import QtQml.Models 2.12
import QtQuick.Layouts 1.12
ApplicationWindow
{
id: root
property bool isSaving: false
minimumWidth: 600
minimumHeight: 400
visible: true
modality: Qt.ApplicationModal
Component.onCompleted:
{
// Update the backend with current saving mode
_FilteredRunwayConfigurationFilesModel.isSavingMode = isSaving
}
DelegateModel
{
id: delegateModel
model: _FilteredRunwayConfigurationFilesModel
delegate: Rectangle
{
id: item_delegate
property bool checked: false
width: ListView.view.width - 10
height: name.implicitHeight
color: model.isChecked? "lightgreen" : "lightblue"
radius: 10
onCheckedChanged:
{
listViewFilter.checkChanged()
}
Connections
{
target: listViewFilter
// Called after the slot onCheckOne of the listViewFilter component
onCheckOne:
{
model.isChecked = (idx === index)
checked = model.isChecked
}
onCheckMul:
{
if (idx > listViewFilter.mulBegin)
{
model.isChecked = (index >= listViewFilter.mulBegin && index <= idx)
checked = model.isChecked
}
else
{
model.isChecked = (index <= listViewFilter.mulBegin && index >= idx)
checked = model.isChecked
}
}
}
Connections
{
target: textFilterString
// Called after this signal has been catched by the textFilterString component
onTextChanged:
{
// Reset all status
model.isChecked = false
checked = model.isChecked
}
}
Rectangle
{
id: leftRectangle
anchors
{
top: parent.top
bottom: parent.bottom
left: parent.left
right: rightRectangle.left
}
color: "transparent"
Text
{
id: name
anchors.fill: parent
anchors.margins: 5
verticalAlignment: Qt.AlignVCenter
horizontalAlignment: Qt.AlignHCenter
text: "%1".arg(model.name)
}
}
Rectangle
{
id: rightRectangle
anchors
{
top: parent.top
bottom: parent.bottom
right: parent.right
}
color: "transparent"
width: parent.width * 0.3
Text
{
id: date
anchors.fill: parent
anchors.margins: 5
verticalAlignment: Qt.AlignVCenter
horizontalAlignment: Qt.AlignHCenter
text:
{
var text = "%1".arg(model.date)
return text
}
}
}
MouseArea
{
anchors.fill: parent
acceptedButtons: Qt.LeftButton
onClicked:
{
if (!isSaving)
{
switch(mouse.modifiers)
{
case Qt.ControlModifier:
model.isChecked = !model.isChecked;
checked = model.isChecked
break
case Qt.ShiftModifier:
listViewFilter.checkMul(index)
break
default:
listViewFilter.checkOne(index)
listViewFilter.mulBegin = index
break
}
}
else
{
textFilterString.text = model.name
}
}
}
}
}
ColumnLayout
{
anchors.fill: parent
anchors.margins: 5
TextField
{
id: textFilterString
Layout.fillWidth: true
Layout.preferredHeight: implicitHeight
horizontalAlignment: Qt.AlignHCenter
verticalAlignment: Qt.AlignVCenter
placeholderText: isSaving ? "Write the filename with the '.atols' extension" : "Write the begin of the filename"
onTextChanged:
{
_FilteredRunwayConfigurationFilesModel.filenameBeginning = text;
listViewFilter.checkChanged()
}
}
RowLayout
{
Layout.fillWidth: true
Layout.preferredHeight: textFilterString.height
Layout.alignment: Qt.AlignHCenter
Button
{
id: buttonLoad
Layout.preferredWidth: 100
Layout.preferredHeight: parent.height
text: "LOAD"
enabled: false
visible: !isSaving
onClicked:
{
_FilteredRunwayConfigurationFilesModel.loadConfigurationFile(listViewFilter.selectedIndex)
}
}
Button
{
id: buttonDelete
Layout.preferredWidth: 100
Layout.preferredHeight: parent.height
text: "DELETE"
enabled: false
visible: !isSaving
onClicked:
{
_FilteredRunwayConfigurationFilesModel.deleteConfigurationFile(listViewFilter.selectedIndex)
}
}
Button
{
id: buttonSave
Layout.preferredWidth: 100
Layout.preferredHeight: parent.height
text: "SAVE"
enabled: textFilterString.text
visible: isSaving
onClicked:
{
// TODO
}
}
}
ListView
{
id: listViewFilter
property int mulBegin: 0
property var selectedIndex: []
signal checkOne(int idx)
signal checkMul(int idx)
// Called first when executing from a delegate item
onCheckOne:
{
listViewFilter.mulBegin = idx
}
function checkChanged()
{
listViewFilter.selectedIndex = []
// Check how many items are selected in the list
var nSelected = 0
for (var i = 0; i < listViewFilter.count; i++)
{
if (listViewFilter.contentItem.children[i] && listViewFilter.contentItem.children[i].checked)
{
nSelected++
listViewFilter.selectedIndex.push(i)
}
}
// Enable or disable buttons to load or delete the selected items
var loadEnable = false
var deleteEnable = false
switch(nSelected)
{
case 1: // One item selected => Load and Delete available
loadEnable = true
deleteEnable = true
break
case 0: // No items selected => Nothing available
loadEnable = false
deleteEnable = false
break
default: // Multiple items selected => Only Delete available
loadEnable = false
deleteEnable = true
break
}
buttonLoad.enabled = loadEnable
buttonDelete.enabled = deleteEnable
}
Layout.fillWidth: true
Layout.fillHeight: true
model: delegateModel
ScrollBar.vertical: ScrollBar
{
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.right: parent.right
policy: listViewFilter.contentHeight > listViewFilter.height ? ScrollBar.AlwaysOn : ScrollBar.AlwaysOff
active: true
}
}
TextField
{
Layout.fillWidth: true
Layout.preferredHeight: textFilterString.height
text: "No files with this filter"
verticalAlignment: Qt.AlignTop
horizontalAlignment: Qt.AlignHCenter
visible: listViewFilter.count === 0
}
}
}
基础型号
#ifndef FILENAMELISTMODEL_H
#define FILENAMELISTMODEL_H
#include <QAbstractListModel>
#include <QDate>
class FilenameListModel : public QAbstractListModel
{
Q_OBJECT
public:
explicit FilenameListModel(QObject *parent = nullptr);
public:
enum Roles
{
NameRole = Qt::UserRole,
DateRole,
CheckedRole
};
int rowCount(const QModelIndex& parent) const override;
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
virtual bool setData(const QModelIndex &index, const QVariant &value, int role) override;
QHash<int, QByteArray> roleNames() const override;
private:
struct Entry
{
QString name;
QDate date;
bool isChecked;
};
QVector<Entry> m_entries;
};
#endif // FILENAMELISTMODEL_H
#include "FilenameListModel.h"
#include <QDebug>
FilenameListModel::FilenameListModel(QObject *parent)
: QAbstractListModel (parent)
{
m_entries = {
Entry{"Tata", QDate(2022, 5, 14)},
Entry{"Tititata", QDate(2020, 3, 12)},
Entry{"Toto", QDate(2018, 1, 10)},
Entry{"Tata", QDate(2019, 2, 11)},
Entry{"Toto", QDate(2021, 4, 13)},
Entry{"Titi", QDate(2023, 6, 15)},
Entry{"Tititata", QDate(2020, 3, 12)},
Entry{"Toto", QDate(2018, 1, 10)},
Entry{"Tata", QDate(2019, 2, 11)},
Entry{"Toto", QDate(2021, 4, 13)},
Entry{"Titi", QDate(2023, 6, 15)},
Entry{"Tititata", QDate(2020, 3, 12)},
Entry{"Toto", QDate(2018, 1, 10)},
Entry{"Tata", QDate(2019, 2, 11)},
Entry{"Toto", QDate(2021, 4, 13)},
Entry{"Titi", QDate(2023, 6, 15)},
Entry{"Tititata", QDate(2020, 3, 12)},
Entry{"Toto", QDate(2018, 1, 10)},
Entry{"Tata", QDate(2019, 2, 11)},
Entry{"Toto", QDate(2021, 4, 13)},
Entry{"Titi", QDate(2023, 6, 15)},
Entry{"Tititata", QDate(2020, 3, 12)},
Entry{"Toto", QDate(2018, 1, 10)},
Entry{"Tata", QDate(2019, 2, 11)},
Entry{"Toto", QDate(2021, 4, 13)},
Entry{"Titi", QDate(2023, 6, 15)},
Entry{"Tititata", QDate(2020, 3, 12)},
Entry{"Toto", QDate(2018, 1, 10)},
Entry{"Tata", QDate(2019, 2, 11)},
Entry{"Toto", QDate(2021, 4, 13)},
Entry{"Titi", QDate(2023, 6, 15)},
Entry{"Tititata", QDate(2020, 3, 12)},
Entry{"Toto", QDate(2018, 1, 10)},
Entry{"Tata", QDate(2019, 2, 11)},
Entry{"Toto", QDate(2021, 4, 13)},
Entry{"Titi", QDate(2023, 6, 15)},
Entry{"Tititata", QDate(2020, 3, 12)},
Entry{"Toto", QDate(2018, 1, 10)},
Entry{"Tata", QDate(2019, 2, 11)},
Entry{"Toto", QDate(2021, 4, 13)},
Entry{"Titi", QDate(2023, 6, 15)},
Entry{"Tititata", QDate(2020, 3, 12)},
Entry{"Toto", QDate(2018, 1, 10)},
Entry{"Tata", QDate(2019, 2, 11)},
Entry{"Toto", QDate(2021, 4, 13)},
Entry{"Titi", QDate(2023, 6, 15)},
Entry{"Tititata", QDate(2020, 3, 12)},
Entry{"Toto", QDate(2018, 1, 10)},
Entry{"Tata", QDate(2019, 2, 11)},
Entry{"Toto", QDate(2021, 4, 13)},
Entry{"Titi", QDate(2023, 6, 15)},
Entry{"Tititata", QDate(2020, 3, 12)},
Entry{"Toto", QDate(2018, 1, 10)},
Entry{"Tata", QDate(2019, 2, 11)},
Entry{"Toto", QDate(2021, 4, 13)},
Entry{"Titi", QDate(2023, 6, 15)}
};
}
int FilenameListModel::rowCount( const QModelIndex& parent) const
{
if (parent.isValid())
return 0;
return m_entries.count();
}
QVariant FilenameListModel::data(const QModelIndex &index, int role) const
{
if ( !index.isValid() )
return QVariant();
const Entry &entry = m_entries.at(index.row());
switch(role)
{
case NameRole:
return entry.name;
case DateRole:
return entry.date.toString("yyyy-MM-dd - hh::mm::ss");
case CheckedRole:
{
return entry.isChecked;
}
default:
return QVariant();
}
}
bool FilenameListModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
// Method called when QML change a parameter of the model
if (!hasIndex(index.row(), index.column(), index.parent()) || !value.isValid())
return false;
if (m_entries[index.row()].isChecked != value.toBool())
qDebug() << "backend:" << index.row() << "/" << value.toBool();
m_entries[index.row()].isChecked = value.toBool();
emit dataChanged(index, index, { role });
return true;
}
QHash<int, QByteArray> FilenameListModel::roleNames() const
{
static QHash<int, QByteArray> mapping {
{NameRole, "name"},
{DateRole, "date"},
{CheckedRole, "isChecked"}
};
return mapping;
}
代理模型
#ifndef FILTERPROXYMODEL_H
#define FILTERPROXYMODEL_H
#include <QSortFilterProxyModel>
class FilterProxyModel : public QSortFilterProxyModel
{
Q_OBJECT
Q_PROPERTY(QString filenameBeginning WRITE setFilenameBeginning READ getFilenameBeginnning NOTIFY filenameBeginningChanged)
Q_PROPERTY(bool isSavingMode WRITE setIsSavingMode NOTIFY isSavingModeChanged)
public:
explicit FilterProxyModel(QObject *parent = nullptr);
void setFilenameBeginning(QString newStr);
QString getFilenameBeginnning();
void setIsSavingMode(bool newMode);
public slots:
Q_INVOKABLE void deleteConfigurationFile(QVector<int> indexToDelete);
Q_INVOKABLE void loadConfigurationFile(QVector<int> indexToLoad);
signals:
void filenameBeginningChanged();
void isSavingModeChanged();
protected:
bool lessThan(const QModelIndex &sourceLeft, const QModelIndex &sourceRight) const override;
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
private:
QString m_filenameBeginning;
bool m_isSavingMode;
};
#endif // FILTERPROXYMODEL_H
#include "FilterProxyModel.h"
#include "FilenameListModel.h"
#include <QDebug>
FilterProxyModel::FilterProxyModel(QObject *parent)
: QSortFilterProxyModel (parent)
{
m_isSavingMode = false;
sort(0, Qt::SortOrder::DescendingOrder);
}
bool FilterProxyModel::lessThan(const QModelIndex &sourceLeft, const QModelIndex &sourceRight) const
{
const QDate leftDate = sourceLeft.data(FilenameListModel::DateRole).toDate();
const QDate rightDate = sourceRight.data(FilenameListModel::DateRole).toDate();
return leftDate < rightDate;
}
bool FilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
{
// In saving mode, keep all files on the list
if (m_isSavingMode)
return true;
// Otherwise, filter the rows
const QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
const QString name = index.data(FilenameListModel::NameRole).toString();
return strncmp(name.toLower().toStdString().c_str(), m_filenameBeginning.toLower().toStdString().c_str(), m_filenameBeginning.size()) == 0;
}
void FilterProxyModel::setFilenameBeginning(QString newStr)
{
m_filenameBeginning = newStr;
emit filenameBeginningChanged();
invalidateFilter();
}
QString FilterProxyModel::getFilenameBeginnning()
{
return m_filenameBeginning;
}
void FilterProxyModel::deleteConfigurationFile(QVector<int> indexToDelete)
{
for (int i = 0; i < indexToDelete.size(); i++)
{
qDebug() << this->data(this->index(indexToDelete[i], 0), FilenameListModel::Roles::NameRole);
}
}
void FilterProxyModel::loadConfigurationFile(QVector<int> indexToLoad)
{
// The input should be with only one element on it
qDebug() << this->data(this->index(indexToLoad[0], 0), FilenameListModel::Roles::DateRole);
}
void FilterProxyModel::setIsSavingMode(bool newMode)
{
m_isSavingMode = newMode;
}
感谢@JarMan的建议,我简化了QML部分,列表视图的委托上不再有算法部分。现在后端会自行更新我想要的模型上每个项目的角色
CheckedRole
。而且滚动不再是问题。
我把代码的修改放在这里:
主要文件
main.cpp(无变化)
main.qml(简化委托并将逻辑放在列表视图上)
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.5
import QtQml.Models 2.12
import QtQuick.Layouts 1.12
ApplicationWindow
{
id: root
property bool isSaving: false
minimumWidth: 600
minimumHeight: 400
visible: true
modality: Qt.ApplicationModal
Component.onCompleted:
{
// Update the backend with current saving mode
_FilteredRunwayConfigurationFilesModel.isSavingMode = isSaving
}
DelegateModel
{
id: delegateModel
model: _FilteredRunwayConfigurationFilesModel
delegate: Rectangle
{
id: item_delegate
width: ListView.view.width - 10
height: name.implicitHeight
color: model.isChecked? "lightgreen" : "lightblue"
radius: 10
Rectangle
{
id: leftRectangle
anchors
{
top: parent.top
bottom: parent.bottom
left: parent.left
right: rightRectangle.left
}
color: "transparent"
Text
{
id: name
anchors.fill: parent
anchors.margins: 5
verticalAlignment: Qt.AlignVCenter
horizontalAlignment: Qt.AlignHCenter
text: "%1".arg(model.name)
}
}
Rectangle
{
id: rightRectangle
anchors
{
top: parent.top
bottom: parent.bottom
right: parent.right
}
color: "transparent"
width: parent.width * 0.3
Text
{
id: date
anchors.fill: parent
anchors.margins: 5
verticalAlignment: Qt.AlignVCenter
horizontalAlignment: Qt.AlignHCenter
text: model.date
}
}
MouseArea
{
anchors.fill: parent
acceptedButtons: Qt.LeftButton
onClicked:
{
if (!isSaving)
{
switch(mouse.modifiers)
{
case Qt.ControlModifier:
listViewFilter.selectCtrl(index)
break
case Qt.ShiftModifier:
listViewFilter.selectShift(index)
break
default:
listViewFilter.selectOne(index)
break
}
}
else
{
textFilterString.text = model.name
}
}
}
}
}
ColumnLayout
{
anchors.fill: parent
anchors.margins: 5
TextField
{
id: textFilterString
Layout.fillWidth: true
Layout.preferredHeight: implicitHeight
horizontalAlignment: Qt.AlignHCenter
verticalAlignment: Qt.AlignVCenter
placeholderText: isSaving ? "Write the filename with the '.atols' extension" : "Write the begin of the filename"
onTextChanged:
{
_FilteredRunwayConfigurationFilesModel.filenameBeginning = text;
}
}
RowLayout
{
Layout.fillWidth: true
Layout.preferredHeight: textFilterString.height
Layout.alignment: Qt.AlignHCenter
Button
{
id: buttonLoad
Layout.preferredWidth: 100
Layout.preferredHeight: parent.height
text: "LOAD"
enabled: false
visible: !isSaving
onClicked:
{
_FilteredRunwayConfigurationFilesModel.loadConfigurationFile(listViewFilter.selectedIndex)
}
}
Button
{
id: buttonDelete
Layout.preferredWidth: 100
Layout.preferredHeight: parent.height
text: "DELETE"
enabled: false
visible: !isSaving
onClicked:
{
_FilteredRunwayConfigurationFilesModel.deleteConfigurationFile(listViewFilter.selectedIndex)
}
}
Button
{
id: buttonSave
Layout.preferredWidth: 100
Layout.preferredHeight: parent.height
text: "SAVE"
enabled: textFilterString.text
visible: isSaving
onClicked:
{
// TODO
}
}
}
ListView
{
id: listViewFilter
property int indexBegin: -1
property int indexEnd: -1
property var selectedIndex: []
signal selectOne(int idx)
signal selectCtrl(int idx)
signal selectShift(int idx)
// Called first when executing from a delegate item
onSelectOne:
{
indexBegin = indexEnd = idx
selectedIndex = [indexBegin]
selectedIndexChanged()
}
onSelectShift:
{
// Add all index between begin and end on the list
if (indexBegin === -1)
{
indexBegin = indexEnd = idx
}
else
{
indexEnd = idx
}
selectedIndex.length = 0
for (var i = Math.min(indexBegin, indexEnd); i <= Math.max(indexBegin, indexEnd); i++)
selectedIndex.push(i)
// Define the new begin with the last item selected
indexBegin = idx
selectedIndexChanged()
}
onSelectCtrl:
{
// Add the index to the list of not already on it
indexBegin = idx
if (selectedIndex.indexOf(idx) === -1)
selectedIndex.push(idx)
selectedIndexChanged()
}
onSelectedIndexChanged:
{
_FilteredRunwayConfigurationFilesModel.setCheckedIndexes(selectedIndex)
}
function checkChanged()
{
listViewFilter.selectedIndex = []
// Check how many items are selected in the list
var nSelected = 0
for (var i = 0; i < listViewFilter.count; i++)
{
if (listViewFilter.contentItem.children[i] && listViewFilter.contentItem.children[i].checked)
{
nSelected++
listViewFilter.selectedIndex.push(i)
}
}
// Enable or disable buttons to load or delete the selected items
var loadEnable = false
var deleteEnable = false
switch(nSelected)
{
case 1: // One item selected => Load and Delete available
loadEnable = true
deleteEnable = true
break
case 0: // No items selected => Nothing available
loadEnable = false
deleteEnable = false
break
default: // Multiple items selected => Only Delete available
loadEnable = false
deleteEnable = true
break
}
buttonLoad.enabled = loadEnable
buttonDelete.enabled = deleteEnable
_FilteredRunwayConfigurationFilesModel.setCheckedIndexes(listViewFilter.selectedIndex)
}
Layout.fillWidth: true
Layout.fillHeight: true
model: delegateModel
ScrollBar.vertical: ScrollBar
{
anchors.top: parent.top
anchors.bottom: parent.bottom
anchors.right: parent.right
policy: listViewFilter.contentHeight > listViewFilter.height ? ScrollBar.AlwaysOn : ScrollBar.AlwaysOff
active: true
}
}
TextField
{
Layout.fillWidth: true
Layout.preferredHeight: textFilterString.height
text: "No files with this filter"
verticalAlignment: Qt.AlignTop
horizontalAlignment: Qt.AlignHCenter
visible: listViewFilter.count === 0
}
}
}
基础型号
FilenameListModel.h(无变化)
文件名ListModel.cpp(无变化)
代理模型
#ifndef FILTERPROXYMODEL_H
#define FILTERPROXYMODEL_H
#include <QSortFilterProxyModel>
class FilterProxyModel : public QSortFilterProxyModel
{
Q_OBJECT
Q_PROPERTY(QString filenameBeginning WRITE setFilenameBeginning READ getFilenameBeginnning NOTIFY filenameBeginningChanged)
Q_PROPERTY(bool isSavingMode WRITE setIsSavingMode NOTIFY isSavingModeChanged)
public:
explicit FilterProxyModel(QObject *parent = nullptr);
void setFilenameBeginning(QString newStr);
QString getFilenameBeginnning();
void setIsSavingMode(bool newMode);
public slots:
Q_INVOKABLE void deleteConfigurationFile(QVector<int> indexToDelete);
Q_INVOKABLE void loadConfigurationFile(QVector<int> indexToLoad);
Q_INVOKABLE void setCheckedIndexes(QVector<int> listIndex); // ------> New slot <------
signals:
void filenameBeginningChanged();
void isSavingModeChanged();
protected:
bool lessThan(const QModelIndex &sourceLeft, const QModelIndex &sourceRight) const override;
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
private:
QString m_filenameBeginning;
bool m_isSavingMode;
};
#endif // FILTERPROXYMODEL_H
#include "FilterProxyModel.h"
#include "FilenameListModel.h"
#include <QDebug>
FilterProxyModel::FilterProxyModel(QObject *parent)
: QSortFilterProxyModel (parent)
{
m_isSavingMode = false;
sort(0, Qt::SortOrder::DescendingOrder);
}
bool FilterProxyModel::lessThan(const QModelIndex &sourceLeft, const QModelIndex &sourceRight) const
{
const QDate leftDate = sourceLeft.data(FilenameListModel::DateRole).toDate();
const QDate rightDate = sourceRight.data(FilenameListModel::DateRole).toDate();
return leftDate < rightDate;
}
bool FilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
{
// In saving mode, keep all files on the list
if (m_isSavingMode)
return true;
// Otherwise, filter the rows
const QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
const QString name = index.data(FilenameListModel::NameRole).toString();
return strncmp(name.toLower().toStdString().c_str(), m_filenameBeginning.toLower().toStdString().c_str(), m_filenameBeginning.size()) == 0;
}
void FilterProxyModel::setFilenameBeginning(QString newStr)
{
m_filenameBeginning = newStr;
emit filenameBeginningChanged();
invalidateFilter();
}
QString FilterProxyModel::getFilenameBeginnning()
{
return m_filenameBeginning;
}
void FilterProxyModel::deleteConfigurationFile(QVector<int> indexToDelete)
{
for (int i = 0; i < indexToDelete.size(); i++)
{
qDebug() << this->data(this->index(indexToDelete[i], 0), FilenameListModel::Roles::NameRole);
}
}
void FilterProxyModel::loadConfigurationFile(QVector<int> indexToLoad)
{
// The input should be with only one element on it
qDebug() << this->data(this->index(indexToLoad[0], 0), FilenameListModel::Roles::DateRole);
}
void FilterProxyModel::setIsSavingMode(bool newMode)
{
m_isSavingMode = newMode;
}
// ------> NEW CODE BELOW <------
void FilterProxyModel::setCheckedIndexes(QVector<int> listIndex)
{
// First reset all checked value already to true
for (int i = 0; i < sourceModel()->rowCount(); i++)
{
if (data(this->index(i, 0), FilenameListModel::Roles::CheckedRole).toBool())
setData(this->index(i, 0), false, FilenameListModel::Roles::CheckedRole);
}
// Then set to true checked value only for selected delegate
for (int i = 0; i < listIndex.size(); i++)
{
setData(this->index(listIndex[i], 0), true, FilenameListModel::Roles::CheckedRole);
}
}