Russian Qt Forum

Qt => Model-View (MV) => Тема начата: CL0NE от Май 17, 2010, 04:04



Название: QFileSystemModel + QTreeView + Checkboxes
Отправлено: CL0NE от Май 17, 2010, 04:04
Читал топики Нужен компонент обзора директорий компьютера. Есть ли что-то такое в QT? (http://www.prog.org.ru/topic_13078_0.html) (из разряда: как прилепить чекбоксы к айтемам в тривью) и QTreeWidget - нажатие на узел дерева (http://www.prog.org.ru/topic_8666_15.html) ("хочу при клике на чекбоксе в тривью отмечались/снимались галки на чайлдах"). По первому пункту было просто: взял себе QFileSystemModel, переопределил методы setData, data и flags. По второму вышла лабуда (реализация - добавлен сигнал и слот при смене состояния айтема в первой колонке)... т.е. дочерние видимые айтемы отмечаются ибо модель обновилась при их раскрытии и добавила файло/папки себе, но их содержимое еще не было получено и, соответственно, данные субайтемы не отметились. Понятное дело, пробежка по нижележащим каталогами займет много времени. Но как отметить все без потерь? :)

И еще 2 нубских вопроса (добавка):
  • Как заставить FileSystemModel следить только за директориями и отображать только их // Ответ - void QFileSystemModel::setFilter ( QDir::Filters filters )
  • setRootPath, судя по документации, сменяет текущую отслеживаемую директорию. как заставить отображать суб-айтемы ниже определенного без соседей и родителей // Ответ - setRootIndex

ниже - текущая реализация:

checkablefilesystemmodel.h
Код
C++ (Qt)
#ifndef CHECKABLEFILESYSTEMMODEL_H
#define CHECKABLEFILESYSTEMMODEL_H
 
#include <QFileSystemModel>
#include <QStandardItem>
 
class CheckableFileSystemModel : public QFileSystemModel
{
   Q_OBJECT
public:
   CheckableFileSystemModel();
   virtual bool setData( const QModelIndex& index, const QVariant& value, int role );
   virtual Qt::ItemFlags flags( const QModelIndex & index ) const;
   virtual QVariant data( const QModelIndex &index, int role )const;
signals:
   void itemChecked(const QModelIndex&);
protected slots:
   void onItemChecked(const QModelIndex& index);
private:
   mutable QMap <qint64, Qt::CheckState> checkedItems;
};
 
#endif // CHECKABLEFILESYSTEMMODEL_H
 

checkablefilesystemmodel.cpp
Код
C++ (Qt)
#include "checkablefilesystemmodel.h"
 
CheckableFileSystemModel::CheckableFileSystemModel()
{
   connect(this, SIGNAL(itemChecked(const QModelIndex&)), SLOT(onItemChecked(const QModelIndex&)));
}
 
bool CheckableFileSystemModel::setData( const QModelIndex& index, const QVariant& value, int role ) {
 
   if( role == Qt::CheckStateRole && index.column() == 0 ) {
 
       checkedItems[ index.internalId() ] = static_cast<Qt::CheckState>( value.toInt() );
       emit itemChecked(index);
       emit dataChanged(index, index.sibling(0,0));
       return true;
 
   }
 
   return QFileSystemModel::setData(index, value, role);
 
}
 
Qt::ItemFlags CheckableFileSystemModel::flags( const QModelIndex & index ) const {
 
   return QFileSystemModel::flags( index ) | Qt::ItemIsUserCheckable;
 
}
 
QVariant CheckableFileSystemModel::data( const QModelIndex& index, int role ) const {
 
   if( role == Qt::CheckStateRole && index.column()==0 ) {
       return QVariant( checkedItems[ index.internalId() ] );
   }
 
   return QFileSystemModel::data( index, role );
}
 
void CheckableFileSystemModel::onItemChecked(const QModelIndex &index)
{
   Qt::CheckState state = checkedItems [index.internalId()];
   fetchMore(index);
   if ( state == Qt::Checked || state == Qt::Unchecked ) {
       for ( int i = 0; i < rowCount(index); i++ ) {
           QModelIndex child = index.child(i, 0);
           if (checkedItems [child.internalId()] != state )
               setData(child, state, Qt::CheckStateRole);
       }
   }
 
   QModelIndex parent = index.parent();
   if (parent.isValid()) {
       state = checkedItems [parent.child(0, 0).internalId()];
       if (state == Qt::PartiallyChecked)
           checkedItems[parent.internalId()] = state;
       else {
           int i = 1;
           while (i < rowCount(parent) && checkedItems [parent.child(i, 0).internalId()] == state)
               i++;
           if (i != rowCount(index))
               state = Qt::PartiallyChecked;
           //setData(parent, state, Qt::CheckStateRole);
           checkedItems [parent.internalId()] = state;
       }
   }
 
}