Russian Qt Forum

Qt => Model-View (MV) => Тема начата: Serega от Март 11, 2015, 15:16



Название: QTreeView + QFileSystemModel - скрыть расширения файлов
Отправлено: Serega от Март 11, 2015, 15:16
Задача собственно получить простейший менеджер с именами файлов без расширения и возможностью редактирования, как здесь:
(http://s018.radikal.ru/i506/1503/d8/5bd24f550105t.jpg) (http://radikal.ru/fp/ae3f6e7691b149799ba52c8b56444caf)

Такая картина если раскомментировать DisplayRole в Реализации модели:
Код:
#include "cfilesystemmodel.hh"
#include <QDebug>
 CFileSystemModel::CFileSystemModel(QObject *parent)
    : QFileSystemModel(parent)
{
}

 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::DisplayRole)
//     {
//         return 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::EditRole)
     {
         return QFileSystemModel::setData(index, value.toString() + "." + fileInfo(index).completeSuffix(), role);
     }
     return QFileSystemModel::setData(index, value, role);
 }
Однако при попытке сохранения отредакированного имени файла, выскакивает окно:
(http://s020.radikal.ru/i703/1503/eb/846b6ddb3ed6t.jpg) (http://radikal.ru/fp/6d8d12f791c24ea39a3d885dc2b5ef58)

Соответственно если закомментировать то при редактировании как положенно мы можем менять имя без раширения, но в отображении расширение имеется, от которого все таки хочется избавиться:
(http://s017.radikal.ru/i417/1503/47/c45ec25dc466t.jpg) (http://radikal.ru/fp/8f23fa43d7d7439a990196de80134e56)

Как поступить? Хотелось бы как можно проще без привлечения собственного делегата.


Название: Re: QTreeView + QFileSystemModel - скрыть расширения файлов
Отправлено: kai666_73 от Март 11, 2015, 18:03
Может так получится
Код
C++ (Qt)
#include "cfilesystemmodel.hh"
#include <QDebug>
CFileSystemModel::CFileSystemModel(QObject *parent)
   : QFileSystemModel(parent)
{
}
 
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::DisplayRole)
    {
        return fileInfo(index).fileName();
    }
    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::EditRole)
    {
        return QFileSystemModel::setData(index, value.toString() + "." + fileInfo(index).completeSuffix(), Qt::DisplayRole);  /// <<<
    }
    return QFileSystemModel::setData(index, value, role);
}
 


Название: Re: QTreeView + QFileSystemModel - скрыть расширения файлов
Отправлено: Serega от Март 11, 2015, 18:35
Спасибо за помощь!
При таком раскладе. В представлении расширение все таки имеется.
Если оставить так:
Код:
     else if (role == Qt::DisplayRole)
     {
         return fileInfo(index).baseName();
     }
Расширение исчезает. Но в обоих случаях не получается переименовать файлы.

Но есть различие с первоначальным вариантом. Окно ошибки не выскакивает.
Однако результат редактирования не сохраняется (в обоих последних вариантах).


Название: Re: QTreeView + QFileSystemModel - скрыть расширения файлов
Отправлено: kai666_73 от Март 11, 2015, 19:08
У меня так работает
Код
C++ (Qt)
#include "CFileSystemModel.h"
 
CFileSystemModel::CFileSystemModel(QObject *parent)
   : QFileSystemModel(parent)
{
   setRootPath("C:/");
   setReadOnly(false);
}
 
CFileSystemModel::~CFileSystemModel()
{
 
}
 
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::DisplayRole)
    {
        return fileInfo(index).fileName();
    }
    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::EditRole)
    {
        return QFileSystemModel::setData(index, value.toString() + "." + fileInfo(index).completeSuffix(), role);
    }
    return QFileSystemModel::setData(index, value, role);
}
 
int CFileSystemModel::columnCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return 1;
}
 
Только расширение скрыть не получается. Все тоже окошко вылетает.
Могу свой тестовый проект приаттачить...


Название: Re: QTreeView + QFileSystemModel - скрыть расширения файлов
Отправлено: Serega от Март 11, 2015, 19:21
Однако первый вариант в точности так и работает (даже попроще вариант). Но как раз хотелось избавиться от расширения при отображении (при редактировании все в порядке - исчезает).
Жаль не хотелось усложнать проект, доволно просто и аккуратно выходило (своего рода встроенный менеджер с единственной корневой папкой, фильтром по расширению и чекбоксами). Но маленькая на первый взгляд проблемка... Наверное придется усложнать проект. Ничего страшного наверное нет, но надеялся на лучший исход.


