@@ -218,8 +218,8 @@ struct QHexRegionObject {
218218
219219 if (sel.end < oldend) {
220220 // break into two ranges
221- P s;
222- s.begin = sel.end ;
221+ P s = * static_cast < const P *>( this ) ;
222+ s.begin = next ( sel.end ) ;
223223 s.end = oldend;
224224
225225 if (locker) {
@@ -240,25 +240,21 @@ struct QHexRegionObject {
240240 QMutex *locker = nullptr ) {
241241 Q_ASSERT (isValid ());
242242 Q_ASSERT (isNormalized ());
243- if (canMerge (sel)) {
244- if (locker) {
245- locker->lock ();
246- }
243+ if (!canMerge (sel)) {
244+ return false ;
245+ }
247246
248- if (this ->begin < sel.end ) {
249- this ->begin = qMin (this ->begin , next (sel.begin ));
250- this ->end = qMax (next (this ->end ), sel.end );
251- } else {
252- this ->begin = qMin (next (this ->begin ), sel.begin );
253- this ->end = qMax (this ->end , next (sel.end ));
254- }
247+ if (locker) {
248+ locker->lock ();
249+ }
255250
256- if (locker) {
257- locker->unlock ();
258- }
259- return true ;
251+ this ->begin = qMin (this ->begin , sel.begin );
252+ this ->end = qMax (this ->end , sel.end );
253+
254+ if (locker) {
255+ locker->unlock ();
260256 }
261- return false ;
257+ return true ;
262258 };
263259
264260 bool isValid () const { return _valid; }
@@ -274,9 +270,9 @@ class QHexRegionObjectList : public QVector<P> {
274270
275271public:
276272 struct MergeAddItem {
277- // indices of items changed in old list
278- QVector<qsizetype> changed ;
279- // indices of new items inserted in new list
273+ // original indices (in the list BEFORE this call) that were removed.
274+ QVector<qsizetype> removed ;
275+ // indices in the final list (AFTER this call) of newly inserted.
280276 QVector<qsizetype> inserted;
281277 };
282278
@@ -299,59 +295,96 @@ class QHexRegionObjectList : public QVector<P> {
299295
300296 // clean up invalid selections
301297 auto cleanup = [](const P &s) { return !s.isValid (); };
302- #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
303298 this ->removeIf (cleanup);
304- #else
305- this ->erase (std::remove_if (this ->begin (), this ->end (), cleanup));
306- #endif
307-
308299 QtConcurrent::blockingMap (
309300 buffer, [&locker, this ](P &s) { mergeAdd (s, &locker); });
310301 }
311302
312- // @return items changed index in old QHexRegionObjectList
313303 MergeAddItem mergeAdd (const P &sel, QMutex *locker = nullptr ) {
314- bool res = false ;
315304 Q_ASSERT (sel.isNormalized ());
316-
317305 MergeAddItem ret;
318- QList<P> regionSlices;
319306
320- auto total = this ->size ();
307+ P sel0 = sel;
308+ qsizetype removedSoFar = 0 ;
309+ QList<P> regionSlices;
310+ QList<P> insertsFromRemoved;
321311 qsizetype i = 0 ;
322- for (i = 0 ; i < total; ++i) {
323- auto p = this ->at (i);
324- auto r = p.mergeRegion (sel, locker);
312+ while (i < this ->size ()) {
313+ auto &p = this ->operator [](i);
314+
315+ if (sel0.contains (p)) {
316+ qsizetype origIndex = static_cast <qsizetype>(i) +
317+ static_cast <qsizetype>(removedSoFar);
318+ ret.removed .append (origIndex);
319+
320+ this ->takeAt (i);
321+ ++removedSoFar;
322+ continue ;
323+ }
324+
325+ auto r = p.mergeRegion (sel0, locker);
325326 if (std::holds_alternative<bool >(r)) {
326- res = std::get<bool >(r);
327- ret.changed .append (i);
328- if (res) {
329- break ;
327+ bool flag = std::get<bool >(r);
328+ qsizetype origIndex = static_cast <qsizetype>(i) +
329+ static_cast <qsizetype>(removedSoFar);
330+
331+ ret.removed .append (origIndex);
332+
333+ P taken = this ->takeAt (i);
334+ ++removedSoFar;
335+
336+ if (flag) {
337+ sel0 = taken;
338+ continue ;
339+ } else {
340+ insertsFromRemoved.append (taken);
341+ continue ;
330342 }
331343 } else {
332344 auto v = std::get<P>(r);
333- ret.changed .append (i);
334345 regionSlices.append (v);
335346 break ;
336347 }
337348 }
338349
339- for (auto &v : regionSlices) {
340- auto idx = std::distance (
341- this ->constBegin (),
342- std::upper_bound (this ->constBegin (), this ->constEnd (), v));
343- ret.inserted .append (idx);
344- this ->insert (idx, v);
350+ QVector<P> toInsert;
351+ for (auto &v : regionSlices)
352+ toInsert.append (v);
353+ for (auto &v : insertsFromRemoved)
354+ toInsert.append (v);
355+
356+ auto equal_by_less = [](const P &a, const P &b) -> bool {
357+ return !(a < b) && !(b < a);
358+ };
359+ bool sel_present = false ;
360+ for (const auto &e : toInsert) {
361+ if (equal_by_less (e, sel0)) {
362+ sel_present = true ;
363+ break ;
364+ }
365+ }
366+ if (!sel_present)
367+ toInsert.append (sel0);
368+
369+ QVector<P> finalInsert;
370+ for (const auto &v : toInsert) {
371+ bool found = false ;
372+ for (const auto &u : finalInsert) {
373+ if (equal_by_less (u, v)) {
374+ found = true ;
375+ break ;
376+ }
377+ }
378+ if (!found)
379+ finalInsert.append (v);
345380 }
346381
347- if (res) {
348- auto m = this ->takeAt (i);
349- mergeAdd (m, locker);
350- } else {
351- this ->insert (std::distance (this ->constBegin (),
352- std::upper_bound (this ->constBegin (),
353- this ->constEnd (), sel)),
354- sel);
382+ for (const auto &v : finalInsert) {
383+ auto it = std::upper_bound (this ->constBegin (), this ->constEnd (), v);
384+ qsizetype idx =
385+ static_cast <qsizetype>(std::distance (this ->constBegin (), it));
386+ this ->insert (idx, v);
387+ ret.inserted .append (idx);
355388 }
356389
357390 return ret;
0 commit comments