Russian Qt Forum

Qt => Model-View (MV) => Тема начата: Serega от Март 12, 2015, 07:49



Название: 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