From f0f9d840f098d701cd5f7c0bf9a801c8201f644f Mon Sep 17 00:00:00 2001 From: Zlatin Balevsky Date: Fri, 18 Oct 2019 22:35:17 +0100 Subject: [PATCH] wip on browse host --- gui/griffon-app/conf/Config.groovy | 5 + .../com/muwire/gui/BrowseController.groovy | 61 ++++++++++ .../com/muwire/gui/SearchTabController.groovy | 16 +++ .../models/com/muwire/gui/BrowseModel.groovy | 19 +++ .../com/muwire/gui/SearchTabModel.groovy | 1 + .../views/com/muwire/gui/BrowseView.groovy | 108 ++++++++++++++++++ .../views/com/muwire/gui/SearchTabView.groovy | 19 ++- 7 files changed, 224 insertions(+), 5 deletions(-) create mode 100644 gui/griffon-app/controllers/com/muwire/gui/BrowseController.groovy create mode 100644 gui/griffon-app/models/com/muwire/gui/BrowseModel.groovy create mode 100644 gui/griffon-app/views/com/muwire/gui/BrowseView.groovy diff --git a/gui/griffon-app/conf/Config.groovy b/gui/griffon-app/conf/Config.groovy index 671dfd8a..a8f1e913 100644 --- a/gui/griffon-app/conf/Config.groovy +++ b/gui/griffon-app/conf/Config.groovy @@ -56,4 +56,9 @@ mvcGroups { view = 'com.muwire.gui.AddCommentView' controller = 'com.muwire.gui.AddCommentController' } + 'browse' { + model = 'com.muwire.gui.BrowseModel' + view = 'com.muwire.gui.BrowseView' + controller = 'com.muwire.gui.BrowseController' + } } diff --git a/gui/griffon-app/controllers/com/muwire/gui/BrowseController.groovy b/gui/griffon-app/controllers/com/muwire/gui/BrowseController.groovy new file mode 100644 index 00000000..fc5dee92 --- /dev/null +++ b/gui/griffon-app/controllers/com/muwire/gui/BrowseController.groovy @@ -0,0 +1,61 @@ +package com.muwire.gui + +import griffon.core.artifact.GriffonController +import griffon.core.controller.ControllerAction +import griffon.inject.MVCMember +import griffon.metadata.ArtifactProviderFor +import javax.annotation.Nonnull + +import com.muwire.core.EventBus +import com.muwire.core.search.BrowseStatusEvent +import com.muwire.core.search.UIResultEvent + +@ArtifactProviderFor(GriffonController) +class BrowseController { + @MVCMember @Nonnull + BrowseModel model + @MVCMember @Nonnull + BrowseView view + + EventBus eventBus + + + void mvcGroupInit(Map args) { + eventBus.register(BrowseStatusEvent.class, this) + eventBus.register(UIResultEvent.class, this) + } + + void mvcGroupDestroy() { + eventBus.unregister(BrowseStatusEvent.class, this) + eventBus.unregister(UIResultEvent.class, this) + } + + void onBrowseStatusEvent(BrowseStatusEvent e) { + runInsideUIAsync { + model.status = e.status + } + } + + void onUIResultEvent(UIResultEvent e) { + runInsideUIAsync { + model.results << e + view.resultsTable.model.fireTableDataChanged() + } + } + + @ControllerAction + void dismiss() { + view.dialog.setVisible(false) + mvcGroup.destroy() + } + + @ControllerAction + void download() { + + } + + @ControllerAction + void viewComment() { + + } +} \ No newline at end of file diff --git a/gui/griffon-app/controllers/com/muwire/gui/SearchTabController.groovy b/gui/griffon-app/controllers/com/muwire/gui/SearchTabController.groovy index 6c70edbf..3085041a 100644 --- a/gui/griffon-app/controllers/com/muwire/gui/SearchTabController.groovy +++ b/gui/griffon-app/controllers/com/muwire/gui/SearchTabController.groovy @@ -7,6 +7,7 @@ import griffon.metadata.ArtifactProviderFor import javax.annotation.Nonnull import com.muwire.core.Core +import com.muwire.core.Persona import com.muwire.core.download.UIDownloadEvent import com.muwire.core.search.UIResultEvent import com.muwire.core.trust.TrustEvent @@ -85,4 +86,19 @@ class SearchTabController { def sender = model.senders[row] core.eventBus.publish( new TrustEvent(persona : sender, level : TrustLevel.NEUTRAL)) } + + @ControllerAction + void browse() { + int selectedSender = view.selectedSenderRow() + if (selectedSender < 0) + return + Persona sender = model.senders[selectedSender] + + String groupId = sender.getHumanReadableName() + Map params = new HashMap<>() + params['host'] = sender + params['eventBus'] = core.eventBus + + mvcGroup.createMVCGroup("browse", groupId, params) + } } \ No newline at end of file diff --git a/gui/griffon-app/models/com/muwire/gui/BrowseModel.groovy b/gui/griffon-app/models/com/muwire/gui/BrowseModel.groovy new file mode 100644 index 00000000..f8220828 --- /dev/null +++ b/gui/griffon-app/models/com/muwire/gui/BrowseModel.groovy @@ -0,0 +1,19 @@ +package com.muwire.gui + +import com.muwire.core.Persona + +import griffon.core.artifact.GriffonModel +import griffon.transform.Observable +import griffon.metadata.ArtifactProviderFor + +import com.muwire.core.search.BrowseStatus + +@ArtifactProviderFor(GriffonModel) +class BrowseModel { + Persona host + @Observable BrowseStatus status + @Observable boolean downloadActionEnabled + @Observable boolean viewCommentActionEnabled + + def results = [] +} \ No newline at end of file diff --git a/gui/griffon-app/models/com/muwire/gui/SearchTabModel.groovy b/gui/griffon-app/models/com/muwire/gui/SearchTabModel.groovy index 988fbb55..b8405056 100644 --- a/gui/griffon-app/models/com/muwire/gui/SearchTabModel.groovy +++ b/gui/griffon-app/models/com/muwire/gui/SearchTabModel.groovy @@ -21,6 +21,7 @@ class SearchTabModel { @Observable boolean downloadActionEnabled @Observable boolean trustButtonsEnabled + @Observable boolean browseActionEnabled Core core UISettings uiSettings diff --git a/gui/griffon-app/views/com/muwire/gui/BrowseView.groovy b/gui/griffon-app/views/com/muwire/gui/BrowseView.groovy new file mode 100644 index 00000000..52179f15 --- /dev/null +++ b/gui/griffon-app/views/com/muwire/gui/BrowseView.groovy @@ -0,0 +1,108 @@ +package com.muwire.gui + +import griffon.core.artifact.GriffonView +import griffon.inject.MVCMember +import griffon.metadata.ArtifactProviderFor + +import javax.swing.JDialog +import javax.swing.SwingConstants +import javax.swing.table.DefaultTableCellRenderer + +import java.awt.BorderLayout +import java.awt.event.WindowAdapter +import java.awt.event.WindowEvent + +import javax.annotation.Nonnull + +@ArtifactProviderFor(GriffonView) +class BrowseView { + @MVCMember @Nonnull + FactoryBuilderSupport builder + @MVCMember @Nonnull + BrowseModel model + + def mainFrame + def dialog + def p + def resultsTable + def lastSortEvent + void initUI() { + mainFrame = application.windowManager.findWindow("main-frame") + dialog = new JDialog(mainFrame, model.host.getHumanReadableName(), true) + dialog.setResizable(true) + + p = builder.panel { + borderLayout() + panel (constraints : BorderLayout.NORTH) { + label(text: "Status:") + label(text: bind {model.status.toString()}) + } + scrollPane (constraints : BorderLayout.CENTER){ + resultsTable = table(autoCreateRowSorter : true) { + tableModel(list : model.results) { + closureColumn(header: "Name", preferredWidth: 350, type: String, read : {row -> row.name.replace('<','_')}) + closureColumn(header: "Size", preferredWidth: 20, type: Long, read : {row -> row.size}) + closureColumn(header: "Comments", preferredWidth: 20, type: Boolean, read : {row -> row.comment != null}) + } + } + } + panel (constraints : BorderLayout.SOUTH) { + button(text : "Download", enabled : bind {model.downloadActionEnabled}, downloadAction) + button(text : "View Comment", enabled : bind{model.viewCommentActionEnabled}, viewCommentAction) + button(text : "Dismiss", dismissAction) + } + } + + + def centerRenderer = new DefaultTableCellRenderer() + centerRenderer.setHorizontalAlignment(JLabel.CENTER) + resultsTable.setDefaultRenderer(Integer.class,centerRenderer) + + resultsTable.columnModel.getColumn(1).setCellRenderer(new SizeRenderer()) + + + resultsTable.rowSorter.addRowSorterListener({evt -> lastSortEvent = evt}) + resultsTable.rowSorter.setSortsOnUpdates(true) + def selectionModel = resultsTable.getSelectionModel() + selectionModel.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION) + selectionModel.addListSelectionListener({ + int[] rows = resultsTable.getSelectedRows() + if (rows.length == 0) { + model.downloadActionEnabled = false + model.viewCommentActionEnabled = false + return + } + + if (lastSortEvent != null) { + for (int i = 0; i < rows.length; i ++) { + rows[i] = resultsTable.rowSorter.convertRowIndexToModel(rows[i]) + } + } + + boolean downloadActionEnabled = true + if (rows.length == 1 && model.results[rows[0]].comment != null) + model.viewCommentActionEnabled = true + else + model.viewCommentActionEnabled = false + + rows.each { + downloadActionEnabled &= mvcGroup.parentGroup.model.canDownload(model.results[it].infohash) + } + model.downloadActionEnabled = downloadActionEnabled + }) + } + + void mvcGroupInit(Map args) { + dialog.getContentPane().add(p) + dialog.pack() + dialog.setLocationRelativeTo(mainFrame) + dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE) + dialog.addWindowListener( new WindowAdapter() { + public void windowClosed(WindowEvent e) { + mvcGroup.destroy() + } + }) + dialog.show() + } + +} \ No newline at end of file diff --git a/gui/griffon-app/views/com/muwire/gui/SearchTabView.groovy b/gui/griffon-app/views/com/muwire/gui/SearchTabView.groovy index df437c51..113c5f25 100644 --- a/gui/griffon-app/views/com/muwire/gui/SearchTabView.groovy +++ b/gui/griffon-app/views/com/muwire/gui/SearchTabView.groovy @@ -63,6 +63,7 @@ class SearchTabView { tableModel(list : model.senders) { closureColumn(header : "Sender", preferredWidth : 500, type: String, read : {row -> row.getHumanReadableName()}) closureColumn(header : "Results", preferredWidth : 20, type: Integer, read : {row -> model.sendersBucket[row].size()}) + closureColumn(header : "Browse", preferredWidth : 20, type: Boolean, read : {row -> model.sendersBucket[row].first().browse}) closureColumn(header : "Trust", preferredWidth : 50, type: String, read : { row -> model.core.trustService.getLevel(row.destination).toString() }) @@ -70,9 +71,15 @@ class SearchTabView { } } panel(constraints : BorderLayout.SOUTH) { - button(text : "Trust", enabled: bind {model.trustButtonsEnabled }, trustAction) - button(text : "Neutral", enabled: bind {model.trustButtonsEnabled}, neutralAction) - button(text : "Distrust", enabled : bind {model.trustButtonsEnabled}, distrustAction) + gridLayout(rows: 1, cols : 2) + panel { + button(text : "Browse Host", enabled : bind {model.browseActionEnabled}, browseAction) + } + panel { + button(text : "Trust", enabled: bind {model.trustButtonsEnabled }, trustAction) + button(text : "Neutral", enabled: bind {model.trustButtonsEnabled}, neutralAction) + button(text : "Distrust", enabled : bind {model.trustButtonsEnabled}, distrustAction) + } } } panel { @@ -193,12 +200,14 @@ class SearchTabView { int row = selectedSenderRow() if (row < 0) { model.trustButtonsEnabled = false + model.browseActionEnabled = false return } else { + Persona sender = model.senders[row] + model.browseActionEnabled = model.sendersBucket[sender].first().browse model.trustButtonsEnabled = true model.results.clear() - Persona p = model.senders[row] - model.results.addAll(model.sendersBucket[p]) + model.results.addAll(model.sendersBucket[sender]) resultsTable.model.fireTableDataChanged() } })