/*
* Copyright (C) 2015 Shashank Tulsyan <shashaank at neembuu.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package neembuu.uploader;
import neembuu.uploader.translation.Translation;
import java.awt.Desktop;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.ClipboardOwner;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.net.URI;
import java.net.URL;
import java.util.Arrays;
import java.util.Vector;
import java.util.logging.Level;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.table.DefaultTableModel;
import neembuu.uploader.interfaces.UploadStatus;
import neembuu.uploader.theme.ThemeCheck;
import neembuu.uploader.utils.NULogger;
/**
*
* @author dsivaji
*/
public class UploadHistory extends javax.swing.JDialog implements ClipboardOwner {
//Singleton instance
private static UploadHistory INSTANCE = new UploadHistory(NeembuuUploader.getInstance(), true);
//reference to system clipboard
private Clipboard clipboard = null;
//reference to tablemodel just for easy typing
DefaultTableModel model;
private static final int FILE = 0;
private static final int HOST = 1;
private static final int DOWNLOADURL = 2;
private static final int DELETEURL = 3;
/**
* Creates new form UploadHistory
*/
public UploadHistory(java.awt.Frame parent, boolean modal) {
super(parent, modal);
initComponents();
clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
model = (DefaultTableModel) uploadTable.getModel();
}
/**
*
* @return the singleton instance. Call setVisible(true) with it.
*/
public static UploadHistory getInstance() {
//Add the rows by reading the recent.log file
//Use the INSTANCE dot when referring nonstatic from static
INSTANCE.updateRows();
//Update the language
updateLanguage();
//Different languages make the component in different size. So pack it finally..
INSTANCE.pack();
//After all these completed, finally return.
return INSTANCE;
}
private static void updateLanguage() {
NULogger.getLogger().log(Level.INFO, "{0}: updating language for components", UploadHistory.class.getName());
INSTANCE.setTitle(Translation.T().title3());
INSTANCE.copyDownloadURLButton.setToolTipText(Translation.T().copyDownloadURL());
INSTANCE.copyDeleteURLButton.setToolTipText(Translation.T().copyDeleteURL());
INSTANCE.gotoDownloadURLButton.setToolTipText(Translation.T().gotoDownloadURL());
INSTANCE.exportButton.setToolTipText(Translation.T().exportLinks());
INSTANCE.clearHistoryButton.setToolTipText(Translation.T().clearHistoryButton());
INSTANCE.removeSelectedButton.setToolTipText(Translation.T().removeSelectedButton());
//This code will clear any renderers or editors. Here this table has none so no problem.
INSTANCE.model.setColumnIdentifiers(new String[]{
Translation.T().File(),
Translation.T().Host(),
Translation.T().Download_URL(),
Translation.T().Delete_URL()
});
}
/**
* private method that updates the rows
*/
private void updateRows() {
NULogger.getLogger().info("Updating rows..");
model.setRowCount(0);
try {
//Get a reader object to this file.
BufferedReader reader = new BufferedReader(new FileReader(System.getProperty("user.home") + File.separator + "recent.log"));
//Update the rows by reading file
String data;
while ((data = reader.readLine()) != null) {
try {
Vector columns = new Vector();
String[] columnarray = data.split("<>");
//Validating url
//new URL(columnarray[DOWNLOADURL]); //This prevents filesonic NA rows to be showed.
columns.addAll(0, Arrays.asList(columnarray));
model.addRow(columns);
} catch (Exception e) {
NULogger.getLogger().log(Level.INFO, "{0}: {1}", new Object[]{getClass().getName(), e});
//If it's not a correct url, ignore it and loop next
continue;
}
}
//It is necessary to close. Otherwise delete() method somewhere else won't work
reader.close();
} catch (Exception ex) {
NULogger.getLogger().severe(ex.toString());
System.err.println(ex);
}
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
uploadHistoryPanel = new javax.swing.JPanel();
jScrollPane1 = new javax.swing.JScrollPane();
uploadTable = new javax.swing.JTable();
clearHistoryButton = new javax.swing.JButton();
exportButton = new javax.swing.JButton();
copyDownloadURLButton = new javax.swing.JButton();
copyDeleteURLButton = new javax.swing.JButton();
gotoDownloadURLButton = new javax.swing.JButton();
removeSelectedButton = new javax.swing.JButton();
jSeparator1 = new javax.swing.JSeparator();
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
uploadTable.setModel(new javax.swing.table.DefaultTableModel(
new Object [][] {
},
new String [] {
"File", "Host", "Download URL", "Delete URL if any"
}
) {
Class[] types = new Class [] {
java.lang.String.class, java.lang.String.class, java.lang.String.class, java.lang.String.class
};
boolean[] canEdit = new boolean [] {
false, false, false, false
};
public Class getColumnClass(int columnIndex) {
return types [columnIndex];
}
public boolean isCellEditable(int rowIndex, int columnIndex) {
return canEdit [columnIndex];
}
});
uploadTable.setSelectionMode(javax.swing.ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
jScrollPane1.setViewportView(uploadTable);
clearHistoryButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/neembuuuploader/resources/popup/clear_history.png"))); // NOI18N
clearHistoryButton.setToolTipText("Clear History");
clearHistoryButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
clearHistoryButtonActionPerformed(evt);
}
});
exportButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/neembuuuploader/resources/popup/exporturl.png"))); // NOI18N
exportButton.setToolTipText("Export links");
exportButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
exportButtonActionPerformed(evt);
}
});
copyDownloadURLButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/neembuuuploader/resources/popup/copydownloadurl.png"))); // NOI18N
copyDownloadURLButton.setToolTipText("Copy Download URL");
copyDownloadURLButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
copyDownloadURLButtonActionPerformed(evt);
}
});
copyDeleteURLButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/neembuuuploader/resources/popup/copydeleteurl.png"))); // NOI18N
copyDeleteURLButton.setToolTipText("Copy Delete URL");
copyDeleteURLButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
copyDeleteURLButtonActionPerformed(evt);
}
});
gotoDownloadURLButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/neembuuuploader/resources/popup/gotodownloadurl.png"))); // NOI18N
gotoDownloadURLButton.setToolTipText("Goto Download URL");
gotoDownloadURLButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
gotoDownloadURLButtonActionPerformed(evt);
}
});
removeSelectedButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/neembuuuploader/resources/popup/removefromlist.png"))); // NOI18N
removeSelectedButton.setToolTipText("Remove selected");
removeSelectedButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
removeSelectedButtonActionPerformed(evt);
}
});
jSeparator1.setOrientation(javax.swing.SwingConstants.VERTICAL);
javax.swing.GroupLayout uploadHistoryPanelLayout = new javax.swing.GroupLayout(uploadHistoryPanel);
uploadHistoryPanel.setLayout(uploadHistoryPanelLayout);
uploadHistoryPanelLayout.setHorizontalGroup(
uploadHistoryPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(uploadHistoryPanelLayout.createSequentialGroup()
.addContainerGap()
.addGroup(uploadHistoryPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(jScrollPane1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, 882, Short.MAX_VALUE)
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, uploadHistoryPanelLayout.createSequentialGroup()
.addComponent(copyDownloadURLButton)
.addGap(18, 18, 18)
.addComponent(copyDeleteURLButton)
.addGap(18, 18, 18)
.addComponent(gotoDownloadURLButton)
.addGap(18, 18, 18)
.addComponent(exportButton)
.addGap(18, 18, 18)
.addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(removeSelectedButton)
.addGap(18, 18, 18)
.addComponent(clearHistoryButton)))
.addContainerGap())
);
uploadHistoryPanelLayout.setVerticalGroup(
uploadHistoryPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(uploadHistoryPanelLayout.createSequentialGroup()
.addContainerGap()
.addGroup(uploadHistoryPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
.addComponent(copyDeleteURLButton)
.addComponent(copyDownloadURLButton)
.addComponent(gotoDownloadURLButton)
.addComponent(exportButton)
.addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(clearHistoryButton)
.addComponent(removeSelectedButton))
.addGap(18, 18, 18)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 341, Short.MAX_VALUE)
.addContainerGap())
);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(0, 0, 0)
.addComponent(uploadHistoryPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(0, 0, 0)
.addComponent(uploadHistoryPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addContainerGap())
);
pack();
}// </editor-fold>//GEN-END:initComponents
private void clearHistoryButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_clearHistoryButtonActionPerformed
ThemeCheck.apply(null);
if (JOptionPane.showConfirmDialog(this, Translation.T().
confirmClear(), "", JOptionPane.YES_NO_OPTION)
!= JOptionPane.YES_OPTION) {
return;
}
NULogger.getLogger().info("Clearing the upload history");
try {
//delete the file
new File(System.getProperty("user.home") + File.separator + "recent.log").delete();
} catch (Exception e) {
NULogger.getLogger().warning(e.toString());
System.err.println(e);
}
//What a cool way to clear rows?
model.setRowCount(0);
}//GEN-LAST:event_clearHistoryButtonActionPerformed
private void exportButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_exportButtonActionPerformed
NULogger.getLogger().log(Level.INFO, "{0}: Export Button clicked", getClass().getName());
//Return if no rows selected.
if (uploadTable.getSelectedRowCount() < 1) {
ThemeCheck.apply(null);
JOptionPane.showMessageDialog(this, Translation.T().noRowsSelected());
return;
}
//Ask for a file to save linklist
JFileChooser fc = new JFileChooser();
//Set File selection only mode
fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
//Set Dialog Title
fc.setDialogTitle(Translation.T().exportLinkDialog());
//Disable All Files option
fc.setAcceptAllFileFilterUsed(false);
//Enable HTML file extension only
fc.setFileFilter(new FileNameExtensionFilter("HTML File", new String[]{"html"}));
//Show save dialog
if (fc.showSaveDialog(this) != JFileChooser.APPROVE_OPTION) {
return;
}
File htmlfile = fc.getSelectedFile();
//Get selected rows
int[] rows = uploadTable.getSelectedRows();
StringBuilder sb = new StringBuilder("<html>"
+ "<head><title>Neembuu Uploader</title>"
+ "<style type='text/css'>"
+ " table { display:block; width:90%; border-top:1px solid #e5eff8; border-right:1px solid #e5eff8; margin:1em auto;border-collapse:collapse;}"
+ " td { color:#7892a8;border-bottom:1px solid #e5eff8;border-left:1px solid #e5eff8;padding:.3em 1em;text-align:center;}"
+ " tr.odd td { background:#f7fbff } tr.odd .column1 {background:#f4f9fe;} .column1 {background:#f9fcfe;}"
+ " th, h3 { background:#f4f9fe; text-align:center; font:bold 1.2em/2em 'Century Gothic','Trebuchet MS',Arial,Helvetica,sans-serif; color:#66a3d3; }"
+ "</style></head>"
+ "<body><center><h3>Neembuu Uploader Exported Linkset</h3></center>"
+ "<table><tr class='odd'><th class='column1'>File</th><th>Host</th><th>Download URL</th><th>Delete URL if any</th></tr>");
int i = 1;
for (int row : rows) {
if (i % 2 == 0) {
sb.append("<tr class='odd'>");
} else {
sb.append("<tr>");
}
for (int column = 0; column < uploadTable.getModel().getColumnCount(); column++) {
if (column == 0) {
sb.append("<td class='column1'>");
} else {
sb.append("<td>");
}
if (column == DOWNLOADURL
&& !(uploadTable.getModel().getValueAt(row, column).equals(UploadStatus.NA.getDefaultLocaleSpecificString())
|| uploadTable.getModel().getValueAt(row, column).equals(UploadStatus.NA.getLocaleSpecificString()))) {
sb.append("<a target='_blank' href='").append(uploadTable.getModel().getValueAt(row, column)).append("'>").append(uploadTable.getModel().getValueAt(row, column)).append("</a>");
} else {
sb.append(uploadTable.getModel().getValueAt(row, column));
}
sb.append("</td>");
}
sb.append("</tr>");
i++;
}
sb.append("</table></body></html>");
try {
NULogger.getLogger().log(Level.INFO, "{0}: Writing links to html file..", getClass().getName());
//Check if file name ends with html
if (!(htmlfile.getName().toLowerCase().endsWith(".html") || htmlfile.getName().toLowerCase().endsWith(".htm"))) {
htmlfile = new File(htmlfile.getAbsolutePath() + ".html");
}
PrintWriter writer = new PrintWriter(new FileWriter(htmlfile));
writer.write(sb.toString());
writer.close();
} catch (Exception ex) {
NULogger.getLogger().log(Level.INFO, "{0}: Error while writing html file\n{1}", new Object[]{getClass().getName(), ex});
System.err.println(ex);
}
}//GEN-LAST:event_exportButtonActionPerformed
private void copyDownloadURLButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_copyDownloadURLButtonActionPerformed
NULogger.getLogger().log(Level.INFO, "{0}: CopyDownloadURL Button clicked", getClass().getName());
//Return if no rows selected.
if (uploadTable.getSelectedRowCount() < 1) {
ThemeCheck.apply(null);
JOptionPane.showMessageDialog(this, Translation.T().noRowsSelected());
return;
}
//initialize a StringBuilder
StringBuilder listofurls = new StringBuilder();
//get selected rows
int[] selectedrows = uploadTable.getSelectedRows();
//Collect the set of urls and set the text in Clipboard
for (int selectedrow : selectedrows) {
listofurls.append(uploadTable.getValueAt(selectedrow, DOWNLOADURL).toString()).append("\n");
}
setClipboardContent(listofurls.toString());
}//GEN-LAST:event_copyDownloadURLButtonActionPerformed
private void copyDeleteURLButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_copyDeleteURLButtonActionPerformed
NULogger.getLogger().log(Level.INFO, "{0}: CopyDeleteURL Button clicked", getClass().getName());
//Return if no rows selected.
if (uploadTable.getSelectedRowCount() < 1) {
ThemeCheck.apply(null);
JOptionPane.showMessageDialog(this, Translation.T().noRowsSelected());
return;
}
//initialize a StringBuilder
StringBuilder listofurls = new StringBuilder();
//get selected rows
int[] selectedrows = uploadTable.getSelectedRows();
//Collect the set of urls and set the text in Clipboard
for (int selectedrow : selectedrows) {
try {
String deleteurl = uploadTable.getValueAt(selectedrow, DELETEURL).toString();
//Validate url
new URL(deleteurl);
listofurls.append(deleteurl).append("\n");
} catch (Exception e) {
NULogger.getLogger().log(Level.INFO, "{0}: {1}", new Object[]{getClass().getName(), e});
//If it's not a correct url, ignore it and loop next
continue;
}
}
setClipboardContent(listofurls.toString());
}//GEN-LAST:event_copyDeleteURLButtonActionPerformed
private void gotoDownloadURLButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_gotoDownloadURLButtonActionPerformed
NULogger.getLogger().log(Level.INFO, "{0}: GotoDownloadURL Button clicked", getClass().getName());
//Return if no rows selected.
if (uploadTable.getSelectedRowCount() < 1) {
ThemeCheck.apply(null);
JOptionPane.showMessageDialog(this, Translation.T().noRowsSelected());
return;
}
//get selected rows
int[] selectedrows = uploadTable.getSelectedRows();
//Collect the set of urls and set the text in Clipboard
//Remember it's a multiple selection interval
for (int selectedrow : selectedrows) {
String url =
uploadTable.getValueAt(selectedrow, DOWNLOADURL).toString();
if (!Desktop.isDesktopSupported()) {
return;
}
try {
NULogger.getLogger().log(Level.INFO, "Opening url in browser: {0}", url);
Desktop.getDesktop().browse(new URI(url));
} catch (Exception ex) {
NULogger.getLogger().log(Level.WARNING, "{0}: Cannot load url: {1}", new Object[]{getClass().getName(), url});
System.err.println(ex);
}
}
}//GEN-LAST:event_gotoDownloadURLButtonActionPerformed
private void removeSelectedButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeSelectedButtonActionPerformed
NULogger.getLogger().log(Level.INFO, "{0}: Remove Selected Button clicked", getClass().getName());
//Return if no rows selected.
if (uploadTable.getSelectedRowCount() < 1) {
ThemeCheck.apply(null);
JOptionPane.showMessageDialog(this, Translation.T().noRowsSelected());
return;
}
deleteRowsAndReprintFile();
}//GEN-LAST:event_removeSelectedButtonActionPerformed
/**
* Place a String on the clipboard, and make this class the owner of the
* clipboard contents.
*/
public void setClipboardContent(String aString) {
StringSelection stringSelection = new StringSelection(aString);
clipboard.setContents(stringSelection, this);
NULogger.getLogger().info("Copied to clipboard");
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton clearHistoryButton;
private javax.swing.JButton copyDeleteURLButton;
private javax.swing.JButton copyDownloadURLButton;
private javax.swing.JButton exportButton;
private javax.swing.JButton gotoDownloadURLButton;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JSeparator jSeparator1;
private javax.swing.JButton removeSelectedButton;
javax.swing.JPanel uploadHistoryPanel;
private javax.swing.JTable uploadTable;
// End of variables declaration//GEN-END:variables
/**
* Implemented method. Hope this method may never be called.
*
* @param clipboard
* @param contents
*/
@Override
public void lostOwnership(Clipboard clipboard, Transferable contents) {
NULogger.getLogger().log(Level.WARNING, "{0}: Lost clipboard ownership", getClass().getName());
}
private void deleteRowsAndReprintFile() {
//get selected rows
int selectedrow;
int[] selectedrows = uploadTable.getSelectedRows();
//Remove the rows from tablemodel from the end..
for (int i = selectedrows.length - 1; i >= 0; i--) {
selectedrow = selectedrows[i];
NULogger.getLogger().log(Level.INFO, "Removing row: {0}", selectedrow);
model.removeRow(selectedrow);
}
uploadTable.repaint();
//Reprint the file.
try {
//Overwrite the file instead of appending..
NULogger.getLogger().info("Reprinting recent.log");
PrintWriter writer = new PrintWriter(new FileWriter(System.getProperty("user.home") + File.separator + "recent.log", false));
for (int row = 0; row < model.getRowCount(); row++) {
writer.write(model.getValueAt(row, FILE) + "<>" + model.getValueAt(row, HOST) + "<>" + model.getValueAt(row, DOWNLOADURL) + "<>" + model.getValueAt(row, DELETEURL) + "\n");
}
writer.close();
} catch (Exception ex) {
NULogger.getLogger().log(Level.INFO, "Error while writing recent.log\n{0}", ex);
}
}
}