Название: Re: QTreeView + QFileSystemModel - скрыть расширения файлов
Отправлено: kai666_73 от Март 11, 2015, 19:46
Ой, извиняюсь, видимо не совсем правильно понял суть проблемы.
Но есть идея - попробуйте еще перекрыть роль QFileSystemModel::FileNameRole


Название: Re: QTreeView + QFileSystemModel - скрыть расширения файлов
Отправлено: kai666_73 от Март 11, 2015, 20:10
Ух, все таки удалось... см. аттач


Название: Re: QTreeView + QFileSystemModel - скрыть расширения файлов
Отправлено: Serega от Март 11, 2015, 20:24
Великолепно!
Интересно то, что задачка вроде и не такая уж и сложная (зарядка), но вроде как часто нужная, а решений простых не находил. Тут быстренько мозговым штурмом... Поздновато у нас. Завтра прикручу к своему простенькому проекту  с чекбоксиками и что бы пользователь не выходил за пределы журнала... :).
Спасибо!


Название: Re: QTreeView + QFileSystemModel - скрыть расширения файлов
Отправлено: Serega от Март 11, 2015, 20:45
Все таки не удержался примерил на своем проекте. Работает с файлами.
Ничего страшного. С переименованием папок пока не порядок. Думаю тут ничего сложного не будет, справлюсь (не обращал внимание). Но  может вам интересно будет довести свой тестовы проект до ума.


Название: Re: QTreeView + QFileSystemModel - скрыть расширения файлов
Отправлено: kai666_73 от Март 11, 2015, 21:37
Не не. Я знаю в чем там дело, но оставлю вам в качестве домашнего задания, тем более что в аттаче есть подсказка)


Название: Re: QTreeView + QFileSystemModel - скрыть расширения файлов
Отправлено: Serega от Март 12, 2015, 04:30
Да действительно доделать оказалось минутным делом:
Код
C++ (Qt)
#include "cfilesystemmodel.hh"
#include <QDebug>
CFileSystemModel::CFileSystemModel(QObject *parent)
   : QFileSystemModel(parent)
   , m_needFilenameWithExt(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::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::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);
 }
 
Ваш переделанный тестовый проект во вложении. Возможно пригодится таким же новичкам с малой практикой как я. Хорош как пример для разбора начинающим, не сложен для понимания и осознания смысла отношений модель-представление (в учебниках как то более мудрено закручено). Здесь же получилось просто, без излишеств и с потенциалом расширения. Легко воткнуть в более сложный проект в качестве менеджера скажем журналов, закладок и не сложно улучшить стиль...

Но если честно не до конца осознал. Конечно сама логика кода не смущает, ее мне не сложно прочитать и понять как устроено и что надо было сделать, что бы все сработало. Но вот саму суть не понял. Почему изначально не сработало. Ведь вроде только просил показать в представлении имя файла и ничего не делать с данными и код уже забарахлил (может пока не было времени посмотреть внимательнее на решение)... Ну да ладно, поковыряю в дебаге... :).

За помощь искреннее спасибо! Пару дней минимум пришлось бы еще затратить на самостоятельные эксперменты, собственно пару и затратил прежде чем решил все таки спросить.

В этой ветке наверное уже нет смысла расширять проект с чекбоксами, возможно стоит открыть дополнительную.
QTreeView + QFileSystemModel - чекбоксы  http://www.prog.org.ru/topic_28586_0.html


Название: Re: QTreeView + QFileSystemModel - скрыть расширения файлов
Отправлено: PimenS от Март 12, 2015, 09:14
Возможно пригодится таким же новичкам с малой практикой как я.

Может быть лучше использовать здесь switch, что и быстрее и нагляднее.

Код:
    switch (role) {
         case Qt::EditRole:
             return fileInfo(index).baseName();
             break;
         case Qt::DisplayRole: {
             if (fileInfo(index).isFile())
                return m_needFilenameWithExt ? fileInfo(index).fileName() :fileInfo(index).baseName();
             else
                 return QFileSystemModel::data(index, role);
             break;
         }
         default:
             return QFileSystemModel::data(index, role);
             break;
     }


Название: Re: QTreeView + QFileSystemModel - скрыть расширения файлов
Отправлено: kai666_73 от Март 12, 2015, 12:20
Но если честно не до конца осознал. Конечно сама логика кода не смущает, ее мне не сложно прочитать и понять как устроено и что надо было сделать, что бы все сработало. Но вот саму суть не понял. Почему изначально не сработало. Ведь вроде только просил показать в представлении имя файла и ничего не делать с данными и код уже забарахлил (может пока не было времени посмотреть внимательнее на решение)... Ну да ладно, поковыряю в дебаге... :).
Тут как раз все просто. Достаточно посмотреть на исходный код QFileSystemModel, конкретнее - на ф-ю setData, и все станет на свои места )