Adding features to "History"
Table-based view. Tracks # of images in a rip, and dates. Sortable. Double-clicking URL allows copying the URL to clipboard. Can selectively re-rip only albums that are 'checked' 'Checked' albums are persisted when RipMe is closed & reopened. For #147 (selective re-ripping)
This commit is contained in:
parent
066b0e9f87
commit
dd55cd1b43
@ -35,7 +35,7 @@ public abstract class AlbumRipper extends AbstractRipper {
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return itemsCompleted.size();
|
||||
return itemsCompleted.size() + itemsErrored.size();
|
||||
}
|
||||
|
||||
public boolean addURLToDownload(URL url, File saveAs, String referrer, Map<String,String> cookies) {
|
||||
|
@ -5,7 +5,9 @@ import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
@ -15,6 +17,13 @@ import org.json.JSONObject;
|
||||
public class History {
|
||||
|
||||
private List<HistoryEntry> list = new ArrayList<HistoryEntry>();
|
||||
private static final String[] COLUMNS = new String[] {
|
||||
"URL",
|
||||
"created",
|
||||
"modified",
|
||||
"#",
|
||||
""
|
||||
};
|
||||
|
||||
public void add(HistoryEntry entry) {
|
||||
list.add(entry);
|
||||
@ -22,9 +31,60 @@ public class History {
|
||||
public void remove(HistoryEntry entry) {
|
||||
list.remove(entry);
|
||||
}
|
||||
public void remove(int index) {
|
||||
list.remove(index);
|
||||
}
|
||||
public void clear() {
|
||||
list.clear();
|
||||
}
|
||||
public HistoryEntry get(int index) {
|
||||
return list.get(index);
|
||||
}
|
||||
public String getColumnName(int index) {
|
||||
return COLUMNS[index];
|
||||
}
|
||||
public int getColumnCount() {
|
||||
return COLUMNS.length;
|
||||
}
|
||||
public Object getValueAt(int row, int col) {
|
||||
HistoryEntry entry = this.list.get(row);
|
||||
switch (col) {
|
||||
case 0:
|
||||
return entry.url;
|
||||
case 1:
|
||||
return dateToHumanReadable(entry.startDate);
|
||||
case 2:
|
||||
return dateToHumanReadable(entry.modifiedDate);
|
||||
case 3:
|
||||
return entry.count;
|
||||
case 4:
|
||||
return entry.selected;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
private String dateToHumanReadable(Date date) {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
|
||||
return sdf.format(date);
|
||||
}
|
||||
|
||||
public boolean containsURL(String url) {
|
||||
for (HistoryEntry entry : this.list) {
|
||||
if (entry.url.equals(url)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public HistoryEntry getEntryByURL(String url) {
|
||||
for (HistoryEntry entry : this.list) {
|
||||
if (entry.url.equals(url)) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("Could not find URL " + url + " in History");
|
||||
}
|
||||
|
||||
public void fromJSON(JSONArray jsonArray) {
|
||||
JSONObject json;
|
||||
|
@ -43,6 +43,7 @@ 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;
|
||||
import javax.swing.ListSelectionModel;
|
||||
@ -53,6 +54,7 @@ import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
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;
|
||||
@ -89,10 +91,11 @@ public class MainWindow implements Runnable, RipStatusHandler {
|
||||
|
||||
// History
|
||||
private static JButton optionHistory;
|
||||
private static final History HISTORY = new History();
|
||||
private static JPanel historyPanel;
|
||||
private static JList historyList;
|
||||
private static DefaultListModel historyListModel;
|
||||
private static JScrollPane historyListScroll;
|
||||
private static JTable historyTable;
|
||||
private static AbstractTableModel historyTableModel;
|
||||
private static JScrollPane historyTableScrollPane;
|
||||
private static JPanel historyButtonPanel;
|
||||
private static JButton historyButtonRemove,
|
||||
historyButtonClear,
|
||||
@ -305,20 +308,66 @@ public class MainWindow implements Runnable, RipStatusHandler {
|
||||
historyPanel.setBorder(emptyBorder);
|
||||
historyPanel.setVisible(false);
|
||||
historyPanel.setPreferredSize(new Dimension(300, 250));
|
||||
historyListModel = new DefaultListModel();
|
||||
historyList = new JList(historyListModel);
|
||||
historyList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
|
||||
historyListScroll = new JScrollPane(historyList,
|
||||
JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
|
||||
JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
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.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 All");
|
||||
historyButtonRerip = new JButton("Re-rip Checked");
|
||||
gbc.gridx = 0;
|
||||
JPanel historyListPanel = new JPanel(new GridBagLayout());
|
||||
historyListPanel.add(historyListScroll, gbc);
|
||||
// History List Panel
|
||||
JPanel historyTablePanel = new JPanel(new GridBagLayout());
|
||||
historyTablePanel.add(historyTableScrollPane, gbc);
|
||||
gbc.ipady = 180;
|
||||
historyPanel.add(historyListPanel, gbc);
|
||||
historyPanel.add(historyTablePanel, gbc);
|
||||
gbc.ipady = 0;
|
||||
historyButtonPanel = new JPanel(new GridBagLayout());
|
||||
historyButtonPanel.setPreferredSize(new Dimension(300, 10));
|
||||
@ -531,17 +580,24 @@ public class MainWindow implements Runnable, RipStatusHandler {
|
||||
historyButtonRemove.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent event) {
|
||||
int[] indices = historyList.getSelectedIndices();
|
||||
int[] indices = historyTable.getSelectedRows();
|
||||
for (int i = indices.length - 1; i >= 0; i--) {
|
||||
historyListModel.remove(indices[i]);
|
||||
int modelIndex = historyTable.convertRowIndexToModel(indices[i]);
|
||||
HISTORY.remove(modelIndex);
|
||||
}
|
||||
try {
|
||||
historyTableModel.fireTableDataChanged();
|
||||
} catch (Exception e) { }
|
||||
saveHistory();
|
||||
}
|
||||
});
|
||||
historyButtonClear.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent event) {
|
||||
historyListModel.clear();
|
||||
HISTORY.clear();
|
||||
try {
|
||||
historyTableModel.fireTableDataChanged();
|
||||
} catch (Exception e) { }
|
||||
saveHistory();
|
||||
}
|
||||
});
|
||||
@ -550,9 +606,27 @@ public class MainWindow implements Runnable, RipStatusHandler {
|
||||
historyButtonRerip.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent event) {
|
||||
for (int i = 0; i < historyListModel.size(); i++) {
|
||||
HistoryEntry entry = (HistoryEntry) historyListModel.get(i);
|
||||
queueListModel.addElement(entry.url);
|
||||
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",
|
||||
"RipMe Error",
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -794,32 +868,25 @@ public class MainWindow implements Runnable, RipStatusHandler {
|
||||
}
|
||||
|
||||
private void loadHistory() {
|
||||
History history = new History();
|
||||
File historyFile = new File("history.json");
|
||||
HISTORY.clear();
|
||||
if (historyFile.exists()) {
|
||||
try {
|
||||
logger.info("Loading history from history.json");
|
||||
history.fromFile("history.json");
|
||||
HISTORY.fromFile("history.json");
|
||||
} catch (IOException e) {
|
||||
logger.error("Failed to load history from file history.json", e);
|
||||
logger.error("Failed to load history from file " + historyFile, e);
|
||||
}
|
||||
}
|
||||
else {
|
||||
logger.info("Loading history from configuration");
|
||||
history.fromList(Utils.getConfigList("download.history"));
|
||||
}
|
||||
for (HistoryEntry entry : history.toList()) {
|
||||
historyListModel.addElement(entry);
|
||||
HISTORY.fromList(Utils.getConfigList("download.history"));
|
||||
}
|
||||
}
|
||||
|
||||
private void saveHistory() {
|
||||
History history = new History();
|
||||
for (int i = 0; i < historyListModel.size(); i++) {
|
||||
history.add( (HistoryEntry) historyListModel.get(i) );
|
||||
}
|
||||
try {
|
||||
history.toFile("history.json");
|
||||
HISTORY.toFile("history.json");
|
||||
} catch (IOException e) {
|
||||
logger.error("Failed to save history to file history.json", e);
|
||||
}
|
||||
@ -977,18 +1044,15 @@ public class MainWindow implements Runnable, RipStatusHandler {
|
||||
break;
|
||||
|
||||
case RIP_COMPLETE:
|
||||
boolean alreadyInHistory = false;
|
||||
RipStatusComplete rsc = (RipStatusComplete) msg.getObject();
|
||||
String url = ripper.getURL().toExternalForm();
|
||||
for (int i = 0; i < historyListModel.size(); i++) {
|
||||
HistoryEntry entry = (HistoryEntry) historyListModel.get(i);
|
||||
if (entry.url.equals(url)) {
|
||||
alreadyInHistory = true;
|
||||
entry.modifiedDate = new Date();
|
||||
break;
|
||||
}
|
||||
if (HISTORY.containsURL(url)) {
|
||||
// TODO update "modifiedDate" of entry in HISTORY
|
||||
HistoryEntry entry = HISTORY.getEntryByURL(url);
|
||||
entry.count = rsc.count;
|
||||
entry.modifiedDate = new Date();
|
||||
}
|
||||
if (!alreadyInHistory) {
|
||||
else {
|
||||
HistoryEntry entry = new HistoryEntry();
|
||||
entry.url = url;
|
||||
entry.dir = rsc.getDir();
|
||||
@ -996,7 +1060,8 @@ public class MainWindow implements Runnable, RipStatusHandler {
|
||||
try {
|
||||
entry.title = ripper.getAlbumTitle(ripper.getURL());
|
||||
} catch (MalformedURLException e) { }
|
||||
historyListModel.addElement(entry);
|
||||
HISTORY.add(entry);
|
||||
historyTableModel.fireTableDataChanged();
|
||||
}
|
||||
if (configPlaySound.isSelected()) {
|
||||
Utils.playSound("camera.wav");
|
||||
|
Loading…
Reference in New Issue
Block a user