public class SubtitlePanel extends AbstractSearchPanel<SubtitleProvider, SubtitlePackage> { private LanguageComboBox languageComboBox = new LanguageComboBox(ALL_LANGUAGES, getSettings()); public SubtitlePanel() { historyPanel.setColumnHeader(0, "Search"); historyPanel.setColumnHeader(1, "Number of Subtitles"); // add after text field add(languageComboBox, "gap indent, sgy button", 1); add(createImageButton(setUserAction), "w pref!, h 2+pref!, gap rel, sgy button", 2); // add at the top right corner add(uploadDropTarget, "width 1.45cm!, height 1.2cm!, pos n 0% 100%-1.8cm n", 0); add(downloadDropTarget, "width 1.45cm!, height 1.2cm!, pos n 0% 100%-0.15cm n", 0); } @Subscribe public void handle(Transferable transferable) throws Exception { SubtitleDropTarget target = downloadDropTarget; List<File> files = FileTransferable.getFilesFromTransferable(transferable); if (files != null && files.size() > 0 && target.getDropAction(files) != DropAction.Cancel) { target.handleDrop(files); } } private final SubtitleDropTarget uploadDropTarget = new SubtitleDropTarget.Upload() { @Override public OpenSubtitlesClient getSubtitleService() { return WebServices.OpenSubtitles; }; @Override protected void paintComponent(Graphics g) { Graphics2D g2d = (Graphics2D) g.create(); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); Path2D path = new Path2D.Float(); path.moveTo(0, 0); path.lineTo(0, getHeight() - 1 - 12); path.lineTo(12, getHeight() - 1); path.lineTo(getWidth() - 1 - 12, getHeight() - 1); path.lineTo(getWidth() - 1, getHeight() - 1 - 12); path.lineTo(getWidth() - 1, 0); g2d.setPaint(getBackground()); g2d.fill(path); g2d.setPaint(Color.gray); g2d.draw(path); g2d.translate(2, 0); super.paintComponent(g2d); g2d.dispose(); } }; private final SubtitleDropTarget downloadDropTarget = new SubtitleDropTarget.Download() { @Override public VideoHashSubtitleService[] getVideoHashSubtitleServices() { Locale locale = languageComboBox.getModel().getSelectedItem() == ALL_LANGUAGES ? Locale.ROOT : languageComboBox.getModel().getSelectedItem().getLocale(); return WebServices.getVideoHashSubtitleServices(locale); } @Override public SubtitleProvider[] getSubtitleProviders() { return WebServices.getSubtitleProviders(); } @Override public OpenSubtitlesClient getSubtitleService() { return WebServices.OpenSubtitles; }; @Override public String getQueryLanguage() { // use currently selected language for drop target return languageComboBox.getModel().getSelectedItem() == ALL_LANGUAGES ? null : languageComboBox.getModel().getSelectedItem().getName(); } @Override protected void paintComponent(Graphics g) { Graphics2D g2d = (Graphics2D) g.create(); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); Path2D path = new Path2D.Float(); path.moveTo(0, 0); path.lineTo(0, getHeight() - 1 - 12); path.lineTo(12, getHeight() - 1); path.lineTo(getWidth() - 1 - 12, getHeight() - 1); path.lineTo(getWidth() - 1, getHeight() - 1 - 12); path.lineTo(getWidth() - 1, 0); g2d.setPaint(getBackground()); g2d.fill(path); g2d.setPaint(Color.gray); g2d.draw(path); g2d.translate(2, 0); super.paintComponent(g2d); g2d.dispose(); } }; @Override protected Collection<String> getHistory(SubtitleProvider engine) throws Exception { List<String> names = new ArrayList<String>(); for (SubtitleSearchResult it : MediaDetection.releaseInfo.getOpenSubtitlesIndex()) { names.add(it.toString()); } return names; }; @Override protected SubtitleProvider[] getSearchEngines() { return WebServices.getSubtitleProviders(); } @Override protected LabelProvider<SubtitleProvider> getSearchEngineLabelProvider() { return SimpleLabelProvider.forClass(SubtitleProvider.class); } @Override protected Settings getSettings() { return Settings.forPackage(SubtitlePanel.class); } @Override protected SubtitleRequestProcessor createRequestProcessor() { SubtitleProvider provider = searchTextField.getSelectButton().getSelectedValue(); if (provider instanceof OpenSubtitlesClient && ((OpenSubtitlesClient) provider).isAnonymous() && !Settings.isAppStore()) { log.info( String.format( "%s: Please enter your login details first.", ((OpenSubtitlesClient) provider).getName())); // automatically open login dialog SwingUtilities.invokeLater( () -> setUserAction.actionPerformed(new ActionEvent(searchTextField, 0, "login"))); return null; } // parse query String query = searchTextField.getText(); int season = seasonFilter.match(query); query = seasonFilter.remove(query).trim(); int episode = episodeFilter.match(query); query = episodeFilter.remove(query).trim(); Language language = languageComboBox.getModel().getSelectedItem(); return new SubtitleRequestProcessor( new SubtitleRequest(provider, query, season, episode, language)); } private final QueryFilter<Integer> seasonFilter = new QueryFilter<Integer>("season", s -> s == null ? -1 : Integer.parseInt(s)); private final QueryFilter<Integer> episodeFilter = new QueryFilter<Integer>("episode", s -> s == null ? -1 : Integer.parseInt(s)); protected static class QueryFilter<T> { private final Pattern pattern; private final Function<String, T> parser; public QueryFilter(String key, Function<String, T> parser) { this.pattern = Pattern.compile( "(?:" + key + "):(\\w+)", Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CHARACTER_CLASS); this.parser = parser; } public T match(String s) { Matcher m = pattern.matcher(s); if (m.find()) { return parser.apply(m.group(m.groupCount())); } return parser.apply(null); } public String remove(String s) { return pattern.matcher(s).replaceAll(""); } } protected static class SubtitleRequest extends Request { private final SubtitleProvider provider; private final Language language; private final int season; private final int episode; public SubtitleRequest( SubtitleProvider provider, String searchText, int season, int episode, Language language) { super(searchText); this.season = season; this.episode = episode; this.provider = provider; this.language = language; } public SubtitleProvider getProvider() { return provider; } public String getLanguageName() { return language == ALL_LANGUAGES ? null : language.getName(); } public int[][] getEpisodeFilter() { return season >= 0 && episode >= 0 ? new int[][] {new int[] {season, episode}} : season >= 0 ? new int[][] {new int[] {season, -1}} : null; } } protected static class SubtitleRequestProcessor extends RequestProcessor<SubtitleRequest, SubtitlePackage> { public SubtitleRequestProcessor(SubtitleRequest request) { super(request, new SubtitleDownloadComponent()); } @Override public Collection<SubtitleSearchResult> search() throws Exception { return request.getProvider().search(request.getSearchText()); } @Override public SubtitleSearchResult getSearchResult() { return (SubtitleSearchResult) super.getSearchResult(); } @Override public Collection<SubtitlePackage> fetch() throws Exception { List<SubtitlePackage> packages = new ArrayList<SubtitlePackage>(); for (SubtitleDescriptor subtitle : request .getProvider() .getSubtitleList( getSearchResult(), request.getEpisodeFilter(), request.getLanguageName())) { packages.add(new SubtitlePackage(request.getProvider(), subtitle)); } return packages; } @Override public URI getLink() { return request .getProvider() .getSubtitleListLink(getSearchResult(), request.getLanguageName()); } @Override public void process(Collection<SubtitlePackage> subtitles) { getComponent().setLanguageVisible(request.getLanguageName() == null); getComponent().getPackageModel().addAll(subtitles); } @Override public SubtitleDownloadComponent getComponent() { return (SubtitleDownloadComponent) super.getComponent(); } @Override public String getStatusMessage(Collection<SubtitlePackage> result) { return (result.isEmpty()) ? "No subtitles found" : String.format("%d subtitles", result.size()); } @Override public Icon getIcon() { return request.provider.getIcon(); } @Override protected void configureSelectDialog(SelectDialog<SearchResult> selectDialog) { super.configureSelectDialog(selectDialog); selectDialog.getMessageLabel().setText("Select a Show / Movie:"); } } protected final Action setUserAction = new AbstractAction("Login", ResourceManager.getIcon("action.user")) { @Override public void actionPerformed(ActionEvent evt) { final JDialog authPanel = new JDialog(getWindow(SubtitlePanel.this), ModalityType.APPLICATION_MODAL); authPanel.setTitle("Login"); authPanel.setLocation(getOffsetLocation(authPanel.getOwner())); JPanel osdbGroup = new JPanel(new MigLayout("fill, insets panel")); osdbGroup.setBorder(new TitledBorder("OpenSubtitles")); osdbGroup.add(new JLabel("Username:"******"gap rel"); final JTextField osdbUser = new JTextField(12); osdbGroup.add(osdbUser, "growx, wrap rel"); osdbGroup.add(new JLabel("Password:"******"gap rel"); final JPasswordField osdbPass = new JPasswordField(12); osdbGroup.add(osdbPass, "growx, wrap unrel"); // restore values String[] osdbAuth = WebServices.getLogin(WebServices.LOGIN_OPENSUBTITLES); osdbUser.setText(osdbAuth[0]); // osdbPass.setText(osdbAuth[1]); // password is stored as MD5 hash so we can't restore it if (osdbUser.getText().isEmpty()) { osdbGroup.add( new LinkButton( "Register Account", "Register to increase your download quota", WebServices.OpenSubtitles.getIcon(), URI.create("http://www.opensubtitles.org/en/newuser")), "spanx 2, tag left"); } else { osdbGroup.add( new LinkButton( "Upgrade Account", "Upgrade to increase your download quota", WebServices.OpenSubtitles.getIcon(), URI.create("http://www.opensubtitles.org/en/support")), "spanx 2, tag left"); } JRootPane container = authPanel.getRootPane(); container.setLayout(new MigLayout("fill, insets dialog")); container.removeAll(); container.add(osdbGroup, "growx, wrap"); Action ok = new AbstractAction("OK", ResourceManager.getIcon("dialog.continue")) { @Override public void actionPerformed(ActionEvent evt) { authPanel.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); boolean approved = true; try { if (osdbUser.getText().length() > 0 && osdbPass.getPassword().length > 0) { final OpenSubtitlesClient osdb = new OpenSubtitlesClient(getApplicationName(), getApplicationVersion()); osdb.setUser(osdbUser.getText(), md5(new String(osdbPass.getPassword()))); osdb.login(); // do some status checks in background (since OpenSubtitles can be really // really slow) WebServices.requestThreadPool.submit( () -> { try { // check download quota for the current user Map<?, ?> limits = (Map<?, ?>) osdb.getServerInfo().get("download_limits"); log.log( Level.INFO, String.format( "Your daily download quota is at %s of %s.", limits.get("client_24h_download_count"), limits.get("client_24h_download_limit"))); // logout from test session osdb.logout(); } catch (Exception e) { debug.warning(e.getMessage()); } }); } else if (osdbUser.getText().isEmpty()) { WebServices.setLogin( WebServices.LOGIN_OPENSUBTITLES, null, null); // delete login details } } catch (Exception e) { log.log(Level.WARNING, "OpenSubtitles: " + e.getMessage()); approved = false; } authPanel.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); if (approved) { WebServices.setLogin( WebServices.LOGIN_OPENSUBTITLES, osdbUser.getText(), new String(osdbPass.getPassword())); authPanel.setVisible(false); } } }; Action cancel = new AbstractAction("Cancel", ResourceManager.getIcon("dialog.cancel")) { @Override public void actionPerformed(ActionEvent evt) { authPanel.setVisible(false); } }; container.add(new JButton(cancel), "tag cancel, split 2"); container.add(new JButton(ok), "tag ok"); authPanel.pack(); authPanel.setVisible(true); } }; }
@Override public void actionPerformed(ActionEvent evt) { final JDialog authPanel = new JDialog(getWindow(SubtitlePanel.this), ModalityType.APPLICATION_MODAL); authPanel.setTitle("Login"); authPanel.setLocation(getOffsetLocation(authPanel.getOwner())); JPanel osdbGroup = new JPanel(new MigLayout("fill, insets panel")); osdbGroup.setBorder(new TitledBorder("OpenSubtitles")); osdbGroup.add(new JLabel("Username:"******"gap rel"); final JTextField osdbUser = new JTextField(12); osdbGroup.add(osdbUser, "growx, wrap rel"); osdbGroup.add(new JLabel("Password:"******"gap rel"); final JPasswordField osdbPass = new JPasswordField(12); osdbGroup.add(osdbPass, "growx, wrap unrel"); // restore values String[] osdbAuth = WebServices.getLogin(WebServices.LOGIN_OPENSUBTITLES); osdbUser.setText(osdbAuth[0]); // osdbPass.setText(osdbAuth[1]); // password is stored as MD5 hash so we can't restore it if (osdbUser.getText().isEmpty()) { osdbGroup.add( new LinkButton( "Register Account", "Register to increase your download quota", WebServices.OpenSubtitles.getIcon(), URI.create("http://www.opensubtitles.org/en/newuser")), "spanx 2, tag left"); } else { osdbGroup.add( new LinkButton( "Upgrade Account", "Upgrade to increase your download quota", WebServices.OpenSubtitles.getIcon(), URI.create("http://www.opensubtitles.org/en/support")), "spanx 2, tag left"); } JRootPane container = authPanel.getRootPane(); container.setLayout(new MigLayout("fill, insets dialog")); container.removeAll(); container.add(osdbGroup, "growx, wrap"); Action ok = new AbstractAction("OK", ResourceManager.getIcon("dialog.continue")) { @Override public void actionPerformed(ActionEvent evt) { authPanel.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); boolean approved = true; try { if (osdbUser.getText().length() > 0 && osdbPass.getPassword().length > 0) { final OpenSubtitlesClient osdb = new OpenSubtitlesClient(getApplicationName(), getApplicationVersion()); osdb.setUser(osdbUser.getText(), md5(new String(osdbPass.getPassword()))); osdb.login(); // do some status checks in background (since OpenSubtitles can be really // really slow) WebServices.requestThreadPool.submit( () -> { try { // check download quota for the current user Map<?, ?> limits = (Map<?, ?>) osdb.getServerInfo().get("download_limits"); log.log( Level.INFO, String.format( "Your daily download quota is at %s of %s.", limits.get("client_24h_download_count"), limits.get("client_24h_download_limit"))); // logout from test session osdb.logout(); } catch (Exception e) { debug.warning(e.getMessage()); } }); } else if (osdbUser.getText().isEmpty()) { WebServices.setLogin( WebServices.LOGIN_OPENSUBTITLES, null, null); // delete login details } } catch (Exception e) { log.log(Level.WARNING, "OpenSubtitles: " + e.getMessage()); approved = false; } authPanel.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); if (approved) { WebServices.setLogin( WebServices.LOGIN_OPENSUBTITLES, osdbUser.getText(), new String(osdbPass.getPassword())); authPanel.setVisible(false); } } }; Action cancel = new AbstractAction("Cancel", ResourceManager.getIcon("dialog.cancel")) { @Override public void actionPerformed(ActionEvent evt) { authPanel.setVisible(false); } }; container.add(new JButton(cancel), "tag cancel, split 2"); container.add(new JButton(ok), "tag ok"); authPanel.pack(); authPanel.setVisible(true); }