OSDN Git Service

ID入力欄でエンターを押した場合にも適用ボタンを押した場合と同様の動作をさせる
[coroid/inqubus.git] / frontend / src / yukihane / inqubus / gui / MainFrame.java
1 /*
2  * MainFrame.java
3  *
4  * Created on 2011/05/28, 18:14:51
5  */
6 package yukihane.inqubus.gui;
7
8 import java.awt.Image;
9 import java.awt.ItemSelectable;
10 import java.awt.Toolkit;
11 import java.awt.datatransfer.DataFlavor;
12 import java.awt.datatransfer.Transferable;
13 import java.awt.event.ActionEvent;
14 import java.awt.event.ActionListener;
15 import java.awt.event.ItemEvent;
16 import java.awt.event.ItemListener;
17 import java.awt.event.KeyEvent;
18 import java.beans.PropertyChangeEvent;
19 import java.beans.PropertyChangeListener;
20 import java.io.File;
21 import java.io.FilenameFilter;
22 import java.io.IOException;
23 import java.net.URL;
24 import java.util.ArrayList;
25 import java.util.Collection;
26 import java.util.List;
27 import java.util.logging.Level;
28 import java.util.logging.Logger;
29 import java.util.regex.Matcher;
30 import java.util.regex.Pattern;
31 import javax.swing.BorderFactory;
32 import javax.swing.DropMode;
33 import javax.swing.GroupLayout;
34 import javax.swing.GroupLayout.Alignment;
35 import javax.swing.JButton;
36 import javax.swing.JCheckBox;
37 import javax.swing.JFrame;
38 import javax.swing.JLabel;
39 import javax.swing.JMenu;
40 import javax.swing.JMenuBar;
41 import javax.swing.JMenuItem;
42 import javax.swing.JOptionPane;
43 import javax.swing.JPanel;
44 import javax.swing.JScrollPane;
45 import javax.swing.JTabbedPane;
46 import javax.swing.JTable;
47 import javax.swing.JTextField;
48 import javax.swing.KeyStroke;
49 import javax.swing.LayoutStyle.ComponentPlacement;
50 import javax.swing.SwingUtilities;
51 import javax.swing.TransferHandler;
52 import javax.swing.WindowConstants;
53 import javax.swing.border.BevelBorder;
54 import org.apache.commons.lang.StringUtils;
55 import org.apache.commons.lang.builder.ToStringBuilder;
56 import saccubus.FfmpegOption;
57 import saccubus.MainFrame_AboutBox;
58 import saccubus.OptionComboBoxModel;
59 import saccubus.util.WayBackTimeParser;
60 import saccubus.worker.impl.convert.ConvertProgress;
61 import saccubus.worker.impl.download.DownloadProgress;
62 import saccubus.worker.WorkerListener;
63 import saccubus.worker.impl.convert.ConvertResult;
64 import saccubus.worker.impl.download.DownloadResult;
65 import saccubus.worker.profile.CommentProfile;
66 import saccubus.worker.profile.ConvertProfile;
67 import saccubus.worker.profile.DownloadProfile;
68 import saccubus.worker.profile.FfmpegProfile;
69 import saccubus.worker.profile.GeneralProfile;
70 import saccubus.worker.profile.LoginProfile;
71 import saccubus.worker.profile.OutputProfile;
72 import saccubus.worker.profile.ProxyProfile;
73 import saccubus.worker.profile.VideoProfile;
74 import yukihane.Util;
75 import yukihane.inqubus.Config;
76 import yukihane.inqubus.manager.RequestProcess;
77 import yukihane.inqubus.manager.TaskKind;
78 import yukihane.inqubus.manager.TaskManage;
79 import yukihane.inqubus.manager.TaskManageListener;
80 import yukihane.inqubus.manager.TaskStatus;
81 import yukihane.inqubus.model.Target;
82 import yukihane.inqubus.model.TargetsTableModel;
83
84 /**
85  *
86  * @author yuki
87  */
88 public class MainFrame extends JFrame {
89
90     private static final long serialVersionUID = 1L;
91     private static final Logger logger = Logger.getLogger(MainFrame.class.getName());
92     private static final String ID_FIELD_TOOLTIP = "動画のIDまたはURLを入力します。";
93     private static final String FILE_LOCALBUTTON_TOOLTIP
94             = "<html>ダウンロードする場合はチェックを外します。<br/>ローカルファイルを使用する場合はチェックを入れます。</html>";
95     private static final String FILE_INPUTFIELD_TOOLTIP
96             = "<html>ダウンロードする場合はファイル命名規則を入力します。<br/>"
97             + "ローカルファイルを使用する場合はパスを含むファイル名を入力します。</html>";
98     private static final String FILE_OUTPUTFIELD_TOOLTIP
99             = "ファイル命名規則入力します。";
100     private final TargetsTableModel targetModel = new TargetsTableModel();
101     private final TaskManage taskManager;
102
103     /** Creates new form MainFrame */
104     public MainFrame() {
105         final URL url = MainFrame_AboutBox.class.getResource("icon.png");
106         final Image icon1 = Toolkit.getDefaultToolkit().createImage(url);
107         final URL url32 = MainFrame_AboutBox.class.getResource("icon32.png");
108         final Image icon2 = Toolkit.getDefaultToolkit().createImage(url32);
109         final List<Image> images = new ArrayList<Image>(2);
110         images.add(icon1);
111         images.add(icon2);
112         setIconImages(images);
113
114         final JPanel pnlMain = new JPanel();
115         final JScrollPane scrDisplay = new JScrollPane();
116         tblDisplay = new JTable(targetModel, new TargetsColumnModel());
117         tblDisplay.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
118         final JPanel pnlButton = new JPanel();
119         final JTabbedPane tbpInput = new JTabbedPane();
120         final JPanel pnlInputMain = new JPanel();
121         final JLabel lblId = new JLabel();
122         fldId.setToolTipText(ID_FIELD_TOOLTIP);
123         final JLabel lblVideo = new JLabel();
124         cbVideoLocal = new JCheckBox();
125         cbVideoLocal.setToolTipText(FILE_LOCALBUTTON_TOOLTIP);
126         fldVideo = new JTextField();
127         fldVideo.setToolTipText(FILE_INPUTFIELD_TOOLTIP);
128         final JLabel lblComment = new JLabel();
129
130         fldBackLog.setToolTipText("YYYY/MM/DD hh:mm:ss形式、あるいは1970/01/01からの経過秒を入力します。");
131         cbBackLog.addItemListener(new ItemListener() {
132
133             @Override
134             public void itemStateChanged(ItemEvent e) {
135                 final boolean selected = (e.getStateChange() == ItemEvent.SELECTED);
136                 fldBackLog.setEnabled(selected);
137             }
138         });
139         cbBackLog.addPropertyChangeListener("enabled", new PropertyChangeListener() {
140
141             @Override
142             public void propertyChange(PropertyChangeEvent evt) {
143                 final boolean enabled = ((Boolean) evt.getNewValue()).booleanValue();
144                 final boolean fldEnabled = enabled ? cbBackLog.isSelected() : false;
145                 fldBackLog.setEnabled(fldEnabled);
146             }
147         });
148         cbBackLogReduce.setToolTipText("「コメントの量を減らす」場合はチェックを付けます。");
149
150         cbCommentLocal = new JCheckBox();
151         cbCommentLocal.setToolTipText(FILE_LOCALBUTTON_TOOLTIP);
152         cbCommentLocal.addItemListener(new ItemListener() {
153
154             @Override
155             public void itemStateChanged(ItemEvent e) {
156                 final boolean selected = (e.getStateChange() == ItemEvent.SELECTED);
157                 cbBackLogReduce.setEnabled(!selected);
158                 cbBackLog.setEnabled(!selected);
159             }
160         });
161         fldComment = new JTextField();
162         fldComment.setToolTipText(FILE_INPUTFIELD_TOOLTIP);
163         final JLabel lblOutput = new JLabel();
164         cbOutputEnable = new JCheckBox();
165         fldOutput = new JTextField();
166         fldOutput.setToolTipText(FILE_OUTPUTFIELD_TOOLTIP);
167
168         setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
169
170         btnStop.addActionListener(new StopActionListener());
171         final ApplyActionListener applyListener = new ApplyActionListener();
172         btnApply.addActionListener(applyListener);
173
174         pnlMain.setBorder(BorderFactory.createEtchedBorder());
175
176         tblDisplay.setDropMode(DropMode.INSERT_ROWS);
177         scrDisplay.setViewportView(tblDisplay);
178
179         pnlButton.setBorder(BorderFactory.createEtchedBorder());
180
181         GroupLayout gl_pnlButton = new GroupLayout(pnlButton);
182         pnlButton.setLayout(gl_pnlButton);
183         gl_pnlButton.setHorizontalGroup(
184             gl_pnlButton.createParallelGroup(Alignment.LEADING)
185             .addGroup(gl_pnlButton.createSequentialGroup()
186                 .addContainerGap()
187                 .addComponent(btnStart)
188                 .addPreferredGap(ComponentPlacement.RELATED)
189                 .addComponent(btnStop)
190                 .addPreferredGap(ComponentPlacement.RELATED, 250, Short.MAX_VALUE)
191                 .addComponent(btnDeselect)
192                 .addContainerGap())
193         );
194         gl_pnlButton.setVerticalGroup(
195             gl_pnlButton.createParallelGroup(Alignment.LEADING)
196             .addGroup(gl_pnlButton.createSequentialGroup()
197                 .addContainerGap()
198                 .addGroup(gl_pnlButton.createParallelGroup(Alignment.BASELINE)
199                     .addComponent(btnStart)
200                     .addComponent(btnStop)
201                     .addComponent(btnDeselect))
202                 .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
203         );
204
205         lblId.setText("ID");
206
207         fldId.addActionListener(applyListener);
208         fldId.addFocusListener(new java.awt.event.FocusAdapter() {
209
210             public void focusLost(java.awt.event.FocusEvent evt) {
211                 idFieldFocusLost(evt);
212             }
213         });
214
215         lblVideo.setText("動画");
216
217         cbVideoLocal.setText("local");
218         cbVideoLocal.addItemListener(new java.awt.event.ItemListener() {
219
220             public void itemStateChanged(java.awt.event.ItemEvent evt) {
221                 useMovieLocalCheckBoxItemStateChanged(evt);
222             }
223         });
224
225         lblComment.setText("コメント");
226
227         cbCommentLocal.setText("local");
228         cbCommentLocal.addItemListener(new java.awt.event.ItemListener() {
229
230             public void itemStateChanged(java.awt.event.ItemEvent evt) {
231                 useMovieLocalCheckBoxItemStateChanged(evt);
232             }
233         });
234
235         lblOutput.setText("出力");
236
237         cbOutputEnable.setText("変換");
238         cbOutputEnable.addItemListener(new java.awt.event.ItemListener() {
239
240             public void itemStateChanged(java.awt.event.ItemEvent evt) {
241                 outputConvertCheckBoxItemStateChanged(evt);
242             }
243         });
244
245
246         final GroupLayout glInputMain = new GroupLayout(pnlInputMain);
247         pnlInputMain.setLayout(glInputMain);
248         glInputMain.setHorizontalGroup(
249             glInputMain.createParallelGroup(Alignment.LEADING)
250             .addGroup(glInputMain.createSequentialGroup()
251                 .addContainerGap()
252                 .addComponent(lblId)
253                 .addPreferredGap(ComponentPlacement.RELATED)
254                 .addComponent(fldId, GroupLayout.PREFERRED_SIZE, 100, Short.MAX_VALUE)
255                 .addPreferredGap(ComponentPlacement.UNRELATED)
256                 .addComponent(cbBackLogReduce)
257                 .addPreferredGap(ComponentPlacement.UNRELATED)
258                 .addComponent(cbBackLog)
259                 .addPreferredGap(ComponentPlacement.RELATED)
260                 .addComponent(fldBackLog, GroupLayout.PREFERRED_SIZE, 150, GroupLayout.PREFERRED_SIZE)
261                 .addContainerGap()
262             )
263             .addGroup(glInputMain.createSequentialGroup()
264                 .addContainerGap()
265                 .addGroup(glInputMain.createParallelGroup(Alignment.LEADING)
266                     .addComponent(lblVideo)
267                     .addComponent(lblComment)
268                     .addComponent(lblOutput)
269                 )
270                 .addPreferredGap(ComponentPlacement.RELATED)
271                 .addGroup(glInputMain.createParallelGroup(Alignment.LEADING)
272                     .addComponent(cbVideoLocal)
273                     .addComponent(cbCommentLocal)
274                     .addComponent(cbOutputEnable)
275                 )
276                 .addPreferredGap(ComponentPlacement.RELATED)
277                 .addGroup(glInputMain.createParallelGroup(Alignment.LEADING)
278                     .addComponent(fldVideo, GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE)
279                     .addComponent(fldComment, GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE)
280                     .addComponent(fldOutput, GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE)
281                 )
282                 .addContainerGap()
283             )
284         );
285
286         glInputMain.setVerticalGroup(
287             glInputMain.createParallelGroup(Alignment.LEADING)
288             .addGroup(glInputMain.createSequentialGroup()
289                 .addContainerGap()
290                 .addGroup(glInputMain.createParallelGroup(Alignment.BASELINE)
291                     .addComponent(fldId, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
292                     .addComponent(lblId)
293                     .addComponent(cbBackLogReduce)
294                     .addComponent(cbBackLog)
295                     .addComponent(fldBackLog)
296                 )
297                 .addPreferredGap(ComponentPlacement.RELATED)
298                 .addGroup(glInputMain.createParallelGroup(Alignment.BASELINE)
299                     .addComponent(lblVideo)
300                     .addComponent(fldVideo, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
301                     .addComponent(cbVideoLocal))
302                 .addPreferredGap(ComponentPlacement.RELATED)
303                 .addGroup(glInputMain.createParallelGroup(Alignment.BASELINE)
304                     .addComponent(lblComment)
305                     .addComponent(fldComment, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
306                     .addComponent(cbCommentLocal))
307                 .addPreferredGap(ComponentPlacement.RELATED)
308                 .addGroup(glInputMain.createParallelGroup(Alignment.BASELINE)
309                     .addComponent(lblOutput)
310                     .addComponent(fldOutput, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
311                     .addComponent(cbOutputEnable)
312                 )
313             )
314         );
315
316         // ffmpeg入力パネル
317         pnlInputFfmpeg.fldFfmpegOptionResizeWidth.setEnabled(false);
318         pnlInputFfmpeg.fldFfmpegOptionResizeHeight.setEnabled(false);
319         pnlInputFfmpeg.cbFfmpegOptionKeepAspect.setEnabled(false);
320         pnlInputFfmpeg.cmbFfmpegOptionFile.addActionListener(new ActionListener() {
321
322             @Override
323             public void actionPerformed(ActionEvent e) {
324                 final boolean notFile = !pnlInputFfmpeg.mdlFfmpegOption.isFile();
325                 pnlInputFfmpeg.fldFfmpegOptionExtension.setEnabled(notFile);
326                 pnlInputFfmpeg.fldFfmpegOptionMain.setEnabled(notFile);
327                 pnlInputFfmpeg.fldFfmpegOptionIn.setEnabled(notFile);
328                 pnlInputFfmpeg.fldFfmpegOptionOut.setEnabled(notFile);
329                 pnlInputFfmpeg.fldFfmpegOptionAv.setEnabled(notFile);
330                 pnlInputFfmpeg.cbFfmpegOptionResize.setEnabled(notFile);
331             }
332         });
333         pnlInputFfmpeg.cbFfmpegOptionResize.addItemListener(new ItemListener() {
334
335             @Override
336             public void itemStateChanged(ItemEvent e) {
337                 final boolean selected = (e.getStateChange() == ItemEvent.SELECTED);
338                 pnlInputFfmpeg.fldFfmpegOptionResizeWidth.setEnabled(selected);
339                 pnlInputFfmpeg.fldFfmpegOptionResizeHeight.setEnabled(selected);
340                 pnlInputFfmpeg.cbFfmpegOptionKeepAspect.setEnabled(selected);
341             }
342         });
343         pnlInputFfmpeg.cbFfmpegOptionResize.addPropertyChangeListener("enabled", new PropertyChangeListener() {
344
345             @Override
346             public void propertyChange(PropertyChangeEvent evt) {
347                 final boolean enabled = ((Boolean) evt.getNewValue()).booleanValue();
348                 final boolean fldEnabled = enabled ? pnlInputFfmpeg.cbFfmpegOptionResize.isSelected() : false;
349                 pnlInputFfmpeg.fldFfmpegOptionResizeWidth.setEnabled(fldEnabled);
350                 pnlInputFfmpeg.fldFfmpegOptionResizeHeight.setEnabled(fldEnabled);
351                 pnlInputFfmpeg.cbFfmpegOptionKeepAspect.setEnabled(fldEnabled);
352             }
353         });
354
355
356         tbpInput.add("メイン", pnlInputMain);
357         tbpInput.add("ffmpeg", pnlInputFfmpeg);
358
359         // 入力部のボタンやメッセージ表示部
360         fldInputMessage.setEditable(false);
361         fldInputMessage.setEnabled(false);
362         fldInputMessage.setBorder(BorderFactory.createEmptyBorder());
363
364         final JPanel pnlInputButton = new JPanel();
365         final GroupLayout glInputButton = new GroupLayout(pnlInputButton);
366         pnlInputButton.setLayout(glInputButton);
367         glInputButton.setHorizontalGroup(glInputButton.createSequentialGroup()
368             .addContainerGap()
369             .addComponent(fldInputMessage, GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE)
370             .addPreferredGap(ComponentPlacement.UNRELATED)
371             .addComponent(btnApply)
372             .addContainerGap()
373         );
374         glInputButton.setVerticalGroup(glInputButton.createSequentialGroup()
375             .addContainerGap()
376             .addGroup(glInputButton.createParallelGroup(Alignment.BASELINE)
377                 .addComponent(fldInputMessage, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
378                 .addComponent(btnApply)
379             )
380             .addContainerGap()
381         );
382
383         // 画面下半分の入力部分
384         final JPanel pnlInputAll = new JPanel();
385         pnlInputAll.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
386         final GroupLayout glInputAll = new GroupLayout(pnlInputAll);
387         pnlInputAll.setLayout(glInputAll);
388         glInputAll.setHorizontalGroup(glInputAll.createParallelGroup()
389             .addComponent(tbpInput)
390             .addComponent(pnlInputButton)
391         );
392         glInputAll.setVerticalGroup(glInputAll.createSequentialGroup()
393             .addComponent(tbpInput)
394             .addComponent(pnlInputButton)
395         );
396
397         GroupLayout gl_pnlMain = new GroupLayout(pnlMain);
398         pnlMain.setLayout(gl_pnlMain);
399         gl_pnlMain.setHorizontalGroup(
400             gl_pnlMain.createParallelGroup(Alignment.LEADING)
401             .addGroup(Alignment.TRAILING, gl_pnlMain.createSequentialGroup()
402                 .addContainerGap()
403                 .addGroup(gl_pnlMain.createParallelGroup(Alignment.TRAILING)
404                     .addComponent(scrDisplay, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, 480, Short.MAX_VALUE)
405                     .addComponent(pnlButton, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
406                     .addComponent(pnlInputAll, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
407                 )
408                 .addContainerGap())
409         );
410         gl_pnlMain.setVerticalGroup(
411             gl_pnlMain.createParallelGroup(Alignment.LEADING)
412             .addGroup(Alignment.TRAILING, gl_pnlMain.createSequentialGroup()
413                 .addContainerGap()
414                 .addComponent(scrDisplay, GroupLayout.DEFAULT_SIZE, 197, Short.MAX_VALUE)
415                 .addPreferredGap(ComponentPlacement.RELATED)
416                 .addComponent(pnlButton, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
417                 .addPreferredGap(ComponentPlacement.RELATED)
418                 .addComponent(pnlInputAll, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
419                 .addContainerGap()
420             )
421         );
422
423
424         JMenuBar menuBar = initMenuBar();
425         setJMenuBar(menuBar);
426
427         GroupLayout layout = new GroupLayout(getContentPane());
428         getContentPane().setLayout(layout);
429         layout.setHorizontalGroup(
430             layout.createParallelGroup(Alignment.LEADING)
431             .addComponent(pnlMain, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
432         );
433         layout.setVerticalGroup(
434             layout.createParallelGroup(Alignment.LEADING)
435             .addComponent(pnlMain, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
436         );
437
438         pack();
439         initInputPanel();
440         pnlMain.setTransferHandler(new DownloadListTransferHandler());
441         tblDisplay.setTransferHandler(new TableTransferHandler());
442
443         final Config p = Config.INSTANCE;
444         final int thDownload = p.getSystemDownloadThread();
445         final int secDownload = p.getSystemDownloadWait();
446         final int thConvert = p.getSystemConvertThread();
447         taskManager = new TaskManage(thDownload, secDownload,thConvert, new GuiTaskManageListener());
448     }
449
450     private class GuiTaskManageListener implements TaskManageListener {
451
452         @Override
453         public void process(final int id, final TaskKind kind, final TaskStatus status, final double percentage,
454                 final String message) {
455             SwingUtilities.invokeLater(new Runnable() {
456
457                 @Override
458                 public void run() {
459                     targetModel.setStatus(id, kind, status, percentage, message);
460                 }
461             });
462         }
463     }
464
465     private class StopActionListener implements ActionListener {
466
467         @Override
468         public void actionPerformed(ActionEvent e) {
469             final int row = tblDisplay.getSelectedRow();
470             final Target t = targetModel.getTarget(row);
471             final boolean res = taskManager.cancel(t.getRowId());
472             logger.log(Level.FINE, "停止: {0} {1}", new Object[]{t.getVideoId(), res});
473             if (res) {
474                 targetModel.setStatus(t.getRowId(), null, TaskStatus.CANCELLED, -1.0, "キャンセル");
475             }
476         }
477     }
478
479     private class ApplyActionListener implements ActionListener {
480
481         @Override
482         public void actionPerformed(ActionEvent e) {
483             try {
484                 final DownloadProfile downProf = new InqubusDownloadProfile();
485                 final String id = Util.getVideoId(fldId.getText());
486                 final InqubusConvertProfile convProf = new InqubusConvertProfile();
487                 logger.log(Level.INFO, downProf.toString());
488                 logger.log(Level.INFO, convProf.toString());
489                 final RequestProcess rp = new RequestProcess(downProf, id, convProf);
490                 taskManager.add(rp);
491                 targetModel.addTarget(new Target(rp));
492                 initInputPanel();
493             } catch (Throwable th) {
494                 logger.log(Level.SEVERE, null, th);
495                 JOptionPane.showMessageDialog(MainFrame.this, th.getMessage(), "中断しました", JOptionPane.ERROR_MESSAGE);
496             }
497         }
498     }
499
500     private File searchFileMatchId(final File dir, final String id) {
501         // TODO 候補は複数返すようにして、その後の対処は呼び出しもとで行ってもらった方が良いかも
502         if (id.isEmpty()) {
503             return null;
504         }
505
506         final File[] lists = dir.listFiles(new FilenameFilter() {
507
508             final Pattern pattern = Pattern.compile(id + "\\D");
509
510             @Override
511             public boolean accept(File dir, String name) {
512                 return pattern.matcher(name).find();
513             }
514         });
515
516         if (lists.length == 1) {
517             return lists[0];
518         } else if (lists.length > 1) {
519             throw new UnsupportedOperationException();
520         } else {
521             return null;
522         }
523     }
524
525     /**
526      * 動画, コメントの"local"チェックボックス更新時の処理.
527      */
528     private void useMovieLocalCheckBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_useMovieLocalCheckBoxItemStateChanged
529         final Config p = Config.INSTANCE;
530
531         final ItemSelectable source = evt.getItemSelectable();
532
533         JTextField field;
534         File dir;
535         if (source == cbVideoLocal) {
536             field = fldVideo;
537             dir = new File(p.getVideoDir());
538         } else {
539             field = fldComment;
540             dir = new File(p.getCommentDir());
541         }
542
543         final boolean useLocal = (evt.getStateChange() == ItemEvent.SELECTED);
544
545         String text;
546         if (useLocal) {
547             final File f = searchFileMatchId(dir, fldId.getText());
548             if (f != null) {
549                 text = f.getPath();
550             } else {
551                 text = "";
552             }
553         } else {
554             text = p.getVideoFileNamePattern();
555         }
556         field.setText(text);
557
558     }//GEN-LAST:event_useMovieLocalCheckBoxItemStateChanged
559
560     private void outputConvertCheckBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_outputConvertCheckBoxItemStateChanged
561         final boolean convert = (evt.getStateChange() == ItemEvent.SELECTED);
562         fldOutput.setEnabled(convert);
563     }//GEN-LAST:event_outputConvertCheckBoxItemStateChanged
564
565     private void idFieldFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_idFieldFocusLost
566         final Config p = Config.INSTANCE;
567         final String id = fldId.getText();
568         if (id.isEmpty()) {
569             return;
570         }
571
572         if (cbVideoLocal.isSelected() && fldVideo.getText().isEmpty()) {
573             final File dir = new File(p.getVideoDir());
574             final File file = searchFileMatchId(dir, id);
575             if (file != null) {
576                 fldVideo.setText(file.getPath());
577             }
578         }
579
580         if (cbCommentLocal.isSelected() && fldComment.getText().isEmpty()) {
581             final File dir = new File(p.getCommentDir());
582             final File file = searchFileMatchId(dir, id);
583             if (file != null) {
584                 fldComment.setText(file.getPath());
585             }
586         }
587
588     }//GEN-LAST:event_idFieldFocusLost
589     // Variables declaration - do not modify//GEN-BEGIN:variables
590     private final JTable tblDisplay;
591     // ボタン領域
592     private final JButton btnStart = new JButton("開始");
593     private final JButton btnStop = new JButton("停止");
594     private final JButton btnDeselect = new JButton("選択解除");
595     // 入力領域 - メイン
596     private final JTextField fldId = new JTextField();
597     private final JCheckBox cbBackLogReduce = new JCheckBox("コメ数減少");
598     private final JCheckBox cbBackLog = new JCheckBox("過去ログ");
599     private final JTextField fldBackLog = new JTextField();
600     private final JCheckBox cbVideoLocal;
601     private final JTextField fldVideo;
602     private final JCheckBox cbCommentLocal;
603     private final JTextField fldComment;
604     private final JCheckBox cbOutputEnable;
605     private final JTextField fldOutput;
606     // 入力領域 - ffmpeg
607     private final FfmpegParamPanel pnlInputFfmpeg = new FfmpegParamPanel();
608     // 適用
609     private final JTextField fldInputMessage = new JTextField();
610     private final JButton btnApply = new JButton("適用");
611     // End of variables declaration//GEN-END:variables
612
613     private void initInputPanel() {
614         initMainTab();
615         initFfmpegTab();
616     }
617
618     private void initMainTab() {
619         final Config p = Config.INSTANCE;
620
621         fldId.setText("");
622         fldBackLog.setEnabled(false);
623         cbBackLog.setEnabled(true);
624
625         final boolean movieLocal = p.getVideoUseLocal();
626         cbVideoLocal.setSelected(movieLocal);
627         if (!movieLocal) {
628             fldVideo.setText(p.getVideoFileNamePattern());
629         }
630
631         final boolean commentLocal = p.getCommentUseLocal();
632         cbCommentLocal.setSelected(commentLocal);
633         if (!commentLocal) {
634             fldComment.setText(p.getCommentFileNamePattern());
635         }
636
637         final boolean convert = p.getOutputEnable();
638         cbOutputEnable.setSelected(convert);
639         fldOutput.setEnabled(convert);
640         fldOutput.setText(p.getOutputFileNamePattern());
641     }
642
643     private void initFfmpegTab() {
644         pnlInputFfmpeg.init(Config.INSTANCE);
645     }
646
647     private JMenuBar initMenuBar() {
648         final JMenuBar menuBar = new JMenuBar();
649
650         final JMenu mnFile = new JMenu("ファイル(F)");
651         menuBar.add(mnFile);
652
653         final JMenuItem itExit = new JMenuItem("終了(X)", KeyEvent.VK_X);
654         itExit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, ActionEvent.CTRL_MASK));
655         itExit.addActionListener(new ActionListener() {
656
657             @Override
658             public void actionPerformed(ActionEvent e) {
659                 throw new UnsupportedOperationException("Not supported yet.");
660             }
661         });
662         mnFile.add(itExit);
663
664         final JMenu mnTool = new JMenu("ツール(T)");
665         menuBar.add(mnTool);
666
667         final JMenuItem itOption = new JMenuItem("オプション(O)...", KeyEvent.VK_O);
668         // TODO ショートカットキー
669         itOption.addActionListener(new ActionListener() {
670
671             @Override
672             public void actionPerformed(ActionEvent e) {
673                 final yukihane.inqubus.gui.ConfigDialog dlg = new yukihane.inqubus.gui.ConfigDialog(MainFrame.this);
674                 dlg.setLocationRelativeTo(MainFrame.this);
675                 dlg.setModal(true);
676                 dlg.setVisible(true);
677             }
678         });
679         mnTool.add(itOption);
680
681         final JMenu mnHelp = new JMenu("ヘルプ(H)");
682         menuBar.add(mnHelp);
683
684         final JMenuItem itAbout = new JMenuItem("このソフトウェアについて(A)...", KeyEvent.VK_A);
685         itAbout.addActionListener(new ActionListener() {
686
687             @Override
688             public void actionPerformed(ActionEvent e) {
689                 MainFrame_AboutBox dlg = new MainFrame_AboutBox(MainFrame.this);
690                 dlg.pack();
691                 dlg.setLocationRelativeTo(MainFrame.this);
692                 dlg.setModal(true);
693                 dlg.setVisible(true);
694             }
695         });
696         mnHelp.add(itAbout);
697
698         return menuBar;
699     }
700
701     private class DownloadProgressListener implements WorkerListener<DownloadResult, DownloadProgress> {
702
703         @Override
704         public void process(DownloadProgress progress) {
705             throw new UnsupportedOperationException("Not supported yet.");
706         }
707
708         @Override
709         public void cancelled() {
710             throw new UnsupportedOperationException("Not supported yet.");
711         }
712
713         @Override
714         public void done(DownloadResult result) {
715             throw new UnsupportedOperationException("Not supported yet.");
716         }
717
718         @Override
719         public void error(Throwable th) {
720             throw new UnsupportedOperationException("Not supported yet.");
721         }
722     }
723
724     private class ConvertProgressListener implements WorkerListener<ConvertResult, ConvertProgress> {
725
726         @Override
727         public void process(ConvertProgress progress) {
728             throw new UnsupportedOperationException("Not supported yet.");
729         }
730
731         @Override
732         public void cancelled() {
733             throw new UnsupportedOperationException("Not supported yet.");
734         }
735
736         @Override
737         public void done(ConvertResult result) {
738             throw new UnsupportedOperationException("Not supported yet.");
739         }
740
741         @Override
742         public void error(Throwable th) {
743             throw new UnsupportedOperationException("Not supported yet.");
744         }
745     }
746
747
748
749     private class DownloadListTransferHandler extends TransferHandler {
750
751         private static final long serialVersionUID = 1L;
752         private final Pattern movieIdPattern = Pattern.compile("(\\w\\w\\d+)");
753
754         @Override
755         public boolean canImport(TransferHandler.TransferSupport support) {
756             Transferable transferable = support.getTransferable();
757             if (transferable.isDataFlavorSupported(DataFlavor.javaFileListFlavor)
758                     || transferable.isDataFlavorSupported(DataFlavor.stringFlavor)) {
759                 return true;
760             }
761             return false;
762         }
763
764         @Override
765         public boolean importData(TransferHandler.TransferSupport support) {
766 //            try {
767 //                Transferable transferable = support.getTransferable();
768 //                if (transferable.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
769 //                    @SuppressWarnings("unchecked")
770 //                    final List<File> data = (List<File>) transferable.getTransferData(DataFlavor.javaFileListFlavor);
771 //                    Collection<Target> targets = Target.from(data);
772 //                    targetModel.addTarget(targets);
773 //                } else if (transferable.isDataFlavorSupported(DataFlavor.stringFlavor)) {
774 //                    String data = (String) transferable.getTransferData(DataFlavor.stringFlavor);
775 //                    Matcher matcher = movieIdPattern.matcher(data);
776 //                    if (matcher.find()) {
777 //                        String movieId = matcher.group(1);
778 //                        Target target = Target.fromId(movieId);
779 //                        targetModel.addTarget(target);
780 //                    } else {
781 //                        return false;
782 //                    }
783 //
784 //                }
785 //                return false;
786 //            } catch (Exception e) {
787 //                logger.log(Level.SEVERE, null, e);
788 //                return false;
789 //            }
790             // TODO 上記実装見直し(Locationは削除された)
791             return false;
792         }
793     }
794
795     private class TableTransferHandler extends DownloadListTransferHandler {
796
797         private static final long serialVersionUID = 1L;
798
799         @Override
800         public boolean canImport(TransferHandler.TransferSupport support) {
801             return super.canImport(support);
802         }
803
804         @Override
805         public boolean importData(TransferHandler.TransferSupport support) {
806             return super.importData(support);
807         }
808     }
809
810     /*
811      * ここからDownloadProfile作成用クラスの定義
812      */
813
814     private class InqubusDownloadProfile implements DownloadProfile {
815
816         private final LoginProfile loginProfile;
817         private final ProxyProfile proxyProfile;
818         private final VideoProfile videoProfile;
819         private final CommentProfile commentProfile;
820         private final GeneralProfile generalProfile;
821
822         private InqubusDownloadProfile() {
823             this.loginProfile = new InqubusLoginProfile();
824             this.proxyProfile = new InqubusProxyProfile();
825             this.videoProfile = new InqubusVideoProfile();
826             this.commentProfile = new InqubusCommentProfile();
827             this.generalProfile = new InqubusGeneralProfile();
828         }
829
830         @Override
831         public LoginProfile getLoginInfo() {
832             return this.loginProfile;
833         }
834
835         @Override
836         public ProxyProfile getProxyProfile() {
837             return this.proxyProfile;
838         }
839
840         @Override
841         public VideoProfile getVideoProfile() {
842             return this.videoProfile;
843         }
844
845         @Override
846         public CommentProfile getCommentProfile() {
847             return this.commentProfile;
848         }
849
850         @Override
851         public GeneralProfile getGeneralProfile() {
852             return this.generalProfile;
853         }
854
855         @Override
856         public String toString(){
857             return ToStringBuilder.reflectionToString(this);
858         }
859     }
860
861     private class InqubusLoginProfile implements LoginProfile {
862         private final String mail;
863         private final String password;
864
865         private InqubusLoginProfile(){
866             final Config p = Config.INSTANCE;
867             this.mail = p.getId();
868             this.password = p.getPassword();
869         }
870
871         @Override
872         public String getMail() {
873             return this.mail;
874         }
875
876         @Override
877         public String getPassword() {
878             return this.password;
879         }
880
881         @Override
882         public String toString(){
883             return ToStringBuilder.reflectionToString(this);
884         }
885     }
886
887     private class InqubusProxyProfile implements ProxyProfile {
888         private final boolean use;
889         private final String host;
890         private final int port;
891
892         private InqubusProxyProfile(){
893             final Config p = Config.INSTANCE;
894             this.use = p.getProxyUse();
895             this.host = p.getProxyHost();
896             final String pp = p.getProxyPort();
897             this.port = StringUtils.isBlank(pp) ? -1 : Integer.parseInt(pp);
898         }
899
900         @Override
901         public boolean use() {
902             return this.use;
903         }
904
905         @Override
906         public String getHost() {
907             return this.host;
908         }
909
910         @Override
911         public int getPort() {
912             return this.port;
913         }
914
915         @Override
916         public String toString(){
917             return ToStringBuilder.reflectionToString(this);
918         }
919     }
920
921     private class InqubusVideoProfile implements VideoProfile {
922         private final boolean download;
923         private final File dir;
924         private final String fileName;
925         private final File localFile;
926
927         private InqubusVideoProfile(){
928             final Config p = Config.INSTANCE;
929             this.download = !cbVideoLocal.isSelected();
930             if (this.download) {
931                 this.dir = new File(p.getVideoDir());
932                 this.fileName = fldVideo.getText();
933                 this.localFile = null;
934             } else {
935                 this.dir = null;
936                 this.fileName = null;
937                 this.localFile = new File(fldVideo.getText());
938             }
939         }
940
941         @Override
942         public boolean isDownload() {
943             return this.download;
944         }
945
946         @Override
947         public File getDir() {
948             return this.dir;
949         }
950
951         @Override
952         public String getFileName() {
953             return this.fileName;
954         }
955
956         @Override
957         public File getLocalFile() {
958             return this.localFile;
959         }
960
961         @Override
962         public String toString(){
963             return ToStringBuilder.reflectionToString(this);
964         }
965     }
966
967     private class InqubusCommentProfile implements CommentProfile {
968         private final boolean download;
969         private final File dir;
970         private final String fileName;
971         private final File localFile;
972         private final int lengthRelatedCommentSize;
973         private final boolean disablePerMinComment;
974         private final int perMinCommentSize;
975         private final long backLogPoint;
976
977         private InqubusCommentProfile() {
978             final Config p = Config.INSTANCE;
979             this.download = !cbCommentLocal.isSelected();
980             if (this.download) {
981                 this.dir = new File(p.getCommentDir());
982                 this.fileName = fldComment.getText();
983                 this.localFile = null;
984             } else {
985                 this.dir = null;
986                 this.fileName = null;
987                 this.localFile = new File(fldComment.getText());
988             }
989
990             if(cbBackLog.isSelected()) {
991                 try {
992                     this.backLogPoint = WayBackTimeParser.parse(fldBackLog.getText());
993                 } catch (IOException ex) {
994                     throw new IllegalArgumentException("過去ログ時刻指定が誤っています。", ex);
995                 }
996             } else {
997                 this.backLogPoint = -1L;
998             }
999
1000             this.disablePerMinComment = cbBackLogReduce.isSelected();
1001             this.lengthRelatedCommentSize
1002                     = (p.getCommentSizeAutosize()) ? -1 : Integer.parseInt(p.getCommentSizeManual());
1003             this.perMinCommentSize
1004                     = (p.getCommentMinSizeAutosize()) ? -1 : Integer.parseInt(p.getCommentMinSizeManual());
1005         }
1006
1007         @Override
1008         public boolean isDownload() {
1009             return this.download;
1010         }
1011
1012         @Override
1013         public File getDir() {
1014             return this.dir;
1015         }
1016
1017         @Override
1018         public String getFileName() {
1019             return this.fileName;
1020         }
1021
1022         @Override
1023         public File getLocalFile() {
1024             return this.localFile;
1025         }
1026
1027         @Override
1028         public int getLengthRelatedCommentSize() {
1029             return this.lengthRelatedCommentSize;
1030         }
1031
1032         @Override
1033         public boolean isDisablePerMinComment() {
1034             return this.disablePerMinComment;
1035         }
1036
1037         @Override
1038         public int getPerMinCommentSize() {
1039             return this.perMinCommentSize;
1040         }
1041
1042         @Override
1043         public long getBackLogPoint() {
1044             return this.backLogPoint;
1045         }
1046
1047         @Override
1048         public String toString(){
1049             return ToStringBuilder.reflectionToString(this);
1050         }
1051     }
1052
1053     private class InqubusGeneralProfile implements GeneralProfile {
1054         private final String replaceFrom;
1055         private final String replaceTo;
1056         private InqubusGeneralProfile() {
1057             final Config p = Config.INSTANCE;
1058             this.replaceFrom = p.getReplaceFrom();
1059             this.replaceTo = p.getReplaceTo();
1060         }
1061
1062         @Override
1063         public String getReplaceFrom() {
1064             return this.replaceFrom;
1065         }
1066
1067         @Override
1068         public String getReplaceTo() {
1069             return this.replaceTo;
1070         }
1071
1072         @Override
1073         public String toString(){
1074             return ToStringBuilder.reflectionToString(this);
1075         }
1076     }
1077
1078     /*
1079      * ここからConvertProfile作成用クラスの定義
1080      */
1081     private class InqubusConvertProfile implements ConvertProfile {
1082         private final OutputProfile outputProfile;
1083         private final GeneralProfile generalProfile;
1084         private final FfmpegProfile ffmpegProfile;
1085         private final boolean convert;
1086         private final File ffmpeg;
1087         private final boolean vhookDisabled;
1088         private final boolean commentOverlay;
1089         private final File vhook;
1090         private final File tmpDir;
1091         private final File font;
1092         private final int fontIndex;
1093         private final boolean commentOpaque;
1094         private final boolean disableFontSizeArrange;
1095         private final int shadowIndex;
1096         private final boolean showConvrting;
1097         private final int maxNumOfComment;
1098         private final HideCondition ngSetting;
1099
1100         private InqubusConvertProfile() throws IOException {
1101             final Config p = Config.INSTANCE;
1102             this.outputProfile = new InqubusOutputProfile();
1103             this.generalProfile = new InqubusGeneralProfile();
1104             this.ffmpegProfile = new InqubusFfmpegProfile();
1105             this.convert = cbOutputEnable.isSelected();
1106             this.ffmpeg = new File(p.getFfmpegPath());
1107             // TODO コンフィグに設定なし
1108             this.vhookDisabled = false;
1109             this.commentOverlay = p.getOutputCommentOverlay();
1110             this.vhook = new File(p.getFfmpegDllPath());
1111             this.tmpDir = new File(p.getSystemTempDir());
1112             this.font = new File(p.getFontPath());
1113             this.fontIndex = Integer.parseInt(p.getFontIndex());
1114             this.commentOpaque = p.getCommentOpaque();
1115             this.disableFontSizeArrange = p.getFontSizeArrangeDisable();
1116             this.shadowIndex = p.getFontShadow();
1117             // TODO コンフィグに設定なし
1118             this.showConvrting = true;
1119             this.maxNumOfComment = (p.getCommentDisplaySizeDefault()) ? -1 : Integer.parseInt(p.
1120                     getCommentDisplaySizeManual());
1121             this.ngSetting = new InqubusHideCondition();
1122         }
1123
1124         @Override
1125         public OutputProfile getOutputProfile() {
1126             return this.outputProfile;
1127         }
1128
1129         @Override
1130         public GeneralProfile getGeneralProfile() {
1131             return this.generalProfile;
1132         }
1133
1134         @Override
1135         public FfmpegProfile getFfmpegOption() {
1136             return this.ffmpegProfile;
1137         }
1138
1139         @Override
1140         public boolean isConvert() {
1141             return this.convert;
1142         }
1143
1144         @Override
1145         public File getFfmpeg() {
1146             return this.ffmpeg;
1147         }
1148
1149         @Override
1150         public boolean isVhookDisabled() {
1151             return this.vhookDisabled;
1152         }
1153
1154         @Override
1155         public boolean isCommentOverlay() {
1156             return this.commentOverlay;
1157         }
1158
1159         @Override
1160         public File getVhook() {
1161             return this.vhook;
1162         }
1163
1164         @Override
1165         public File getTempDir() {
1166             return this.tmpDir;
1167         }
1168
1169         @Override
1170         public File getFont() {
1171             return this.font;
1172         }
1173
1174         @Override
1175         public int getFontIndex() {
1176             return this.fontIndex;
1177         }
1178
1179         @Override
1180         public boolean isCommentOpaque() {
1181             return this.commentOpaque;
1182         }
1183
1184         @Override
1185         public boolean isDisableFontSizeArrange() {
1186             return this.disableFontSizeArrange;
1187         }
1188
1189         @Override
1190         public int getShadowIndex() {
1191             return this.shadowIndex;
1192         }
1193
1194         @Override
1195         public boolean isShowConverting() {
1196             return this.showConvrting;
1197         }
1198
1199         @Override
1200         public int getMaxNumOfComment() {
1201             return this.maxNumOfComment;
1202         }
1203
1204         @Override
1205         public HideCondition getNgSetting() {
1206             return this.ngSetting;
1207         }
1208
1209         @Override
1210         public String toString(){
1211             return ToStringBuilder.reflectionToString(this);
1212         }
1213     }
1214
1215     private class InqubusOutputProfile implements OutputProfile {
1216         private final File dir;
1217         private final String fileName;
1218         private final String videoId;
1219         private final String title;
1220
1221
1222         private InqubusOutputProfile(){
1223             final Config p = Config.INSTANCE;
1224             this.dir = new File(p.getOutputDir());
1225             this.fileName = fldOutput.getText();
1226             // TODO この時点でのID/Titleはどうするか…
1227             this.videoId = "";
1228             this.title = "";
1229         }
1230
1231         @Override
1232         public File getDir() {
1233             return this.dir;
1234         }
1235
1236         @Override
1237         public String getFileName() {
1238             return this.fileName;
1239         }
1240
1241         @Override
1242         public String getVideoId() {
1243             return this.videoId;
1244         }
1245
1246         @Override
1247         public String getTitile() {
1248             return this.title;
1249         }
1250
1251         @Override
1252         public String toString(){
1253             return ToStringBuilder.reflectionToString(this);
1254         }
1255     }
1256
1257     private class InqubusFfmpegProfile implements FfmpegProfile {
1258         private final String extOption;
1259         private final String inOption;
1260         private final String mainOption;
1261         private final String outOption;
1262         private final String avOption;
1263         private final boolean resize;
1264         private final int resizeWidth;
1265         private final int resizeHeight;
1266         private final boolean adjustRatio;
1267
1268         private InqubusFfmpegProfile() throws IOException {
1269             final File file = pnlInputFfmpeg.mdlFfmpegOption.getSelectedFile();
1270             if (file != null) {
1271                 final FfmpegOption ffop = FfmpegOption.load(file);
1272                 this.extOption = ffop.getExtOption();
1273                 this.inOption = ffop.getInOption();
1274                 this.mainOption = ffop.getMainOption();
1275                 this.outOption = ffop.getMainOption();
1276                 this.avOption = ffop.getAvfilterOption();
1277                 this.resize = ffop.isResize();
1278                 this.resizeWidth = ffop.getResizeWidth();
1279                 this.resizeHeight = ffop.getResizeHeight();
1280                 this.adjustRatio = ffop.isAdjustRatio();
1281             } else {
1282                 this.extOption = pnlInputFfmpeg.fldFfmpegOptionExtension.getText();
1283                 this.inOption = pnlInputFfmpeg.fldFfmpegOptionIn.getText();
1284                 this.mainOption = pnlInputFfmpeg.fldFfmpegOptionMain.getText();
1285                 this.outOption = pnlInputFfmpeg.fldFfmpegOptionOut.getText();
1286                 this.avOption = pnlInputFfmpeg.fldFfmpegOptionAv.getText();
1287                 this.resize = pnlInputFfmpeg.cbFfmpegOptionResize.isSelected();
1288                 this.resizeWidth = Integer.parseInt(pnlInputFfmpeg.fldFfmpegOptionResizeWidth.getText());
1289                 this.resizeHeight = Integer.parseInt(pnlInputFfmpeg.fldFfmpegOptionResizeHeight.getText());
1290                 this.adjustRatio = pnlInputFfmpeg.cbFfmpegOptionKeepAspect.isSelected();
1291             }
1292         }
1293
1294         @Override
1295         public String getExtOption() {
1296             return this.extOption;
1297         }
1298
1299         @Override
1300         public String getInOption() {
1301             return this.inOption;
1302         }
1303
1304         @Override
1305         public String getMainOption() {
1306             return this.mainOption;
1307         }
1308
1309         @Override
1310         public String getOutOption() {
1311             return this.outOption;
1312         }
1313
1314         @Override
1315         public String getAvfilterOption() {
1316             return this.avOption;
1317         }
1318
1319         @Override
1320         public boolean isResize() {
1321             return this.resize;
1322         }
1323
1324         @Override
1325         public int getResizeWidth() {
1326             return this.resizeWidth;
1327         }
1328
1329         @Override
1330         public int getResizeHeight() {
1331             return this.resizeHeight;
1332         }
1333
1334         @Override
1335         public boolean isAdjustRatio() {
1336             return this.adjustRatio;
1337         }
1338
1339         @Override
1340         public String toString(){
1341             return ToStringBuilder.reflectionToString(this);
1342         }
1343     }
1344
1345     private class InqubusHideCondition implements ConvertProfile.HideCondition{
1346
1347         @Override
1348         public String getWord() {
1349             // TODO
1350             return "";
1351         }
1352
1353         @Override
1354         public String getId() {
1355             // TODO
1356             return "";
1357         }
1358
1359         @Override
1360         public String toString(){
1361             return ToStringBuilder.reflectionToString(this);
1362         }
1363     }
1364 }