1 /* This file is part of the KDE Project
2 Copyright (c) 2008 Sebastian Trueg <trueg@kde.org>
4 Based on CollectionSetup.cpp from the Amarok project
5 (C) 2003 Scott Wheeler <wheeler@kde.org>
6 (C) 2004 Max Howell <max.howell@methylblue.com>
7 (C) 2004 Mark Kretschmann <markey@web.de>
8 (C) 2008 Seb Ruiz <ruiz@kde.org>
9 (C) 2008 Sebastian Trueg <trueg@kde.org>
11 This library is free software; you can redistribute it and/or
12 modify it under the terms of the GNU Library General Public
13 License version 2 as published by the Free Software Foundation.
15 This library is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Library General Public License for more details.
20 You should have received a copy of the GNU Library General Public License
21 along with this library; see the file COPYING.LIB. If not, write to
22 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23 Boston, MA 02110-1301, USA.
26 #include "folderselectionmodel.h"
28 #include <QtCore/QDir>
29 #include <QtCore/QFileInfo>
30 #include <QtGui/QColor>
31 #include <QtGui/QBrush>
32 #include <QtGui/QPalette>
39 FolderSelectionModel::FolderSelectionModel( QObject
* parent
)
40 : QFileSystemModel( parent
)
42 setFilter( QDir::AllDirs
| QDir::NoDotAndDotDot
);
46 FolderSelectionModel::~FolderSelectionModel()
51 Qt::ItemFlags
FolderSelectionModel::flags( const QModelIndex
&index
) const
53 Qt::ItemFlags flags
= QFileSystemModel::flags( index
);
54 flags
|= Qt::ItemIsUserCheckable
;
55 if( isForbiddenPath( filePath( index
) ) )
56 flags
^= Qt::ItemIsEnabled
; //disabled!
61 QVariant
FolderSelectionModel::data( const QModelIndex
& index
, int role
) const
63 if( index
.isValid() && index
.column() == 0 ) {
64 if( role
== Qt::CheckStateRole
) {
65 const IncludeState state
= includeState( index
);
69 case StateExcludeInherited
:
72 case StateIncludeInherited
:
76 else if( role
== IncludeStateRole
) {
77 return includeState( index
);
79 else if( role
== Qt::ForegroundRole
) {
80 IncludeState state
= includeState( index
);
81 QBrush brush
= QFileSystemModel::data( index
, role
).value
<QBrush
>();
84 case StateIncludeInherited
:
85 // brush = QPalette().brush( QPalette::Disabled, QPalette::Foreground );
89 case StateExcludeInherited
:
90 brush
= QPalette().brush( QPalette::Disabled
, QPalette::Foreground
);
93 return QVariant::fromValue( brush
);
95 else if ( role
== Qt::ToolTipRole
) {
96 IncludeState state
= includeState( index
);
97 if ( state
== StateInclude
|| state
== StateIncludeInherited
) {
98 return i18nc( "@info:tooltip %1 is the path of the folder in a listview",
99 "<filename>%1</filename><nl/>(will be indexed for desktop search)", filePath( index
) );
102 return i18nc( "@info:tooltip %1 is the path of the folder in a listview",
103 "<filename>%1</filename><nl/> (will <emphasis>not</emphasis> be indexed for desktop search)", filePath( index
) );
106 else if ( role
== Qt::DecorationRole
) {
107 if ( filePath( index
) == QDir::homePath() ) {
108 return KIcon( "user-home" );
113 return QFileSystemModel::data( index
, role
);
117 bool FolderSelectionModel::setData( const QModelIndex
& index
, const QVariant
& value
, int role
)
119 if( index
.isValid() && index
.column() == 0 && role
== Qt::CheckStateRole
) {
120 const QString path
= filePath( index
);
121 const IncludeState state
= includeState( path
);
123 // here we ignore the check value, we treat it as a toggle
124 // This is due to our using the Qt checking system in a virtual way
125 if( state
== StateInclude
||
126 state
== StateIncludeInherited
) {
137 return QFileSystemModel::setData( index
, value
, role
);
142 void removeSubDirs( const QString
& path
, QSet
<QString
>& set
) {
143 QSet
<QString
>::iterator it
= set
.begin();
144 while( it
!= set
.end() ) {
145 if( it
->startsWith( path
) )
146 it
= set
.erase( it
);
152 QModelIndex
findLastLeaf( const QModelIndex
& index
, FolderSelectionModel
* model
) {
153 int rows
= model
->rowCount( index
);
155 return findLastLeaf( model
->index( rows
-1, 0, index
), model
);
163 void FolderSelectionModel::includePath( const QString
& path
)
165 if( !m_included
.contains( path
) ) {
166 // remove all subdirs
167 removeSubDirs( path
, m_included
);
168 removeSubDirs( path
, m_excluded
);
169 m_excluded
.remove( path
);
171 // only really include if the parent is not already included
172 if( includeState( path
) != StateIncludeInherited
) {
173 m_included
.insert( path
);
175 emit
dataChanged( index( path
), findLastLeaf( index( path
), this ) );
180 void FolderSelectionModel::excludePath( const QString
& path
)
182 if( !m_excluded
.contains( path
) ) {
183 // remove all subdirs
184 removeSubDirs( path
, m_included
);
185 removeSubDirs( path
, m_excluded
);
186 m_included
.remove( path
);
188 // only really exclude the path if a parent is included
189 if( includeState( path
) == StateIncludeInherited
) {
190 m_excluded
.insert( path
);
192 emit
dataChanged( index( path
), findLastLeaf( index( path
), this ) );
197 void FolderSelectionModel::setFolders( const QStringList
& includeDirs
, const QStringList
& excludeDirs
)
199 m_included
= QSet
<QString
>::fromList( includeDirs
);
200 m_excluded
= QSet
<QString
>::fromList( excludeDirs
);
205 QStringList
FolderSelectionModel::includeFolders() const
207 return m_included
.toList();
211 QStringList
FolderSelectionModel::excludeFolders() const
213 return m_excluded
.toList();
217 inline bool FolderSelectionModel::isForbiddenPath( const QString
& path
) const
219 // we need the trailing slash otherwise we could forbid "/dev-music" for example
220 QString _path
= path
.endsWith( "/" ) ? path
: path
+ "/";
221 QFileInfo
fi( _path
);
222 return( _path
.startsWith( "/proc/" ) ||
223 _path
.startsWith( "/dev/" ) ||
224 _path
.startsWith( "/sys/" ) ||
226 !fi
.isExecutable() );
230 FolderSelectionModel::IncludeState
FolderSelectionModel::includeState( const QModelIndex
& index
) const
232 return includeState( filePath( index
) );
236 FolderSelectionModel::IncludeState
FolderSelectionModel::includeState( const QString
& path
) const
238 if( m_included
.contains( path
) ) {
241 else if( m_excluded
.contains( path
) ) {
245 QString parent
= path
.section( QDir::separator(), 0, -2, QString::SectionSkipEmpty
|QString::SectionIncludeLeadingSep
);
246 if( parent
.isEmpty() ) {
250 IncludeState state
= includeState( parent
);
251 if( state
== StateNone
)
253 else if( state
== StateInclude
|| state
== StateIncludeInherited
)
254 return StateIncludeInherited
;
256 return StateExcludeInherited
;
261 #include "folderselectionmodel.moc"