1 | /* |
2 | This file is part of libkldap. |
3 | Copyright (c) 2006 Sean Harmer <sh@theharmers.co.uk> |
4 | |
5 | This library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Library General Public |
7 | License as published by the Free Software Foundation; either |
8 | version 2 of the License, or (at your option) any later version. |
9 | |
10 | This library is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Library General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU Library General Public License |
16 | along with this library; see the file COPYING.LIB. If not, write to |
17 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
18 | Boston, MA 02110-1301, USA. |
19 | */ |
20 | |
21 | #include "ldapmodel.h" |
22 | #include "ldapmodel_p.h" |
23 | #include "ldapmodelnode_p.h" |
24 | #include "ldapsearch.h" |
25 | |
26 | #include <kdebug.h> |
27 | #include <klocalizedstring.h> |
28 | #include <kglobal.h> |
29 | |
30 | static const KCatalogLoader loader( QLatin1String("libkldap" ) ); |
31 | |
32 | using namespace KLDAP; |
33 | |
34 | LdapModel::LdapModel( QObject *parent ) |
35 | : QAbstractItemModel( parent ), |
36 | m_d( new LdapModelPrivate( this ) ) |
37 | { |
38 | m_d->createConnections(); |
39 | } |
40 | |
41 | LdapModel::LdapModel( LdapConnection &connection, QObject *parent ) |
42 | : QAbstractItemModel( parent ), |
43 | m_d( new LdapModelPrivate( this, connection ) ) |
44 | { |
45 | m_d->createConnections(); |
46 | |
47 | // Populate items from the root object to that representing the baseDN |
48 | m_d->populateRootToBaseDN(); |
49 | } |
50 | |
51 | LdapModel::~LdapModel() |
52 | { |
53 | delete m_d; |
54 | } |
55 | |
56 | void LdapModel::setConnection( LdapConnection &connection ) |
57 | { |
58 | m_d->setConnection( connection ); |
59 | |
60 | // Refresh the model |
61 | m_d->recreateRootItem(); |
62 | |
63 | // Populate the root object by searching the baseDN |
64 | m_d->populateRootToBaseDN(); |
65 | } |
66 | |
67 | QModelIndex LdapModel::parent( const QModelIndex &child ) const |
68 | { |
69 | if ( !child.isValid() ) { |
70 | return QModelIndex(); |
71 | } |
72 | |
73 | LdapModelNode *childItem = static_cast<LdapModelNode*>( child.internalPointer() ); |
74 | LdapModelDNNode *parentItem = childItem->parent(); |
75 | |
76 | if ( parentItem == m_d->rootNode() ) { |
77 | return QModelIndex(); |
78 | } |
79 | |
80 | return createIndex( parentItem->row(), 0, parentItem ); |
81 | } |
82 | |
83 | QModelIndex LdapModel::index( int row, int col, const QModelIndex &parent ) const |
84 | { |
85 | // Retrieve a pointer to the parent item |
86 | LdapModelDNNode *parentItem; |
87 | if ( !parent.isValid() ) { |
88 | parentItem = m_d->rootNode(); |
89 | } else { |
90 | parentItem = static_cast<LdapModelDNNode*>( parent.internalPointer() ); |
91 | } |
92 | |
93 | LdapModelNode *childItem = parentItem->child( row ); |
94 | if ( childItem ) { |
95 | return createIndex( row, col, childItem ); |
96 | } |
97 | kDebug() << "Could not create valid index for row =" << row << ", col =" << col; |
98 | return QModelIndex(); |
99 | } |
100 | |
101 | QVariant LdapModel::data( const QModelIndex &index, int role ) const |
102 | { |
103 | if ( !index.isValid() ) { |
104 | return QVariant(); |
105 | } |
106 | |
107 | if ( role == Qt::DisplayRole ) { |
108 | // This is what gets displayed by the view delegates. |
109 | LdapModelNode *node = static_cast<LdapModelNode*>( index.internalPointer() ); |
110 | if ( node->nodeType() == LdapModelNode::DN ) { |
111 | LdapModelDNNode* dn = static_cast<LdapModelDNNode*>( node ); |
112 | if ( index.column() == 0 ) { |
113 | return dn->dn().rdnString(); |
114 | } else { |
115 | return QVariant(); |
116 | } |
117 | } else { |
118 | LdapModelAttrNode* attr = static_cast<LdapModelAttrNode*>( node ); |
119 | if ( index.column() == 0 ) { |
120 | return QVariant( attr->attributeName() ); |
121 | } else { |
122 | return QVariant( QLatin1String( attr->attributeData().constData() ) ); |
123 | } |
124 | } |
125 | } else if ( role == NodeTypeRole ) { |
126 | LdapModelNode* node = static_cast<LdapModelNode*>( index.internalPointer() ); |
127 | return QVariant( int( node->nodeType() ) ); |
128 | } |
129 | |
130 | /** \todo Include support for nice decorative icons dependent upon |
131 | the objectClass + other role data. */ |
132 | /** \todo Include support for other roles as needed */ |
133 | |
134 | return QVariant(); |
135 | } |
136 | |
137 | bool LdapModel::setData( const QModelIndex &index, |
138 | const QVariant &value, |
139 | int role ) |
140 | { |
141 | Q_UNUSED( index ); |
142 | Q_UNUSED( value ); |
143 | Q_UNUSED( role ); |
144 | return false; |
145 | } |
146 | |
147 | QVariant LdapModel::( int section, Qt::Orientation orientation, int role ) const |
148 | { |
149 | if ( orientation == Qt::Horizontal && role == Qt::DisplayRole ) { |
150 | if ( section == 0 ) { |
151 | return i18n( "Attribute" ); |
152 | } else { |
153 | return i18n( "Value" ); |
154 | } |
155 | } |
156 | |
157 | return QVariant(); |
158 | } |
159 | |
160 | Qt::ItemFlags LdapModel::flags( const QModelIndex &index ) const |
161 | { |
162 | /** \TODO Read-only for now, make read-write upon request */ |
163 | if ( !index.isValid() ) { |
164 | return Qt::ItemIsEnabled; |
165 | } |
166 | |
167 | return Qt::ItemFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable ); |
168 | } |
169 | |
170 | int LdapModel::columnCount( const QModelIndex &parent ) const |
171 | { |
172 | LdapModelDNNode *parentNode = |
173 | parent.isValid() ? static_cast<LdapModelDNNode*>( parent.internalPointer() ) : m_d->rootNode(); |
174 | return parentNode->columnCount(); |
175 | } |
176 | |
177 | int LdapModel::rowCount( const QModelIndex &parent ) const |
178 | { |
179 | if ( parent.column() > 0 ) { |
180 | return 0; |
181 | } |
182 | |
183 | const LdapModelDNNode *parentNode = |
184 | parent.isValid() ? static_cast<LdapModelDNNode*>( parent.internalPointer() ) : m_d->rootNode(); |
185 | return parentNode->childCount(); |
186 | } |
187 | |
188 | bool LdapModel::hasChildren( const QModelIndex &parent ) const |
189 | { |
190 | // We return true unless the item has been populated and we are able to do a definitive test |
191 | const LdapModelNode *node = parent.isValid() ? |
192 | static_cast<const LdapModelNode*>( parent.internalPointer() ) : |
193 | m_d->rootNode(); |
194 | |
195 | if ( node->nodeType() != LdapModelNode::DN ) { |
196 | return false; |
197 | } |
198 | |
199 | const LdapModelDNNode* parentNode = static_cast<const LdapModelDNNode*>( node ); |
200 | if ( !parent.isValid() || parentNode->isPopulated() ) { |
201 | return parentNode->childCount() > 0; |
202 | } |
203 | return true; |
204 | } |
205 | |
206 | bool LdapModel::canFetchMore( const QModelIndex &parent ) const |
207 | { |
208 | const LdapModelDNNode *parentNode = |
209 | parent.isValid() ? static_cast<LdapModelDNNode*>( parent.internalPointer() ) : m_d->rootNode(); |
210 | return !parentNode->isPopulated(); |
211 | } |
212 | |
213 | void LdapModel::fetchMore( const QModelIndex &parent ) |
214 | { |
215 | LdapModelDNNode *parentNode = |
216 | parent.isValid() ? static_cast<LdapModelDNNode*>( parent.internalPointer() ) : m_d->rootNode(); |
217 | |
218 | // Search for the immediate children of parentItem. |
219 | m_d->searchResults().clear(); |
220 | m_d->setSearchType( LdapModelPrivate::ChildObjects, parentNode ); |
221 | m_d->search( parentNode->dn(), // DN to search from |
222 | LdapUrl::One, // What to search |
223 | QString() ); // Attributes to retrieve |
224 | parentNode->setPopulated( true ); |
225 | } |
226 | |
227 | bool LdapModel::insertRows( int row, int count, |
228 | const QModelIndex &parent ) |
229 | { |
230 | Q_UNUSED( row ); |
231 | Q_UNUSED( count ); |
232 | Q_UNUSED( parent ); |
233 | return false; |
234 | } |
235 | |
236 | bool LdapModel::removeRows( int row, int count, |
237 | const QModelIndex &parent ) |
238 | { |
239 | Q_UNUSED( row ); |
240 | Q_UNUSED( count ); |
241 | Q_UNUSED( parent ); |
242 | return false; |
243 | } |
244 | |
245 | void LdapModel::sort( int column, Qt::SortOrder order ) |
246 | { |
247 | Q_UNUSED( column ); |
248 | Q_UNUSED( order ); |
249 | } |
250 | |
251 | Qt::DropActions LdapModel::supportedDropActions() const |
252 | { |
253 | return Qt::MoveAction; |
254 | } |
255 | |
256 | QMimeData *LdapModel::mimeData( const QModelIndexList &indexes ) const |
257 | { |
258 | Q_UNUSED( indexes ); |
259 | return 0; |
260 | } |
261 | |
262 | bool LdapModel::dropMimeData( const QMimeData *data, Qt::DropAction action, |
263 | int row, int column, const QModelIndex &parent ) |
264 | { |
265 | /** \todo Implement drag and drop for LdapModel */ |
266 | Q_UNUSED( data ); |
267 | Q_UNUSED( action ); |
268 | Q_UNUSED( row ); |
269 | Q_UNUSED( column ); |
270 | Q_UNUSED( parent ); |
271 | return false; |
272 | } |
273 | |
274 | bool LdapModel::hasChildrenOfType( const QModelIndex &parent, LdapDataType type ) const |
275 | { |
276 | // Map from LdapDataType to our internal NodeType |
277 | LdapModelNode::NodeType nodeType; |
278 | switch ( type ) { |
279 | case Attribute: |
280 | nodeType = LdapModelNode::Attr; |
281 | break; |
282 | |
283 | case DistinguishedName: |
284 | default: |
285 | nodeType = LdapModelNode::DN; |
286 | break; |
287 | } |
288 | |
289 | const LdapModelNode *node = parent.isValid() ? |
290 | static_cast<const LdapModelNode*>( parent.internalPointer() ) : |
291 | m_d->rootNode(); |
292 | |
293 | const LdapModelDNNode* parentNode = static_cast<const LdapModelDNNode*>( node ); |
294 | if ( !parent.isValid() || parentNode->isPopulated() ) { |
295 | // Check to see if the parent has any children of the specified type |
296 | const QList<LdapModelNode*>& children = parentNode->children(); |
297 | foreach ( LdapModelNode *child, children ) { |
298 | if ( child->nodeType() == nodeType ) { |
299 | return true; |
300 | } |
301 | } |
302 | |
303 | // Either there are no children or only children of a different type |
304 | return false; |
305 | } |
306 | |
307 | // If the node is not populated or is the root node (invalid), then return |
308 | // true to be on the safe side. |
309 | return true; |
310 | } |
311 | |
312 | void LdapModel::revert() |
313 | { |
314 | |
315 | } |
316 | |
317 | bool LdapModel::submit() |
318 | { |
319 | return false; |
320 | } |
321 | |
322 | #include "moc_ldapmodel.cpp" |
323 | |