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

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

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

Сообщений: 127


Просмотр профиля
« : Март 11, 2015, 15:16 »

Задача собственно получить простейший менеджер с именами файлов без расширения и возможностью редактирования, как здесь:


Такая картина если раскомментировать 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);
 }
Однако при попытке сохранения отредакированного имени файла, выскакивает окно:


Соответственно если закомментировать то при редактировании как положенно мы можем менять имя без раширения, но в отображении расширение имеется, от которого все таки хочется избавиться:


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

Сообщений: 319


Просмотр профиля
« Ответ #1 : Март 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);
}
 
« Последнее редактирование: Март 11, 2015, 18:06 от kai666_73 » Записан
Serega
Самовар
**
Offline Offline

Сообщений: 127


Просмотр профиля
« Ответ #2 : Март 11, 2015, 18:35 »

Спасибо за помощь!
При таком раскладе. В представлении расширение все таки имеется.
Если оставить так:
Код:
     else if (role == Qt::DisplayRole)
     {
         return fileInfo(index).baseName();
     }
Расширение исчезает. Но в обоих случаях не получается переименовать файлы.

Но есть различие с первоначальным вариантом. Окно ошибки не выскакивает.
Однако результат редактирования не сохраняется (в обоих последних вариантах).
« Последнее редактирование: Март 11, 2015, 18:37 от Serega » Записан
kai666_73
Крякер
****
Offline Offline

Сообщений: 319


Просмотр профиля
« Ответ #3 : Март 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;
}
 
Только расширение скрыть не получается. Все тоже окошко вылетает.
Могу свой тестовый проект приаттачить...
Записан
Serega
Самовар
**
Offline Offline

Сообщений: 127


Просмотр профиля
« Ответ #4 : Март 11, 2015, 19:21 »

Однако первый вариант в точности так и работает (даже попроще вариант). Но как раз хотелось избавиться от расширения при отображении (при редактировании все в порядке - исчезает).
Жаль не хотелось усложнать проект, доволно просто и аккуратно выходило (своего рода встроенный менеджер с единственной корневой папкой, фильтром по расширению и чекбоксами). Но маленькая на первый взгляд проблемка... Наверное придется усложнать проект. Ничего страшного наверное нет, но надеялся на лучший исход.
Записан
kai666_73
Крякер
****
Offline Offline

Сообщений: 319


Просмотр профиля
« Ответ #5 : Март 11, 2015, 19:46 »

Ой, извиняюсь, видимо не совсем правильно понял суть проблемы.
Но есть идея - попробуйте еще перекрыть роль QFileSystemModel::FileNameRole
Записан
kai666_73
Крякер
****
Offline Offline

Сообщений: 319


Просмотр профиля
« Ответ #6 : Март 11, 2015, 20:10 »

Ух, все таки удалось... см. аттач
Записан
Serega
Самовар
**
Offline Offline

Сообщений: 127


Просмотр профиля
« Ответ #7 : Март 11, 2015, 20:24 »

Великолепно!
Интересно то, что задачка вроде и не такая уж и сложная (зарядка), но вроде как часто нужная, а решений простых не находил. Тут быстренько мозговым штурмом... Поздновато у нас. Завтра прикручу к своему простенькому проекту  с чекбоксиками и что бы пользователь не выходил за пределы журнала... Улыбающийся.
Спасибо!
Записан
Serega
Самовар
**
Offline Offline

Сообщений: 127


Просмотр профиля
« Ответ #8 : Март 11, 2015, 20:45 »

Все таки не удержался примерил на своем проекте. Работает с файлами.
Ничего страшного. С переименованием папок пока не порядок. Думаю тут ничего сложного не будет, справлюсь (не обращал внимание). Но  может вам интересно будет довести свой тестовы проект до ума.
Записан
kai666_73
Крякер
****
Offline Offline

Сообщений: 319


Просмотр профиля
« Ответ #9 : Март 11, 2015, 21:37 »

Не не. Я знаю в чем там дело, но оставлю вам в качестве домашнего задания, тем более что в аттаче есть подсказка)
Записан
Serega
Самовар
**
Offline Offline

Сообщений: 127


Просмотр профиля
« Ответ #10 : Март 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
« Последнее редактирование: Март 12, 2015, 14:38 от Serega » Записан
PimenS
Крякер
****
Offline Offline

Сообщений: 371


Просмотр профиля
« Ответ #11 : Март 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;
     }
Записан
kai666_73
Крякер
****
Offline Offline

Сообщений: 319


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

Но если честно не до конца осознал. Конечно сама логика кода не смущает, ее мне не сложно прочитать и понять как устроено и что надо было сделать, что бы все сработало. Но вот саму суть не понял. Почему изначально не сработало. Ведь вроде только просил показать в представлении имя файла и ничего не делать с данными и код уже забарахлил (может пока не было времени посмотреть внимательнее на решение)... Ну да ладно, поковыряю в дебаге... Улыбающийся.
Тут как раз все просто. Достаточно посмотреть на исходный код QFileSystemModel, конкретнее - на ф-ю setData, и все станет на свои места )
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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