Further speedups for filebrowser/catalog

This commit is contained in:
Ingo Weyrich
2019-07-27 17:39:16 +02:00
parent 1320791052
commit de963c54de
7 changed files with 159 additions and 85 deletions

View File

@@ -28,7 +28,7 @@
using namespace std;
ThumbBrowserBase::ThumbBrowserBase ()
: location(THLOC_FILEBROWSER), inspector(nullptr), isInspectorActive(false), eventTime(0), lastClicked(nullptr), previewHeight(options.thumbSize), numOfCols(1), arrangement(TB_Horizontal)
: location(THLOC_FILEBROWSER), inspector(nullptr), isInspectorActive(false), eventTime(0), lastClicked(nullptr), previewHeight(options.thumbSize), numOfCols(1), lastRowHeight(0), arrangement(TB_Horizontal)
{
inW = -1;
inH = -1;
@@ -44,6 +44,8 @@ ThumbBrowserBase::ThumbBrowserBase ()
show_all ();
vscroll.get_adjustment()->set_lower(0);
hscroll.get_adjustment()->set_lower(0);
vscroll.signal_value_changed().connect( sigc::mem_fun(*this, &ThumbBrowserBase::scrollChanged) );
hscroll.signal_value_changed().connect( sigc::mem_fun(*this, &ThumbBrowserBase::scrollChanged) );
@@ -543,7 +545,6 @@ void ThumbBrowserBase::configScrollBars ()
auto ha = hscroll.get_adjustment();
int iw = internal.get_width();
ha->set_upper(inW);
ha->set_lower(0);
ha->set_step_increment(!fd.empty() ? fd[0]->getEffectiveWidth() : 0);
ha->set_page_increment(iw);
ha->set_page_size(iw);
@@ -558,7 +559,6 @@ void ThumbBrowserBase::configScrollBars ()
auto va = vscroll.get_adjustment();
va->set_upper(inH);
va->set_lower(0);
const auto height = !fd.empty() ? fd[0]->getEffectiveHeight() : 0;
va->set_step_increment(height);
va->set_page_increment(height == 0 ? ih : (ih / height) * height);
@@ -572,8 +572,22 @@ void ThumbBrowserBase::configScrollBars ()
}
}
void ThumbBrowserBase::arrangeFiles(bool checkfilter)
void ThumbBrowserBase::arrangeFiles(ThumbBrowserEntryBase* entry)
{
if (fd.empty()) {
// nothing to arrange
resizeThumbnailArea(0, 0);
return;
}
if(entry && entry->filtered) {
// a filtered entry was added, nothing to arrange, but has to be marked not drawable
MYREADERLOCK(l, entryRW);
entry->drawable = false;
MYREADERLOCK_RELEASE(l);
return;
}
MYREADERLOCK(l, entryRW);
// GUI already locked by ::redraw, the only caller of this method for now.
@@ -581,17 +595,22 @@ void ThumbBrowserBase::arrangeFiles(bool checkfilter)
//GThreadLock lock;
int rowHeight = 0;
for (const auto entry : fd) {
if (checkfilter) {
// apply filter
entry->filtered = !checkFilter(entry);
}
if (entry) {
// we got the reference to the added entry, makes calculation of rowHeight O(1)
lastRowHeight = rowHeight = std::max(lastRowHeight, entry->getMinimalHeight());
} else {
// compute size of the items
if (!entry->filtered) {
rowHeight = std::max(entry->getMinimalHeight(), rowHeight);
lastRowHeight = 0;
for (const auto thumb : fd) {
// apply filter
thumb->filtered = !checkFilter(thumb);
// compute max rowHeight
if (!thumb->filtered) {
rowHeight = std::max(thumb->getMinimalHeight(), rowHeight);
}
}
}
if (arrangement == TB_Horizontal) {
numOfCols = 1;
@@ -622,14 +641,16 @@ void ThumbBrowserBase::arrangeFiles(bool checkfilter)
const int availWidth = internal.get_width();
// initial number of columns
int oldNumOfCols = numOfCols;
numOfCols = 0;
int colsWidth = 0;
for (unsigned int i = 0; i < fd.size(); ++i) {
if (!fd[i]->filtered && colsWidth + fd[i]->getMinimalWidth() <= availWidth) {
colsWidth += fd[numOfCols]->getMinimalWidth();
colsWidth += fd[i]->getMinimalWidth();
++numOfCols;
if(colsWidth > availWidth) {
--numOfCols;
break;
}
}
@@ -640,6 +661,7 @@ void ThumbBrowserBase::arrangeFiles(bool checkfilter)
}
std::vector<int> colWidths;
std::vector<int> oldColWidths;
for (; numOfCols > 0; --numOfCols) {
// compute column widths
@@ -663,10 +685,77 @@ void ThumbBrowserBase::arrangeFiles(bool checkfilter)
}
}
if (oldNumOfCols == numOfCols) {
int oldColsWidth = 0;
for (; oldNumOfCols > 0; --oldNumOfCols) {
// compute old column widths
oldColWidths.assign(oldNumOfCols, 0);
for (unsigned int i = 0, j = 0; i < fd.size(); ++i) {
if (fd[i] != entry && !fd[i]->filtered && fd[i]->getMinimalWidth() > oldColWidths[j % oldNumOfCols]) {
oldColWidths[j % oldNumOfCols] = fd[i]->getMinimalWidth();
}
if (fd[i] != entry && !fd[i]->filtered) {
++j;
}
}
// if not wider than the space available, arrange it and we are ready
oldColsWidth = std::accumulate(oldColWidths.begin(), oldColWidths.end(), 0);
if (oldNumOfCols == 1 || oldColsWidth < availWidth) {
break;
}
}
}
bool arrangeAll = true;
if (entry && oldNumOfCols == numOfCols && oldColWidths.size() > 0) {
arrangeAll = false;
for (int i = 0; i < numOfCols; ++i) {
if(colWidths[i] != oldColWidths[i]) {
arrangeAll = true;
break;
}
}
}
// arrange files
int curry = 0;
size_t ct = 0;
if (entry && !arrangeAll) {
int i = 0;
// Find currently added entry
for (; ct < fd.size() && fd[ct] != entry; i += !fd[ct]->filtered, ++ct) {
}
//Calculate the position of currently added entry
const int row = i / numOfCols;
const int col = i % numOfCols;
curry = row * rowHeight;
int currx = 0;
for (int c = 0; c < col; ++c) {
currx += colWidths[c];
}
// arrange all entries in the row beginning with the currently added one
for (int i = col; ct < fd.size() && i < numOfCols; ++i, ++ct) {
for (; ct < fd.size() && fd[ct]->filtered; ++ct) {
fd[ct]->drawable = false;
}
if (ct < fd.size()) {
fd[ct]->setPosition(currx, curry, colWidths[i], rowHeight);
fd[ct]->drawable = true;
currx += colWidths[i];
}
}
if (currx > 0) { // there were thumbnails placed in the row
curry += rowHeight;
}
}
// arrange remaining entries, if any, that's the most expensive part
for (; ct < fd.size();) {
for (unsigned int ct = 0; ct < fd.size();) {
// arrange items in the row
int currx = 0;
@@ -689,7 +778,7 @@ void ThumbBrowserBase::arrangeFiles(bool checkfilter)
MYREADERLOCK_RELEASE(l);
// This will require a Writer access
resizeThumbnailArea (colsWidth, curry);
resizeThumbnailArea(colsWidth, curry);
}
}
@@ -979,11 +1068,11 @@ bool ThumbBrowserBase::Internal::on_scroll_event (GdkEventScroll* event)
}
void ThumbBrowserBase::redraw (bool checkfilter)
void ThumbBrowserBase::redraw (ThumbBrowserEntryBase* entry)
{
GThreadLock lock;
arrangeFiles(checkfilter);
arrangeFiles(entry);
queue_draw();
}