OSDN Git Service

Merge branch テーブルのtooltipにサムネイル情報を表示する機能
authoryukihane <yukihane.feather@gmail.com>
Sun, 18 Sep 2011 08:00:24 +0000 (17:00 +0900)
committeryukihane <yukihane.feather@gmail.com>
Sun, 18 Sep 2011 08:00:24 +0000 (17:00 +0900)
frontend/src/yukihane/inqubus/gui/MainFrame.java
frontend/src/yukihane/inqubus/thumbnail/Repository.java [new file with mode: 0644]
frontend/src/yukihane/inqubus/thumbnail/Thumbnail.java [new file with mode: 0644]

index f78c80a..f22e5b5 100644 (file)
@@ -15,12 +15,14 @@ import java.awt.event.ActionListener;
 import java.awt.event.ItemEvent;
 import java.awt.event.ItemListener;
 import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
 import java.awt.event.WindowAdapter;
 import java.awt.event.WindowEvent;
 import java.beans.PropertyChangeEvent;
 import java.beans.PropertyChangeListener;
 import java.io.File;
 import java.io.IOException;
+import java.net.MalformedURLException;
 import java.net.URL;
 import java.nio.file.FileSystem;
 import java.nio.file.FileSystems;
@@ -56,6 +58,7 @@ import javax.swing.LayoutStyle.ComponentPlacement;
 import javax.swing.SwingUtilities;
 import javax.swing.WindowConstants;
 import javax.swing.border.BevelBorder;
+import javax.swing.table.TableModel;
 import org.apache.commons.configuration.ConfigurationException;
 import org.apache.commons.lang.builder.ToStringBuilder;
 import saccubus.MainFrame_AboutBox;
@@ -86,6 +89,8 @@ import yukihane.inqubus.manager.TaskManageListener;
 import yukihane.inqubus.manager.TaskStatus;
 import yukihane.inqubus.model.Target;
 import yukihane.inqubus.model.TargetsTableModel;
