KDEUI
kbreadcrumbselectionmodel.cpp
Go to the documentation of this file.
00001 /* 00002 Copyright (C) 2010 Klarälvdalens Datakonsult AB, 00003 a KDAB Group company, info@kdab.net, 00004 author Stephen Kelly <stephen@kdab.com> 00005 00006 This library is free software; you can redistribute it and/or modify it 00007 under the terms of the GNU Library General Public License as published by 00008 the Free Software Foundation; either version 2 of the License, or (at your 00009 option) any later version. 00010 00011 This library is distributed in the hope that it will be useful, but WITHOUT 00012 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00013 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 00014 License for more details. 00015 00016 You should have received a copy of the GNU Library General Public License 00017 along with this library; see the file COPYING.LIB. If not, write to the 00018 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 00019 02110-1301, USA. 00020 */ 00021 00022 00023 #include "kbreadcrumbselectionmodel.h" 00024 00025 #include "kdebug.h" 00026 00027 class KBreadcrumbSelectionModelPrivate 00028 { 00029 Q_DECLARE_PUBLIC(KBreadcrumbSelectionModel) 00030 KBreadcrumbSelectionModel * const q_ptr; 00031 public: 00032 KBreadcrumbSelectionModelPrivate(KBreadcrumbSelectionModel *breadcrumbSelector, QItemSelectionModel *selectionModel, KBreadcrumbSelectionModel::BreadcrumbTarget direction) 00033 : q_ptr(breadcrumbSelector), 00034 m_includeActualSelection(true), 00035 m_selectionDepth(-1), 00036 m_showHiddenAscendantData(false), 00037 m_selectionModel(selectionModel), 00038 m_direction(direction), 00039 m_ignoreCurrentChanged(false) 00040 { 00041 00042 } 00043 00047 QItemSelection getBreadcrumbSelection(const QModelIndex &index); 00048 00052 QItemSelection getBreadcrumbSelection(const QItemSelection &selection); 00053 00054 void sourceSelectionChanged(const QItemSelection &selected, const QItemSelection &deselected); 00055 00056 void init(); 00057 void syncBreadcrumbs(); 00058 00059 bool m_includeActualSelection; 00060 int m_selectionDepth; 00061 bool m_showHiddenAscendantData; 00062 QItemSelectionModel *m_selectionModel; 00063 KBreadcrumbSelectionModel::BreadcrumbTarget m_direction; 00064 bool m_ignoreCurrentChanged; 00065 }; 00066 00067 KBreadcrumbSelectionModel::KBreadcrumbSelectionModel(QItemSelectionModel *selectionModel, QObject* parent) 00068 : QItemSelectionModel(const_cast<QAbstractItemModel *>(selectionModel->model()), parent), 00069 d_ptr(new KBreadcrumbSelectionModelPrivate(this, selectionModel, MakeBreadcrumbSelectionInSelf)) 00070 { 00071 d_ptr->init(); 00072 } 00073 00074 KBreadcrumbSelectionModel::KBreadcrumbSelectionModel(QItemSelectionModel *selectionModel, BreadcrumbTarget direction, QObject* parent) 00075 : QItemSelectionModel(const_cast<QAbstractItemModel *>(selectionModel->model()), parent), 00076 d_ptr(new KBreadcrumbSelectionModelPrivate(this, selectionModel, direction)) 00077 { 00078 if ( direction != MakeBreadcrumbSelectionInSelf) 00079 connect(selectionModel, SIGNAL(selectionChanged(const QItemSelection&,const QItemSelection&)), 00080 this, SLOT(sourceSelectionChanged(const QItemSelection&,const QItemSelection&))); 00081 00082 d_ptr->init(); 00083 } 00084 00085 KBreadcrumbSelectionModel::~KBreadcrumbSelectionModel() 00086 { 00087 delete d_ptr; 00088 } 00089 00090 bool KBreadcrumbSelectionModel::isActualSelectionIncluded() const 00091 { 00092 Q_D(const KBreadcrumbSelectionModel); 00093 return d->m_includeActualSelection; 00094 } 00095 00096 void KBreadcrumbSelectionModel::setActualSelectionIncluded(bool includeActualSelection) 00097 { 00098 Q_D(KBreadcrumbSelectionModel); 00099 d->m_includeActualSelection = includeActualSelection; 00100 } 00101 00102 int KBreadcrumbSelectionModel::breadcrumbLength() const 00103 { 00104 Q_D(const KBreadcrumbSelectionModel); 00105 return d->m_selectionDepth; 00106 } 00107 00108 void KBreadcrumbSelectionModel::setBreadcrumbLength(int breadcrumbLength) 00109 { 00110 Q_D(KBreadcrumbSelectionModel); 00111 d->m_selectionDepth = breadcrumbLength; 00112 } 00113 00114 QItemSelection KBreadcrumbSelectionModelPrivate::getBreadcrumbSelection(const QModelIndex& index) 00115 { 00116 QItemSelection breadcrumbSelection; 00117 00118 if (m_includeActualSelection) 00119 breadcrumbSelection.append(QItemSelectionRange(index)); 00120 00121 QModelIndex parent = index.parent(); 00122 int sumBreadcrumbs = 0; 00123 bool includeAll = m_selectionDepth < 0; 00124 while (parent.isValid() && (includeAll || sumBreadcrumbs < m_selectionDepth)) { 00125 breadcrumbSelection.append(QItemSelectionRange(parent)); 00126 parent = parent.parent(); 00127 } 00128 return breadcrumbSelection; 00129 } 00130 00131 QItemSelection KBreadcrumbSelectionModelPrivate::getBreadcrumbSelection(const QItemSelection& selection) 00132 { 00133 QItemSelection breadcrumbSelection; 00134 00135 if (m_includeActualSelection) 00136 breadcrumbSelection = selection; 00137 00138 QItemSelection::const_iterator it = selection.constBegin(); 00139 const QItemSelection::const_iterator end = selection.constEnd(); 00140 00141 for ( ; it != end; ++it) 00142 { 00143 QModelIndex parent = it->parent(); 00144 00145 if (breadcrumbSelection.contains(parent)) 00146 continue; 00147 00148 int sumBreadcrumbs = 0; 00149 bool includeAll = m_selectionDepth < 0; 00150 00151 while (parent.isValid() && (includeAll || sumBreadcrumbs < m_selectionDepth)) 00152 { 00153 breadcrumbSelection.append(QItemSelectionRange(parent)); 00154 parent = parent.parent(); 00155 00156 if (breadcrumbSelection.contains(parent)) 00157 break; 00158 00159 ++sumBreadcrumbs; 00160 } 00161 } 00162 return breadcrumbSelection; 00163 } 00164 00165 void KBreadcrumbSelectionModelPrivate::sourceSelectionChanged(const QItemSelection& selected, const QItemSelection& deselected) 00166 { 00167 Q_Q(KBreadcrumbSelectionModel); 00168 QItemSelection deselectedCrumbs = getBreadcrumbSelection(deselected); 00169 QItemSelection selectedCrumbs = getBreadcrumbSelection(selected); 00170 00171 QItemSelection removed = deselectedCrumbs; 00172 foreach(const QItemSelectionRange &range, selectedCrumbs) 00173 { 00174 removed.removeAll(range); 00175 } 00176 00177 QItemSelection added = selectedCrumbs; 00178 foreach(const QItemSelectionRange &range, deselectedCrumbs) 00179 { 00180 added.removeAll(range); 00181 } 00182 00183 if (!removed.isEmpty()) 00184 { 00185 q->QItemSelectionModel::select(removed, QItemSelectionModel::Deselect); 00186 } 00187 if (!added.isEmpty()) 00188 { 00189 q->QItemSelectionModel::select(added, QItemSelectionModel::Select); 00190 } 00191 } 00192 00193 void KBreadcrumbSelectionModel::select(const QModelIndex &index, QItemSelectionModel::SelectionFlags command) 00194 { 00195 Q_D(KBreadcrumbSelectionModel); 00196 // When an item is removed, the current index is set to the top index in the model. 00197 // That causes a selectionChanged signal with a selection which we do not want. 00198 if ( d->m_ignoreCurrentChanged ) 00199 { 00200 d->m_ignoreCurrentChanged = false; 00201 return; 00202 } 00203 if ( d->m_direction == MakeBreadcrumbSelectionInOther ) 00204 { 00205 d->m_selectionModel->select(d->getBreadcrumbSelection(index), command); 00206 QItemSelectionModel::select(index, command); 00207 } else { 00208 d->m_selectionModel->select(index, command); 00209 QItemSelectionModel::select(d->getBreadcrumbSelection(index), command); 00210 } 00211 } 00212 00213 void KBreadcrumbSelectionModel::select(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command) 00214 { 00215 Q_D(KBreadcrumbSelectionModel); 00216 QItemSelection bcc = d->getBreadcrumbSelection(selection); 00217 if ( d->m_direction == MakeBreadcrumbSelectionInOther ) 00218 { 00219 d->m_selectionModel->select(selection, command); 00220 QItemSelectionModel::select(bcc, command); 00221 } else { 00222 d->m_selectionModel->select(bcc, command); 00223 QItemSelectionModel::select(selection, command); 00224 } 00225 } 00226 00227 void KBreadcrumbSelectionModelPrivate::init() 00228 { 00229 Q_Q(KBreadcrumbSelectionModel); 00230 q->connect(m_selectionModel->model(), SIGNAL(layoutChanged()), SLOT(syncBreadcrumbs())); 00231 q->connect(m_selectionModel->model(), SIGNAL(modelReset()), SLOT(syncBreadcrumbs())); 00232 q->connect(m_selectionModel->model(), SIGNAL(rowsMoved(QModelIndex, int, int, QModelIndex, int)), SLOT(syncBreadcrumbs())); 00233 // Don't need to handle insert & remove because they can't change the breadcrumbs on their own. 00234 } 00235 00236 void KBreadcrumbSelectionModelPrivate::syncBreadcrumbs() 00237 { 00238 Q_Q(KBreadcrumbSelectionModel); 00239 q->select(m_selectionModel->selection(), QItemSelectionModel::ClearAndSelect); 00240 } 00241 00242 00243 #include "kbreadcrumbselectionmodel.moc"
KDE 4.6 API Reference