From d3bc3b664a4063f67e60f5ca6cc2546332ac000c Mon Sep 17 00:00:00 2001 From: lantzelot-swe Date: Tue, 29 Dec 2020 23:03:46 +0100 Subject: [PATCH] Adds composer to scraper. Various bug fixes in list selection. --- src/main/java/se/lantz/gui/BaseDialog.java | 2 +- src/main/java/se/lantz/gui/ListPanel.java | 5 +- src/main/java/se/lantz/gui/MainPanel.java | 2 +- .../java/se/lantz/gui/ScreenshotsPanel.java | 3 + .../gui/scraper/MobyGamesOptionsPanel.java | 130 ++++++++++++------ .../se/lantz/gui/scraper/ScraperDialog.java | 9 ++ .../se/lantz/gui/scraper/ScraperWorker.java | 5 +- .../java/se/lantz/manager/ScraperManager.java | 4 + .../java/se/lantz/model/MainViewModel.java | 41 ++++-- src/main/java/se/lantz/model/SystemModel.java | 2 + .../se/lantz/model/data/ScraperFields.java | 9 ++ .../se/lantz/scraper/MobyGamesScraper.java | 47 +++++++ 12 files changed, 203 insertions(+), 56 deletions(-) diff --git a/src/main/java/se/lantz/gui/BaseDialog.java b/src/main/java/se/lantz/gui/BaseDialog.java index f9e0a1f..1e686e6 100644 --- a/src/main/java/se/lantz/gui/BaseDialog.java +++ b/src/main/java/se/lantz/gui/BaseDialog.java @@ -95,7 +95,7 @@ public class BaseDialog extends JDialog return buttonPanel; } - protected JButton getOkButton() + public JButton getOkButton() { if (okButton == null) { diff --git a/src/main/java/se/lantz/gui/ListPanel.java b/src/main/java/se/lantz/gui/ListPanel.java index 247ff05..6a19cac 100644 --- a/src/main/java/se/lantz/gui/ListPanel.java +++ b/src/main/java/se/lantz/gui/ListPanel.java @@ -181,8 +181,8 @@ public class ListPanel extends JPanel { indexToSelect = uiModel.getGameListModel().getSize() - 1; } - list.clearSelection(); - list.setSelectedIndex(indexToSelect); + list.setSelectionInterval(indexToSelect, indexToSelect); + updateSelectedGame(); list.ensureIndexIsVisible(indexToSelect); } @@ -350,7 +350,6 @@ public class ListPanel extends JPanel private void updateSelectedGame() { - System.out.println("Update selected Game!!!"); SwingUtilities .invokeLater(() -> mainPanel.getGameDetailsBackgroundPanel().updateSelectedGame(list.getSelectedValue())); } diff --git a/src/main/java/se/lantz/gui/MainPanel.java b/src/main/java/se/lantz/gui/MainPanel.java index cd6cfe9..fe5aff0 100644 --- a/src/main/java/se/lantz/gui/MainPanel.java +++ b/src/main/java/se/lantz/gui/MainPanel.java @@ -117,7 +117,7 @@ public class MainPanel extends JPanel int currentSelectedIndex = getListPanel().getSelectedIndexInList(); uiModel.deleteCurrentGame(); repaintAfterModifications(); - SwingUtilities.invokeLater(() -> getListPanel().setSelectedIndexInList(currentSelectedIndex)); + getListPanel().setSelectedIndexInList(currentSelectedIndex); } } } diff --git a/src/main/java/se/lantz/gui/ScreenshotsPanel.java b/src/main/java/se/lantz/gui/ScreenshotsPanel.java index c69205a..34d3813 100644 --- a/src/main/java/se/lantz/gui/ScreenshotsPanel.java +++ b/src/main/java/se/lantz/gui/ScreenshotsPanel.java @@ -144,6 +144,7 @@ public class ScreenshotsPanel extends JPanel String modelCoverFile = model.getCoverFile(); if (modelCoverFile.isEmpty()) { + currentCoverFile = ""; getCoverImageLabel().setIcon(getMissingCoverImageIcon()); } else if (!modelCoverFile.equals(currentCoverFile)) @@ -170,6 +171,7 @@ public class ScreenshotsPanel extends JPanel String modelScreen1File = model.getScreens1File(); if (modelScreen1File.isEmpty()) { + currentScreen1File = ""; getScreen1ImageLabel().setIcon(getMissingScreenshotImageIcon()); } else if (!model.getScreens1File().equals(currentScreen1File)) @@ -196,6 +198,7 @@ public class ScreenshotsPanel extends JPanel String modelScreen2File = model.getScreens2File(); if (modelScreen2File.isEmpty()) { + currentScreen2File = ""; getScreen2ImageLabel().setIcon(getMissingScreenshotImageIcon()); } else if (!modelScreen2File.equals(currentScreen2File)) diff --git a/src/main/java/se/lantz/gui/scraper/MobyGamesOptionsPanel.java b/src/main/java/se/lantz/gui/scraper/MobyGamesOptionsPanel.java index a2a0d84..b8c9b2d 100644 --- a/src/main/java/se/lantz/gui/scraper/MobyGamesOptionsPanel.java +++ b/src/main/java/se/lantz/gui/scraper/MobyGamesOptionsPanel.java @@ -8,6 +8,8 @@ import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; import java.io.IOException; import java.net.URISyntaxException; @@ -17,11 +19,12 @@ import javax.swing.JEditorPane; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; +import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.event.HyperlinkEvent; +import se.lantz.gui.BaseDialog; import se.lantz.manager.ScraperManager; -import se.lantz.model.MainViewModel; import se.lantz.model.data.ScraperFields; import se.lantz.util.ExceptionHandler; @@ -40,12 +43,12 @@ public class MobyGamesOptionsPanel extends JPanel private ScraperManager scraper; private JButton connectButton; private JLabel connectionStatusLabel; - + private Cursor waitCursor = new Cursor(Cursor.WAIT_CURSOR); private Cursor defaultCursor = new Cursor(Cursor.DEFAULT_CURSOR); private JButton okButton; private JCheckBox genreCheckBox; - + private JCheckBox composerCheckBox; public MobyGamesOptionsPanel(ScraperManager scraper, JButton okButton) { @@ -124,12 +127,23 @@ public class MobyGamesOptionsPanel extends JPanel return infoEditorPane; } - private JTextField getUrlTextField() + JTextField getUrlTextField() { if (urlTextField == null) { urlTextField = new JTextField(); urlTextField.setText("https://www.mobygames.com/game/"); + urlTextField.addKeyListener(new KeyAdapter() + { + @Override + public void keyPressed(KeyEvent e) + { + if (e.getKeyCode() == KeyEvent.VK_ENTER) + { + getConnectButton().doClick(); + } + } + }); } return urlTextField; } @@ -161,11 +175,17 @@ public class MobyGamesOptionsPanel extends JPanel gbc_authorCheckBox.gridx = 0; gbc_authorCheckBox.gridy = 2; fieldsPanel.add(getAuthorCheckBox(), gbc_authorCheckBox); + GridBagConstraints gbc_composerCheckBox = new GridBagConstraints(); + gbc_composerCheckBox.anchor = GridBagConstraints.WEST; + gbc_composerCheckBox.insets = new Insets(0, 0, 5, 5); + gbc_composerCheckBox.gridx = 1; + gbc_composerCheckBox.gridy = 2; + fieldsPanel.add(getComposerCheckBox(), gbc_composerCheckBox); GridBagConstraints gbc_coverCheckBox = new GridBagConstraints(); gbc_coverCheckBox.anchor = GridBagConstraints.WEST; - gbc_coverCheckBox.insets = new Insets(0, 0, 5, 0); + gbc_coverCheckBox.insets = new Insets(0, 0, 5, 5); gbc_coverCheckBox.gridx = 1; - gbc_coverCheckBox.gridy = 2; + gbc_coverCheckBox.gridy = 3; fieldsPanel.add(getCoverCheckBox(), gbc_coverCheckBox); GridBagConstraints gbc_yearCheckBox = new GridBagConstraints(); gbc_yearCheckBox.insets = new Insets(0, 0, 5, 5); @@ -174,22 +194,22 @@ public class MobyGamesOptionsPanel extends JPanel gbc_yearCheckBox.gridy = 3; fieldsPanel.add(getYearCheckBox(), gbc_yearCheckBox); GridBagConstraints gbc_descriptionCheckBox = new GridBagConstraints(); - gbc_descriptionCheckBox.insets = new Insets(0, 0, 5, 0); + gbc_descriptionCheckBox.insets = new Insets(0, 0, 5, 5); gbc_descriptionCheckBox.anchor = GridBagConstraints.WEST; gbc_descriptionCheckBox.gridx = 1; gbc_descriptionCheckBox.gridy = 1; fieldsPanel.add(getDescriptionCheckBox(), gbc_descriptionCheckBox); GridBagConstraints gbc_genreCheckBox = new GridBagConstraints(); - gbc_genreCheckBox.insets = new Insets(0, 0, 5, 5); + gbc_genreCheckBox.insets = new Insets(0, 0, 0, 5); gbc_genreCheckBox.anchor = GridBagConstraints.WEST; gbc_genreCheckBox.gridx = 0; gbc_genreCheckBox.gridy = 4; fieldsPanel.add(getGenreCheckBox(), gbc_genreCheckBox); GridBagConstraints gbc_screensCheckBox = new GridBagConstraints(); - gbc_screensCheckBox.insets = new Insets(0, 0, 5, 0); + gbc_screensCheckBox.insets = new Insets(0, 0, 0, 5); gbc_screensCheckBox.anchor = GridBagConstraints.WEST; gbc_screensCheckBox.gridx = 1; - gbc_screensCheckBox.gridy = 3; + gbc_screensCheckBox.gridy = 4; fieldsPanel.add(getScreensCheckBox(), gbc_screensCheckBox); } return fieldsPanel; @@ -269,7 +289,7 @@ public class MobyGamesOptionsPanel extends JPanel } return screensCheckBox; } - + private void enableCheckBoxes(boolean enable) { titleCheckBox.setEnabled(enable); @@ -279,8 +299,9 @@ public class MobyGamesOptionsPanel extends JPanel coverCheckBox.setEnabled(enable); screensCheckBox.setEnabled(enable); genreCheckBox.setEnabled(enable); + composerCheckBox.setEnabled(enable); } - + public ScraperFields getScraperFields() { ScraperFields returnValue = new ScraperFields(); @@ -291,47 +312,72 @@ public class MobyGamesOptionsPanel extends JPanel returnValue.setDescription(descriptionCheckBox.isSelected()); returnValue.setCover(coverCheckBox.isSelected()); returnValue.setScreenshots(screensCheckBox.isSelected()); + returnValue.setComposer(composerCheckBox.isSelected()); return returnValue; } - private JButton getConnectButton() { - if (connectButton == null) { - connectButton = new JButton("Connect"); - connectButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - try + + JButton getConnectButton() + { + if (connectButton == null) + { + connectButton = new JButton("Connect"); + connectButton.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent e) { - MobyGamesOptionsPanel.this.setCursor(waitCursor); - scraper.connectScraper(urlTextField.getText()); - getConnectionStatusLabel().setText("Connection status: OK"); - enableCheckBoxes(true); - okButton.setEnabled(true); - MobyGamesOptionsPanel.this.setCursor(defaultCursor); + try + { + MobyGamesOptionsPanel.this.setCursor(waitCursor); + scraper.connectScraper(urlTextField.getText()); + getConnectionStatusLabel().setText("Connection status: OK"); + enableCheckBoxes(true); + okButton.setEnabled(true); + MobyGamesOptionsPanel.this.setCursor(defaultCursor); + SwingUtilities.invokeLater(() -> SwingUtilities.getRootPane(connectButton).setDefaultButton(okButton)); + } + catch (Exception e2) + { + getConnectionStatusLabel().setText("Connection status: Error. Invalid URL?"); + enableCheckBoxes(false); + okButton.setEnabled(false); + MobyGamesOptionsPanel.this.setCursor(defaultCursor); + SwingUtilities.invokeLater(() -> SwingUtilities.getRootPane(connectButton).setDefaultButton(connectButton)); + } } - catch (Exception e2) - { - getConnectionStatusLabel().setText("Connection status: Error. Invalid URL?"); - enableCheckBoxes(false); - okButton.setEnabled(false); - MobyGamesOptionsPanel.this.setCursor(defaultCursor); - } - } - }); + }); } return connectButton; } - private JLabel getConnectionStatusLabel() { - if (connectionStatusLabel == null) { - connectionStatusLabel = new JLabel(" "); - connectionStatusLabel.setFont(connectionStatusLabel.getFont().deriveFont(Font.BOLD)); + + private JLabel getConnectionStatusLabel() + { + if (connectionStatusLabel == null) + { + connectionStatusLabel = new JLabel(" "); + connectionStatusLabel.setFont(connectionStatusLabel.getFont().deriveFont(Font.BOLD)); } return connectionStatusLabel; } - private JCheckBox getGenreCheckBox() { - if (genreCheckBox == null) { - genreCheckBox = new JCheckBox("Genre"); - genreCheckBox.setSelected(true); - genreCheckBox.setEnabled(false); + + private JCheckBox getGenreCheckBox() + { + if (genreCheckBox == null) + { + genreCheckBox = new JCheckBox("Genre"); + genreCheckBox.setSelected(true); + genreCheckBox.setEnabled(false); } return genreCheckBox; } + + private JCheckBox getComposerCheckBox() + { + if (composerCheckBox == null) + { + composerCheckBox = new JCheckBox("Composer"); + composerCheckBox.setSelected(true); + composerCheckBox.setEnabled(false); + } + return composerCheckBox; + } } diff --git a/src/main/java/se/lantz/gui/scraper/ScraperDialog.java b/src/main/java/se/lantz/gui/scraper/ScraperDialog.java index 4899d55..b6bf50f 100644 --- a/src/main/java/se/lantz/gui/scraper/ScraperDialog.java +++ b/src/main/java/se/lantz/gui/scraper/ScraperDialog.java @@ -38,4 +38,13 @@ public class ScraperDialog extends BaseDialog { return getMobyGamesPanel().getScraperFields(); } + + @Override + public boolean showDialog() + { + getMobyGamesPanel().getUrlTextField().requestFocusInWindow(); + this.getRootPane().setDefaultButton(getMobyGamesPanel().getConnectButton()); + + return super.showDialog(); + } } diff --git a/src/main/java/se/lantz/gui/scraper/ScraperWorker.java b/src/main/java/se/lantz/gui/scraper/ScraperWorker.java index 6296753..6b623bf 100644 --- a/src/main/java/se/lantz/gui/scraper/ScraperWorker.java +++ b/src/main/java/se/lantz/gui/scraper/ScraperWorker.java @@ -26,7 +26,10 @@ public class ScraperWorker extends SwingWorker { scraperManager.scrapeGameInformation(fields); publish(""); - scraperManager.scrapeScreenshots(); + if (fields.isScreenshots()) + { + scraperManager.scrapeScreenshots(); + } return null; } diff --git a/src/main/java/se/lantz/manager/ScraperManager.java b/src/main/java/se/lantz/manager/ScraperManager.java index f58bac4..4861ce3 100644 --- a/src/main/java/se/lantz/manager/ScraperManager.java +++ b/src/main/java/se/lantz/manager/ScraperManager.java @@ -68,6 +68,10 @@ public class ScraperManager infoModel.setGenre(genre); } } + if (fields.isComposer()) + { + infoModel.setComposer(scraper.getComposer()); + } if (fields.isCover()) { infoModel.setCoverImage(scraper.getCover()); diff --git a/src/main/java/se/lantz/model/MainViewModel.java b/src/main/java/se/lantz/model/MainViewModel.java index a1b3b8c..7f9ec96 100644 --- a/src/main/java/se/lantz/model/MainViewModel.java +++ b/src/main/java/se/lantz/model/MainViewModel.java @@ -67,6 +67,24 @@ public class MainViewModel extends AbstractModel resetDataChangedAfterInit(); } + @Override + public void disableChangeNotification(boolean disable) + { + super.disableChangeNotification(disable); + infoModel.disableChangeNotification(disable); + joy1Model.disableChangeNotification(disable); + joy2Model.disableChangeNotification(disable); + systemModel.disableChangeNotification(disable); + } + + protected void notifyChangeForAllModels() + { + infoModel.notifyChange(); + joy1Model.notifyChange(); + joy2Model.notifyChange(); + systemModel.notifyChange(); + } + private void setupGameViews() { //Setup game views @@ -79,7 +97,7 @@ public class MainViewModel extends AbstractModel favoritesView.setName("Favorites"); favoritesView.setSqlQuery(" WHERE Favorite = 1"); gameViewModel.addElement(favoritesView); - + List gameViewList = dbConnector.loadGameViews(); Collections.sort(gameViewList); for (GameView gameView : gameViewList) @@ -116,6 +134,8 @@ public class MainViewModel extends AbstractModel // Read from db, update all models after that. details = dbConnector.getGameDetails(selectedData.getGameId()); } + disableChangeNotification(true); + // Map to models infoModel.setTitleFromDb(details.getTitle()); @@ -132,20 +152,25 @@ public class MainViewModel extends AbstractModel //Reset and images that where added previously infoModel.resetImages(); - infoModel.resetDataChanged(); - joy1Model.setConfigStringFromDb(details.getJoy1()); - joy1Model.resetDataChanged(); + joy2Model.setConfigStringFromDb(details.getJoy2()); - joy2Model.resetDataChanged(); + systemModel.setConfigStringFromDb(details.getSystem()); systemModel.setVerticalShift(details.getVerticalShift()); - systemModel.resetDataChanged(); + //Set empty title to trigger a change if (selectedData.getGameId().isEmpty()) { infoModel.setTitle(""); } + disableChangeNotification(false); + notifyChangeForAllModels(); + //Do not reset unsaved for new entry + if (!selectedData.getGameId().isEmpty()) + { + resetDataChanged(); + } } public StringBuilder importGameInfo(List rowValues, ImportManager.Options option, boolean addAsFavorite) @@ -426,7 +451,7 @@ public class MainViewModel extends AbstractModel resetDataChanged(); } } - + public void toggleFavorite(GameListData data) { if (data != null && !data.getGameId().isEmpty()) @@ -436,7 +461,7 @@ public class MainViewModel extends AbstractModel gameListModel.notifyChange(); } } - + public void runGameInVice() { fileManager.runGameInVice(); diff --git a/src/main/java/se/lantz/model/SystemModel.java b/src/main/java/se/lantz/model/SystemModel.java index 08119d2..22ffd76 100644 --- a/src/main/java/se/lantz/model/SystemModel.java +++ b/src/main/java/se/lantz/model/SystemModel.java @@ -139,6 +139,7 @@ public class SystemModel extends AbstractModel resetValues(); if (configString == null || configString.isEmpty()) { + disableChangeNotification(false); return; } else @@ -154,6 +155,7 @@ public class SystemModel extends AbstractModel { setC64(true); setPal(true); + setVic(false); setAccurateDisk(false); setDriveIcon(false); setReadOnly(false); diff --git a/src/main/java/se/lantz/model/data/ScraperFields.java b/src/main/java/se/lantz/model/data/ScraperFields.java index cf02cec..772e993 100644 --- a/src/main/java/se/lantz/model/data/ScraperFields.java +++ b/src/main/java/se/lantz/model/data/ScraperFields.java @@ -9,6 +9,7 @@ public class ScraperFields private boolean genre = true; private boolean cover = true; private boolean screenshots = true; + private boolean composer = true; public ScraperFields() { @@ -69,5 +70,13 @@ public class ScraperFields { this.genre = genre; } + public boolean isComposer() + { + return composer; + } + public void setComposer(boolean composer) + { + this.composer = composer; + } } diff --git a/src/main/java/se/lantz/scraper/MobyGamesScraper.java b/src/main/java/se/lantz/scraper/MobyGamesScraper.java index a282a82..0e70461 100644 --- a/src/main/java/se/lantz/scraper/MobyGamesScraper.java +++ b/src/main/java/se/lantz/scraper/MobyGamesScraper.java @@ -16,6 +16,7 @@ import org.jsoup.Connection; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; +import org.jsoup.nodes.Node; import org.jsoup.nodes.TextNode; import org.jsoup.select.Elements; import org.slf4j.Logger; @@ -57,6 +58,8 @@ public class MobyGamesScraper private String scrapedDescription = ""; private String scrapedGenre = ""; + + private String scrapedComposer = ""; private BufferedImage scrapedCover = null; @@ -120,10 +123,15 @@ public class MobyGamesScraper scrapedGenre = genre; } } + if (fields.isComposer()) + { + scrapedComposer = scrapeComposer(doc); + } if (fields.isCover()) { scrapedCover = scrapeCover(doc); } + } catch (IOException e) { @@ -155,6 +163,11 @@ public class MobyGamesScraper { return scrapedGenre; } + + public String getComposer() + { + return scrapedComposer; + } public BufferedImage getCover() { @@ -215,6 +228,40 @@ public class MobyGamesScraper } return value; } + + public String scrapeComposer(Document doc) + { + String value = ""; + //Look for div with music in sidebar + String cssQuery = ".sideBarContent"; + Elements queryElements = doc.select(cssQuery); + Element first = queryElements.first(); + if (first != null) + { + boolean musicFound = false; + for (Node node : first.childNodes()) + { + if (node instanceof TextNode) + { + String test = ((TextNode)node).text(); + //TODO: Add more possible labels + if (test.contains("Music") || test.contains("music")) + { + musicFound = true; + } + } + else if (node instanceof Element && musicFound) + { + value = ((Element)node).text(); + if (!value.isEmpty()) + { + break; + } + } + } + } + return value; + } public BufferedImage scrapeCover(Document doc) {