ImgScroll/src/main/java/com/rarchives/ripme/ui/MainWindow.java

1207 lines
51 KiB
Java
Raw Normal View History

package com.rarchives.ripme.ui;
import java.awt.CheckboxMenuItem;
import java.awt.Color;
import java.awt.Container;
import java.awt.Desktop;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.TrayIcon;
import java.awt.TrayIcon.MessageType;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FilenameFilter;
2014-04-27 19:09:52 +02:00
import java.io.IOException;
2014-03-09 08:59:36 +01:00
import java.net.MalformedURLException;
2014-04-27 19:09:52 +02:00
import java.net.URI;
import java.net.URL;
import java.util.Collections;
2015-01-11 09:23:43 +01:00
import java.util.Date;
2014-04-27 19:09:52 +02:00
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.DefaultListModel;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
2014-04-06 11:41:04 +02:00
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.JTextPane;
2014-03-09 08:59:36 +01:00
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
2014-07-30 16:48:52 +02:00
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.text.BadLocationException;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.FileAppender;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import com.rarchives.ripme.ripper.AbstractRipper;
import com.rarchives.ripme.utils.RipUtils;
import com.rarchives.ripme.utils.Utils;
2014-03-09 09:20:22 +01:00
/**
* Everything UI-related starts and ends here.
*/
public class MainWindow implements Runnable, RipStatusHandler {
private static final Logger logger = Logger.getLogger(MainWindow.class);
2014-03-09 08:59:36 +01:00
2014-07-30 16:48:52 +02:00
private boolean isRipping = false; // Flag to indicate if we're ripping something
private static JFrame mainFrame;
private static JTextField ripTextfield;
2014-04-18 07:11:37 +02:00
private static JButton ripButton,
stopButton;
private static JLabel statusLabel;
private static JButton openButton;
private static JProgressBar statusProgress;
// Log
private static JButton optionLog;
private static JPanel logPanel;
private static JTextPane logText;
private static JScrollPane logTextScroll;
// History
private static JButton optionHistory;
private static final History HISTORY = new History();
private static JPanel historyPanel;
private static JTable historyTable;
private static AbstractTableModel historyTableModel;
private static JScrollPane historyTableScrollPane;
2014-03-09 08:59:36 +01:00
private static JPanel historyButtonPanel;
private static JButton historyButtonRemove,
historyButtonClear,
historyButtonRerip;
2014-07-30 16:48:52 +02:00
// Queue
private static JButton optionQueue;
private static JPanel queuePanel;
private static JList<String> queueList;
private static DefaultListModel<String> queueListModel;
2014-07-30 16:48:52 +02:00
private static JScrollPane queueListScroll;
// Configuration
private static JButton optionConfiguration;
private static JPanel configurationPanel;
private static JButton configUpdateButton;
private static JLabel configUpdateLabel;
private static JTextField configTimeoutText;
private static JTextField configThreadsText;
private static JCheckBox configOverwriteCheckbox;
2014-04-06 11:41:04 +02:00
private static JLabel configSaveDirLabel;
private static JButton configSaveDirButton;
private static JTextField configRetriesText;
private static JCheckBox configAutoupdateCheckbox;
private static JComboBox<String> configLogLevelCombobox;
private static JCheckBox configPlaySound;
private static JCheckBox configSaveOrderCheckbox;
private static JCheckBox configShowPopup;
private static JCheckBox configSaveLogs;
private static JCheckBox configSaveURLsOnly;
private static JCheckBox configSaveAlbumTitles;
private static JCheckBox configClipboardAutorip;
2014-04-06 11:41:04 +02:00
private static TrayIcon trayIcon;
private static MenuItem trayMenuMain;
private static MenuItem trayMenuAbout;
private static MenuItem trayMenuExit;
private static CheckboxMenuItem trayMenuAutorip;
private static Image mainIcon;
2014-04-18 06:43:34 +02:00
private static AbstractRipper ripper;
public MainWindow() {
2014-04-06 12:27:30 +02:00
mainFrame = new JFrame("RipMe v" + UpdateUtils.getThisJarVersion());
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setResizable(false);
mainFrame.setLayout(new GridBagLayout());
createUI(mainFrame.getContentPane());
loadHistory();
setupHandlers();
2014-04-06 11:41:04 +02:00
Thread shutdownThread = new Thread() {
@Override
public void run() {
shutdownCleanup();
2014-04-06 11:41:04 +02:00
}
};
Runtime.getRuntime().addShutdownHook(shutdownThread);
if (Utils.getConfigBoolean("auto.update", true)) {
upgradeProgram();
}
2014-08-01 19:31:23 +02:00
boolean autoripEnabled = Utils.getConfigBoolean("clipboard.autorip", false);
ClipboardUtils.setClipboardAutoRip(autoripEnabled);
trayMenuAutorip.setState(autoripEnabled);
}
public void upgradeProgram() {
if (!configurationPanel.isVisible()) {
optionConfiguration.doClick();
}
Runnable r = new Runnable() {
@Override
public void run() {
UpdateUtils.updateProgram(configUpdateLabel);
}
};
new Thread(r).start();
}
public void run() {
pack();
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible(true);
}
2014-04-06 11:41:04 +02:00
public void shutdownCleanup() {
2014-04-06 11:41:04 +02:00
Utils.setConfigBoolean("file.overwrite", configOverwriteCheckbox.isSelected());
Utils.setConfigInteger("threads.size", Integer.parseInt(configThreadsText.getText()));
Utils.setConfigInteger("download.retries", Integer.parseInt(configRetriesText.getText()));
Utils.setConfigInteger("download.timeout", Integer.parseInt(configTimeoutText.getText()));
Utils.setConfigBoolean("clipboard.autorip", ClipboardUtils.getClipboardAutoRip());
Utils.setConfigBoolean("auto.update", configAutoupdateCheckbox.isSelected());
Utils.setConfigString("log.level", configLogLevelCombobox.getSelectedItem().toString());
Utils.setConfigBoolean("play.sound", configPlaySound.isSelected());
Utils.setConfigBoolean("download.save_order", configSaveOrderCheckbox.isSelected());
Utils.setConfigBoolean("download.show_popup", configShowPopup.isSelected());
Utils.setConfigBoolean("log.save", configSaveLogs.isSelected());
Utils.setConfigBoolean("urls_only.save", configSaveURLsOnly.isSelected());
Utils.setConfigBoolean("album_titles.save", configSaveAlbumTitles.isSelected());
Utils.setConfigBoolean("clipboard.autorip", configClipboardAutorip.isSelected());
saveHistory();
2014-04-06 11:41:04 +02:00
Utils.saveConfig();
}
2014-03-13 20:38:11 +01:00
private void status(String text) {
statusWithColor(text, Color.BLACK);
}
private void error(String text) {
statusWithColor(text, Color.RED);
}
private void statusWithColor(String text, Color color) {
statusLabel.setForeground(color);
statusLabel.setText(text);
pack();
}
private void pack() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
mainFrame.pack();
}
});
}
private void createUI(Container pane) {
setupTrayIcon();
EmptyBorder emptyBorder = new EmptyBorder(5, 5, 5, 5);
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.BOTH;
gbc.weightx = 2; gbc.ipadx = 2; gbc.gridx = 0;
gbc.weighty = 2; gbc.ipady = 2; gbc.gridy = 0;
2014-04-06 06:54:22 +02:00
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
logger.error("[!] Exception setting system theme:", e);
}
ripTextfield = new JTextField("", 20);
ripTextfield.addMouseListener(new ContextMenuMouseListener());
2014-04-18 07:11:37 +02:00
ImageIcon ripIcon = new ImageIcon(mainIcon);
ripButton = new JButton("<html><font size=\"5\"><b>Rip</b></font></html>", ripIcon);
2014-04-18 07:11:37 +02:00
stopButton = new JButton("<html><font size=\"5\"><b>Stop</b></font></html>");
2014-07-30 16:48:52 +02:00
stopButton.setEnabled(false);
2014-04-18 07:11:37 +02:00
try {
Image stopIcon = ImageIO.read(getClass().getClassLoader().getResource("stop.png"));
stopButton.setIcon(new ImageIcon(stopIcon));
} catch (Exception e) { }
JPanel ripPanel = new JPanel(new GridBagLayout());
ripPanel.setBorder(emptyBorder);
gbc.gridx = 0; ripPanel.add(new JLabel("URL:", JLabel.RIGHT), gbc);
gbc.gridx = 1; ripPanel.add(ripTextfield, gbc);
gbc.gridx = 2; ripPanel.add(ripButton, gbc);
2014-07-30 16:48:52 +02:00
gbc.gridx = 3; ripPanel.add(stopButton, gbc);
statusLabel = new JLabel("Inactive");
statusLabel.setHorizontalAlignment(JLabel.CENTER);
openButton = new JButton();
openButton.setVisible(false);
JPanel statusPanel = new JPanel(new GridBagLayout());
statusPanel.setBorder(emptyBorder);
gbc.gridx = 0; statusPanel.add(statusLabel, gbc);
gbc.gridy = 1; statusPanel.add(openButton, gbc);
gbc.gridy = 0;
JPanel progressPanel = new JPanel(new GridBagLayout());
progressPanel.setBorder(emptyBorder);
statusProgress = new JProgressBar(0, 100);
progressPanel.add(statusProgress, gbc);
JPanel optionsPanel = new JPanel(new GridBagLayout());
optionsPanel.setBorder(emptyBorder);
optionLog = new JButton("Log");
optionHistory = new JButton("History");
2014-07-30 16:48:52 +02:00
optionQueue = new JButton("Queue");
optionConfiguration = new JButton("Configuration");
2014-04-18 06:43:34 +02:00
try {
Image icon;
icon = ImageIO.read(getClass().getClassLoader().getResource("comment.png"));
optionLog.setIcon(new ImageIcon(icon));
icon = ImageIO.read(getClass().getClassLoader().getResource("time.png"));
optionHistory.setIcon(new ImageIcon(icon));
2014-07-30 16:48:52 +02:00
icon = ImageIO.read(getClass().getClassLoader().getResource("list.png"));
optionQueue.setIcon(new ImageIcon(icon));
2014-04-18 06:43:34 +02:00
icon = ImageIO.read(getClass().getClassLoader().getResource("gear.png"));
optionConfiguration.setIcon(new ImageIcon(icon));
} catch (Exception e) { }
gbc.gridx = 0; optionsPanel.add(optionLog, gbc);
gbc.gridx = 1; optionsPanel.add(optionHistory, gbc);
2014-07-30 16:48:52 +02:00
gbc.gridx = 2; optionsPanel.add(optionQueue, gbc);
gbc.gridx = 3; optionsPanel.add(optionConfiguration, gbc);
logPanel = new JPanel(new GridBagLayout());
logPanel.setBorder(emptyBorder);
logText = new JTextPaneNoWrap();
logTextScroll = new JScrollPane(logText);
logPanel.setVisible(false);
2014-03-11 09:29:26 +01:00
logPanel.setPreferredSize(new Dimension(300, 250));
logPanel.add(logTextScroll, gbc);
2014-03-08 20:27:30 +01:00
historyPanel = new JPanel(new GridBagLayout());
historyPanel.setBorder(emptyBorder);
historyPanel.setVisible(false);
2014-03-11 09:29:26 +01:00
historyPanel.setPreferredSize(new Dimension(300, 250));
historyTableModel = new AbstractTableModel() {
private static final long serialVersionUID = 1L;
@Override
public String getColumnName(int col) {
return HISTORY.getColumnName(col);
}
public Class<? extends Object> getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
@Override
public Object getValueAt(int row, int col) {
return HISTORY.getValueAt(row, col);
}
@Override
public int getRowCount() {
return HISTORY.toList().size();
}
@Override
public int getColumnCount() {
return HISTORY.getColumnCount();
}
@Override
public boolean isCellEditable(int row, int col) {
return (col == 0 || col == 4);
}
@Override
public void setValueAt(Object value, int row, int col) {
if (col == 4) {
HISTORY.get(row).selected = (Boolean) value;
historyTableModel.fireTableDataChanged();
}
}
};
historyTable = new JTable(historyTableModel);
historyTable.addMouseListener(new HistoryMenuMouseListener());
historyTable.setAutoCreateRowSorter(true);
for (int i = 0; i < historyTable.getColumnModel().getColumnCount(); i++) {
int width = 130; // Default
switch (i) {
case 0: // URL
width = 270;
break;
case 3:
width = 40;
break;
case 4:
width = 15;
break;
}
historyTable.getColumnModel().getColumn(i).setPreferredWidth(width);
}
historyTableScrollPane = new JScrollPane(historyTable);
historyButtonRemove = new JButton("Remove");
historyButtonClear = new JButton("Clear");
historyButtonRerip = new JButton("Re-rip Checked");
gbc.gridx = 0;
// History List Panel
JPanel historyTablePanel = new JPanel(new GridBagLayout());
historyTablePanel.add(historyTableScrollPane, gbc);
2014-07-30 16:48:52 +02:00
gbc.ipady = 180;
historyPanel.add(historyTablePanel, gbc);
gbc.ipady = 0;
2014-03-09 08:59:36 +01:00
historyButtonPanel = new JPanel(new GridBagLayout());
2014-03-11 09:29:26 +01:00
historyButtonPanel.setPreferredSize(new Dimension(300, 10));
historyButtonPanel.setBorder(emptyBorder);
gbc.gridx = 0; historyButtonPanel.add(historyButtonRemove, gbc);
gbc.gridx = 1; historyButtonPanel.add(historyButtonClear, gbc);
gbc.gridx = 2; historyButtonPanel.add(historyButtonRerip, gbc);
gbc.gridy = 1; gbc.gridx = 0;
historyPanel.add(historyButtonPanel, gbc);
2014-07-30 16:48:52 +02:00
queuePanel = new JPanel(new GridBagLayout());
queuePanel.setBorder(emptyBorder);
queuePanel.setVisible(false);
queuePanel.setPreferredSize(new Dimension(300, 250));
queueListModel = new DefaultListModel<String>();
queueList = new JList<String>(queueListModel);
2014-07-30 16:48:52 +02:00
queueList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
queueListScroll = new JScrollPane(queueList,
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
gbc.gridx = 0;
JPanel queueListPanel = new JPanel(new GridBagLayout());
queueListPanel.add(queueListScroll, gbc);
queuePanel.add(queueListPanel, gbc);
gbc.ipady = 0;
configurationPanel = new JPanel(new GridBagLayout());
configurationPanel.setBorder(emptyBorder);
configurationPanel.setVisible(false);
2014-03-11 09:29:26 +01:00
configurationPanel.setPreferredSize(new Dimension(300, 250));
// TODO Configuration components
configUpdateButton = new JButton("Check for updates");
configUpdateLabel = new JLabel("Current version: " + UpdateUtils.getThisJarVersion(), JLabel.RIGHT);
JLabel configThreadsLabel = new JLabel("Maximum download threads:", JLabel.RIGHT);
2014-04-06 11:41:04 +02:00
JLabel configTimeoutLabel = new JLabel("Timeout (in milliseconds):", JLabel.RIGHT);
JLabel configRetriesLabel = new JLabel("Retry download count:", JLabel.RIGHT);
configThreadsText = new JTextField(Integer.toString(Utils.getConfigInteger("threads.size", 3)));
2014-04-06 11:41:04 +02:00
configTimeoutText = new JTextField(Integer.toString(Utils.getConfigInteger("download.timeout", 60000)));
configRetriesText = new JTextField(Integer.toString(Utils.getConfigInteger("download.retries", 3)));
configOverwriteCheckbox = new JCheckBox("Overwrite existing files?", Utils.getConfigBoolean("file.overwrite", false));
configOverwriteCheckbox.setHorizontalAlignment(JCheckBox.RIGHT);
configOverwriteCheckbox.setHorizontalTextPosition(JCheckBox.LEFT);
configAutoupdateCheckbox = new JCheckBox("Auto-update?", Utils.getConfigBoolean("auto.update", true));
configAutoupdateCheckbox.setHorizontalAlignment(JCheckBox.RIGHT);
configAutoupdateCheckbox.setHorizontalTextPosition(JCheckBox.LEFT);
configLogLevelCombobox = new JComboBox<String>(new String[] {"Log level: Error", "Log level: Warn", "Log level: Info", "Log level: Debug"});
configLogLevelCombobox.setSelectedItem(Utils.getConfigString("log.level", "Log level: Debug"));
setLogLevel(configLogLevelCombobox.getSelectedItem().toString());
configPlaySound = new JCheckBox("Sound when rip completes", Utils.getConfigBoolean("play.sound", false));
configPlaySound.setHorizontalAlignment(JCheckBox.RIGHT);
configPlaySound.setHorizontalTextPosition(JCheckBox.LEFT);
configSaveOrderCheckbox = new JCheckBox("Preserve order", Utils.getConfigBoolean("download.save_order", true));
configSaveOrderCheckbox.setHorizontalAlignment(JCheckBox.RIGHT);
configSaveOrderCheckbox.setHorizontalTextPosition(JCheckBox.LEFT);
configShowPopup = new JCheckBox("Notification when rip starts", Utils.getConfigBoolean("download.show_popup", false));
configShowPopup.setHorizontalAlignment(JCheckBox.RIGHT);
configShowPopup.setHorizontalTextPosition(JCheckBox.LEFT);
configSaveLogs = new JCheckBox("Save logs", Utils.getConfigBoolean("log.save", false));
configSaveLogs.setHorizontalAlignment(JCheckBox.RIGHT);
configSaveLogs.setHorizontalTextPosition(JCheckBox.LEFT);
configSaveURLsOnly = new JCheckBox("Save URLs only", Utils.getConfigBoolean("urls_only.save", false));
configSaveURLsOnly.setHorizontalAlignment(JCheckBox.RIGHT);
configSaveURLsOnly.setHorizontalTextPosition(JCheckBox.LEFT);
configSaveAlbumTitles = new JCheckBox("Save album titles", Utils.getConfigBoolean("album_titles.save", true));
configSaveAlbumTitles.setHorizontalAlignment(JCheckBox.RIGHT);
configSaveAlbumTitles.setHorizontalTextPosition(JCheckBox.LEFT);
configClipboardAutorip = new JCheckBox("Autorip from Clipboard", Utils.getConfigBoolean("clipboard.autorip", false));
configClipboardAutorip.setHorizontalAlignment(JCheckBox.RIGHT);
configClipboardAutorip.setHorizontalTextPosition(JCheckBox.LEFT);
2014-04-06 11:41:04 +02:00
configSaveDirLabel = new JLabel();
try {
String workingDir = (Utils.shortenPath(Utils.getWorkingDirectory()));
configSaveDirLabel.setText(workingDir);
} catch (Exception e) { }
configSaveDirLabel.setToolTipText(configSaveDirLabel.getText());
configSaveDirLabel.setHorizontalAlignment(JLabel.RIGHT);
2014-07-30 16:48:52 +02:00
configSaveDirButton = new JButton("Select Save Directory...");
gbc.gridy = 0; gbc.gridx = 0; configurationPanel.add(configUpdateLabel, gbc);
gbc.gridx = 1; configurationPanel.add(configUpdateButton, gbc);
gbc.gridy = 1; gbc.gridx = 0; configurationPanel.add(configAutoupdateCheckbox, gbc);
gbc.gridx = 1; configurationPanel.add(configLogLevelCombobox, gbc);
gbc.gridy = 2; gbc.gridx = 0; configurationPanel.add(configThreadsLabel, gbc);
gbc.gridx = 1; configurationPanel.add(configThreadsText, gbc);
gbc.gridy = 3; gbc.gridx = 0; configurationPanel.add(configTimeoutLabel, gbc);
2014-04-06 11:41:04 +02:00
gbc.gridx = 1; configurationPanel.add(configTimeoutText, gbc);
gbc.gridy = 4; gbc.gridx = 0; configurationPanel.add(configRetriesLabel, gbc);
2014-04-06 11:41:04 +02:00
gbc.gridx = 1; configurationPanel.add(configRetriesText, gbc);
gbc.gridy = 5; gbc.gridx = 0; configurationPanel.add(configOverwriteCheckbox, gbc);
gbc.gridx = 1; configurationPanel.add(configSaveOrderCheckbox, gbc);
gbc.gridy = 6; gbc.gridx = 0; configurationPanel.add(configPlaySound, gbc);
gbc.gridx = 1; configurationPanel.add(configSaveLogs, gbc);
gbc.gridy = 7; gbc.gridx = 0; configurationPanel.add(configShowPopup, gbc);
gbc.gridx = 1; configurationPanel.add(configSaveURLsOnly, gbc);
gbc.gridy = 8; gbc.gridx = 0; configurationPanel.add(configClipboardAutorip, gbc);
gbc.gridx = 1; configurationPanel.add(configSaveAlbumTitles, gbc);
gbc.gridy = 9; gbc.gridx = 0; configurationPanel.add(configSaveDirLabel, gbc);
2014-04-06 11:41:04 +02:00
gbc.gridx = 1; configurationPanel.add(configSaveDirButton, gbc);
gbc.gridy = 0; pane.add(ripPanel, gbc);
gbc.gridy = 1; pane.add(statusPanel, gbc);
gbc.gridy = 2; pane.add(progressPanel, gbc);
gbc.gridy = 3; pane.add(optionsPanel, gbc);
gbc.gridy = 4; pane.add(logPanel, gbc);
gbc.gridy = 5; pane.add(historyPanel, gbc);
2014-07-30 16:48:52 +02:00
gbc.gridy = 5; pane.add(queuePanel, gbc);
gbc.gridy = 5; pane.add(configurationPanel, gbc);
}
private void setupHandlers() {
ripButton.addActionListener(new RipButtonHandler());
ripTextfield.addActionListener(new RipButtonHandler());
ripTextfield.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void removeUpdate(DocumentEvent e) {
update();
}
@Override
public void insertUpdate(DocumentEvent e) {
update();
}
@Override
public void changedUpdate(DocumentEvent e) {
update();
}
private void update() {
try {
String urlText = ripTextfield.getText().trim();
if (urlText.equals("")) {
return;
}
2014-06-12 08:01:16 +02:00
if (!urlText.startsWith("http")) {
urlText = "http://" + urlText;
}
URL url = new URL(urlText);
AbstractRipper ripper = AbstractRipper.getRipper(url);
statusWithColor(ripper.getHost() + " album detected", Color.GREEN);
} catch (Exception e) {
statusWithColor("Can't rip this URL: "+e.getMessage(), Color.RED);
}
}
});
2014-04-18 07:11:37 +02:00
stopButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
if (ripper != null) {
ripper.stop();
isRipping = false;
2014-07-30 16:48:52 +02:00
stopButton.setEnabled(false);
2014-04-18 07:11:37 +02:00
statusProgress.setValue(0);
statusProgress.setVisible(false);
pack();
2014-04-18 07:11:37 +02:00
statusProgress.setValue(0);
status("Ripping interrupted");
appendLog("Ripper interrupted", Color.RED);
}
}
});
optionLog.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
logPanel.setVisible(!logPanel.isVisible());
historyPanel.setVisible(false);
2014-07-30 16:48:52 +02:00
queuePanel.setVisible(false);
configurationPanel.setVisible(false);
optionLog.setFont(optionLog.getFont().deriveFont(Font.BOLD));
optionHistory.setFont(optionLog.getFont().deriveFont(Font.PLAIN));
2014-07-30 16:48:52 +02:00
optionQueue.setFont(optionLog.getFont().deriveFont(Font.PLAIN));
optionConfiguration.setFont(optionLog.getFont().deriveFont(Font.PLAIN));
pack();
}
});
optionHistory.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
logPanel.setVisible(false);
historyPanel.setVisible(!historyPanel.isVisible());
2014-07-30 16:48:52 +02:00
queuePanel.setVisible(false);
configurationPanel.setVisible(false);
optionLog.setFont(optionLog.getFont().deriveFont(Font.PLAIN));
optionHistory.setFont(optionLog.getFont().deriveFont(Font.BOLD));
2014-07-30 16:48:52 +02:00
optionQueue.setFont(optionLog.getFont().deriveFont(Font.PLAIN));
optionConfiguration.setFont(optionLog.getFont().deriveFont(Font.PLAIN));
pack();
}
});
optionQueue.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
logPanel.setVisible(false);
historyPanel.setVisible(false);
queuePanel.setVisible(!queuePanel.isVisible());
configurationPanel.setVisible(false);
optionLog.setFont(optionLog.getFont().deriveFont(Font.PLAIN));
optionHistory.setFont(optionLog.getFont().deriveFont(Font.PLAIN));
optionQueue.setFont(optionLog.getFont().deriveFont(Font.BOLD));
optionConfiguration.setFont(optionLog.getFont().deriveFont(Font.PLAIN));
pack();
}
});
optionConfiguration.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
logPanel.setVisible(false);
historyPanel.setVisible(false);
2014-07-30 16:48:52 +02:00
queuePanel.setVisible(false);
configurationPanel.setVisible(!configurationPanel.isVisible());
optionLog.setFont(optionLog.getFont().deriveFont(Font.PLAIN));
optionHistory.setFont(optionLog.getFont().deriveFont(Font.PLAIN));
2014-07-30 16:48:52 +02:00
optionQueue.setFont(optionLog.getFont().deriveFont(Font.PLAIN));
optionConfiguration.setFont(optionLog.getFont().deriveFont(Font.BOLD));
pack();
}
});
2014-03-09 08:59:36 +01:00
historyButtonRemove.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
int[] indices = historyTable.getSelectedRows();
2014-03-09 08:59:36 +01:00
for (int i = indices.length - 1; i >= 0; i--) {
int modelIndex = historyTable.convertRowIndexToModel(indices[i]);
HISTORY.remove(modelIndex);
2014-03-09 08:59:36 +01:00
}
try {
historyTableModel.fireTableDataChanged();
} catch (Exception e) { }
2014-03-09 08:59:36 +01:00
saveHistory();
}
});
historyButtonClear.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
HISTORY.clear();
try {
historyTableModel.fireTableDataChanged();
} catch (Exception e) { }
2014-03-09 08:59:36 +01:00
saveHistory();
}
});
// Re-rip all history
historyButtonRerip.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
if (HISTORY.toList().size() == 0) {
JOptionPane.showMessageDialog(null,
"There are no history entries to re-rip. Rip some albums first",
"RipMe Error",
JOptionPane.ERROR_MESSAGE);
return;
}
int added = 0;
for (HistoryEntry entry : HISTORY.toList()) {
if (entry.selected) {
added++;
queueListModel.addElement(entry.url);
}
}
if (added == 0) {
JOptionPane.showMessageDialog(null,
"No history entries have been 'Checked'\n" +
"Check an entry by clicking the checkbox to the right of the URL or Right-click a URL to check/uncheck all items",
"RipMe Error",
JOptionPane.ERROR_MESSAGE);
return;
}
2014-03-09 08:59:36 +01:00
}
});
configUpdateButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
Thread t = new Thread() {
@Override
public void run() {
UpdateUtils.updateProgram(configUpdateLabel);
}
};
t.start();
}
});
configLogLevelCombobox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
String level = ((JComboBox<?>) arg0.getSource()).getSelectedItem().toString();
setLogLevel(level);
}
});
2014-04-06 11:41:04 +02:00
configSaveDirButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
JFileChooser jfc = new JFileChooser(Utils.getWorkingDirectory());
jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int returnVal = jfc.showDialog(null, "select directory");
if (returnVal != JFileChooser.APPROVE_OPTION) {
return;
}
File chosenFile = jfc.getSelectedFile();
String chosenPath = null;
try {
chosenPath = chosenFile.getCanonicalPath();
} catch (Exception e) {
logger.error("Error while getting selected path: ", e);
return;
}
configSaveDirLabel.setText(Utils.shortenPath(chosenPath));
Utils.setConfigString("rips.directory", chosenPath);
}
2014-05-26 05:10:49 +02:00
});
configOverwriteCheckbox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
Utils.setConfigBoolean("file.overwrite", configOverwriteCheckbox.isSelected());
}
2014-04-06 11:41:04 +02:00
});
configSaveOrderCheckbox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
Utils.setConfigBoolean("download.save_order", configSaveOrderCheckbox.isSelected());
}
});
configSaveLogs.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
Utils.setConfigBoolean("log.save", configSaveLogs.isSelected());
Utils.configureLogger();
}
});
configSaveURLsOnly.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
Utils.setConfigBoolean("urls_only.save", configSaveURLsOnly.isSelected());
Utils.configureLogger();
}
});
configSaveAlbumTitles.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
Utils.setConfigBoolean("album_titles.save", configSaveAlbumTitles.isSelected());
Utils.configureLogger();
}
});
configClipboardAutorip.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
Utils.setConfigBoolean("clipboard.autorip", configClipboardAutorip.isSelected());
ClipboardUtils.setClipboardAutoRip(configClipboardAutorip.isSelected());
trayMenuAutorip.setState(configClipboardAutorip.isSelected());
Utils.configureLogger();
}
});
2014-07-30 16:48:52 +02:00
queueListModel.addListDataListener(new ListDataListener() {
@Override
public void intervalAdded(ListDataEvent arg0) {
if (queueListModel.size() > 0) {
optionQueue.setText("Queue (" + queueListModel.size() + ")");
} else {
optionQueue.setText("Queue");
}
if (!isRipping) {
ripNextAlbum();
}
}
@Override
public void contentsChanged(ListDataEvent arg0) { }
@Override
public void intervalRemoved(ListDataEvent arg0) { }
});
}
private void setLogLevel(String level) {
Level newLevel = Level.ERROR;
level = level.substring(level.lastIndexOf(' ') + 1);
if (level.equals("Debug")) {
newLevel = Level.DEBUG;
}
else if (level.equals("Info")) {
newLevel = Level.INFO;
}
else if (level.equals("Warn")) {
newLevel = Level.WARN;
}
else if (level.equals("Error")) {
newLevel = Level.ERROR;
}
Logger.getRootLogger().setLevel(newLevel);
logger.setLevel(newLevel);
2015-02-20 16:36:12 +01:00
ConsoleAppender ca = (ConsoleAppender)Logger.getRootLogger().getAppender("stdout");
if (ca != null) {
ca.setThreshold(newLevel);
}
FileAppender fa = (FileAppender)Logger.getRootLogger().getAppender("FILE");
if (fa != null) {
fa.setThreshold(newLevel);
}
}
private void setupTrayIcon() {
mainFrame.addWindowListener(new WindowAdapter() {
public void windowActivated(WindowEvent e) { trayMenuMain.setLabel("Hide"); }
public void windowDeactivated(WindowEvent e) { trayMenuMain.setLabel("Show"); }
public void windowDeiconified(WindowEvent e) { trayMenuMain.setLabel("Hide"); }
public void windowIconified(WindowEvent e) { trayMenuMain.setLabel("Show"); }
});
PopupMenu trayMenu = new PopupMenu();
trayMenuMain = new MenuItem("Hide");
trayMenuMain.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
toggleTrayClick();
}
});
trayMenuAbout = new MenuItem("About " + mainFrame.getTitle());
trayMenuAbout.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
2014-04-27 19:09:52 +02:00
StringBuilder about = new StringBuilder();
about.append("<html><h1>")
.append(mainFrame.getTitle())
.append("</h1>");
about.append("Download albums from various websites:");
try {
List<String> rippers = Utils.getListOfAlbumRippers();
about.append("<ul>");
for (String ripper : rippers) {
about.append("<li>");
ripper = ripper.substring(ripper.lastIndexOf('.') + 1);
if (ripper.contains("Ripper")) {
ripper = ripper.substring(0, ripper.indexOf("Ripper"));
}
about.append(ripper);
about.append("</li>");
}
about.append("</ul>");
} catch (Exception e) { }
about.append("<br>And download videos from video sites:");
try {
List<String> rippers = Utils.getListOfVideoRippers();
about.append("<ul>");
for (String ripper : rippers) {
about.append("<li>");
ripper = ripper.substring(ripper.lastIndexOf('.') + 1);
if (ripper.contains("Ripper")) {
ripper = ripper.substring(0, ripper.indexOf("Ripper"));
}
about.append(ripper);
about.append("</li>");
}
about.append("</ul>");
} catch (Exception e) { }
about.append("Do you want to visit the project homepage on Github?");
about.append("</html>");
int response = JOptionPane.showConfirmDialog(null,
about.toString(),
mainFrame.getTitle(),
2014-04-27 19:09:52 +02:00
JOptionPane.YES_NO_OPTION,
JOptionPane.PLAIN_MESSAGE,
new ImageIcon(mainIcon));
2014-04-27 19:09:52 +02:00
if (response == JOptionPane.YES_OPTION) {
try {
Desktop.getDesktop().browse(URI.create("http://github.com/4pr0n/ripme"));
} catch (IOException e) {
logger.error("Exception while opening project home page", e);
}
}
}
});
trayMenuExit = new MenuItem("Exit");
trayMenuExit.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
System.exit(0);
}
});
trayMenuAutorip = new CheckboxMenuItem("Clipboard Autorip");
trayMenuAutorip.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent arg0) {
ClipboardUtils.setClipboardAutoRip(trayMenuAutorip.getState());
configClipboardAutorip.setSelected(trayMenuAutorip.getState());
}
});
trayMenu.add(trayMenuMain);
trayMenu.add(trayMenuAbout);
trayMenu.addSeparator();
trayMenu.add(trayMenuAutorip);
trayMenu.addSeparator();
trayMenu.add(trayMenuExit);
try {
mainIcon = ImageIO.read(getClass().getClassLoader().getResource("icon.png"));
trayIcon = new TrayIcon(mainIcon);
trayIcon.setToolTip(mainFrame.getTitle());
trayIcon.setImageAutoSize(true);
trayIcon.setPopupMenu(trayMenu);
SystemTray.getSystemTray().add(trayIcon);
trayIcon.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
toggleTrayClick();
if (mainFrame.getExtendedState() != JFrame.NORMAL) {
mainFrame.setExtendedState(JFrame.NORMAL);
}
mainFrame.setAlwaysOnTop(true);
mainFrame.setAlwaysOnTop(false);
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
private void toggleTrayClick() {
if (mainFrame.getExtendedState() == JFrame.ICONIFIED
|| !mainFrame.isActive()
|| !mainFrame.isVisible()) {
mainFrame.setVisible(true);
mainFrame.setAlwaysOnTop(true);
mainFrame.setAlwaysOnTop(false);
trayMenuMain.setLabel("Hide");
}
else {
mainFrame.setVisible(false);
trayMenuMain.setLabel("Show");
}
}
private void appendLog(final String text, final Color color) {
SimpleAttributeSet sas = new SimpleAttributeSet();
StyleConstants.setForeground(sas, color);
StyledDocument sd = logText.getStyledDocument();
try {
synchronized (this) {
sd.insertString(sd.getLength(), text + "\n", sas);
}
} catch (BadLocationException e) { }
logText.setCaretPosition(sd.getLength());
}
private void loadHistory() {
2014-07-30 16:48:52 +02:00
File historyFile = new File("history.json");
HISTORY.clear();
2014-07-30 16:48:52 +02:00
if (historyFile.exists()) {
try {
logger.info("Loading history from history.json");
HISTORY.fromFile("history.json");
2014-07-30 16:48:52 +02:00
} catch (IOException e) {
logger.error("Failed to load history from file " + historyFile, e);
JOptionPane.showMessageDialog(null,
"RipMe failed to load the history file at " + historyFile.getAbsolutePath() + "\n\n" +
"Error: " + e.getMessage() + "\n\n" +
"Closing RipMe will automatically overwrite the contents of this file,\n" +
"so you may want to back the file up before closing RipMe!",
"RipMe - history load failure",
JOptionPane.ERROR_MESSAGE);
2014-07-30 16:48:52 +02:00
}
}
else {
logger.info("Loading history from configuration");
HISTORY.fromList(Utils.getConfigList("download.history"));
if (HISTORY.toList().size() == 0) {
// Loaded from config, still no entries.
// Guess rip history based on rip folder
String[] dirs = Utils.getWorkingDirectory().list(new FilenameFilter() {
@Override
public boolean accept(File dir, String file) {
return new File(dir.getAbsolutePath() + File.separator + file).isDirectory();
}
});
for (String dir : dirs) {
String url = RipUtils.urlFromDirectoryName(dir);
if (url != null) {
// We found one, add it to history
HistoryEntry entry = new HistoryEntry();
entry.url = url;
HISTORY.add(entry);
}
}
}
}
}
private void saveHistory() {
2014-07-30 16:48:52 +02:00
try {
HISTORY.toFile("history.json");
Utils.setConfigList("download.history", Collections.emptyList());
2014-07-30 16:48:52 +02:00
} catch (IOException e) {
logger.error("Failed to save history to file history.json", e);
}
}
private void ripNextAlbum() {
isRipping = true;
if (queueListModel.size() == 0) {
// End of queue
isRipping = false;
return;
}
String nextAlbum = (String) queueListModel.remove(0);
if (queueListModel.size() == 0) {
optionQueue.setText("Queue");
}
else {
optionQueue.setText("Queue (" + queueListModel.size() + ")");
}
Thread t = ripAlbum(nextAlbum);
if (t == null) {
try {
Thread.sleep(500);
} catch (InterruptedException ie) {
logger.error("Interrupted while waiting to rip next album", ie);
}
ripNextAlbum();
}
else {
t.start();
}
}
2014-03-09 08:59:36 +01:00
private Thread ripAlbum(String urlString) {
//shutdownCleanup();
if (!logPanel.isVisible()) {
optionLog.doClick();
}
urlString = urlString.trim();
if (urlString.toLowerCase().startsWith("gonewild:")) {
urlString = "http://gonewild.com/user/" + urlString.substring(urlString.indexOf(':') + 1);
}
if (!urlString.startsWith("http")) {
urlString = "http://" + urlString;
}
2014-03-09 08:59:36 +01:00
URL url = null;
try {
url = new URL(urlString);
} catch (MalformedURLException e) {
logger.error("[!] Could not generate URL for '" + urlString + "'", e);
error("Given URL is not valid, expecting http://website.com/page/...");
2014-03-09 08:59:36 +01:00
return null;
}
2014-07-30 16:48:52 +02:00
stopButton.setEnabled(true);
2014-03-09 08:59:36 +01:00
statusProgress.setValue(100);
openButton.setVisible(false);
statusLabel.setVisible(true);
pack();
boolean failed = false;
2014-03-09 08:59:36 +01:00
try {
ripper = AbstractRipper.getRipper(url);
ripper.setup();
2014-03-09 08:59:36 +01:00
} catch (Exception e) {
failed = true;
logger.error("Could not find ripper for URL " + url, e);
2014-07-30 16:48:52 +02:00
error(e.getMessage());
}
if (!failed) {
try {
mainFrame.setTitle("Ripping - RipMe v" + UpdateUtils.getThisJarVersion());
status("Starting rip...");
ripper.setObserver((RipStatusHandler) this);
Thread t = new Thread(ripper);
if (configShowPopup.isSelected() &&
(!mainFrame.isVisible() || !mainFrame.isActive())) {
mainFrame.toFront();
mainFrame.setAlwaysOnTop(true);
trayIcon.displayMessage(mainFrame.getTitle(), "Started ripping " + ripper.getURL().toExternalForm(), MessageType.INFO);
mainFrame.setAlwaysOnTop(false);
}
return t;
} catch (Exception e) {
logger.error("[!] Error while ripping: " + e.getMessage(), e);
error("Unable to rip this URL: " + e.getMessage());
}
2014-03-09 08:59:36 +01:00
}
2014-07-30 16:48:52 +02:00
stopButton.setEnabled(false);
statusProgress.setValue(0);
pack();
return null;
2014-03-09 08:59:36 +01:00
}
class RipButtonHandler implements ActionListener {
public void actionPerformed(ActionEvent event) {
2014-07-30 16:48:52 +02:00
if (!queueListModel.contains(ripTextfield.getText())) {
queueListModel.add(queueListModel.size(), ripTextfield.getText());
ripTextfield.setText("");
}
else {
if (!isRipping) {
ripNextAlbum();
}
}
}
}
private class StatusEvent implements Runnable {
private final AbstractRipper ripper;
private final RipStatusMessage msg;
public StatusEvent(AbstractRipper ripper, RipStatusMessage msg) {
this.ripper = ripper;
this.msg = msg;
}
public void run() {
handleEvent(this);
}
}
private synchronized void handleEvent(StatusEvent evt) {
2014-04-18 07:11:37 +02:00
if (ripper.isStopped()) {
return;
}
RipStatusMessage msg = evt.msg;
int completedPercent = evt.ripper.getCompletionPercentage();
statusProgress.setValue(completedPercent);
2014-04-20 09:12:48 +02:00
statusProgress.setVisible(true);
status( evt.ripper.getStatusText() );
switch(msg.getStatus()) {
case LOADING_RESOURCE:
case DOWNLOAD_STARTED:
if (logger.isEnabledFor(Level.INFO)) {
appendLog( "Downloading " + (String) msg.getObject(), Color.BLACK);
}
break;
case DOWNLOAD_COMPLETE:
appendLog( "Downloaded " + (String) msg.getObject(), Color.GREEN);
break;
case DOWNLOAD_ERRORED:
if (logger.isEnabledFor(Level.ERROR)) {
appendLog((String) msg.getObject(), Color.RED);
}
break;
case DOWNLOAD_WARN:
appendLog((String) msg.getObject(), Color.ORANGE);
break;
case RIP_ERRORED:
if (logger.isEnabledFor(Level.ERROR)) {
appendLog((String) msg.getObject(), Color.RED);
}
2014-07-30 16:48:52 +02:00
stopButton.setEnabled(false);
statusProgress.setValue(0);
statusProgress.setVisible(false);
openButton.setVisible(false);
pack();
statusWithColor("Error: " + (String) msg.getObject(), Color.RED);
break;
case RIP_COMPLETE:
2015-01-11 09:23:43 +01:00
RipStatusComplete rsc = (RipStatusComplete) msg.getObject();
String url = ripper.getURL().toExternalForm();
if (HISTORY.containsURL(url)) {
// TODO update "modifiedDate" of entry in HISTORY
HistoryEntry entry = HISTORY.getEntryByURL(url);
entry.count = rsc.count;
entry.modifiedDate = new Date();
}
else {
HistoryEntry entry = new HistoryEntry();
entry.url = url;
2015-01-11 09:23:43 +01:00
entry.dir = rsc.getDir();
entry.count = rsc.count;
try {
entry.title = ripper.getAlbumTitle(ripper.getURL());
} catch (MalformedURLException e) { }
HISTORY.add(entry);
historyTableModel.fireTableDataChanged();
}
if (configPlaySound.isSelected()) {
Utils.playSound("camera.wav");
}
saveHistory();
2014-07-30 16:48:52 +02:00
stopButton.setEnabled(false);
statusProgress.setValue(0);
statusProgress.setVisible(false);
openButton.setVisible(true);
2015-01-11 09:23:43 +01:00
File f = rsc.dir;
2014-04-06 11:41:04 +02:00
String prettyFile = Utils.shortenPath(f);
openButton.setText("Open " + prettyFile);
mainFrame.setTitle("RipMe v" + UpdateUtils.getThisJarVersion());
2014-04-18 06:43:34 +02:00
try {
Image folderIcon = ImageIO.read(getClass().getClassLoader().getResource("folder.png"));
openButton.setIcon(new ImageIcon(folderIcon));
2014-04-18 07:11:37 +02:00
} catch (Exception e) { }
appendLog( "Rip complete, saved to " + f.getAbsolutePath(), Color.GREEN);
openButton.setActionCommand(f.toString());
openButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
try {
Desktop.getDesktop().open(new File(event.getActionCommand()));
} catch (Exception e) {
logger.error(e);
}
}
});
pack();
2014-07-30 16:48:52 +02:00
ripNextAlbum();
break;
case COMPLETED_BYTES:
// Update completed bytes
break;
case TOTAL_BYTES:
// Update total bytes
break;
}
}
public void update(AbstractRipper ripper, RipStatusMessage message) {
StatusEvent event = new StatusEvent(ripper, message);
SwingUtilities.invokeLater(event);
}
2014-03-02 10:30:52 +01:00
/** Simple TextPane that allows horizontal scrolling. */
class JTextPaneNoWrap extends JTextPane {
2014-03-02 10:30:52 +01:00
private static final long serialVersionUID = 1L;
@Override
public boolean getScrollableTracksViewportWidth() {
return false;
}
}
public static void ripAlbumStatic(String url) {
ripTextfield.setText(url.trim());
ripButton.doClick();
}
}