Changeset View
Changeset View
Standalone View
Standalone View
plugins/quickopen/expandingtree/expandingwidgetmodel.cpp
Show First 20 Lines • Show All 83 Lines • ▼ Show 20 Line(s) | 65 | { | |||
---|---|---|---|---|---|
84 | return KColorUtils::tint(background, totalColor, tintStrength ).rgb(); | 84 | return KColorUtils::tint(background, totalColor, tintStrength ).rgb(); | ||
85 | }else{ | 85 | }else{ | ||
86 | return 0; | 86 | return 0; | ||
87 | } | 87 | } | ||
88 | } | 88 | } | ||
89 | 89 | | |||
90 | QVariant ExpandingWidgetModel::data( const QModelIndex & index, int role ) const | 90 | QVariant ExpandingWidgetModel::data( const QModelIndex & index, int role ) const | ||
91 | { | 91 | { | ||
92 | switch( role ) { | 92 | switch( role ) { | ||
brauch: rename this to "sourceIndex" or so, having "index" and "idx" in the scope is confusing. | |||||
93 | case Qt::BackgroundRole: | 93 | case Qt::BackgroundRole: | ||
94 | { | 94 | { | ||
95 | if( index.column() == 0 ) { | 95 | if( index.column() == 0 ) { | ||
96 | //Highlight by match-quality | 96 | //Highlight by match-quality | ||
97 | uint color = matchColor(index); | 97 | uint color = matchColor(index); | ||
98 | if( color ) | 98 | if( color ) | ||
99 | return QBrush( color ); | 99 | return QBrush( color ); | ||
100 | } | 100 | } | ||
101 | //Use a special background-color for expanded items | 101 | //Use a special background-color for expanded items | ||
102 | if( isExpanded(index) ) { | 102 | if( isExpanded(index) ) { | ||
103 | if( index.row() & 1 ) { | 103 | if( index.row() & 1 ) { | ||
104 | return doAlternate(treeView()->palette().toolTipBase().color()); | 104 | return doAlternate(treeView()->palette().toolTipBase().color()); | ||
105 | } else { | 105 | } else { | ||
106 | return treeView()->palette().toolTipBase(); | 106 | return treeView()->palette().toolTipBase(); | ||
107 | } | 107 | } | ||
108 | } | 108 | } | ||
109 | } | 109 | } | ||
110 | } | 110 | } | ||
111 | return QVariant(); | 111 | return QVariant(); | ||
112 | } | 112 | } | ||
113 | 113 | | |||
114 | QModelIndex ExpandingWidgetModel::mapFromSource(const QModelIndex& index) const | ||||
115 | { | ||||
116 | const auto proxyModel = qobject_cast<QAbstractProxyModel*>(treeView()->model()); | ||||
117 | Q_ASSERT(proxyModel); | ||||
118 | Q_ASSERT(index.model() == this); | ||||
119 | return proxyModel->mapFromSource(index); | ||||
120 | } | ||||
121 | | ||||
122 | QModelIndex ExpandingWidgetModel::mapToSource(const QModelIndex& index) const | ||||
123 | { | ||||
124 | const auto proxyModel = qobject_cast<QAbstractProxyModel*>(treeView()->model()); | ||||
125 | Q_ASSERT(proxyModel); | ||||
126 | Q_ASSERT(index.model() == proxyModel); | ||||
127 | return proxyModel->mapToSource(index); | ||||
128 | } | ||||
129 | | ||||
114 | void ExpandingWidgetModel::clearMatchQualities() { | 130 | void ExpandingWidgetModel::clearMatchQualities() { | ||
115 | m_contextMatchQualities.clear(); | 131 | m_contextMatchQualities.clear(); | ||
116 | } | 132 | } | ||
117 | 133 | | |||
118 | QModelIndex ExpandingWidgetModel::partiallyExpandedRow() const { | 134 | QModelIndex ExpandingWidgetModel::partiallyExpandedRow() const { | ||
119 | if( m_partiallyExpanded.isEmpty() ) | 135 | if( m_partiallyExpanded.isEmpty() ) | ||
120 | return QModelIndex(); | 136 | return QModelIndex(); | ||
121 | else | 137 | else | ||
Show All 30 Lines | |||||
152 | } | 168 | } | ||
153 | 169 | | |||
154 | int ExpandingWidgetModel::partiallyExpandWidgetHeight() const { | 170 | int ExpandingWidgetModel::partiallyExpandWidgetHeight() const { | ||
155 | return 60; ///@todo use font-metrics text-height*2 for 2 lines | 171 | return 60; ///@todo use font-metrics text-height*2 for 2 lines | ||
156 | } | 172 | } | ||
157 | 173 | | |||
158 | void ExpandingWidgetModel::rowSelected(const QModelIndex& idx_) | 174 | void ExpandingWidgetModel::rowSelected(const QModelIndex& idx_) | ||
159 | { | 175 | { | ||
176 | Q_ASSERT(idx_.model() == this); | ||||
brauch: use a local variable | |||||
177 | | ||||
160 | QModelIndex idx( firstColumn(idx_) ); | 178 | QModelIndex idx( firstColumn(idx_) ); | ||
161 | if( !m_partiallyExpanded.contains( idx ) ) | 179 | if( !m_partiallyExpanded.contains( idx ) ) | ||
162 | { | 180 | { | ||
163 | QModelIndex oldIndex = partiallyExpandedRow(); | 181 | QModelIndex oldIndex = partiallyExpandedRow(); | ||
164 | //Unexpand the previous partially expanded row | 182 | //Unexpand the previous partially expanded row | ||
165 | if( !m_partiallyExpanded.isEmpty() ) | 183 | if( !m_partiallyExpanded.isEmpty() ) | ||
166 | { ///@todo allow multiple partially expanded rows | 184 | { ///@todo allow multiple partially expanded rows | ||
167 | while( !m_partiallyExpanded.isEmpty() ) | 185 | while( !m_partiallyExpanded.isEmpty() ) | ||
Show All 18 Lines | 203 | else | |||
186 | m_partiallyExpanded.insert(idx, ExpandDownwards); | 204 | m_partiallyExpanded.insert(idx, ExpandDownwards); | ||
187 | 205 | | |||
188 | //Say that one row above until one row below has changed, so no items will need to be moved(the space that is taken from one item is given to the other) | 206 | //Say that one row above until one row below has changed, so no items will need to be moved(the space that is taken from one item is given to the other) | ||
189 | if( oldIndex.isValid() && oldIndex < idx ) { | 207 | if( oldIndex.isValid() && oldIndex < idx ) { | ||
190 | emit dataChanged(oldIndex, idx); | 208 | emit dataChanged(oldIndex, idx); | ||
191 | 209 | | |||
192 | if( treeView()->verticalScrollMode() == QAbstractItemView::ScrollPerItem ) | 210 | if( treeView()->verticalScrollMode() == QAbstractItemView::ScrollPerItem ) | ||
193 | { | 211 | { | ||
212 | const QModelIndex viewIndex = mapFromSource(idx); | ||||
194 | //Qt fails to correctly scroll in ScrollPerItem mode, so the selected index is completely visible, | 213 | //Qt fails to correctly scroll in ScrollPerItem mode, so the selected index is completely visible, | ||
195 | //so we do the scrolling by hand. | 214 | //so we do the scrolling by hand. | ||
196 | QRect selectedRect = treeView()->visualRect(idx); | 215 | QRect selectedRect = treeView()->visualRect(viewIndex); | ||
197 | QRect frameRect = treeView()->frameRect(); | 216 | QRect frameRect = treeView()->frameRect(); | ||
198 | 217 | | |||
199 | if( selectedRect.bottom() > frameRect.bottom() ) { | 218 | if( selectedRect.bottom() > frameRect.bottom() ) { | ||
200 | int diff = selectedRect.bottom() - frameRect.bottom(); | 219 | int diff = selectedRect.bottom() - frameRect.bottom(); | ||
201 | //We need to scroll down | 220 | //We need to scroll down | ||
202 | QModelIndex newTopIndex = idx; | 221 | QModelIndex newTopIndex = viewIndex; | ||
203 | 222 | | |||
204 | QModelIndex nextTopIndex = idx; | 223 | QModelIndex nextTopIndex = viewIndex; | ||
205 | QRect nextRect = treeView()->visualRect(nextTopIndex); | 224 | QRect nextRect = treeView()->visualRect(nextTopIndex); | ||
206 | while( nextTopIndex.isValid() && nextRect.isValid() && nextRect.top() >= diff ) { | 225 | while( nextTopIndex.isValid() && nextRect.isValid() && nextRect.top() >= diff ) { | ||
207 | newTopIndex = nextTopIndex; | 226 | newTopIndex = nextTopIndex; | ||
208 | nextTopIndex = treeView()->indexAbove(nextTopIndex); | 227 | nextTopIndex = treeView()->indexAbove(nextTopIndex); | ||
209 | if( nextTopIndex.isValid() ) | 228 | if( nextTopIndex.isValid() ) | ||
210 | nextRect = treeView()->visualRect(nextTopIndex); | 229 | nextRect = treeView()->visualRect(nextTopIndex); | ||
211 | } | 230 | } | ||
212 | treeView()->scrollTo( newTopIndex, QAbstractItemView::PositionAtTop ); | 231 | treeView()->scrollTo( newTopIndex, QAbstractItemView::PositionAtTop ); | ||
Show All 24 Lines | 254 | //We are not partially expanding a new row, but we previously had a partially expanded row. So signalize that it has been unexpanded. | |||
237 | emit dataChanged(oldIndex, oldIndex); | 256 | emit dataChanged(oldIndex, oldIndex); | ||
238 | } | 257 | } | ||
239 | } | 258 | } | ||
240 | }else{ | 259 | }else{ | ||
241 | qCDebug( PLUGIN_QUICKOPEN ) << "ExpandingWidgetModel::rowSelected: Row is already partially expanded"; | 260 | qCDebug( PLUGIN_QUICKOPEN ) << "ExpandingWidgetModel::rowSelected: Row is already partially expanded"; | ||
242 | } | 261 | } | ||
243 | } | 262 | } | ||
244 | 263 | | |||
245 | QString ExpandingWidgetModel::partialExpandText(const QModelIndex& idx) const { | 264 | QString ExpandingWidgetModel::partialExpandText(const QModelIndex& idx) const | ||
265 | { | ||||
266 | Q_ASSERT(idx.model() == this); | ||||
267 | | ||||
246 | if( !idx.isValid() ) | 268 | if( !idx.isValid() ) | ||
247 | return QString(); | 269 | return QString(); | ||
248 | 270 | | |||
249 | return data(firstColumn(idx), CodeCompletionModel::ItemSelected).toString(); | 271 | return data(firstColumn(idx), CodeCompletionModel::ItemSelected).toString(); | ||
250 | } | 272 | } | ||
251 | 273 | | |||
252 | QRect ExpandingWidgetModel::partialExpandRect(const QModelIndex& idx_) const | 274 | QRect ExpandingWidgetModel::partialExpandRect(const QModelIndex& idx_) const | ||
253 | { | 275 | { | ||
276 | Q_ASSERT(idx_.model() == this); | ||||
277 | | ||||
254 | QModelIndex idx(firstColumn(idx_)); | 278 | QModelIndex idx(firstColumn(idx_)); | ||
255 | 279 | | |||
256 | if( !idx.isValid() ) | 280 | if( !idx.isValid() ) | ||
257 | return QRect(); | 281 | return QRect(); | ||
258 | 282 | | |||
259 | ExpansionType expansion = ExpandDownwards; | 283 | ExpansionType expansion = ExpandDownwards; | ||
260 | 284 | | |||
261 | if( m_partiallyExpanded.find(idx) != m_partiallyExpanded.constEnd() ) | 285 | if( m_partiallyExpanded.find(idx) != m_partiallyExpanded.constEnd() ) | ||
262 | expansion = m_partiallyExpanded[idx]; | 286 | expansion = m_partiallyExpanded[idx]; | ||
263 | 287 | | |||
264 | //Get the whole rectangle of the row: | 288 | //Get the whole rectangle of the row: | ||
265 | QModelIndex rightMostIndex = idx; | 289 | const QModelIndex viewIndex = mapFromSource(idx); | ||
266 | QModelIndex tempIndex = idx; | 290 | QModelIndex rightMostIndex = viewIndex; | ||
291 | QModelIndex tempIndex = viewIndex; | ||||
267 | while( (tempIndex = rightMostIndex.sibling(rightMostIndex.row(), rightMostIndex.column()+1)).isValid() ) | 292 | while( (tempIndex = rightMostIndex.sibling(rightMostIndex.row(), rightMostIndex.column()+1)).isValid() ) | ||
268 | rightMostIndex = tempIndex; | 293 | rightMostIndex = tempIndex; | ||
269 | 294 | | |||
270 | QRect rect = treeView()->visualRect(idx); | 295 | QRect rect = treeView()->visualRect(viewIndex); | ||
271 | QRect rightMostRect = treeView()->visualRect(rightMostIndex); | 296 | QRect rightMostRect = treeView()->visualRect(rightMostIndex); | ||
272 | 297 | | |||
273 | rect.setLeft( rect.left() + 20 ); | 298 | rect.setLeft( rect.left() + 20 ); | ||
274 | rect.setRight( rightMostRect.right() - 5 ); | 299 | rect.setRight( rightMostRect.right() - 5 ); | ||
275 | 300 | | |||
276 | //These offsets must match exactly those used in ExpandingDelegate::sizeHint() | 301 | //These offsets must match exactly those used in ExpandingDelegate::sizeHint() | ||
277 | int top = rect.top() + 5; | 302 | int top = rect.top() + 5; | ||
278 | int bottom = rightMostRect.bottom() - 5 ; | 303 | int bottom = rightMostRect.bottom() - 5 ; | ||
279 | 304 | | |||
280 | if( expansion == ExpandDownwards ) | 305 | if( expansion == ExpandDownwards ) | ||
281 | top += basicRowHeight(idx); | 306 | top += basicRowHeight(viewIndex); | ||
282 | else | 307 | else | ||
283 | bottom -= basicRowHeight(idx); | 308 | bottom -= basicRowHeight(viewIndex); | ||
284 | 309 | | |||
285 | rect.setTop( top ); | 310 | rect.setTop( top ); | ||
286 | rect.setBottom( bottom ); | 311 | rect.setBottom( bottom ); | ||
287 | 312 | | |||
288 | return rect; | 313 | return rect; | ||
289 | } | 314 | } | ||
290 | 315 | | |||
291 | bool ExpandingWidgetModel::isExpandable(const QModelIndex& idx_) const | 316 | bool ExpandingWidgetModel::isExpandable(const QModelIndex& idx_) const | ||
292 | { | 317 | { | ||
318 | Q_ASSERT(idx_.model() == this); | ||||
319 | | ||||
293 | QModelIndex idx(firstColumn(idx_)); | 320 | QModelIndex idx(firstColumn(idx_)); | ||
294 | 321 | | |||
295 | if( !m_expandState.contains(idx) ) | 322 | if( !m_expandState.contains(idx) ) | ||
296 | { | 323 | { | ||
297 | m_expandState.insert(idx, NotExpandable); | 324 | m_expandState.insert(idx, NotExpandable); | ||
298 | QVariant v = data(idx, CodeCompletionModel::IsExpandable); | 325 | QVariant v = data(idx, CodeCompletionModel::IsExpandable); | ||
299 | if( v.canConvert<bool>() && v.toBool() ) | 326 | if( v.canConvert<bool>() && v.toBool() ) | ||
300 | m_expandState[idx] = Expandable; | 327 | m_expandState[idx] = Expandable; | ||
301 | } | 328 | } | ||
302 | 329 | | |||
303 | return m_expandState[idx] != NotExpandable; | 330 | return m_expandState[idx] != NotExpandable; | ||
304 | } | 331 | } | ||
305 | 332 | | |||
306 | bool ExpandingWidgetModel::isExpanded(const QModelIndex& idx_) const | 333 | bool ExpandingWidgetModel::isExpanded(const QModelIndex& idx_) const | ||
307 | { | 334 | { | ||
335 | Q_ASSERT(idx_.model() == this); | ||||
336 | | ||||
308 | QModelIndex idx(firstColumn(idx_)); | 337 | QModelIndex idx(firstColumn(idx_)); | ||
309 | return m_expandState.contains(idx) && m_expandState[idx] == Expanded; | 338 | return m_expandState.contains(idx) && m_expandState[idx] == Expanded; | ||
310 | } | 339 | } | ||
311 | 340 | | |||
312 | void ExpandingWidgetModel::setExpanded(QModelIndex idx_, bool expanded) | 341 | void ExpandingWidgetModel::setExpanded(QModelIndex idx_, bool expanded) | ||
313 | { | 342 | { | ||
343 | Q_ASSERT(idx_.model() == this); | ||||
344 | | ||||
314 | QModelIndex idx(firstColumn(idx_)); | 345 | QModelIndex idx(firstColumn(idx_)); | ||
315 | 346 | | |||
316 | //qCDebug( PLUGIN_QUICKOPEN ) << "Setting expand-state of row " << idx.row() << " to " << expanded; | 347 | qCDebug( PLUGIN_QUICKOPEN ) << "Setting expand-state of row " << idx.row() << " to " << expanded; | ||
317 | if( !idx.isValid() ) | 348 | if( !idx.isValid() ) | ||
318 | return; | 349 | return; | ||
319 | 350 | | |||
320 | if( isExpandable(idx) ) { | 351 | if( isExpandable(idx) ) { | ||
321 | if( !expanded && m_expandingWidgets.contains(idx) && m_expandingWidgets[idx] ) { | 352 | if( !expanded && m_expandingWidgets.contains(idx) && m_expandingWidgets[idx] ) { | ||
322 | m_expandingWidgets[idx]->hide(); | 353 | m_expandingWidgets[idx]->hide(); | ||
323 | } | 354 | } | ||
324 | 355 | | |||
Show All 15 Lines | 367 | } else if( v.canConvert<QString>() ) { | |||
340 | edit->resize(200, 50); //Make the widget small so it embeds nicely. | 371 | edit->resize(200, 50); //Make the widget small so it embeds nicely. | ||
341 | m_expandingWidgets[idx] = edit; | 372 | m_expandingWidgets[idx] = edit; | ||
342 | } else { | 373 | } else { | ||
343 | m_expandingWidgets[idx] = nullptr; | 374 | m_expandingWidgets[idx] = nullptr; | ||
344 | } | 375 | } | ||
345 | } | 376 | } | ||
346 | 377 | | |||
347 | //Eventually partially expand the row | 378 | //Eventually partially expand the row | ||
348 | if( !expanded && firstColumn(treeView()->currentIndex()) == idx && (isPartiallyExpanded(idx) == ExpandingWidgetModel::ExpansionType::NotExpanded) ) | 379 | if( !expanded && firstColumn(mapToSource(treeView()->currentIndex())) == idx && (isPartiallyExpanded(idx) == ExpandingWidgetModel::ExpansionType::NotExpanded) ) | ||
349 | rowSelected(idx); //Partially expand the row. | 380 | rowSelected(idx); //Partially expand the row. | ||
350 | 381 | | |||
351 | emit dataChanged(idx, idx); | 382 | emit dataChanged(idx, idx); | ||
352 | 383 | | |||
353 | if(treeView()) | 384 | if(treeView()) | ||
354 | treeView()->scrollTo(idx); | 385 | treeView()->scrollTo(mapFromSource(idx)); | ||
355 | } | 386 | } | ||
356 | } | 387 | } | ||
357 | 388 | | |||
358 | int ExpandingWidgetModel::basicRowHeight( const QModelIndex& idx_ ) const | 389 | int ExpandingWidgetModel::basicRowHeight( const QModelIndex& idx_ ) const | ||
359 | { | 390 | { | ||
391 | Q_ASSERT(idx_.model() == treeView()->model()); | ||||
392 | | ||||
360 | QModelIndex idx(firstColumn(idx_)); | 393 | QModelIndex idx(firstColumn(idx_)); | ||
361 | 394 | | |||
362 | ExpandingDelegate* delegate = dynamic_cast<ExpandingDelegate*>( treeView()->itemDelegate(idx) ); | 395 | ExpandingDelegate* delegate = dynamic_cast<ExpandingDelegate*>( treeView()->itemDelegate(idx) ); | ||
363 | if( !delegate || !idx.isValid() ) { | 396 | if( !delegate || !idx.isValid() ) { | ||
364 | qCDebug( PLUGIN_QUICKOPEN ) << "ExpandingWidgetModel::basicRowHeight: Could not get delegate"; | 397 | qCDebug( PLUGIN_QUICKOPEN ) << "ExpandingWidgetModel::basicRowHeight: Could not get delegate"; | ||
365 | return 15; | 398 | return 15; | ||
366 | } | 399 | } | ||
367 | return delegate->basicSizeHint( idx ).height(); | 400 | return delegate->basicSizeHint( idx ).height(); | ||
368 | } | 401 | } | ||
369 | 402 | | |||
370 | 403 | | |||
371 | void ExpandingWidgetModel::placeExpandingWidget(const QModelIndex& idx_) | 404 | void ExpandingWidgetModel::placeExpandingWidget(const QModelIndex& idx_) | ||
372 | { | 405 | { | ||
406 | Q_ASSERT(idx_.model() == this); | ||||
407 | | ||||
373 | QModelIndex idx(firstColumn(idx_)); | 408 | QModelIndex idx(firstColumn(idx_)); | ||
374 | 409 | | |||
375 | QWidget* w = nullptr; | 410 | QWidget* w = nullptr; | ||
376 | if( m_expandingWidgets.contains(idx) ) | 411 | if( m_expandingWidgets.contains(idx) ) | ||
377 | w = m_expandingWidgets[idx]; | 412 | w = m_expandingWidgets[idx]; | ||
378 | 413 | | |||
379 | if( w && isExpanded(idx) ) { | 414 | if( w && isExpanded(idx) ) { | ||
380 | if( !idx.isValid() ) | 415 | if( !idx.isValid() ) | ||
381 | return; | 416 | return; | ||
382 | 417 | | |||
383 | QRect rect = treeView()->visualRect(idx); | 418 | const QModelIndex viewIndex = mapFromSource(idx_); | ||
419 | QRect rect = treeView()->visualRect(viewIndex); | ||||
384 | 420 | | |||
385 | if( !rect.isValid() || rect.bottom() < 0 || rect.top() >= treeView()->height() ) { | 421 | if( !rect.isValid() || rect.bottom() < 0 || rect.top() >= treeView()->height() ) { | ||
386 | //The item is currently not visible | 422 | //The item is currently not visible | ||
387 | w->hide(); | 423 | w->hide(); | ||
388 | return; | 424 | return; | ||
389 | } | 425 | } | ||
390 | 426 | | |||
391 | QModelIndex rightMostIndex = idx; | 427 | QModelIndex rightMostIndex = viewIndex; | ||
392 | QModelIndex tempIndex = idx; | 428 | QModelIndex tempIndex = viewIndex; | ||
393 | while( (tempIndex = rightMostIndex.sibling(rightMostIndex.row(), rightMostIndex.column()+1)).isValid() ) | 429 | while( (tempIndex = rightMostIndex.sibling(rightMostIndex.row(), rightMostIndex.column()+1)).isValid() ) | ||
394 | rightMostIndex = tempIndex; | 430 | rightMostIndex = tempIndex; | ||
395 | 431 | | |||
396 | QRect rightMostRect = treeView()->visualRect(rightMostIndex); | 432 | QRect rightMostRect = treeView()->visualRect(rightMostIndex); | ||
397 | 433 | | |||
398 | //Find out the basic height of the row | 434 | //Find out the basic height of the row | ||
399 | rect.setLeft( rect.left() + 20 ); | 435 | rect.setLeft( rect.left() + 20 ); | ||
400 | rect.setRight( rightMostRect.right() - 5 ); | 436 | rect.setRight( rightMostRect.right() - 5 ); | ||
401 | 437 | | |||
402 | //These offsets must match exactly those used in KateCompletionDeleage::sizeHint() | 438 | //These offsets must match exactly those used in KateCompletionDeleage::sizeHint() | ||
403 | rect.setTop( rect.top() + basicRowHeight(idx) + 5 ); | 439 | rect.setTop( rect.top() + basicRowHeight(viewIndex) + 5 ); | ||
404 | rect.setHeight( w->height() ); | 440 | rect.setHeight( w->height() ); | ||
405 | 441 | | |||
406 | if( w->parent() != treeView()->viewport() || w->geometry() != rect || !w->isVisible() ) { | 442 | if( w->parent() != treeView()->viewport() || w->geometry() != rect || !w->isVisible() ) { | ||
407 | w->setParent( treeView()->viewport() ); | 443 | w->setParent( treeView()->viewport() ); | ||
408 | 444 | | |||
409 | w->setGeometry(rect); | 445 | w->setGeometry(rect); | ||
410 | w->show(); | 446 | w->show(); | ||
411 | } | 447 | } | ||
▲ Show 20 Lines • Show All 118 Lines • Show Last 20 Lines |
rename this to "sourceIndex" or so, having "index" and "idx" in the scope is confusing.