package thaw.plugins.queueWatcher;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.util.Iterator;
import java.util.Vector;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.table.JTableHeader;
import thaw.core.Core;
import thaw.core.ThawThread;
import thaw.core.ThawRunnable;
import thaw.gui.FileChooser;
import thaw.core.I18n;
import thaw.gui.IconBox;
import thaw.core.Logger;
import thaw.fcp.FCPClientGet;
import thaw.fcp.FCPTransferQuery;
import thaw.gui.Table;
import thaw.plugins.QueueWatcher;
public class QueuePanel implements MouseListener, ActionListener, KeyListener {
public final static int ACTION_REMOVE_FINISHED = 0;
public final static int ACTION_DOWNLOAD_SELECTED = 1; /* locally */
public final static int ACTION_REMOVE_SELECTED = 2;
public final static int ACTION_CANCEL_SELECTED = 3;
public final static int ACTION_DELAY_SELECTED = 4;
public final static int ACTION_RESTART_SELECTED = 5;
public final static int ACTION_COPY_KEYS_SELECTED = 6;
public final static int ACTION_CHANGE_PRIORITY_SELECTED = 7;
public final static int FIRST_COLUMN_SIZE = 20;
private Core core;
private JButton button;
private Table table = null;
private JScrollPane scrollPane = null;
private JPanel panel;
private QueueTableModel tableModel;
private DetailPanel detailPanel;
private JPopupMenu rightClickMenu;
private JMenuItem clearFinishedItem;
private JMenuItem removeItem;
private JMenuItem cancelItem;
private JMenuItem delayItem;
private JMenuItem downloadItem;
private JMenuItem forceRestartItem;
private JMenuItem copyKeysItem;
private JRadioButtonMenuItem[] priorityRadioButton;
private JRadioButtonMenuItem unknowPriority;
private ButtonGroup priorityGroup;
public final static int MIN_PRIORITY = 6;
private int[] selectedRows;
private boolean insertionQueue = false;
public QueueWatcher queueWatcher;
public QueuePanel(final Core core, final QueueWatcher queueWatcher,
final DetailPanel detailPanel, boolean isForInsertionQueue) {
this.queueWatcher = queueWatcher;
insertionQueue = isForInsertionQueue;
this.core = core;
this.detailPanel = detailPanel;
tableModel = new QueueTableModel(isForInsertionQueue,
core.getPluginManager(),
core.getQueueManager());
table = new Table(core.getConfig(),
isForInsertionQueue ? "table_insertions" : "table_downloads",
tableModel);
table.setShowGrid(false);
table.setIntercellSpacing(new java.awt.Dimension(0, 0));
table.showStatusInProgressBars(false);
final JTableHeader header = table.getTableHeader();
header.setUpdateTableInRealTime(true);
header.addMouseListener(tableModel.new ColumnListener(table));
header.setReorderingAllowed(true);
if(isForInsertionQueue) {
button = new JButton(I18n.getMessage("thaw.common.insertions"));
button.setIcon(IconBox.insertions);
} else {
button = new JButton(I18n.getMessage("thaw.common.downloads"));
button.setIcon(IconBox.downloads);
}
button.setEnabled(false);
button.setVerticalAlignment(SwingConstants.CENTER);
button.setHorizontalAlignment(SwingConstants.LEFT);
button.setPreferredSize(new Dimension(190, 40));
final JPanel buttonPanel = new JPanel(new BorderLayout());
buttonPanel.add(button, BorderLayout.EAST);
buttonPanel.add(new JLabel(""), BorderLayout.CENTER);
panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.add(buttonPanel, BorderLayout.NORTH);
scrollPane = new JScrollPane(table);
panel.add(scrollPane, BorderLayout.CENTER);
//table.setDefaultRenderer( table.getColumnClass(0), new ProgressRenderer(table, tableModel, isForInsertionQueue) );
tableModel.addTableModelListener(table);
rightClickMenu = new JPopupMenu();
clearFinishedItem = new JMenuItem(I18n.getMessage("thaw.common.clearFinished"));
removeItem = new JMenuItem(I18n.getMessage("thaw.common.removeFromTheList"), IconBox.minDelete);
cancelItem = new JMenuItem(I18n.getMessage("thaw.common.cancel"), IconBox.minStop);
delayItem = new JMenuItem(I18n.getMessage("thaw.common.delay"));
downloadItem = new JMenuItem(I18n.getMessage("thaw.common.downloadLocally"));
forceRestartItem = new JMenuItem(I18n.getMessage("thaw.common.forceRestart"), IconBox.minRefreshAction);
copyKeysItem = new JMenuItem(I18n.getMessage("thaw.common.copyKeysToClipboard"), IconBox.minCopy);
final JMenu priorityMenu = new JMenu(I18n.getMessage("thaw.common.priority"));
priorityGroup = new ButtonGroup();
priorityRadioButton = new JRadioButtonMenuItem[MIN_PRIORITY+1];
for(int i =0 ; i <= MIN_PRIORITY ; i++) {
priorityRadioButton[i] = new JRadioButtonMenuItem(I18n.getMessage("thaw.plugin.priority.p"+Integer.toString(i)));
priorityRadioButton[i].addActionListener(this);
priorityMenu.add(priorityRadioButton[i]);
priorityGroup.add(priorityRadioButton[i]);
}
unknowPriority = new JRadioButtonMenuItem("Coin");
priorityGroup.add(unknowPriority);
rightClickMenu.add(clearFinishedItem);
rightClickMenu.add(removeItem);
if( (Integer.parseInt(core.getConfig().getValue("maxSimultaneousDownloads")) >= 0)
|| (Integer.parseInt(core.getConfig().getValue("maxSimultaneousInsertions")) >= 0))
rightClickMenu.add(cancelItem);
if( (Integer.parseInt(core.getConfig().getValue("maxSimultaneousDownloads")) >= 0)
|| (Integer.parseInt(core.getConfig().getValue("maxSimultaneousInsertions")) >= 0))
rightClickMenu.add(delayItem);
/* this option can't work with localSocket == true */
if(!isForInsertionQueue && !Boolean.valueOf(core.getConfig().getValue("sameComputer")).booleanValue())
rightClickMenu.add(downloadItem);
rightClickMenu.add(forceRestartItem);
rightClickMenu.add(copyKeysItem);
if( Boolean.valueOf(core.getConfig().getValue("advancedMode")).booleanValue() == true) {
rightClickMenu.add(priorityMenu);
}
clearFinishedItem.addActionListener(this);
removeItem.addActionListener(this);
cancelItem.addActionListener(this);
copyKeysItem.addActionListener(this);
forceRestartItem.addActionListener(this);
delayItem.addActionListener(this);
downloadItem.addActionListener(this);
table.addMouseListener(this);
table.addKeyListener(this);
/* we really really want a column 0 with a size of FIRST_COLUMN_SIZE ! */
table.getColumnModel().getColumn(0).setPreferredWidth(FIRST_COLUMN_SIZE);
table.getColumnModel().getColumn(0).setResizable(false);
table.getColumnModel().getColumn(0).setPreferredWidth(FIRST_COLUMN_SIZE);
table.getColumnModel().getColumn(0).setMinWidth(FIRST_COLUMN_SIZE);
table.getColumnModel().getColumn(0).setMaxWidth(FIRST_COLUMN_SIZE);
/* If a queue is already existing, we need to add it */
if(core.getQueueManager() != null) {
this.addToTable(core.getQueueManager().getRunningQueue());
final Vector[] pendingQueues = core.getQueueManager().getPendingQueues();
for(int i = 0 ; i < pendingQueues.length ; i++) {
this.addToTable(pendingQueues[i]);
}
}
}
public void addMenuItem(final JMenuItem item) {
rightClickMenu.insert(item, 0);
}
public void addActionListenerToTheButton(ActionListener a) {
button.setEnabled(true);
button.addActionListener(a);
}
public void removeActionListenerFromTheButton(ActionListener a) {
button.removeActionListener(a);
if (button.getActionListeners() == null
|| button.getActionListeners().length == 0)
button.setEnabled(false);
}
public void reloadSelections() {
selectedRows = table.getSelectedRows();
if((selectedRows.length > 1) || (selectedRows.length < 1)) {
resetPriorityRadioButtons();
} else {
final FCPTransferQuery query = tableModel.getQuery(selectedRows[0]);
if (query == null)
return;
priorityRadioButton[query.getFCPPriority()].setSelected(true);
}
}
/**
* return a vector made of FCPTransferQueries.
* Doesn't refresh the selection !
*/
public Vector getSelectedQueries() {
final Vector queries = new Vector();
final Vector initialQueries = tableModel.getQueries();
if(selectedRows == null)
return queries;
/* Create a separate vector to avoid collisions */
for(int i = 0 ; i < selectedRows.length; i++) {
if (initialQueries.size() > selectedRows[i])
queries.add(initialQueries.get(selectedRows[i]));
}
return queries;
}
public void resetTable() {
tableModel.resetTable();
}
public void addToTable(final FCPTransferQuery query) {
if( (insertionQueue && (query.getQueryType() == 2))
|| (!insertionQueue && (query.getQueryType() == 1))) {
tableModel.addQuery(query);
}
}
/**
* @param queries Vector of FCPTransferQuery only
*/
public synchronized void addToTable(final Vector queries) {
synchronized(queries) {
for(final Iterator queryIt = queries.iterator();
queryIt.hasNext();) {
final FCPTransferQuery query = (FCPTransferQuery)queryIt.next();
this.addToTable(query);
}
}
}
public void refreshDetailPanel() {
final int selected = table.getSelectedRow();
if(selected != -1) {
final FCPTransferQuery query = tableModel.getQuery(selected);
detailPanel.setQuery(query);
}
}
private void resetPriorityRadioButtons() {
unknowPriority.setSelected(true);
}
public JPanel getPanel() {
return panel;
}
public JTable getTable() {
return table;
}
public void unselectAll() {
table.clearSelection();
selectedRows = null;
}
public class ActionReplier implements ThawRunnable {
private int action;
private int new_priority;
private Vector queries;
public ActionReplier(final int action, final int new_priority) {
this.action = action;
if (selectedRows != null)
this.queries = getSelectedQueries();
else
this.queries = new Vector();
this.new_priority = (action == ACTION_CHANGE_PRIORITY_SELECTED) ? new_priority : -1;
}
public void run() {
String keys = "";
File dir = null;
if(action == ACTION_REMOVE_FINISHED) {
final Vector qs = tableModel.getQueries();
for(final Iterator it = qs.iterator();
it.hasNext(); ) {
final FCPTransferQuery query = (FCPTransferQuery)it.next();
if(query.isFinished() && query.isSuccessful() &&
(!(query instanceof FCPClientGet) || (!query.isSuccessful() || ((FCPClientGet)query).isWritingSuccessful()))) {
if(query.stop(core.getQueueManager())) {
core.getQueueManager().remove(query);
}
}
}
return;
}
if(action == ACTION_DOWNLOAD_SELECTED) {
final FileChooser fileChooser = new FileChooser();
fileChooser.setTitle(I18n.getMessage("thaw.common.downloadLocally"));
fileChooser.setDirectoryOnly(true);
fileChooser.setDialogType(JFileChooser.SAVE_DIALOG);
dir = fileChooser.askOneFile();
if(dir == null)
return;
}
for(final Iterator queryIt = queries.iterator() ; queryIt.hasNext() ;) {
final FCPTransferQuery query = (FCPTransferQuery)queryIt.next();
if(query == null)
continue;
if(new_priority >= 0) {
if(query.isPersistent()) {
query.setFCPPriority(new_priority);
query.updatePersistentRequest(false);
}
}
if(action == ACTION_REMOVE_SELECTED) {
if(query.stop(core.getQueueManager())) {
core.getQueueManager().remove(query);
}
}
if(action == ACTION_CANCEL_SELECTED) {
query.stop(core.getQueueManager());
}
if(action == ACTION_DELAY_SELECTED) {
if(query.isRunning() && !query.isFinished()) {
query.pause(core.getQueueManager());
core.getQueueManager().moveFromRunningToPendingQueue(query);
}
}
if(action == ACTION_RESTART_SELECTED) {
query.stop(core.getQueueManager());
if ((query instanceof FCPClientGet) && query.getPath() != null) {
File target = new File(query.getPath());
if (target.exists())
target.delete();
}
if(query.getMaxAttempt() >= 0)
query.setAttempt(0);
query.start(core.getQueueManager());
}
if (action == ACTION_COPY_KEYS_SELECTED) {
if((query.getFileKey() != null)
&& !"".equals( query.getFileKey() ))
keys = keys + query.getFileKey() + "\n";
}
if (action == ACTION_DOWNLOAD_SELECTED
&& (dir != null)) {
if(query.isPersistent()) {
query.saveFileTo(dir.getPath());
if(query.getIdentifier().startsWith(core.getConfig().getValue("thawId")))
query.updatePersistentRequest(true);
}
}
} /* for i in selectedRows */
if (action == ACTION_COPY_KEYS_SELECTED) {
thaw.gui.GUIHelper.copyToClipboard(keys);
}
}
public void stop() {
/* \_o< */
}
}
public void removeSelectedTransfers() {
reloadSelections();
Thread th = new ThawThread(new ActionReplier(ACTION_REMOVE_SELECTED, -1),
"Action replier : Remove selected", this);
th.start();
}
public void removeAllFinishedTransfers() {
reloadSelections();
Thread th = new ThawThread(new ActionReplier(ACTION_REMOVE_FINISHED, -1),
"Action replier : Remove finished", this);
th.start();
}
/**
* Manage it on a different thread to avoid UI freeze.
*/
public void actionPerformed(final ActionEvent e) {
int prioritySelected = 0;
int action = ACTION_CHANGE_PRIORITY_SELECTED;
for(prioritySelected = 0;
prioritySelected <= MIN_PRIORITY;
prioritySelected++) {
if(priorityRadioButton[prioritySelected] == e.getSource()) {
break;
}
}
if(prioritySelected > MIN_PRIORITY) {
prioritySelected = -1;
if (e.getSource() == clearFinishedItem) action = ACTION_REMOVE_FINISHED;
else if (e.getSource() == removeItem) action = ACTION_REMOVE_SELECTED;
else if (e.getSource() == cancelItem) action = ACTION_CANCEL_SELECTED;
else if (e.getSource() == delayItem) action = ACTION_DELAY_SELECTED;
else if (e.getSource() == downloadItem) action = ACTION_DOWNLOAD_SELECTED;
else if (e.getSource() == forceRestartItem) action = ACTION_RESTART_SELECTED;
else if (e.getSource() == copyKeysItem) action = ACTION_COPY_KEYS_SELECTED;
else {
Logger.error(this, "Unknow action ?!");
return;
}
}
final Thread actionTh = new ThawThread(new ActionReplier(action, prioritySelected),
"Action replier : "+Integer.toString(action),
this);
actionTh.start();
}
public void mouseClicked(final MouseEvent e) {
if(e.getButton() == MouseEvent.BUTTON3) {
reloadSelections();
rightClickMenu.show(e.getComponent(), e.getX(), e.getY());
}
if(e.getButton() == MouseEvent.BUTTON1) {
queueWatcher.unselectAllExcept(insertionQueue ? QueueWatcher.INSERTION_PANEL : QueueWatcher.DOWNLOAD_PANEL);
refreshDetailPanel();
}
}
public void mouseEntered(final MouseEvent e) { }
public void mouseExited(final MouseEvent e) { }
public void mousePressed(final MouseEvent e) { }
public void mouseReleased(final MouseEvent e) { }
public void keyPressed(final KeyEvent e) { }
public void keyReleased(final KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_DELETE) {
removeSelectedTransfers();
}
refreshDetailPanel();
}
public void keyTyped(final KeyEvent e) { }
}