Название: QTreeView + QFileSystemModel - чекбоксы
Отправлено: Serega от Март 12, 2015, 07:49
Немного усложним файловый виджет http://www.prog.org.ru/topic_28581_0.html (http://www.prog.org.ru/topic_28581_0.html) (http://s018.radikal.ru/i509/1503/c1/3e9f80f21e62t.jpg) (http://radikal.ru/fp/6716578fc58b429e8c4d9373fc43bbdf) C++ (Qt) Qt::ItemFlags CFileSystemModel::flags(const QModelIndex &index) const { return QFileSystemModel::flags(index) | Qt::ItemIsUserCheckable | Qt::ItemIsEditable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; } QVariant CFileSystemModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) { return QVariant(); } else if(role == Qt::CheckStateRole) { return checkedIndexes.contains(index) ? Qt::Checked : Qt::Unchecked; } else if (role == Qt::DisplayRole && fileInfo(index).isFile() ) { return m_needFilenameWithExt ? fileInfo(index).fileName() : fileInfo(index).baseName(); } else if (role == Qt::EditRole) { return fileInfo(index).baseName(); } else { return QFileSystemModel::data(index, role); } } bool CFileSystemModel::setData(const QModelIndex &index, const QVariant &value, int role) { if(index.isValid() && role == Qt::CheckStateRole) { if(value == Qt::Checked) { checkedIndexes.insert(index); if(hasChildren(index) == true) { recursiveCheck(index, value); } } else { checkedIndexes.remove(index); if(hasChildren(index) == true) { recursiveCheck(index, value); } } emit dataChanged(index, index); return true; } else if (index.isValid() && role == Qt::EditRole && fileInfo(index).isFile()) { m_needFilenameWithExt = true; bool result = QFileSystemModel::setData(index, value.toString() + "." + fileInfo(index).completeSuffix(), role); m_needFilenameWithExt = false; return result; } return QFileSystemModel::setData(index, value, role); } bool CFileSystemModel::recursiveCheck(const QModelIndex &index, const QVariant &value) { if(hasChildren(index)) { int i; int childrenCount = rowCount(index); QModelIndex child; for(i=0; i<childrenCount; i++) { child = QFileSystemModel::index(i, 0, index); setData(child, value, Qt::CheckStateRole); } } }
Тестовый виджет прикреплен. Что не нравится на данный момент: - Если отметить папку, отмечаются рекурсивно все подкаталоги и их содержимое. Необходимо, что бы отмечались только файлы корневого каталога. - Реализовать тройной чекбокс с неопределенным состоянием. И соответственно сам вопрос, как доработать минимальными силами? Вопрос решаем, но как показала практика лучше поучиться у профи, чем днями ковырять код. P.S. Один вопрос вопрос снят с повестки. Первый пока недорабтан. По поводу третьего. Флажок то есть, но видимо его установки не достаточно.
Название: Re: QTreeView + QFileSystemModel - чекбоксы
Отправлено: kambala от Март 12, 2015, 12:29
для последнего есть соответствующий флажок
Название: Re: QTreeView + QFileSystemModel - чекбоксы
Отправлено: Serega от Март 13, 2015, 10:35
Еще одним вопросом меньше. Вариант без рекурсии, захода во внутренние папки. Если есть замечания или более компактные варианты, буду рад выслушать. Во вложении пример виджета. C++ (Qt) #include "cfilesystemmodel.hh" #include <QDebug> CFileSystemModel::CFileSystemModel(QObject *parent) : QFileSystemModel(parent) , m_needFilenameWithExt(false) , m_topFolder(false) { } Qt::ItemFlags CFileSystemModel::flags(const QModelIndex &index) const { return QFileSystemModel::flags(index) | Qt::ItemIsUserCheckable | Qt::ItemIsEditable } QVariant CFileSystemModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) { return QVariant(); } else if(role == Qt::CheckStateRole) { return checkedIndexes.contains(index) ? Qt::Checked : Qt::Unchecked; } else if (role == Qt::DisplayRole && fileInfo(index).isFile()) { return m_needFilenameWithExt ? fileInfo(index).fileName() : fileInfo(index).baseName(); } else if (role == Qt::EditRole) { return fileInfo(index).baseName(); } else { return QFileSystemModel::data(index, role); } } bool CFileSystemModel::setData(const QModelIndex &index, const QVariant &value, int role) { if(index.isValid() && role == Qt::CheckStateRole) { if(value == Qt::Checked) { if (fileInfo(index).isFile() || m_topFolder == false) { checkedIndexes.insert(index); } if(hasChildren(index) == true && m_topFolder == false) { recursiveCheck(index, value); } } else { if (fileInfo(index).isFile() || m_topFolder == false) { checkedIndexes.remove(index); } if(hasChildren(index) == true && m_topFolder == false) { recursiveCheck(index, value); } } emit dataChanged(index, index); return true; } else if (index.isValid() && role == Qt::EditRole && fileInfo(index).isFile()) { m_needFilenameWithExt = true; bool result = QFileSystemModel::setData(index, value.toString() + "." + fileInfo(index).completeSuffix(), role); m_needFilenameWithExt = false; return result; } return QFileSystemModel::setData(index, value, role); } bool CFileSystemModel::recursiveCheck(const QModelIndex &index, const QVariant &value) { m_topFolder = true; if(hasChildren(index)) { int i; int childrenCount = rowCount(index); QModelIndex child; for(i=0; i<childrenCount; i++) { child = QFileSystemModel::index(i, 0, index); setData(child, value, Qt::CheckStateRole); } } m_topFolder = false; }
Название: Re: QTreeView + QFileSystemModel - чекбоксы
Отправлено: gil9red от Март 13, 2015, 10:51
В setData можно сократить код: C++ (Qt) ... if (fileInfo(index).isFile() || m_topFolder == false) { if(value == Qt::Checked) checkedIndexes.insert(index); else checkedIndexes.remove(index); } ...
Название: Re: QTreeView + QFileSystemModel - чекбоксы
Отправлено: Serega от Март 13, 2015, 11:07
Спасибо, учту. C++ (Qt) #include "cfilesystemmodel.hh" #include <QDebug> CFileSystemModel::CFileSystemModel(QObject *parent) : QFileSystemModel(parent) , m_needFilenameWithExt(false) , m_topFolder(false) { } Qt::ItemFlags CFileSystemModel::flags(const QModelIndex &index) const { return QFileSystemModel::flags(index) | Qt::ItemIsUserCheckable | Qt::ItemIsEditable } QVariant CFileSystemModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) { return QVariant(); } else if(role == Qt::CheckStateRole) { return checkedIndexes.contains(index) ? Qt::Checked : Qt::Unchecked; } else if (role == Qt::DisplayRole && fileInfo(index).isFile()) { return m_needFilenameWithExt ? fileInfo(index).fileName() : fileInfo(index).baseName(); } else if (role == Qt::EditRole) { return fileInfo(index).baseName(); } else { return QFileSystemModel::data(index, role); } } bool CFileSystemModel::setData(const QModelIndex &index, const QVariant &value, int role) { if(index.isValid() && role == Qt::CheckStateRole) { if (fileInfo(index).isFile() || m_topFolder == false) { if(value == Qt::Checked) checkedIndexes.insert(index); else checkedIndexes.remove(index); } if(hasChildren(index) == true && m_topFolder == false) { recursiveCheck(index, value); } emit dataChanged(index, index); return true; } else if (index.isValid() && role == Qt::EditRole && fileInfo(index).isFile()) { m_needFilenameWithExt = true; bool result = QFileSystemModel::setData(index, value.toString() + "." + fileInfo(index).completeSuffix(), role); m_needFilenameWithExt = false; return result; } return QFileSystemModel::setData(index, value, role); } bool CFileSystemModel::recursiveCheck(const QModelIndex &index, const QVariant &value) { m_topFolder = true; if(hasChildren(index)) { int i; int childrenCount = rowCount(index); QModelIndex child; for(i=0; i<childrenCount; i++) { child = QFileSystemModel::index(i, 0, index); setData(child, value, Qt::CheckStateRole); } } m_topFolder = false; }
Однако пока, что то тут не совсем все в порядке. Пока папка в первый раз не открыта, то при проставке галочки, внутренние файлы не отмечаются. Третья часть QTreeView + QFileSystemModel - Drag and Drop http://www.prog.org.ru/index.php?topic=28603.msg209271#msg209271
|