+import yukihane.inqubus.thumbnail.Repository;
+import yukihane.inqubus.thumbnail.Thumbnail;
 
 /**
  *
@@ -95,6 +100,7 @@ public class MainFrame extends JFrame {
 
     private static final long serialVersionUID = 1L;
     private static final Logger logger = LoggerFactory.getLogger(MainFrame.class);
+    private final Repository thumbRepository = new Repository();
     private final TargetsTableModel targetModel = new TargetsTableModel();
     private final TaskManage taskManager;
     private final Thread videoFileWatcherThread;
@@ -150,7 +156,31 @@ public class MainFrame extends JFrame {
 
         final JPanel pnlMain = new JPanel();
         final JScrollPane scrDisplay = new JScrollPane();
-        tblDisplay = new JTable(targetModel, new TargetsColumnModel());
+        tblDisplay = new JTable(targetModel, new TargetsColumnModel()) {
+
+            @Override
+            public String getToolTipText(MouseEvent e) {
+                int row = convertRowIndexToModel(rowAtPoint(e.getPoint()));
+                TableModel m = getModel();
+                final String videoId = (String) m.getValueAt(row, 0);
+                try {
+                    final Thumbnail thumbnail = thumbRepository.getThumnail(videoId);
+                    if (thumbnail == null) {
+                        return videoId + ": 動画情報未取得";
+                    }
+
+                    final URL imageUrl = thumbnail.getImageFile().toURI().toURL();
+
+                    return "<html>" + videoId + ": " + thumbnail.getTitle()
+                            + " (" + thumbnail.getLength() + ")" + "<br/>"
+                            + "<img src=\"" + imageUrl + "\"/>"
+                            + "</html>";
+                } catch (Throwable ex) {
+                    logger.warn(null, ex);
+                    return videoId + ": 情報取得できません";
+                }
+            }
+        };
         tblDisplay.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
         final JPanel pnlButton = new JPanel();
         final JPanel pnlInputMain = new JPanel();
@@ -576,6 +606,10 @@ public class MainFrame extends JFrame {
                 final InqubusConvertProfile convProf = new InqubusConvertProfile();
                 logger.debug(downProf.toString());
                 logger.debug(convProf.toString());
+
+                final File tempDir = new File(Config.INSTANCE.getSystemTempDir());
+                thumbRepository.request(downProf.getProxyProfile(), tempDir, id);
+
                 final RequestProcess rp = new RequestProcess(downProf, id, convProf);
                 taskManager.add(rp);
                 targetModel.addTarget(new Target(rp));
diff --git a/frontend/src/yukihane/inqubus/thumbnail/Repository.java b/frontend/src/yukihane/inqubus/thumbnail/Repository.java
new file mode 100644 (file)
index 0000000..c0a89c1
--- /dev/null
@@ -0,0 +1,96 @@
+package yukihane.inqubus.thumbnail;
+
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import javax.imageio.ImageIO;
+import nicobrowser.NicoHttpClient;
+import nicobrowser.util.RssContent;
+import nicobrowser.util.RssContentParser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import saccubus.worker.profile.ProxyProfile;
+
+/**
+ *
+ * @author yuki
+ */
+public class Repository {
+
+    private static final Logger logger = LoggerFactory.getLogger(Repository.class);
+    private final ExecutorService executorService = Executors.newCachedThreadPool();
+    private final Map<String, Thumbnail> thumbnailMap = new HashMap<>();
+
+    public void request(ProxyProfile proxy, File tempDir, String videoId) {
+        synchronized (thumbnailMap) {
+            final Thumbnail value = thumbnailMap.get(videoId);
+            if (value != null) {
+                return;
+            }
+        }
+
+        executorService.execute(new ThumnailFetchWorker(proxy, tempDir, videoId));
+    }
+
+    public Thumbnail getThumnail(String videoId) {
+        synchronized (thumbnailMap) {
+            return thumbnailMap.get(videoId);
+        }
+    }
+
+    private class ThumnailFetchWorker implements Runnable {
+
+        private final ProxyProfile proxy;
+        private final String videoId;
+        private final File tempDir;
+
+        private ThumnailFetchWorker(ProxyProfile proxy, File tempDir, String videoId) {
+            this.proxy = proxy;
+            this.videoId = videoId;
+            this.tempDir = tempDir;
+        }
+
+        @Override
+        public void run() {
+            work();
+        }
+
+        private void work() {
+            final NicoHttpClient client = createClient(proxy);
+
+            try (InputStream is = client.getThumbInfo(videoId)) {
+                final RssContent cont = new RssContentParser().parse(is);
+                final URL thumbUrl = new URL(cont.getThumbnail_url());
+
+                final File imageFile;
+                try (InputStream imageStream = client.get(thumbUrl)) {
+                    final BufferedImage image = ImageIO.read(imageStream);
+                    imageFile = File.createTempFile("thumb", ".jpg", tempDir);
+                    imageFile.deleteOnExit();
+                    ImageIO.write(image, "jpeg", imageFile);
+                }
+                final Thumbnail thumb = new Thumbnail(cont.getTitle(), cont.getLength(), imageFile);
+
+                synchronized (thumbnailMap) {
+                    thumbnailMap.put(videoId, thumb);
+                }
+            } catch (IOException ex) {
+                logger.error(null, ex);
+            }
+        }
+
+        private NicoHttpClient createClient(ProxyProfile proxy) {
+            if (proxy.use()) {
+                return new NicoHttpClient(proxy.getHost(), proxy.getPort());
+            } else {
+                return new NicoHttpClient();
+            }
+        }
+    }
+}
diff --git a/frontend/src/yukihane/inqubus/thumbnail/Thumbnail.java b/frontend/src/yukihane/inqubus/thumbnail/Thumbnail.java
new file mode 100644 (file)
index 0000000..0d8572e
--- /dev/null
@@ -0,0 +1,33 @@
+package yukihane.inqubus.thumbnail;
+
+import java.io.File;
+import javax.swing.ImageIcon;
+
+/**
+ *
+ * @author yuki
+ */
+public class Thumbnail {
+
+    private final String title;
+    private final String length;
+    private final File imageFile;
+
+    Thumbnail(String title, String length, File imageFile) {
+        this.title = title;
+        this.length = length;
+        this.imageFile = imageFile;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public String getLength() {
+        return length;
+    }
+
+    public File getImageFile() {
+        return imageFile;
+    }
+}