Skip to content

Commit 310eabe

Browse files
authored
Merge pull request #1230 from letsfindaway/fix-thumbnail-sync
Fix thumbnail sync
2 parents fb6e538 + 5c0b001 commit 310eabe

10 files changed

Lines changed: 101 additions & 82 deletions

src/core/UBPersistenceManager.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -858,6 +858,13 @@ void UBPersistenceManager::duplicateDocumentScene(std::shared_ptr<UBDocumentProx
858858
{
859859
checkIfDocumentRepositoryExists();
860860

861+
auto scene = mSceneCache.value(proxy, index);
862+
863+
if (scene && scene->isModified())
864+
{
865+
persistDocumentScene(proxy, scene, index, false, true);
866+
}
867+
861868
for (int i = proxy->pageCount(); i > index + 1; i--)
862869
{
863870
renamePage(proxy, i - 1 , i);
@@ -869,7 +876,7 @@ void UBPersistenceManager::duplicateDocumentScene(std::shared_ptr<UBDocumentProx
869876
copyPage(proxy, index , index + 1);
870877

871878
//TODO: write a proper way to handle object on disk
872-
std::shared_ptr<UBGraphicsScene> scene = loadDocumentScene(proxy, index + 1);
879+
scene = loadDocumentScene(proxy, index + 1);
873880

874881
foreach(QGraphicsItem* item, scene->items())
875882
{

src/document/UBDocument.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ void UBDocument::duplicatePage(int index)
6969
{
7070
UBPersistenceManager::persistenceManager()->duplicateDocumentScene(mProxy, index);
7171

72-
mThumbnailScene->insertThumbnail(index);
72+
mThumbnailScene->insertThumbnail(index + 1);
7373
}
7474

7575
void UBDocument::movePage(int fromIndex, int toIndex)

src/frameworks/UBBackgroundLoader.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,12 @@ UBBackgroundLoader::~UBBackgroundLoader()
4444
wait();
4545
}
4646

47+
bool UBBackgroundLoader::isIdle()
48+
{
49+
QMutexLocker lock{&mMutex};
50+
return mPaths.empty() && mResults.empty();
51+
}
52+
4753
bool UBBackgroundLoader::isResultAvailable()
4854
{
4955
QMutexLocker lock{&mMutex};

src/frameworks/UBBackgroundLoader.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class UBBackgroundLoader : public QThread
3737
UBBackgroundLoader(QList<std::pair<int, QString>> paths, QObject* parent = nullptr);
3838
virtual ~UBBackgroundLoader();
3939

40+
bool isIdle();
4041
bool isResultAvailable();
4142
std::pair<int, QByteArray> takeResult();
4243

src/gui/UBBoardThumbnailsView.cpp

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -165,19 +165,6 @@ void UBBoardThumbnailsView::updateActiveThumbnail(int newActiveIndex)
165165
update();
166166
}
167167

168-
void UBBoardThumbnailsView::updateExposure()
169-
{
170-
QRect viewportRect(QPoint(0, 0), viewport()->size());
171-
QRectF visibleSceneRect = mapToScene(viewportRect).boundingRect();
172-
173-
int index = 0;
174-
175-
while (auto thumbnail = mDocument->thumbnailScene()->thumbnailAt(index++))
176-
{
177-
thumbnail->setExposed(visibleSceneRect.intersects(thumbnail->sceneBoundingRect()));
178-
}
179-
}
180-
181168
void UBBoardThumbnailsView::resizeEvent(QResizeEvent *event)
182169
{
183170
bool scrollbarWasHidden = mScrollbarVisible && !verticalScrollBar()->isVisible();
@@ -275,7 +262,6 @@ void UBBoardThumbnailsView::mouseReleaseEvent(QMouseEvent *event)
275262
void UBBoardThumbnailsView::scrollContentsBy(int dx, int dy)
276263
{
277264
QGraphicsView::scrollContentsBy(dx, dy);
278-
updateExposure();
279265
}
280266

281267
void UBBoardThumbnailsView::dragEnterEvent(QDragEnterEvent *event)

src/gui/UBBoardThumbnailsView.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,6 @@ public slots:
8080
void moveThumbnailRequired(int from, int to);
8181

8282
private:
83-
void updateExposure();
84-
8583
std::shared_ptr<UBDocument> mDocument;
8684

8785
int mThumbnailWidth;

src/gui/UBThumbnail.cpp

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ UBThumbnail::UBThumbnail()
4545
// accept hover to show/hide UI buttons
4646
setAcceptHoverEvents(true);
4747

48+
// make it selectable
49+
setFlag(QGraphicsItem::ItemIsSelectable, true);
50+
4851
// arrange child items behind the transparent parent
4952
mPixmapItem->setFlag(QGraphicsItem::ItemStacksBehindParent);
5053
mTextItem->setFlag(QGraphicsItem::ItemStacksBehindParent);
@@ -137,16 +140,6 @@ void UBThumbnail::setPageScene(std::shared_ptr<UBGraphicsScene> pageScene)
137140
adjustThumbnail();
138141
}
139142

140-
void UBThumbnail::setExposed(bool exposed)
141-
{
142-
mExposed = exposed;
143-
}
144-
145-
bool UBThumbnail::isExposed() const
146-
{
147-
return mExposed;
148-
}
149-
150143
void UBThumbnail::setDeletable(bool deletable)
151144
{
152145
mDeletable = deletable;
@@ -156,7 +149,7 @@ void UBThumbnail::updatePixmap(const QRectF& region)
156149
{
157150
auto pageScene = mPageScene.lock();
158151

159-
if (pageScene && !mPixmapItem->pixmap().isNull() && mExposed)
152+
if (pageScene && !mPixmapItem->pixmap().isNull())
160153
{
161154
QPixmap pixmap = this->pixmap();
162155
QRectF pixmapRect;

src/gui/UBThumbnail.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,6 @@ class UBThumbnail : public QGraphicsRectItem
5555
int row() const;
5656

5757
void setPageScene(std::shared_ptr<UBGraphicsScene> pageScene);
58-
void setExposed(bool exposed);
59-
bool isExposed() const;
6058
void setDeletable(bool deletable);
6159

6260
void updatePixmap(const QRectF& region = QRectF());
@@ -81,7 +79,6 @@ class UBThumbnail : public QGraphicsRectItem
8179
int mColumn{0};
8280
int mRow{0};
8381
std::weak_ptr<UBGraphicsScene> mPageScene{}; // weak, don't keep the scene from being deleted
84-
bool mExposed{false};
8582
QTransform mTransform{};
8683
bool mEditable{false};
8784
bool mDeletable{true};

src/gui/UBThumbnailScene.cpp

Lines changed: 80 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333

3434
UBThumbnailScene::UBThumbnailScene(UBDocument* document)
3535
: mDocument{document}
36+
, mThumbnailItems{document->proxy()->pageCount()}
3637
{
3738
}
3839

@@ -82,20 +83,22 @@ void UBThumbnailScene::arrangeThumbnails(int fromIndex, int toIndex)
8283
for (int i = fromIndex; i < toIndex; ++i)
8384
{
8485
auto thumbnail = mThumbnailItems.at(i);
85-
thumbnail->setThumbnailSize(thumbnailSize);
86-
thumbnail->setFlag(QGraphicsItem::ItemIsSelectable, true);
8786

88-
thumbnail->setColumn(columnIndex);
89-
thumbnail->setRow(rowIndex);
90-
91-
// start with a margin left
92-
// step by width + spacing
93-
// start with margin top
94-
// step by height including label + spacing
95-
const auto posX = margins.left() + columnIndex * gridSize.width() + horizontalCenterOffset;
96-
const auto posY = margins.top() + rowIndex * gridSize.height();
97-
98-
thumbnail->setPos(posX, posY);
87+
if (thumbnail)
88+
{
89+
thumbnail->setThumbnailSize(thumbnailSize);
90+
thumbnail->setColumn(columnIndex);
91+
thumbnail->setRow(rowIndex);
92+
93+
// start with a margin left
94+
// step by width + spacing
95+
// start with margin top
96+
// step by height including label + spacing
97+
const auto posX = margins.left() + columnIndex * gridSize.width() + horizontalCenterOffset;
98+
const auto posY = margins.top() + rowIndex * gridSize.height();
99+
100+
thumbnail->setPos(posX, posY);
101+
}
99102

100103
if (++columnIndex >= nbColumns)
101104
{
@@ -130,7 +133,7 @@ void UBThumbnailScene::hightlightItem(int index, bool only)
130133

131134
if (index >= 0 && index < mThumbnailItems.size())
132135
{
133-
mThumbnailItems.at(index)->setSelected(true);
136+
thumbnailAt(index)->setSelected(true);
134137
}
135138
}
136139

@@ -139,23 +142,36 @@ int UBThumbnailScene::thumbnailCount() const
139142
return mThumbnailItems.size();
140143
}
141144

142-
UBThumbnail* UBThumbnailScene::thumbnailAt(int index) const
145+
UBThumbnail* UBThumbnailScene::thumbnailAt(int index)
143146
{
144147
if (index >= 0 && index < mThumbnailItems.size())
145148
{
149+
if (!mThumbnailItems.at(index))
150+
{
151+
// create the missing thumbnail
152+
auto thumbnailItem = new UBThumbnail;
153+
154+
thumbnailItem->setPixmap(UBThumbnailAdaptor::get(mDocument->proxy(), index));
155+
thumbnailItem->setSceneIndex(index);
156+
157+
mThumbnailItems[index] = thumbnailItem;
158+
addItem(thumbnailItem);
159+
160+
arrangeThumbnails(index, index + 1);
161+
}
162+
146163
return mThumbnailItems.at(index);
147164
}
148165

149166
return nullptr;
150167
}
151168

152169
/**
153-
* @brief (Re-)create all thumbnails for this scene.
170+
* @brief Create thumbnails for this scene.
154171
*
155-
* Already existing thumbnails are first removed from the scene and deleted.
156-
* Then all thumbnails for the document pages are asynchronously loaded and
157-
* positioned on the scene. The application remains responsive even while
158-
* loading thumbnails.
172+
* Thumbnails for the document pages above startIndex are asynchronously
173+
* loaded and positioned on the scene. The application remains responsive
174+
* even while loading thumbnails.
159175
*
160176
* It is even possible to interact with the already loaded thumbnails during
161177
* the loading process. So the already loaded pages can be moved, copied,
@@ -164,13 +180,10 @@ UBThumbnail* UBThumbnailScene::thumbnailAt(int index) const
164180
*/
165181
void UBThumbnailScene::createThumbnails(int startIndex)
166182
{
167-
// delete current thumbnails above startIndex
168-
for (int index = mThumbnailItems.size() - 1; index >= startIndex; --index)
183+
// skip already loaded thumbnails
184+
while (startIndex < mThumbnailItems.count() && mThumbnailItems.at(startIndex))
169185
{
170-
auto item = mThumbnailItems.at(index);
171-
removeItem(item);
172-
mThumbnailItems.removeAt(index);
173-
delete item;
186+
++startIndex;
174187
}
175188

176189
// create the list of all thumbnail paths
@@ -187,6 +200,12 @@ void UBThumbnailScene::createThumbnails(int startIndex)
187200
// abort a running loader
188201
mLoader->abort();
189202
delete mLoader;
203+
mLoader = nullptr;
204+
}
205+
206+
if (paths.empty())
207+
{
208+
return;
190209
}
191210

192211
mLoader = new UBBackgroundLoader{paths, this};
@@ -236,7 +255,7 @@ void UBThumbnailScene::insertThumbnail(int pageIndex, std::shared_ptr<UBGraphics
236255
if (mLoader)
237256
{
238257
// restart loading remaining thumbnails
239-
createThumbnails(mThumbnailItems.size());
258+
createThumbnails(pageIndex);
240259
}
241260
}
242261

@@ -259,7 +278,7 @@ void UBThumbnailScene::deleteThumbnail(int pageIndex, bool rearrange)
259278
if (mLoader)
260279
{
261280
// restart loading remaining thumbnails
262-
createThumbnails(mThumbnailItems.size());
281+
createThumbnails(pageIndex);
263282
}
264283

265284
if (mThumbnailItems.size() == 1)
@@ -288,7 +307,7 @@ void UBThumbnailScene::moveThumbnail(int fromIndex, int toIndex)
288307
if (mLoader)
289308
{
290309
// restart loading remaining thumbnails
291-
createThumbnails(mThumbnailItems.size());
310+
createThumbnails(fromIndex);
292311
}
293312
}
294313

@@ -298,7 +317,7 @@ void UBThumbnailScene::reloadThumbnail(int pageIndex)
298317
{
299318
auto thumbnail = mThumbnailItems.at(pageIndex);
300319

301-
if (thumbnail && !thumbnail->isExposed())
320+
if (thumbnail)
302321
{
303322
thumbnail->setPixmap(UBThumbnailAdaptor::get(mDocument->proxy(), pageIndex));
304323
}
@@ -334,7 +353,7 @@ void UBThumbnailScene::loadNextThumbnail()
334353
// max number of thumbnails to load in one pass
335354
constexpr int bulkSize{10};
336355

337-
if (mThumbnailItems.size() < mDocument->proxy()->pageCount())
356+
if (!mLoader->isIdle())
338357
{
339358
if (UBApplication::isClosing)
340359
{
@@ -348,7 +367,7 @@ void UBThumbnailScene::loadNextThumbnail()
348367
return;
349368
}
350369

351-
const auto firstIndex = mThumbnailItems.size();
370+
int firstIndex = -1;
352371

353372
for (int i = 0; i < bulkSize; ++i)
354373
{
@@ -357,31 +376,43 @@ void UBThumbnailScene::loadNextThumbnail()
357376
break;
358377
}
359378

360-
// take next result and determine index from current number of thumbnails and
361-
// not from result, because pages may have been added or removed in the meantime
379+
// take and process next result
362380
const auto result = mLoader->takeResult();
363-
const auto nextIndex = mThumbnailItems.size();
364-
QPixmap pixmap;
381+
const auto index = result.first;
382+
auto thumbnailItem = mThumbnailItems.at(index);
365383

366-
if (result.second.isEmpty())
384+
if (!thumbnailItem)
367385
{
368-
pixmap = UBThumbnailAdaptor::generateMissingThumbnail(mDocument->proxy(), nextIndex);
369-
}
370-
else
371-
{
372-
pixmap.loadFromData(result.second);
373-
}
386+
QPixmap pixmap;
374387

375-
auto thumbnailItem = new UBThumbnail;
388+
if (result.second.isEmpty())
389+
{
390+
pixmap = UBThumbnailAdaptor::generateMissingThumbnail(mDocument->proxy(), index);
391+
}
392+
else
393+
{
394+
pixmap.loadFromData(result.second);
395+
}
376396

377-
thumbnailItem->setPixmap(pixmap);
378-
thumbnailItem->setSceneIndex(nextIndex);
397+
thumbnailItem = new UBThumbnail;
379398

380-
mThumbnailItems << thumbnailItem;
381-
addItem(thumbnailItem);
399+
thumbnailItem->setPixmap(pixmap);
400+
thumbnailItem->setSceneIndex(index);
401+
402+
mThumbnailItems[index] = thumbnailItem;
403+
addItem(thumbnailItem);
404+
405+
if (firstIndex < 0)
406+
{
407+
firstIndex = index;
408+
}
409+
}
382410
}
383411

384-
arrangeThumbnails(firstIndex);
412+
if (firstIndex >= 0)
413+
{
414+
arrangeThumbnails(firstIndex);
415+
}
385416

386417
// load next thumbnails in a deferred task executed on the main thread when it is idle.
387418
QTimer::singleShot(1, mLoader, [this]() { loadNextThumbnail(); });

src/gui/UBThumbnailScene.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ class UBThumbnailScene : public QGraphicsScene
5757
void arrangeThumbnails(int fromIndex = 0, int toIndex = -1);
5858
void hightlightItem(int index, bool only = false);
5959
int thumbnailCount() const;
60-
UBThumbnail* thumbnailAt(int index) const;
60+
UBThumbnail* thumbnailAt(int index);
6161

6262
protected:
6363
// only to be called from UBDocument

0 commit comments

Comments
 (0)