more efficient updating of group-by-sender view. GitHub issue #129

dbus-notify
Zlatin Balevsky 2022-03-23 17:10:57 +00:00
parent a41ccb190c
commit d7880a866c
No known key found for this signature in database
GPG Key ID: A72832072D525E41
2 changed files with 105 additions and 29 deletions

View File

@ -129,12 +129,11 @@ class SearchTabModel {
hashBucket[event.infohash] = bucket hashBucket[event.infohash] = bucket
} }
def senderBucket = sendersBucket.get(event.sender) SenderBucket senderBucket = sendersBucket.get(event.sender)
if (senderBucket == null) { if (senderBucket == null) {
senderBucket = [] senderBucket = new SenderBucket(event.sender, senders.size())
sendersBucket[event.sender] = senderBucket sendersBucket[event.sender] = senderBucket
senders.clear() senders << senderBucket
senders.addAll(sendersBucket.keySet())
} }
Set sourceBucket = sourcesBucket.get(event.infohash) Set sourceBucket = sourcesBucket.get(event.infohash)
@ -145,7 +144,7 @@ class SearchTabModel {
sourceBucket.addAll(event.sources) sourceBucket.addAll(event.sources)
bucket.add event bucket.add event
senderBucket << event senderBucket.results << event
} }
@ -160,7 +159,8 @@ class SearchTabModel {
allResults2.addAll(hashBucket.keySet()) allResults2.addAll(hashBucket.keySet())
allResults2.stream().filter({ InfoHash ih -> filter(ih) }).forEach({ results2.add it }) allResults2.stream().filter({ InfoHash ih -> filter(ih) }).forEach({ results2.add it })
} }
view.refreshResults() view.addPendingResults()
view.updateResultsTable2()
dirty = false dirty = false
} }
} else if (!copy.isEmpty()) } else if (!copy.isEmpty())
@ -245,6 +245,26 @@ class SearchTabModel {
} }
} }
static class SenderBucket {
final Persona sender
private final int rowIdx
final List<UIResultEvent> results = []
private int lastUpdatedIdx
SenderBucket(Persona sender, int rowIdx) {
this.sender = sender
this.rowIdx = rowIdx
}
List<UIResultEvent> getPendingResults() {
if (lastUpdatedIdx == results.size())
return Collections.emptyList()
def rv = results.subList(lastUpdatedIdx, results.size())
lastUpdatedIdx = results.size()
return rv
}
}
private class Filterer extends SwingWorker<Void, InfoHash> { private class Filterer extends SwingWorker<Void, InfoHash> {
private volatile boolean cancelled private volatile boolean cancelled

View File

@ -1,6 +1,7 @@
package com.muwire.gui package com.muwire.gui
import com.muwire.core.SharedFile import com.muwire.core.SharedFile
import com.muwire.gui.SearchTabModel.SenderBucket
import griffon.core.artifact.GriffonView import griffon.core.artifact.GriffonView
import net.i2p.data.Destination import net.i2p.data.Destination
@ -11,6 +12,7 @@ import javax.swing.JTabbedPane
import javax.swing.JTextField import javax.swing.JTextField
import javax.swing.KeyStroke import javax.swing.KeyStroke
import javax.swing.RowSorter import javax.swing.RowSorter
import javax.swing.table.DefaultTableModel
import javax.swing.tree.TreePath import javax.swing.tree.TreePath
import java.awt.Component import java.awt.Component
import java.awt.event.ActionEvent import java.awt.event.ActionEvent
@ -93,15 +95,15 @@ class SearchTabView {
scrollPane (constraints : BorderLayout.CENTER) { scrollPane (constraints : BorderLayout.CENTER) {
sendersTable = table(id : "senders-table", autoCreateRowSorter : true, rowHeight : rowHeight) { sendersTable = table(id : "senders-table", autoCreateRowSorter : true, rowHeight : rowHeight) {
tableModel(list : model.senders) { tableModel(list : model.senders) {
closureColumn(header : trans("SENDER"), preferredWidth : 500, type: String, read : {row -> row.getHumanReadableName()}) closureColumn(header : trans("SENDER"), preferredWidth : 500, type: String, read : { SenderBucket row -> row.sender.getHumanReadableName()})
closureColumn(header : trans("RESULTS"), preferredWidth : 20, type: Integer, read : {row -> model.sendersBucket[row].size()}) closureColumn(header : trans("RESULTS"), preferredWidth : 20, type: Integer, read : {SenderBucket row -> row.results.size()})
closureColumn(header : trans("BROWSE"), preferredWidth : 20, type: Boolean, read : {row -> model.sendersBucket[row].first().browse}) closureColumn(header : trans("BROWSE"), preferredWidth : 20, type: Boolean, read : {SenderBucket row -> row.results[0].browse})
closureColumn(header : trans("COLLECTIONS"), preferredWidth : 20, type: Boolean, read : {row -> model.sendersBucket[row].first().browseCollections}) closureColumn(header : trans("COLLECTIONS"), preferredWidth : 20, type: Boolean, read : {SenderBucket row -> row.results[0].browseCollections})
closureColumn(header : trans("FEED"), preferredWidth : 20, type : Boolean, read : {row -> model.sendersBucket[row].first().feed}) closureColumn(header : trans("FEED"), preferredWidth : 20, type : Boolean, read : {SenderBucket row -> row.results[0].feed})
closureColumn(header : trans("MESSAGES"), preferredWidth : 20, type : Boolean, read : {row -> model.sendersBucket[row].first().messages}) closureColumn(header : trans("MESSAGES"), preferredWidth : 20, type : Boolean, read : {SenderBucket row -> row.results[0].messages})
closureColumn(header : trans("CHAT"), preferredWidth : 20, type : Boolean, read : {row -> model.sendersBucket[row].first().chat}) closureColumn(header : trans("CHAT"), preferredWidth : 20, type : Boolean, read : {SenderBucket row -> row.results[0].chat})
closureColumn(header : trans("TRUST_NOUN"), preferredWidth : 50, type: String, read : { row -> closureColumn(header : trans("TRUST_NOUN"), preferredWidth : 50, type: String, read : { SenderBucket row ->
trans(model.core.trustService.getLevel(row.destination).name()) trans(model.core.trustService.getLevel(row.sender.destination).name())
}) })
} }
} }
@ -409,21 +411,22 @@ class SearchTabView {
model.messageActionEnabled = false model.messageActionEnabled = false
return return
} else { } else {
Persona sender = model.senders[row] SenderBucket bucket = model.senders[row]
model.browseActionEnabled = model.sendersBucket[sender].first().browse Persona sender = bucket.sender
model.browseCollectionsActionEnabled = model.sendersBucket[sender].first().browseCollections model.browseActionEnabled = bucket.results[0].browse
model.chatActionEnabled = model.sendersBucket[sender].first().chat model.browseCollectionsActionEnabled = bucket.results[0].browseCollections
model.messageActionEnabled = model.sendersBucket[sender].first().messages model.chatActionEnabled = bucket.results[0].chat
model.subscribeActionEnabled = model.sendersBucket[sender].first().feed && model.messageActionEnabled = bucket.results[0].messages
model.subscribeActionEnabled = bucket.results[0].feed &&
model.core.feedManager.getFeed(sender) == null model.core.feedManager.getFeed(sender) == null
model.trustButtonsEnabled = true model.trustButtonsEnabled = true
model.results.clear() model.results.clear()
model.results.addAll(model.sendersBucket[sender]) model.results.addAll(bucket.results)
resultsTable.model.fireTableDataChanged() resultsTable.model.fireTableDataChanged()
model.root.removeAllChildren() model.root.removeAllChildren()
for(UIResultEvent event : model.sendersBucket[sender]) for(UIResultEvent event : bucket.results)
model.treeModel.addToTree(event) model.treeModel.addToTree(event)
model.treeModel.nodeStructureChanged(model.root) model.treeModel.nodeStructureChanged(model.root)
TreeUtil.expand(resultTree) TreeUtil.expand(resultTree)
@ -676,7 +679,7 @@ class SearchTabView {
if (model.groupedByFile) if (model.groupedByFile)
return model.senders2[row]?.sender return model.senders2[row]?.sender
else else
return model.senders[row] return model.senders[row]?.sender
} }
def showSenderGrouping = { def showSenderGrouping = {
@ -708,6 +711,58 @@ class SearchTabView {
return sequentialDownloadCheckbox.model.isSelected() return sequentialDownloadCheckbox.model.isSelected()
} }
void addPendingResults() {
JTable table = builder.getVariable("senders-table")
int selectedRow = table.getSelectedRow()
int newRowsStart = -1
int newRowsEnd = -1
for (int row = 0; row < model.senders.size(); row++) {
SenderBucket sb = model.senders[row]
List<UIResultEvent> pending = sb.getPendingResults()
if (pending.isEmpty())
continue
if (pending.size() == sb.results.size()) {
if (newRowsStart == -1)
newRowsStart = row
newRowsEnd = row
} else {
table.model.fireTableRowsUpdated(row, row)
}
if (row == selectedRow)
displayPendingResults(pending)
}
if (newRowsStart >= 0 && newRowsEnd >= 0) {
table.model.fireTableRowsInserted(newRowsStart, newRowsEnd)
} else {
boolean shouldSort = false
for (RowSorter.SortKey key : table.rowSorter.getSortKeys()) {
if (key.column == 1) {
shouldSort = true
break
}
}
if (shouldSort) {
table.model.fireTableDataChanged()
}
}
}
private void displayPendingResults(List<UIResultEvent> pending) {
int rowCount = model.results.size()
model.results.addAll(pending)
resultsTable.model.fireTableRowsInserted(rowCount - 1, model.results.size() - 1)
if (!resultsTable.rowSorter.getSortKeys().isEmpty())
resultsTable.model.fireTableDataChanged()
for (UIResultEvent event : pending)
model.treeModel.addToTree(event)
model.treeModel.nodeStructureChanged(model.root)
// TODO: decide whether to expand
}
void refreshResults() { void refreshResults() {
JTable table = builder.getVariable("senders-table") JTable table = builder.getVariable("senders-table")
int selectedRow = table.getSelectedRow() int selectedRow = table.getSelectedRow()
@ -719,8 +774,11 @@ class SearchTabView {
table.selectionModel.setSelectionInterval(selectedRow, selectedRow) table.selectionModel.setSelectionInterval(selectedRow, selectedRow)
} }
updateResultsTable2()
}
table = builder.getVariable("results-table2") void updateResultsTable2() {
JTable table = builder.getVariable("results-table2")
int [] selectedRows = table.getSelectedRows() int [] selectedRows = table.getSelectedRows()
for (int i = 0; i < selectedRows.length; i++) for (int i = 0; i < selectedRows.length; i++)
selectedRows[i] = table.rowSorter.convertRowIndexToModel(selectedRows[i]) selectedRows[i] = table.rowSorter.convertRowIndexToModel(selectedRows[i])
@ -742,9 +800,7 @@ class SearchTabView {
// there should be exactly 1 entry if at all. // there should be exactly 1 entry if at all.
if (!model.sendersBucket.containsKey(persona)) if (!model.sendersBucket.containsKey(persona))
return return
int index = model.senders.indexOf(persona) int index = model.sendersBucket[persona].rowIdx
if (index < 0)
return // should not happen!
// 2. it exists in the senders table, update the row // 2. it exists in the senders table, update the row
JTable table = builder.getVariable("senders-table") JTable table = builder.getVariable("senders-table")