Russian Qt Forum
Май 14, 2024, 02:57 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: QTreeView + QFileSystemModel - чекбоксы  (Прочитано 5334 раз)
Serega
Самовар
**
Offline Offline

Сообщений: 127


Просмотр профиля
« : Март 12, 2015, 07:49 »

Немного усложним файловый виджет http://www.prog.org.ru/topic_28581_0.html

Код
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. Один вопрос вопрос снят с повестки. Первый пока недорабтан.
По поводу третьего. Флажок то есть, но видимо его установки не достаточно.
« Последнее редактирование: Март 12, 2015, 16:38 от Serega » Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4727



Просмотр профиля WWW
« Ответ #1 : Март 12, 2015, 12:29 »

для последнего есть соответствующий флажок
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Serega
Самовар
**
Offline Offline

Сообщений: 127


Просмотр профиля
« Ответ #2 : Март 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;
}
Записан
gil9red
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1805



Просмотр профиля WWW
« Ответ #3 : Март 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);
            }
...
 
Записан

Serega
Самовар
**
Offline Offline

Сообщений: 127


Просмотр профиля
« Ответ #4 : Март 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
« Последнее редактирование: Март 15, 2015, 11:57 от Serega » Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.154 секунд. Запросов: 22.