From 642044b7e2856d8ab20317d496a5808bc298b6b4 Mon Sep 17 00:00:00 2001 From: Zlatin Balevsky Date: Mon, 4 Nov 2019 18:33:25 +0000 Subject: [PATCH] ui elements for certificate fetching --- gui/griffon-app/conf/Config.groovy | 5 + .../gui/FetchCertificatesController.groovy | 71 +++++++++++ .../com/muwire/gui/SearchTabController.groovy | 17 +++ .../muwire/gui/FetchCertificatesModel.groovy | 21 ++++ .../com/muwire/gui/SearchTabModel.groovy | 1 + .../views/com/muwire/gui/BrowseView.groovy | 20 ++-- .../muwire/gui/FetchCertificatesView.groovy | 113 ++++++++++++++++++ .../views/com/muwire/gui/SearchTabView.groovy | 10 ++ 8 files changed, 248 insertions(+), 10 deletions(-) create mode 100644 gui/griffon-app/controllers/com/muwire/gui/FetchCertificatesController.groovy create mode 100644 gui/griffon-app/models/com/muwire/gui/FetchCertificatesModel.groovy create mode 100644 gui/griffon-app/views/com/muwire/gui/FetchCertificatesView.groovy diff --git a/gui/griffon-app/conf/Config.groovy b/gui/griffon-app/conf/Config.groovy index fa162818..fb5aa11c 100644 --- a/gui/griffon-app/conf/Config.groovy +++ b/gui/griffon-app/conf/Config.groovy @@ -86,4 +86,9 @@ mvcGroups { view = 'com.muwire.gui.AdvancedSharingView' controller = 'com.muwire.gui.AdvancedSharingController' } + 'fetch-certificates' { + model = 'com.muwire.gui.FetchCertificatesModel' + view = 'com.muwire.gui.FetchCertificatesView' + controller = 'com.muwire.gui.FetchCertificatesController' + } } diff --git a/gui/griffon-app/controllers/com/muwire/gui/FetchCertificatesController.groovy b/gui/griffon-app/controllers/com/muwire/gui/FetchCertificatesController.groovy new file mode 100644 index 00000000..e2f534d8 --- /dev/null +++ b/gui/griffon-app/controllers/com/muwire/gui/FetchCertificatesController.groovy @@ -0,0 +1,71 @@ +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 javax.swing.JOptionPane + +import com.muwire.core.EventBus +import com.muwire.core.filecert.CertificateFetchEvent +import com.muwire.core.filecert.CertificateFetchStatus +import com.muwire.core.filecert.CertificateFetchedEvent +import com.muwire.core.filecert.UIFetchCertificatesEvent +import com.muwire.core.filecert.UIImportCertificateEvent + +@ArtifactProviderFor(GriffonController) +class FetchCertificatesController { + @MVCMember @Nonnull + FetchCertificatesModel model + @MVCMember @Nonnull + FetchCertificatesView view + + EventBus eventBus + + void register() { + eventBus.with { + register(CertificateFetchEvent.class, this) + register(CertificateFetchedEvent.class, this) + publish(new UIFetchCertificatesEvent(host : model.result.sender, infoHash : model.result.infohash)) + } + } + + void mvcGroupDestroy() { + eventBus.unregister(CertificateFetchEvent.class, this) + eventBus.unregister(CertificateFetchedEvent.class, this) + } + + void onCertificateFetchEvent(CertificateFetchEvent e) { + runInsideUIAsync { + model.status = e.status + if (e.status == CertificateFetchStatus.FETCHING) + model.totalCertificates = e.count + } + } + + void onCertificateFetchedEvent(CertificateFetchedEvent e) { + runInsideUIAsync { + model.certificates << e.certificate + model.certificateCount = model.certificates.size() + view.certsTable.model.fireTableDataChanged() + } + } + + @ControllerAction + void importCertificates() { + def selectedCerts = view.selectedCertificates() + if (selectedCerts == null) + return + selectedCerts.each { + eventBus.publish(new UIImportCertificateEvent(certificate : it)) + } + JOptionPane.showMessageDialog(null, "Certificates imported.") + } + + @ControllerAction + void dismiss() { + view.dialog.setVisible(false) + mvcGroup.destroy() + } +} \ 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 39c3fe51..38663961 100644 --- a/gui/griffon-app/controllers/com/muwire/gui/SearchTabController.groovy +++ b/gui/griffon-app/controllers/com/muwire/gui/SearchTabController.groovy @@ -121,4 +121,21 @@ class SearchTabController { mvcGroup.createMVCGroup("show-comment", groupId, params) } + + @ControllerAction + void viewCertificates() { + int[] selectedRows = view.resultsTable.getSelectedRows() + if (selectedRows.length != 1) + return + if (view.lastSortEvent != null) + selectedRows[0] = view.resultsTable.rowSorter.convertRowIndexToModel(selectedRows[0]) + UIResultEvent event = model.results[selectedRows[0]] + if (event.certificates <= 0) + return + + def params = [:] + params['result'] = event + params['eventBus'] = core.eventBus + mvcGroup.createMVCGroup("fetch-certificates", params) + } } \ No newline at end of file diff --git a/gui/griffon-app/models/com/muwire/gui/FetchCertificatesModel.groovy b/gui/griffon-app/models/com/muwire/gui/FetchCertificatesModel.groovy new file mode 100644 index 00000000..bb31cb28 --- /dev/null +++ b/gui/griffon-app/models/com/muwire/gui/FetchCertificatesModel.groovy @@ -0,0 +1,21 @@ +package com.muwire.gui + +import com.muwire.core.filecert.CertificateFetchStatus +import com.muwire.core.search.UIResultEvent + +import griffon.core.artifact.GriffonModel +import griffon.transform.Observable +import griffon.metadata.ArtifactProviderFor + +@ArtifactProviderFor(GriffonModel) +class FetchCertificatesModel { + UIResultEvent result + + @Observable CertificateFetchStatus status + @Observable int totalCertificates + @Observable int certificateCount + + @Observable boolean importActionEnabled + + def certificates = [] +} \ 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 07de3cff..94760a9f 100644 --- a/gui/griffon-app/models/com/muwire/gui/SearchTabModel.groovy +++ b/gui/griffon-app/models/com/muwire/gui/SearchTabModel.groovy @@ -23,6 +23,7 @@ class SearchTabModel { @Observable boolean trustButtonsEnabled @Observable boolean browseActionEnabled @Observable boolean viewCommentActionEnabled + @Observable boolean viewCertificatesActionEnabled 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 index 162ccc71..b1d248b6 100644 --- a/gui/griffon-app/views/com/muwire/gui/BrowseView.groovy +++ b/gui/griffon-app/views/com/muwire/gui/BrowseView.groovy @@ -104,16 +104,16 @@ class BrowseView { } model.downloadActionEnabled = downloadActionEnabled - resultsTable.addMouseListener(new MouseAdapter() { - public void mouseReleased(MouseEvent e) { - if (e.isPopupTrigger()) - showMenu(e) - } - public void mousePressed(MouseEvent e) { - if (e.isPopupTrigger()) - showMenu(e) - } - }) + }) + resultsTable.addMouseListener(new MouseAdapter() { + public void mouseReleased(MouseEvent e) { + if (e.isPopupTrigger()) + showMenu(e) + } + public void mousePressed(MouseEvent e) { + if (e.isPopupTrigger()) + showMenu(e) + } }) } diff --git a/gui/griffon-app/views/com/muwire/gui/FetchCertificatesView.groovy b/gui/griffon-app/views/com/muwire/gui/FetchCertificatesView.groovy new file mode 100644 index 00000000..8f5627e2 --- /dev/null +++ b/gui/griffon-app/views/com/muwire/gui/FetchCertificatesView.groovy @@ -0,0 +1,113 @@ +package com.muwire.gui + +import griffon.core.artifact.GriffonView +import griffon.inject.MVCMember +import griffon.metadata.ArtifactProviderFor + +import javax.swing.JDialog +import javax.swing.JMenuItem +import javax.swing.JPopupMenu +import javax.swing.ListSelectionModel +import javax.swing.SwingConstants + +import com.muwire.core.filecert.Certificate + +import java.awt.BorderLayout +import java.awt.event.MouseAdapter +import java.awt.event.MouseEvent + +import javax.annotation.Nonnull + +@ArtifactProviderFor(GriffonView) +class FetchCertificatesView { + @MVCMember @Nonnull + FactoryBuilderSupport builder + @MVCMember @Nonnull + FetchCertificatesModel model + @MVCMember @Nonnull + FetchCertificatesController controller + + def mainFrame + def dialog + def p + def certsTable + def lastSortEvent + + void initUI() { + mainFrame = application.windowManager.findWindow("main-frame") + dialog = new JDialog(mainFrame, model.result.name, true) + dialog.setResizable(true) + + p = builder.panel { + borderLayout() + panel(constraints : BorderLayout.NORTH) { + label(text : "Status:") + label(text : bind {model.status.toString()}) + label(text : bind {model.certificateCount == 0 ? "" : Math.round(model.certificateCount * 100 / model.totalCertificates)+"%"}) + } + scrollPane(constraints : BorderLayout.CENTER) { + certsTable = table(autoCreateRowSorter : true) { + tableModel(list : model.certificates) { + closureColumn(header : "Issuer", preferredWidth : 200, type : String, read : {it.issuer.getHumanReadableName()}) + closureColumn(header : "Name", preferredWidth : 200, type: String, read : {it.name.toString()}) + closureColumn(header : "Issued", preferredWidth : 100, type : String, read : { + def date = new Date(it.timestamp) + date.toString() + }) + } + } + } + panel(constraints : BorderLayout.SOUTH) { + button(text : "Import", enabled : bind {model.importActionEnabled}, importCertificatesAction) + button(text : "Dismiss", dismissAction) + } + } + + certsTable.rowSorter.addRowSorterListener({evt -> lastSortEvent = evt}) + certsTable.rowSorter.setSortsOnUpdates(true) + + def selectionModel = certsTable.getSelectionModel() + selectionModel.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION) + selectionModel.addListSelectionListener({ + int[] rows = certsTable.getSelectedRows() + model.importActionEnabled = rows.length > 0 + }) + + certsTable.addMouseListener(new MouseAdapter() { + public void mouseReleased(MouseEvent e) { + if (e.isPopupTrigger()) + showMenu(e) + } + public void mousePressed(MouseEvent e) { + if (e.isPopupTrigger()) + showMenu(e) + } + }) + + } + + private void showMenu(MouseEvent e) { + JPopupMenu menu = new JPopupMenu() + JMenuItem importItem = new JMenuItem("Import") + importItem.addActionListener({controller.importCertificates()}) + menu.add(importItem) + menu.showing(e.getComponent(), e.getX(), e.getY()) + } + + def selectedCertificates() { + int [] rows = certsTable.getSelectedRows() + if (rows.length == 0) + return null + if (lastSortEvent != null) { + for(int i = 0; i< rows.length; i++) { + rows[i] = certsTable.rowSorter.convertRowIndexToModel(rows[i]) + } + } + + List rv = new ArrayList<>() + for (Integer i : rows) + rv << model.certificates[i] + rv + } + +} \ 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 ec67dd22..779bfcdc 100644 --- a/gui/griffon-app/views/com/muwire/gui/SearchTabView.groovy +++ b/gui/griffon-app/views/com/muwire/gui/SearchTabView.groovy @@ -103,6 +103,7 @@ class SearchTabView { panel { button(text : "Download", enabled : bind {model.downloadActionEnabled}, downloadAction) button(text : "View Comment", enabled : bind {model.viewCommentActionEnabled}, showCommentAction) + button(text : "View Certificates", enabled : bind {model.viewCertificatesActionEnabled}, viewCertificatesAction) } panel { gridBagLayout() @@ -197,9 +198,11 @@ class SearchTabView { def result = getSelectedResult() if (result == null) { model.viewCommentActionEnabled = false + model.viewCertificatesActionEnabled = false return } else { model.viewCommentActionEnabled = result.comment != null + model.viewCertificatesActionEnabled = result.certificates > 0 } }) @@ -259,6 +262,13 @@ class SearchTabView { showComment.addActionListener({mvcGroup.controller.showComment()}) menu.add(showComment) } + + // view certificates if any + if (model.viewCertificatesActionEnabled) { + JMenuItem viewCerts = new JMenuItem("View Certificates") + viewCerts.addActionListener({mvcGroup.controller.viewCertificates()}) + menu.add(viewCerts) + } } if (showMenu) menu.show(e.getComponent(), e.getX(), e.getY())