• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

タイニー番組ナビゲータ本体


Commit MetaInfo

Revision5514c5c3a0df8a22ec8f0eba27e9df9f77050d87 (tree)
Zeit2019-06-15 00:35:27
AutorMasahiko Kimura <mkimura@u01....>
CommiterMasahiko Kimura

Log Message

Ver.1.12 (2019/06/15):

  1. [新聞形式]改ページしないとページャーが正しく機能しない問題の対応
  2. [新聞形式]番組ジャンプ機能で左端の放送局の番組に正しくジャンプできない問題の対応
  3. [ツールバー]「一括予約」ボタンがリスト形式タブのリストが未選択でもEnableになる問題の対応
  4. [番組情報]起動時に可能なら高速キャッシュファイルから番組情報をロードする
  5. [番組情報]キャッシュファイルからロードした時は過去ログに出力しない
  6. [新聞形式]「現在放送中」ノード選択中でもページ切替時はスクロール位置を調整しない
  7. [タイトル一覧]「コピー」「DLNA_OID」欄を追加する
  8. [その他]予約した番組が始まる前にメッセージを通知できるようにする
  9. [その他]エラーログは赤色で表示する

Ändern Zusammenfassung

Diff

--- a/TinyBannavi/src/tainavi/AbsChannelSortView.java
+++ b/TinyBannavi/src/tainavi/AbsChannelSortView.java
@@ -762,8 +762,8 @@ public abstract class AbsChannelSortView extends JScrollPane {
762762 }
763763
764764 // 1行ごとに背景色を互い違いにする。またソートが無効な場合はグレーアウト
765- int page = 1 + getPageIndex(1+this.convertRowIndexToView(row));
766- int pagemax = 1 + getPageIndex(rowData.size());
765+ int page = 1 + getPageIndex(this.convertRowIndexToView(row));
766+ int pagemax = 1 + getPageIndex(rowData.size()-1);
767767 String color = ( ! jtgl_chsort.isSelected())?(PAGEDIS_COLOR):((page % 2 == 0)?(PAGEEN_ODD_COLOR):(PAGEEN_EVEN_COLOR));
768768 String text = String.format("%d / %d", page, pagemax);
769769 return CommonSwingUtils.getColoredString(color, text);
@@ -786,7 +786,7 @@ public abstract class AbsChannelSortView extends JScrollPane {
786786 public int getPageIndex(int n) {
787787 if (pageBreaks.size() > 0){
788788 for (int pno=0; pno<pageBreaks.size(); pno++){
789- if (n <= pageBreaks.get(pno)){
789+ if (n < pageBreaks.get(pno)){
790790 return pno;
791791 }
792792 }
@@ -795,6 +795,6 @@ public abstract class AbsChannelSortView extends JScrollPane {
795795 }
796796
797797 int rem = n % centerPerPage;
798- return (n-rem)/centerPerPage + ((rem==0)?(0):(1)) - 1;
798+ return (n-rem)/centerPerPage;
799799 }
800800 }
--- a/TinyBannavi/src/tainavi/AbsListedView.java
+++ b/TinyBannavi/src/tainavi/AbsListedView.java
@@ -113,6 +113,7 @@ public abstract class AbsListedView extends JPanel implements TickTimerListener
113113
114114 protected abstract void ringBeep();
115115
116+ protected abstract void updateBatchReservationEnabled();
116117 // クラス内のイベントから呼び出されるもの
117118
118119 /**
@@ -1700,6 +1701,8 @@ public abstract class AbsListedView extends JPanel implements TickTimerListener
17001701 jTextPane_detail.setLabel("","","");
17011702 jTextPane_detail.setText("");
17021703 }
1704+
1705+ updateBatchReservationEnabled();
17031706 }
17041707 };
17051708
@@ -2440,6 +2443,13 @@ public abstract class AbsListedView extends JPanel implements TickTimerListener
24402443 }
24412444 }
24422445
2446+ /*
2447+ * リストの選択行を取得する
2448+ */
2449+ public int getSelectedRowCount(){
2450+ return jTable_listed.getSelectedRowCount();
2451+ }
2452+
24432453 /**
24442454 * 他のクラスで発生したイベント中に呼び出されてリスト形式の予約マーク表示を更新するためのメソッド。
24452455 * ★synchronized(rowData)★
@@ -3990,7 +4000,7 @@ public abstract class AbsListedView extends JPanel implements TickTimerListener
39904000 ter.load();
39914001 }
39924002 catch (Exception e) {
3993- MWin.appendMessage(ERRID+"ツリー展開情報の解析で問題が発生しました");
4003+ MWin.appendError(ERRID+"ツリー展開情報の解析で問題が発生しました");
39944004 e.printStackTrace();
39954005 }
39964006
--- a/TinyBannavi/src/tainavi/AbsPaperView.java
+++ b/TinyBannavi/src/tainavi/AbsPaperView.java
@@ -595,18 +595,33 @@ public abstract class AbsPaperView extends JPanel implements TickTimerListener,H
595595 return true;
596596 }
597597
598+ /**
599+ * ページャーの選択変更により描画する
600+ */
601+ public void redrawByPager() {
602+ Point vp = vport.getViewPosition();
603+ Dimension vs = vport.getSize();
604+
605+ redrawByCurrentSelection();
606+
607+ jLayeredPane_space_main_view.scrollRectToVisible(new Rectangle(vp, vs));
608+ }
609+
598610 /*
599611 * 現在の選択状態で再描画する
600612 */
601613 public void redrawByCurrentSelection() {
602614 TreePath path = jTree_tree.getSelectionPath();
615+ // 何も選択されていない場合
616+ if (path == null)
617+ return;
603618
604- if ( path != null && path.getPathCount() == 2 ) {
619+ if ( path.getPathCount() == 2 ) {
605620 // 親ノードとか触られても…
606621 return;
607622 }
608623
609- if ( path != null && path.getPathCount() == 3 ) {
624+ if ( path.getPathCount() == 3 ) {
610625
611626 if (env.getDebug()) System.out.println(DBGID+"SELECTED treeSelListner "+path);
612627
@@ -1549,7 +1564,7 @@ public abstract class AbsPaperView extends JPanel implements TickTimerListener,H
15491564 selectedpage = 0;
15501565 }
15511566 else {
1552- int maxindex = env.getPageIndex(pli.size());
1567+ int maxindex = env.getPageIndex(pli.size()-1);
15531568 if ( selectedpage > maxindex ) {
15541569 // ページ数かわったら、インデックスがはみだしちゃった
15551570 selectedpage = 0;
@@ -1565,7 +1580,7 @@ public abstract class AbsPaperView extends JPanel implements TickTimerListener,H
15651580 ringBeep();
15661581 crindex = 0;
15671582 }
1568- selectedpage = env.getPageIndex(1+crindex);
1583+ selectedpage = env.getPageIndex(crindex);
15691584 }
15701585
15711586 // 開始位置・終了位置・局数
@@ -1573,7 +1588,7 @@ public abstract class AbsPaperView extends JPanel implements TickTimerListener,H
15731588 colmax = colmin + env.getCentersInPage(selectedpage)-1;
15741589
15751590 // ページャーコンボボックスの書き換え
1576- setPagerItems(pli,env.getPageIndex(1+colmin));
1591+ setPagerItems(pli,env.getPageIndex(colmin));
15771592 pli.rewind();
15781593
15791594 // ページャーは有効だよ
@@ -2989,7 +3004,7 @@ public abstract class AbsPaperView extends JPanel implements TickTimerListener,H
29893004 ter.load();
29903005 }
29913006 catch (Exception e) {
2992- MWin.appendMessage(ERRID+"ツリー展開情報の解析で問題が発生しました");
3007+ MWin.appendError(ERRID+"ツリー展開情報の解析で問題が発生しました");
29933008 e.printStackTrace();
29943009 }
29953010
--- a/TinyBannavi/src/tainavi/AbsReserveDialog.java
+++ b/TinyBannavi/src/tainavi/AbsReserveDialog.java
@@ -359,12 +359,12 @@ abstract class AbsReserveDialog extends JEscCancelDialog implements HDDRecorderL
359359
360360 ReserveList myrsv = myrec.getReserveList(rsvId);
361361 if ( myrsv == null ) {
362- MWin.appendMessage(ERRID+"更新すべき予約情報が見つかりません: "+myself+", "+rsvId);
362+ MWin.appendError(ERRID+"更新すべき予約情報が見つかりません: "+myself+", "+rsvId);
363363 ringBeep();
364364 return false; // ここに来たらバグ
365365 }
366366 if ( myrsv.getCh_name() == null ) {
367- MWin.appendMessage(ERRID+"予約情報の放送局名が不正です: "+myrsv.getStartDateTime()+", "+myrsv.getTitle());
367+ MWin.appendError(ERRID+"予約情報の放送局名が不正です: "+myrsv.getStartDateTime()+", "+myrsv.getTitle());
368368 ringBeep();
369369 return false;
370370 }
--- a/TinyBannavi/src/tainavi/AbsReserveListView.java
+++ b/TinyBannavi/src/tainavi/AbsReserveListView.java
@@ -751,6 +751,72 @@ public abstract class AbsReserveListView extends JScrollPane implements TickTime
751751 this.getRowHeader().setVisible(b);
752752 }
753753
754+ /**
755+ * 通知すべき予約情報を取得する
756+ */
757+ public boolean getReservesToNotify(ArrayList<String>list) {
758+ list.clear();
759+
760+ String os = System.getProperty("os.name");
761+ boolean isWin10 = os != null && os.contains("Windows 10");
762+
763+ // 現在日時
764+ int min = env.getMinsBeforeProgStart();
765+ String dtmin = CommonUtils.getDateTime(min*60);
766+ String dtmax = CommonUtils.getDateTime((min+1)*60);
767+
768+ // 選択されたレコーダ
769+ HDDRecorderList recs = recorders.findInstance(getSelectedRecorderOnToolbar());
770+
771+ String bodyAll = "";
772+ String head = "予約済の番組が" + min + "分後に始まります\n";
773+
774+ for ( HDDRecorder recorder : recs ) {
775+ if ( recorder.isBackgroundOnly() ) {
776+ continue;
777+ }
778+
779+ // 並べ替えるために新しいリストを作成する
780+ for ( ReserveList ro : recorder.getReserves() ) {
781+ if (!ro.getExec())
782+ continue;
783+
784+ ArrayList<String> starts = new ArrayList<String>();
785+ ArrayList<String> ends = new ArrayList<String>();
786+ CommonUtils.getStartEndList(starts, ends, ro);
787+ if (starts.size() == 0)
788+ continue;
789+
790+ // 開始時刻、終了時刻
791+ String nextstart = CommonUtils.getDate(CommonUtils.getCalendar(starts.get(0)), false)+" "+ro.getAhh()+":"+ro.getAmm();
792+
793+ // 予約開始まで規定時間以内の場合
794+ if ( nextstart.compareTo(dtmin) >= 0 && nextstart.compareTo(dtmax) < 0 ) {
795+// String chname = (ro.getCh_name()!=null && ro.getCh_name().length()>0)?(ro.getCh_name()):("★放送局名不正("+ro.getChannel()+")");
796+// String length = ro.getRec_min();
797+ String title = ro.getTitle();
798+ String stime = ro.getAhh()+":"+ro.getAmm();
799+ String etime = ro.getZhh()+":"+ro.getZmm();
800+ String body =
801+ "「" + title + "」\n" +
802+ "(" + stime + "~" + etime + ")\n";
803+
804+ if (isWin10){
805+ list.add(head + body);
806+ }
807+ else{
808+ bodyAll += body;
809+ }
810+ }
811+ }
812+ }
813+
814+ if (!isWin10 && !bodyAll.isEmpty())
815+ list.add(head + bodyAll);
816+
817+ return list.size() > 0;
818+ }
819+
754820 // 内部的な
755821
756822 /**
--- a/TinyBannavi/src/tainavi/AbsSettingView.java
+++ b/TinyBannavi/src/tainavi/AbsSettingView.java
@@ -279,6 +279,7 @@ public abstract class AbsSettingView extends JScrollPane {
279279 private JCheckBoxPanel jCBP_downloadProgramOnFixedTime = null;
280280 private JCheckBoxPanel jCBP_downloadProgramInBackground = null;
281281 private JTextFieldWithPopup jTextField_downloadProgramTimeList = null;
282+ private JCheckBoxPanel jCBP_useProgCache = null;
282283
283284 // レコーダ対応
284285 private JRadioButtonPanel jRBP_getRdReserveDetails = null;
@@ -306,6 +307,8 @@ public abstract class AbsSettingView extends JScrollPane {
306307 private JLabel jLabel_rsv_recedcolor = null;
307308 private JCCLabel jCCL_rsv_recedcolor = null;
308309 private JCheckBoxPanel jCBP_useAutocomplete = null;
310+ private JCheckBoxPanel jCBP_notifyBeforeProgStart = null;
311+ private JSliderPanel jSP_minsBeforeProgStart = null;
309312
310313 // タイトル一覧
311314 private JLabel jLabel_title = null;
@@ -314,6 +317,7 @@ public abstract class AbsSettingView extends JScrollPane {
314317 private JButton jButton_title_up = null;
315318 private JButton jButton_title_down = null;
316319 private JButton jButton_title_default = null;
320+ private JCheckBoxPanel jCBP_showTitleDetail = null;
317321
318322 // その他
319323 private JComboBoxPanel jCBX_updateMethod = null;
@@ -913,8 +917,14 @@ public abstract class AbsSettingView extends JScrollPane {
913917 // 連動設定
914918 jCBP_downloadProgramOnFixedTime.addItemListener(al_downloadProgramOnFixedTime);
915919 jCBP_downloadProgramOnFixedTime.setSelected( ! jCBP_downloadProgramOnFixedTime.isSelected());
920+ // RELOADリスナー不要
916921 }
917922
923+ CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_useProgCache = new JCheckBoxPanel("高速キャッシュファイルを使用する",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
924+ jCBP_useProgCache.setSelected(env.getUseProgCache());
925+ // RELOADリスナー不要
926+ y+=(PARTS_HEIGHT+SEP_HEIGHT);
927+
918928 return y;
919929 }
920930
@@ -1066,6 +1076,18 @@ public abstract class AbsSettingView extends JScrollPane {
10661076 // RELOADリスナー不要
10671077 y+=(PARTS_HEIGHT+SEP_HEIGHT);
10681078
1079+ CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_notifyBeforeProgStart = new JCheckBoxPanel("予約番組が開始する前に通知する(Windows 10のみ)",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
1080+ jCBP_notifyBeforeProgStart.setSelected(env.getNotifyBeforeProgStart());
1081+ jCBP_notifyBeforeProgStart.addItemListener(il_notifyBeforeProgStart);
1082+ // RELOADリスナー不要
1083+ y+=(PARTS_HEIGHT+SEP_HEIGHT);
1084+
1085+ CommonSwingUtils.putComponentOn(jPanel_setting, jSP_minsBeforeProgStart = new JSliderPanel("┗ 開始何分前に通知するか",LABEL_WIDTH,0,72,200), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
1086+ jSP_minsBeforeProgStart.setValue(env.getMinsBeforeProgStart());
1087+ jSP_minsBeforeProgStart.setEnabled(jCBP_notifyBeforeProgStart.isSelected());
1088+ // RELOADリスナー不要
1089+ y+=(PARTS_HEIGHT+SEP_HEIGHT);
1090+
10691091 return y;
10701092 }
10711093
@@ -1085,6 +1107,11 @@ public abstract class AbsSettingView extends JScrollPane {
10851107 CommonSwingUtils.putComponentOn(jPanel_setting, getJButton_title_default("初期値"), 75, PARTS_HEIGHT, LABEL_WIDTH+SEP_WIDTH+10+tlitems_w, y+tlitems_h-PARTS_HEIGHT);
10861108 y+=(tlitems_h+SEP_HEIGHT);
10871109
1110+ CommonSwingUtils.putComponentOn(jPanel_setting, jCBP_showTitleDetail = new JCheckBoxPanel("タイトル詳細を表示する",LABEL_WIDTH), PARTS_WIDTH, PARTS_HEIGHT, SEP_WIDTH, y);
1111+ jCBP_showTitleDetail.setSelected(env.getShowTitleDetail());
1112+ // RELOADリスナー不要
1113+ y+=(PARTS_HEIGHT+SEP_HEIGHT);
1114+
10881115 return y;
10891116 }
10901117
@@ -1363,6 +1390,7 @@ public abstract class AbsSettingView extends JScrollPane {
13631390 env.setDownloadProgramOnFixedTime(jCBP_downloadProgramOnFixedTime.isSelected());
13641391 env.setDownloadProgramInBackground(jCBP_downloadProgramInBackground.isSelected());
13651392 env.setDownloadProgramTimeList(jTextField_downloadProgramTimeList.getText());
1393+ env.setUseProgCache(jCBP_useProgCache.isSelected());
13661394
13671395 // レコーダ対応
13681396 env.setForceLoadReserveDetails(jRBP_getRdReserveDetails.getSelectedIndex());
@@ -1407,6 +1435,11 @@ public abstract class AbsSettingView extends JScrollPane {
14071435 env.setTunerShortColor(jCCL_rsv_tunshortcolor.getChoosed());
14081436 env.setRecordedColor(jCCL_rsv_recedcolor.getChoosed());
14091437 env.setUseAutocomplete(jCBP_useAutocomplete.isSelected());
1438+ env.setNotifyBeforeProgStart(jCBP_notifyBeforeProgStart.isSelected());
1439+ env.setMinsBeforeProgStart(jSP_minsBeforeProgStart.getValue());
1440+
1441+ // タイトル一覧関係
1442+ env.setShowTitleDetail(jCBP_showTitleDetail.isSelected());
14101443
14111444 // その他の設定
14121445 env.setUpdateMethod((UpdateOn) jCBX_updateMethod.getSelectedItem());
@@ -1781,6 +1814,12 @@ public abstract class AbsSettingView extends JScrollPane {
17811814 }
17821815 };
17831816
1817+ private final ItemListener il_notifyBeforeProgStart = new ItemListener() {
1818+ @Override
1819+ public void itemStateChanged(ItemEvent e) {
1820+ jSP_minsBeforeProgStart.setEnabled(jCBP_notifyBeforeProgStart.isSelected());
1821+ }
1822+ };
17841823
17851824 /*******************************************************************************
17861825 * コンポーネント
--- a/TinyBannavi/src/tainavi/AbsTitleListView.java
+++ b/TinyBannavi/src/tainavi/AbsTitleListView.java
@@ -163,6 +163,8 @@ public abstract class AbsTitleListView extends JPanel {
163163
164164 private static final String ICONFILE_PULLDOWNMENU = "icon/down-arrow.png";
165165
166+ public static final String MOVEONLY = "移動のみ";
167+
166168 /*******************************************************************************
167169 * 部品
168170 ******************************************************************************/
@@ -205,6 +207,8 @@ public abstract class AbsTitleListView extends JPanel {
205207 FOLDER ("フォルダ", 300),
206208 GENRE ("ジャンル", 100),
207209 RECORDER ("レコーダ", 250),
210+ COPYCOUNT ("コピー", 60),
211+ DLNAOID ("DLNA OID", 100),
208212 ;
209213
210214 private String name;
@@ -244,6 +248,8 @@ public abstract class AbsTitleListView extends JPanel {
244248 String genre;
245249 String recname;
246250 String recorder;
251+ String copycount;
252+ String dlna_oid;
247253
248254 String hide_ttlid;
249255 String hide_detail;
@@ -263,6 +269,8 @@ public abstract class AbsTitleListView extends JPanel {
263269 c.addData(folder);
264270 c.addData(genre);
265271 c.addData(recname);
272+ c.addData(copycount.equals("1") ? MOVEONLY : copycount + "回");
273+ c.addData(dlna_oid);
266274 c.addData(recorder);
267275
268276 c.addData(hide_ttlid);
@@ -402,6 +410,8 @@ public abstract class AbsTitleListView extends JPanel {
402410
403411 updateGenreList();
404412
413+ setDetailVisible(true);
414+
405415 this.addComponentListener(cl_tabShown);
406416
407417 addListeners();
@@ -880,6 +890,8 @@ public abstract class AbsTitleListView extends JPanel {
880890 sa.genre = ro.getGenreNameList();
881891 sa.recname = rec.getDispName();
882892 sa.recorder = rec.Myself();
893+ sa.copycount = ro.getHidden_params().get("copycount");
894+ sa.dlna_oid = ro.getHidden_params().get("dlnaObjectID");
883895
884896 sa.hide_ttlid = ro.getId();
885897 sa.hide_detail = ro.getDetail();
@@ -965,6 +977,19 @@ public abstract class AbsTitleListView extends JPanel {
965977 menuItem.doClick();
966978 }
967979
980+ /**
981+ * 画面下部のタイトル詳細領域の表示のON/OFF
982+ */
983+ public void setDetailVisible(boolean b) {
984+ if (!env.getShowTitleDetail())
985+ b = false;
986+
987+ jsc_detail.setVisible(b);
988+
989+ SpringLayout layout = (SpringLayout)this.getLayout();
990+ layout.putConstraint(SpringLayout.NORTH, jsc_detail, b ? -DETAIL_HEIGHT : 0, SpringLayout.SOUTH, this);
991+ }
992+
968993 // 内部的な
969994 /**
970995 * テーブル(の中の人)に追加
@@ -1568,6 +1593,12 @@ public abstract class AbsTitleListView extends JPanel {
15681593 case RECORDER:
15691594 value = ra.recname;
15701595 break;
1596+ case COPYCOUNT:
1597+ value = ra.copycount;
1598+ break;
1599+ case DLNAOID:
1600+ value = ra.dlna_oid;
1601+ break;
15711602 }
15721603
15731604 if (value == null)
@@ -1619,8 +1650,8 @@ public abstract class AbsTitleListView extends JPanel {
16191650 */
16201651 private JScrollPane getJTextPane_detail() {
16211652 if ( jsc_detail == null ) {
1622- jsc_detail = new JScrollPane(jta_detail = new JTextAreaWithPopup(),JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
1623- jta_detail.setRows(8);
1653+ jsc_detail = new JScrollPane(jta_detail = new JTextAreaWithPopup(),JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
1654+ jta_detail.setRows(6);
16241655 jta_detail.setEditable(false);
16251656 jta_detail.setBackground(Color.LIGHT_GRAY);
16261657 }
@@ -1659,6 +1690,21 @@ public abstract class AbsTitleListView extends JPanel {
16591690 TableColumn col = getColumn(TitleColumn.LENGTH);
16601691 if (col != null)
16611692 sorter.setComparator(col.getModelIndex(),lengthcomp);
1693+
1694+ // コピー回数でソートする項目用の計算式(番組長とか)
1695+ final Comparator<String> copycomp = new Comparator<String>() {
1696+
1697+ @Override
1698+ public int compare(String str1, String str2) {
1699+ int num1 = str1.equals(MOVEONLY) ? 1 : Integer.parseInt(str1.substring(0, str1.length()-1));
1700+ int num2 = str2.equals(MOVEONLY) ? 1 : Integer.parseInt(str2.substring(0, str2.length()-1));
1701+ return num1 - num2;
1702+ }
1703+ };
1704+
1705+ col = getColumn(TitleColumn.COPYCOUNT);
1706+ if (col != null)
1707+ sorter.setComparator(col.getModelIndex(), copycomp);
16621708 }
16631709
16641710 /*
--- a/TinyBannavi/src/tainavi/AbsToolBar.java
+++ b/TinyBannavi/src/tainavi/AbsToolBar.java
@@ -565,7 +565,7 @@ public abstract class AbsToolBar extends JToolBar implements HDDRecorderSelectab
565565 return;
566566 }
567567
568- int total_page = 1+env.getPageIndex(pli.size());
568+ int total_page = 1+env.getPageIndex(pli.size()-1);
569569
570570 // イベント停止
571571 jComboBox_pager.removeItemListener(il_pagerSelected);
@@ -582,7 +582,7 @@ public abstract class AbsToolBar extends JToolBar implements HDDRecorderSelectab
582582 }
583583
584584 pli.rewind(); // 巻き戻してください
585- int idx = 1;
585+ int idx = 0;
586586
587587 for (int np=0; np<total_page; np++) {
588588 String centers = "";
--- a/TinyBannavi/src/tainavi/Env.java
+++ b/TinyBannavi/src/tainavi/Env.java
@@ -371,7 +371,7 @@ public class Env {
371371 public int getPageIndex(int n) {
372372 if (pageBreakEnabled && pageBreaks.size() > 0){
373373 for (int pno=0; pno<pageBreaks.size(); pno++){
374- if (n <= pageBreaks.get(pno)){
374+ if (n < pageBreaks.get(pno)){
375375 return pno;
376376 }
377377 }
@@ -380,7 +380,7 @@ public class Env {
380380 }
381381
382382 int rem = n % centerPerPage;
383- return (n-rem)/centerPerPage + ((rem==0)?(0):(1)) - 1;
383+ return (n-rem)/centerPerPage;
384384 }
385385 /*
386386 * ページ内でのオフセットを取得する
@@ -389,7 +389,7 @@ public class Env {
389389 if (pageBreakEnabled && pageBreaks.size() > 0){
390390 int cnum = 0;
391391 for (int pno=0; pno<pageBreaks.size(); pno++){
392- if (n <= pageBreaks.get(pno)){
392+ if (n < pageBreaks.get(pno)){
393393 return n - cnum;
394394 }
395395
@@ -659,6 +659,12 @@ public class Env {
659659 // Web番組表のキャッシュ保持時間
660660 public int getCacheTimeLimit() { return cacheTimeLimit; }
661661 public void setCacheTimeLimit(int w) { cacheTimeLimit = w; }
662+
663+ // 高速キャッシュファイルを使用するか
664+ public boolean getUseProgCache(){ return useProgCache; }
665+ public void setUseProgCache(boolean b){ useProgCache = b;}
666+ private boolean useProgCache = true;
667+
662668 public boolean isShutdownEnabled() { return (cacheTimeLimit == 0)&&(shutdownCmd!=null&&shutdownCmd.length()>0); }
663669 private int cacheTimeLimit = 12;
664670 // シャットダウンコマンド
@@ -881,6 +887,24 @@ public class Env {
881887 public void setUseAutocomplete(boolean b) { useAutocomplete = b; }
882888 private boolean useAutocomplete = false;
883889
890+ // 予約番組の開始を通知するか(Windows10のみ)
891+ public boolean getNotifyBeforeProgStart(){ return notifyBeforeProgStart; }
892+ public void setNotifyBeforeProgStart(boolean b){ notifyBeforeProgStart = b; }
893+ private boolean notifyBeforeProgStart = false;
894+
895+ // 開始何分前に通知するか
896+ public int getMinsBeforeProgStart(){ return minsBeforeProgStart; }
897+ public void setMinsBeforeProgStart(int n){ minsBeforeProgStart = n; }
898+ private int minsBeforeProgStart = 5;
899+
900+ /*
901+ * タイトル一覧関係
902+ */
903+ // タイトル詳細を表示するか
904+ public boolean getShowTitleDetail(){ return showTitleDetail; }
905+ public void setShowTitleDetail(boolean b){ showTitleDetail = b; }
906+ private boolean showTitleDetail = true;
907+
884908 /*
885909 * その他の設定
886910 */
--- a/TinyBannavi/src/tainavi/ProgDateList.java
+++ b/TinyBannavi/src/tainavi/ProgDateList.java
@@ -2,14 +2,83 @@ package tainavi;
22
33 import java.util.ArrayList;
44
5+import tainavi.ProgDetailList.WrHeader;
6+
57 public class ProgDateList {
68 public String Date;
79 public int row;
810 public ArrayList<ProgDetailList> pdetail;
9-
11+
1012 public ProgDateList() {
1113 Date = "";
1214 row = 0;
1315 pdetail = new ArrayList<ProgDetailList>();
1416 }
17+
18+ /*
19+ * 文字列に変換する
20+ */
21+ public String toString(){
22+ StringBuilder sb = new StringBuilder();
23+ // 属性をヘッダー行にエンコードする
24+ sb.append(Date + ":");
25+ sb.append(String.valueOf(row) + ":");
26+ sb.append(pdetail.size());
27+ sb.append("\n");
28+
29+ // pdetail を文字列にエンコードする
30+ for (ProgDetailList d : pdetail) {
31+ sb.append(d.toString());
32+ }
33+
34+ return sb.toString();
35+ }
36+
37+ /*
38+ * 文字列からインスタンスを生成する
39+ */
40+ public ProgDateList(String txt){
41+ Date = "";
42+ row = 0;
43+ pdetail = new ArrayList<ProgDetailList>();
44+
45+ // ヘッダー行を切り出す
46+ int he = txt.indexOf("\n");
47+ String th = txt.substring(0, he);
48+ if (th == null)
49+ return;
50+
51+ // ヘッダー行をトークンに分割する
52+ String []tokens = th.split(":");
53+ if (tokens.length < 3)
54+ return;
55+
56+ // トークンを属性にコピーする
57+ Date = tokens[0];
58+ row = Integer.parseInt(tokens[1]);
59+ int size = Integer.parseInt(tokens[2]);
60+
61+ // 残りの文字列からpdetail を生成する
62+ int index = 0;
63+ txt = txt.substring(he+1);
64+ for (int n=0; n<size; n++){
65+ // 番組ヘッダを探す
66+ int newtop = txt.indexOf(WrHeader.STARTMARK.toString(),index);
67+ if ( newtop == -1 ) {
68+ break;
69+ }
70+ newtop += WrHeader.STARTMARK.toString().length()+1;
71+
72+ // 番組フッタを探す
73+ int newtail = txt.indexOf(WrHeader.ENDMARK.toString(),newtop);
74+ if ( newtail == -1 ) {
75+ break;
76+ }
77+ index = newtail+WrHeader.ENDMARK.toString().length()+1;
78+
79+ // 解析する
80+ ProgDetailList pdl = new ProgDetailList(txt.substring(newtop,newtail));
81+ pdetail.add(pdl);
82+ }
83+ }
1584 }
--- a/TinyBannavi/src/tainavi/ProgList.java
+++ b/TinyBannavi/src/tainavi/ProgList.java
@@ -2,7 +2,6 @@ package tainavi;
22
33 import java.awt.Color;
44 import java.util.ArrayList;
5-import tainavi.ProgDateList;
65
76 public class ProgList {
87 public String Area;
@@ -14,7 +13,9 @@ public class ProgList {
1413 public Color BgColor;
1514 public boolean enabled;
1615 public ArrayList<ProgDateList> pdate;
17-
16+
17+ private static final String PDEND = "#PDEND\n"; // 文字列エンコード時のProgDateListのターミネータ
18+
1819 public ProgList() {
1920 Area = "";
2021 SubArea = "";
@@ -26,4 +27,85 @@ public class ProgList {
2627 enabled = true;
2728 pdate = new ArrayList<ProgDateList>();
2829 }
30+
31+ /*
32+ * インスタンスを文字列に変換する
33+ */
34+ public String toString(){
35+ StringBuilder sb = new StringBuilder();
36+
37+ // 属性をヘッダー行にエンコードする
38+ sb.append(Area + ":");
39+ sb.append(SubArea + ":");
40+ sb.append(Type + ":");
41+ sb.append(Center + ":");
42+ sb.append(CenterId + ":");
43+ sb.append(ChId + ":");
44+ sb.append(CommonUtils.color2str(BgColor) + ":");
45+ sb.append((enabled ? "1" : "0") + ":");
46+ sb.append(pdate.size());
47+ sb.append("\n");
48+
49+ // 日付の配列を文字列に変換して追加する。PDENDでターミネートする
50+ for ( ProgDateList c : pdate ) {
51+ sb.append(c.toString());
52+ sb.append(PDEND);
53+ }
54+
55+ return sb.toString();
56+ }
57+
58+ /*
59+ * 文字列からインスタンスを生成する
60+ */
61+ public ProgList(String txt){
62+ Area = "";
63+ SubArea = "";
64+ Type = "";
65+ Center = "";
66+ CenterId = "";
67+ ChId = "";
68+ BgColor = new Color(180,180,180);
69+ enabled = true;
70+ pdate = new ArrayList<ProgDateList>();
71+
72+ // ヘッダー行を取り出す
73+ int he = txt.indexOf("\n");
74+ String th = txt.substring(0, he);
75+ if (th == null)
76+ return;
77+
78+ // ヘッダー行をトークンに分割する
79+ String []tokens = th.split(":");
80+ if (tokens.length < 9)
81+ return;
82+
83+ // トークンを属性にコピーする
84+ Area = tokens[0];
85+ SubArea = tokens[1];
86+ Type = tokens[2];
87+ Center = tokens[3];
88+ CenterId = tokens[4];
89+ ChId = tokens[5];
90+ BgColor = CommonUtils.str2color(tokens[6]);
91+ enabled = tokens[7].equals("1");
92+ int size = Integer.parseInt(tokens[8]);
93+
94+ // 残りの文字列から pdate を生成する
95+ String tdl = txt.substring(he+1);
96+ for (int n=0; n<size; n++){
97+ // ターミネートまでの文字列を切りだす
98+ int dd = tdl.indexOf(PDEND);
99+ String td = tdl.substring(0, dd);
100+
101+ // 文字列からインスタンスを生成して配列に追加する
102+ ProgDateList d = new ProgDateList(td);
103+ pdate.add(d);
104+
105+ // 残りの文字列を切り出す
106+ if (dd == -1)
107+ break;
108+ tdl = tdl.substring(dd+PDEND.length());
109+ }
110+ }
29111 }
--- a/TinyBannavi/src/tainavi/TVProgram.java
+++ b/TinyBannavi/src/tainavi/TVProgram.java
@@ -378,5 +378,6 @@ public interface TVProgram {
378378 public boolean setOptString(String s);
379379 public String getOptString();
380380
381-
381+ // キャッシュファイルからのみのロードか
382+ public boolean getCacheFileOnly();
382383 }
--- a/TinyBannavi/src/tainavi/TVProgramUtils.java
+++ b/TinyBannavi/src/tainavi/TVProgramUtils.java
@@ -145,6 +145,13 @@ public class TVProgramUtils implements Cloneable {
145145
146146 private static boolean cancelRequested = false;
147147
148+ /*
149+ * 高速キャッシュファイルを使用するか
150+ */
151+ public static void setUseProgCache(boolean b){ useProgCache = b;}
152+ public static boolean getUseProgCache(){ return useProgCache; }
153+ private static boolean useProgCache = true;
154+
148155 /*******************************************************************************
149156 * オプション確認
150157 ******************************************************************************/
@@ -173,6 +180,9 @@ public class TVProgramUtils implements Cloneable {
173180 private static final String DBGID = "[DEBUG]"+MSGID;
174181 private static final String ERRID = "[ERROR]"+MSGID;
175182
183+ // キャッシュファイルで使用する放送局のターミネータ
184+ private static final String PLEND = "#PLEND\n";
185+
176186 /*******************************************************************************
177187 * メンバ変数関連
178188 ******************************************************************************/
@@ -232,6 +242,10 @@ public class TVProgramUtils implements Cloneable {
232242 //public boolean getAbnormal() { return abnormal; }
233243 //private boolean abnormal = false;
234244
245+ // 今回の取得でキャッシュのみを使用したか
246+ public void setCacheFileOnly(boolean b){ cacheFileOnly = b; }
247+ public boolean getCacheFileOnly(){ return cacheFileOnly; }
248+ private boolean cacheFileOnly = false;
235249
236250 /*******************************************************************************
237251 * 番組表固有の情報
@@ -1518,4 +1532,98 @@ public class TVProgramUtils implements Cloneable {
15181532 public boolean setOptString(String s) { return true; } // ダミー
15191533 public String getOptString() { return null; } // ダミー
15201534
1535+ /*
1536+ * 番組情報をキャッシュファイルに保存する
1537+ */
1538+ public boolean saveToProgCache(String prefix){
1539+ if (!useProgCache){
1540+ System.out.println("高速キャッシュファイルは使用しません");
1541+ return false;
1542+ }
1543+
1544+ // キャッシュファイルのパス名を生成する
1545+ String file = String.format(getProgDir()+File.separator+prefix +"_ALL.txt");
1546+
1547+ File f = new File(file);
1548+ f.delete();
1549+
1550+ // 番組情報を文字列に変換する
1551+ StringBuilder sb = new StringBuilder();
1552+ for ( ProgList p : pcenter ) {
1553+ sb.append(p.toString());
1554+ sb.append(PLEND);
1555+ }
1556+
1557+ // キャッシュファイルに保存する
1558+ System.out.println("高速キャッシュファイルに保存しています(" + file + ")...");
1559+ if ( ! CommonUtils.write2file(file, sb.toString()) ) {
1560+ System.out.println("高速キャッシュファイルへの保存に失敗しました。");
1561+ return false;
1562+ }
1563+
1564+ System.out.println("高速キャッシュファイルへの保存に成功しました。");
1565+ return true;
1566+ }
1567+
1568+ /*
1569+ * 番組情報をキャッシュファイルから読み込む
1570+ */
1571+ public boolean loadFromProgCache(String prefix){
1572+ if (!useProgCache){
1573+ System.out.println("高速キャッシュファイルは使用しません");
1574+ return false;
1575+ }
1576+ // キャッシュファイルのパス名を生成する
1577+ String file = String.format(getProgDir()+File.separator+prefix +"_ALL.txt");
1578+ System.out.println("高速キャッシュファイルを読み込んでいます(" + file + ")...");
1579+
1580+ File f = new File(file);
1581+ if (!f.exists()){
1582+ System.out.println("高速キャッシュファイルはありません");
1583+ return false;
1584+ }
1585+
1586+ // 当日保存されたものかどうかをチェックする
1587+ String curDate = CommonUtils.getDate529(0,true);
1588+
1589+ GregorianCalendar c = new GregorianCalendar();
1590+ c.setTimeInMillis(f.lastModified());
1591+
1592+ String fdate = CommonUtils.getDate529(c, false);
1593+ String today = CommonUtils.getDate529(0, false);
1594+ if (!fdate.equals(today)){
1595+ System.out.println("高速キャッシュファイルは古いです");
1596+ return false;
1597+ }
1598+
1599+ String txt = CommonUtils.read4file(file, false);
1600+ if ( txt == null ) {
1601+ System.out.println("高速キャッシュファイルの読み込みに失敗しました");
1602+ return false;
1603+ }
1604+
1605+ ArrayList<ProgList> pcl = new ArrayList<ProgList>();
1606+
1607+ // 文字列から番組情報を読み込む
1608+ int index = 0;
1609+ while ( index < txt.length() ){
1610+ // 放送局のターミネータを検索する
1611+ int le = txt.indexOf(PLEND, index);
1612+
1613+ // 1放送局分を文字列から生成する
1614+ ProgList pl = new ProgList(txt.substring(index, le));
1615+ pcl.add(pl);
1616+
1617+ if (le == -1)
1618+ break;
1619+
1620+ // 残りの文字列のインデックスを計算する
1621+ index = le + PLEND.length();
1622+ }
1623+
1624+ pcenter = pcl;
1625+
1626+ System.out.println("高速キャッシュファイルの読み込みに成功しました");
1627+ return true;
1628+ }
15211629 }
--- a/TinyBannavi/src/tainavi/TitleListColumnInfoList.java
+++ b/TinyBannavi/src/tainavi/TitleListColumnInfoList.java
@@ -96,11 +96,36 @@ public class TitleListColumnInfoList extends ArrayList<ListColumnInfo> implement
9696 this.add(c);
9797 }
9898
99+ addNewColumns();
100+
99101 return true;
100102 }
101103
102104 /*
103- * 初期化する
105+ * 新しい列を追加する
106+ */
107+ private void addNewColumns(){
108+ TitleListColumnInfoList cl = new TitleListColumnInfoList();
109+ cl.setDefault();
110+
111+ for (int n=0; n<cl.size(); n++){
112+ ListColumnInfo c = cl.get(n);
113+
114+ int n2=0;
115+ for (n2=0; n2<this.size(); n2++){
116+ ListColumnInfo c2 = this.get(n2);
117+ if (c.getName().equals(c2.getName()))
118+ break;
119+ }
120+
121+ if (n2 == this.size()){
122+ this.add((ListColumnInfo)c.clone());
123+ }
124+ }
125+ }
126+
127+ /*
128+ * デフォルトの設定にする
104129 */
105130 public void setDefault(){
106131 this.clear();
@@ -117,6 +142,8 @@ public class TitleListColumnInfoList extends ArrayList<ListColumnInfo> implement
117142 {true, "フォルダ", idx++},
118143 {true, "ジャンル", idx++},
119144 {true, "レコーダ", idx++},
145+ {true, "コピー", idx++},
146+ {false, "DLNA OID", idx++},
120147 };
121148 for (int i=0; i<o.length; i++) {
122149 ListColumnInfo cb = new ListColumnInfo();
--- a/TinyBannavi/src/tainavi/VWStatusTextArea.java
+++ b/TinyBannavi/src/tainavi/VWStatusTextArea.java
@@ -1,10 +1,16 @@
11 package tainavi;
22
33 import java.awt.BorderLayout;
4+import java.awt.Color;
5+import java.awt.Dimension;
46
57 import javax.swing.JPanel;
68 import javax.swing.JScrollPane;
7-import javax.swing.JTextArea;
9+import javax.swing.JTextPane;
10+import javax.swing.text.BadLocationException;
11+import javax.swing.text.Document;
12+import javax.swing.text.SimpleAttributeSet;
13+import javax.swing.text.StyleConstants;
814
915 public class VWStatusTextArea extends JPanel implements StatusTextArea {
1016
@@ -15,7 +21,7 @@ public class VWStatusTextArea extends JPanel implements StatusTextArea {
1521 */
1622
1723 private JScrollPane jsp = null;
18- private JTextArea jta = null;
24+ private JTextPane jtp = null;
1925
2026 /*
2127 * コンストラクタ
@@ -33,19 +39,18 @@ public class VWStatusTextArea extends JPanel implements StatusTextArea {
3339
3440 private JScrollPane getJScrollPane_statusarea() {
3541 if (jsp == null) {
36- jsp = new JScrollPane(getJTextArea_statusarea(),JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
42+ jsp = new JScrollPane(getJTextPane_statusarea(),JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
43+ setRows(5);
3744 }
3845 return(jsp);
3946 }
4047
41- private JTextArea getJTextArea_statusarea() {
42- if (jta == null) {
43- jta = new JTextAreaWithPopup(4,0);
44- jta.setLineWrap(true); // 改行、する!
45- jta.setWrapStyleWord(false); // 画面端で折り返し、する!
46- jta.setEditable(false); // 編集、させない!
48+ private JTextPane getJTextPane_statusarea() {
49+ if (jtp == null) {
50+ jtp = new JTextPane();
51+ jtp.setEditable(false); // 編集、させない!
4752 }
48- return jta;
53+ return jtp;
4954 }
5055
5156 /*
@@ -54,35 +59,50 @@ public class VWStatusTextArea extends JPanel implements StatusTextArea {
5459
5560 @Override
5661 public void clear() {
57- jta.setText("");
62+ jtp.setText("");
5863 }
5964
60- private void append(String message) {
61- jta.append("\n"+ message);
62- jta.setCaretPosition(jta.getText().length());
63- }
65+ private void appendToPane(String msg, Color c){
66+ SimpleAttributeSet attr = new SimpleAttributeSet();
67+ StyleConstants.setForeground(attr, c);
68+
69+ Document doc = jtp.getDocument();
70+ if (doc == null)
71+ return;
72+
73+ try {
74+ doc.insertString(doc.getLength(), msg, attr);
75+ jtp.setCaretPosition(doc.getLength());
76+ } catch (BadLocationException e) {
77+ e.printStackTrace();
78+ }
79+ }
6480
6581 @Override
6682 public void appendMessage(String message) {
6783 String msg = CommonUtils.getNow() + message;
68- this.append(msg);
84+ appendToPane("\n" + msg, Color.BLACK);
6985 System.out.println(msg);
7086 }
7187
7288 @Override
7389 public void appendError(String message) {
7490 String msg = CommonUtils.getNow() + message;
75- this.append(msg);
91+ appendToPane("\n" + msg, Color.RED);
7692 System.err.println(msg);
7793 }
7894
7995 @Override
8096 public int getRows() {
81- return jta.getRows();
97+ return (int)(jtp.getHeight() / jtp.getFont().getSize()/1.8);
8298 }
8399
84100 @Override
85101 public void setRows(int rows) {
86- jta.setRows(rows);
102+ if (jsp == null)
103+ return;
104+ Dimension dim = jsp.getPreferredSize();
105+ dim.height = (int)(jtp.getFont().getSize()*1.8*rows);
106+ jsp.setPreferredSize(dim);
87107 }
88108 }
--- a/TinyBannavi/src/tainavi/VersionInfo.java
+++ b/TinyBannavi/src/tainavi/VersionInfo.java
@@ -5,7 +5,7 @@ import java.util.regex.Pattern;
55
66
77 public class VersionInfo {
8- private static final String Version = "タイニー番組ナビゲータ for DBR-T2007 3.22.18β+1.11";
8+ private static final String Version = "タイニー番組ナビゲータ for DBR-T2007 3.22.18β+1.12";
99
1010 private static final String OSname = System.getProperty("os.name");
1111 private static final String OSvers = System.getProperty("os.version");
--- a/TinyBannavi/src/tainavi/Viewer.java
+++ b/TinyBannavi/src/tainavi/Viewer.java
@@ -18,6 +18,7 @@ import java.awt.Rectangle;
1818 import java.awt.SystemTray;
1919 import java.awt.Toolkit;
2020 import java.awt.TrayIcon;
21+import java.awt.TrayIcon.MessageType;
2122 import java.awt.datatransfer.Clipboard;
2223 import java.awt.datatransfer.StringSelection;
2324 import java.awt.event.ActionEvent;
@@ -154,6 +155,7 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
154155 private String pxport = null; // ProxtPort指定
155156
156157 private boolean downloadInProgress = false; // TVプログラムを取得中か
158+ private boolean cacheFileOnly = false; // キャッシュファイルからのみの読み込みか
157159
158160 /*******************************************************************************
159161 * 定数
@@ -435,24 +437,28 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
435437 protected void onShown() {
436438 // キーワード登録ボタンはリスト形式のみ
437439 toolBar.setAddkeywordEnabled(true);
438- // 一括予約はリスト形式のみ
439- toolBar.setBatchReservationEnabled(true);
440440 // スナップショットを有効にする
441441 toolBar.setSnapShotEnabled(true);
442442 // 新聞形式以外ではマッチ枠を無効にする
443443 toolBar.setBorderToggleEnabled(true, bounds.getShowReservedBackground());
444+ updateBatchReservationEnabled();
444445 }
445446
446447 @Override
447448 protected void onHidden() {
448449 // キーワード登録ボタンはリスト形式のみ
449450 toolBar.setAddkeywordEnabled(false);
450- // 一括予約はリスト形式のみ
451- toolBar.setBatchReservationEnabled(false);
452451 // スナップショットを無効にする
453452 toolBar.setSnapShotEnabled(false);
454453 // 新聞形式以外ではマッチ枠を無効にする
455454 toolBar.setBorderToggleEnabled(false, bounds.getShowReservedBackground());
455+ updateBatchReservationEnabled();
456+ }
457+
458+ @Override
459+ protected void updateBatchReservationEnabled(){
460+ // 一括予約はリスト形式のみ
461+ toolBar.setBatchReservationEnabled(this.isVisible() && getSelectedRowCount() > 0);
456462 }
457463
458464 @Override
@@ -1904,7 +1910,7 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
19041910 @Override
19051911 protected void redrawByPager() {
19061912 timer_now.pause();
1907- paper.redrawByCurrentSelection();
1913+ paper.redrawByPager();
19081914 timer_now.start();
19091915 }
19101916
@@ -2109,9 +2115,26 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
21092115 public void timerRised(TickTimerRiseEvent e) {
21102116 if (env.getDebug()) System.out.println("Timer Rised: now="+CommonUtils.getDateTimeYMDx(e.getCalendar()));
21112117 setTitleBar();
2118+ checkReservesForNotify();
21122119 checkDownloadProgramTime(e.getCalendar());
21132120 }
21142121
2122+ /*
2123+ * 開始間もなくの予約を通知する
2124+ */
2125+ private void checkReservesForNotify(){
2126+ if (!env.getNotifyBeforeProgStart())
2127+ return;
2128+ if (reserved == null)
2129+ return;
2130+
2131+ ArrayList<String> list = new ArrayList<String>();
2132+ reserved.getReservesToNotify(list);
2133+
2134+ for (String s : list){
2135+ trayicon.displayMessage("TinyBannavi", s, MessageType.INFO);
2136+ }
2137+ }
21152138
21162139 /*******************************************************************************
21172140 * 共通メソッド群
@@ -3238,7 +3261,7 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
32383261 }
32393262 else {
32403263 ringBeep();
3241- mwin.appendMessage(String.format("【設定情報の取得処理に失敗しました】 所要時間: %.2f秒",tc.end()));
3264+ mwin.appendError(String.format("【設定情報の取得処理に失敗しました】 所要時間: %.2f秒",tc.end()));
32423265 }
32433266
32443267 return null;
@@ -3329,7 +3352,7 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
33293352 }
33303353 else {
33313354 ringBeep();
3332- mwin.appendMessage(String.format("【予約詳細の取得処理に失敗しました】 所要時間: %.2f秒",tc.end()));
3355+ mwin.appendError(String.format("【予約詳細の取得処理に失敗しました】 所要時間: %.2f秒",tc.end()));
33333356 }
33343357 return null;
33353358 }
@@ -3392,7 +3415,7 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
33923415 }
33933416 else {
33943417 ringBeep();
3395- mwin.appendMessage(String.format("【録画結果一覧の取得処理に失敗しました】 所要時間: %.2f秒",tc.end()));
3418+ mwin.appendError(String.format("【録画結果一覧の取得処理に失敗しました】 所要時間: %.2f秒",tc.end()));
33963419 }
33973420 return null;
33983421 }
@@ -3453,7 +3476,7 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
34533476 }
34543477 else {
34553478 ringBeep();
3456- mwin.appendMessage(String.format("【自動予約一覧の取得処理に失敗しました】 所要時間: %.2f秒",tc.end()));
3479+ mwin.appendError(String.format("【自動予約一覧の取得処理に失敗しました】 所要時間: %.2f秒",tc.end()));
34573480 }
34583481
34593482 return null;
@@ -3519,7 +3542,7 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
35193542 }
35203543 else {
35213544 ringBeep();
3522- mwin.appendMessage(String.format("【タイトル一覧の取得処理に失敗しました】 所要時間: %.2f秒",tc.end()));
3545+ mwin.appendError(String.format("【タイトル一覧の取得処理に失敗しました】 所要時間: %.2f秒",tc.end()));
35233546 }
35243547
35253548 return null;
@@ -4001,6 +4024,7 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
40014024 final String ERRID = "[ERROR]"+FUNCID;
40024025
40034026 try {
4027+ cacheFileOnly = true;
40044028 stwin.resetWindowCloseRequested();
40054029 TVProgramUtils.setCancelRequested(false);
40064030
@@ -4018,6 +4042,8 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
40184042 if (!loadTVProgramOnce(tvp, sType, tvp.getSelectedArea(), false, force)){
40194043 return false;
40204044 }
4045+ if (!tvp.getCacheFileOnly())
4046+ cacheFileOnly = false;
40214047 }
40224048 else {
40234049 reportTVProgramProgress(FUNCID+sType+"へのアクセスはスキップされました: "+tvp.getTVProgramId());
@@ -4037,6 +4063,8 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
40374063 loadTVProgramPostProcess(force);
40384064 return false;
40394065 }
4066+ if (!tvp.getCacheFileOnly())
4067+ cacheFileOnly = false;
40404068 }
40414069 else {
40424070 reportTVProgramProgress(FUNCID+sType+"へのアクセスはスキップされました: "+tvp.getTVProgramId());
@@ -4057,6 +4085,8 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
40574085 loadTVProgramPostProcess(force);
40584086 return false;
40594087 }
4088+ if (!tvp.getCacheFileOnly())
4089+ cacheFileOnly = false;
40604090 }
40614091 else {
40624092 reportTVProgramProgress(FUNCID+sType+"へのアクセスはスキップされました: "+tvp.getTVProgramId());
@@ -4122,7 +4152,7 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
41224152 mpList.build(tvprograms, trKeys.getTraceKeys(), srKeys.getSearchKeys());
41234153
41244154 // 過去ログ
4125- if ( !env.getUsePassedProgram()) {
4155+ if ( !env.getUsePassedProgram() || cacheFileOnly) {
41264156 reportTVProgramProgress(FUNCID+"過去ログは記録されません.");
41274157 }
41284158 else {
@@ -4135,6 +4165,7 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
41354165 }
41364166 }
41374167
4168+
41384169 // 分割
41394170 private boolean loadTVProgramOnce(TVProgram tvp, String sType, String aName, boolean loadonly, boolean force) {
41404171
@@ -4149,7 +4180,7 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
41494180 // 読み込み
41504181 //tvp.setProgressArea(stwin);
41514182 if (!tvp.loadProgram(tvp.getSelectedCode(), force)){
4152- if (mwin!=null) mwin.appendMessage(FUNCID+"番組情報の取得に失敗しました。");
4183+ if (mwin!=null) mwin.appendError(FUNCID+"番組情報の取得に失敗しました。");
41534184 return false;
41544185 }
41554186
@@ -4166,7 +4197,7 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
41664197 if (errmsg != null) {
41674198 msg = FUNCID+"取得した情報が不正です:"+errmsg;
41684199 reportTVProgramProgress(msg);
4169- if (mainWindow!=null) mwin.appendMessage(msg);
4200+ if (mainWindow!=null) mwin.appendError(msg);
41704201 ringBeep();
41714202 // return false;
41724203 return true;
@@ -4641,6 +4672,7 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
46414672 // タイトル一覧の再構築
46424673 titled.copyColumnWidth();
46434674 titled.reflectColumnEnv();
4675+ titled.setDetailVisible(mwin.isVisible());
46444676
46454677 // 新聞形式にフォントを反映する
46464678 paper.updateFonts(env);
@@ -5392,6 +5424,7 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
53925424
53935425 TVProgramUtils.setProgressArea(stwin);
53945426 TVProgramUtils.setChConv(chconv);
5427+ TVProgramUtils.setUseProgCache(nEnv.getUseProgCache());
53955428 }
53965429
53975430 //
@@ -5586,11 +5619,13 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
55865619 if (b) {
55875620 listed.setDetailVisible(true);
55885621 paper.setDetailVisible(true);
5622+ titled.setDetailVisible(true);
55895623 MWinSetVisible(true);
55905624 }
55915625 else {
55925626 listed.setDetailVisible(false);
55935627 paper.setDetailVisible(false);
5628+ titled.setDetailVisible(false);
55945629 MWinSetVisible(false);
55955630 }
55965631 }
@@ -6285,7 +6320,7 @@ public class Viewer extends JFrame implements ChangeListener,TickTimerListener,H
62856320 loadRdReservesAll(runRecLoad, null);
62866321
62876322 // 録画タイトルを読み込む
6288- loadRdTitlesAll(false, null);
6323+// loadRdTitlesAll(false, null);
62896324 }
62906325 catch ( Exception e ) {
62916326 System.err.println("【致命的エラー】設定の初期化に失敗しました");
--- a/TinyBannavi/src/tainavi/pluginrec/PlugIn_RecDBR_T2007.java
+++ b/TinyBannavi/src/tainavi/pluginrec/PlugIn_RecDBR_T2007.java
@@ -14,6 +14,7 @@ import java.util.Locale;
1414 import java.util.regex.Matcher;
1515 import java.util.regex.Pattern;
1616
17+import tainavi.AbsTitleListView;
1718 import tainavi.AribCharMap;
1819 import tainavi.ChannelCode;
1920 import tainavi.ChapterInfo;
@@ -310,14 +311,16 @@ public class PlugIn_RecDBR_T2007 extends HDDRecorderUtils implements HDDRecorder
310311 ReservesToFile(getReserves(), rsvedFile);
311312
312313 // 取得した情報の表示
313- System.out.println("---Reserved List Start---");
314- for ( int i = 0; i<getReserves().size(); i++ ) {
315- // 詳細情報の取得
316- ReserveList e = getReserves().get(i);
317- System.out.println(String.format("[%s] %s\t%s\t%s\t%s:%s\t%s:%s\t%sm\t%s\t%s(%s)\t%s\t%s",
318- (i+1), e.getId(), e.getRec_pattern(), e.getRec_nextdate(), e.getAhh(), e.getAmm(), e.getZhh(), e.getZmm(), e.getRec_min(), e.getRec_mode(), e.getTitle(), e.getTitlePop(), e.getChannel(), e.getCh_name()));
314+ if (getDebug()){
315+ System.out.println("---Reserved List Start---");
316+ for ( int i = 0; i<getReserves().size(); i++ ) {
317+ // 詳細情報の取得
318+ ReserveList e = getReserves().get(i);
319+ System.out.println(String.format("[%s] %s\t%s\t%s\t%s:%s\t%s:%s\t%sm\t%s\t%s(%s)\t%s\t%s",
320+ (i+1), e.getId(), e.getRec_pattern(), e.getRec_nextdate(), e.getAhh(), e.getAmm(), e.getZhh(), e.getZmm(), e.getRec_min(), e.getRec_mode(), e.getTitle(), e.getTitlePop(), e.getChannel(), e.getCh_name()));
321+ }
322+ System.out.println("---Reserved List End---");
319323 }
320- System.out.println("---Reserved List End---");
321324
322325 return(true);
323326 }
@@ -643,15 +646,17 @@ public class PlugIn_RecDBR_T2007 extends HDDRecorderUtils implements HDDRecorder
643646 saveTitles(device_id);
644647
645648 // 取得した情報の表示
646- System.out.println("---Title List Start---");
647- for ( int i = 0; i<getTitles().size(); i++ ) {
648- // 詳細情報の取得
649- TitleInfo t = getTitles().get(i);
650- System.out.println(String.format("[%s] %s\t%s\t%s:%s\t%s:%s\t%sm\t%s\t%s\t%s",
651- (i+1), t.getId(), t.getRec_date(), t.getAhh(), t.getAmm(), t.getZhh(), t.getZmm(), t.getRec_min(),
652- t.getTitle(), t.getChannel(), t.getCh_name()));
649+ if (getDebug()){
650+ System.out.println("---Title List Start---");
651+ for ( int i = 0; i<getTitles().size(); i++ ) {
652+ // 詳細情報の取得
653+ TitleInfo t = getTitles().get(i);
654+ System.out.println(String.format("[%s] %s\t%s\t%s:%s\t%s:%s\t%sm\t%s\t%s\t%s",
655+ (i+1), t.getId(), t.getRec_date(), t.getAhh(), t.getAmm(), t.getZhh(), t.getZmm(), t.getRec_min(),
656+ t.getTitle(), t.getChannel(), t.getCh_name()));
657+ }
658+ System.out.println("---Title List End---");
653659 }
654- System.out.println("---Title List End---");
655660
656661 // 各種設定情報をレコーダから取得する
657662 if (setSettingDevice()){
@@ -1395,7 +1400,9 @@ public class PlugIn_RecDBR_T2007 extends HDDRecorderUtils implements HDDRecorder
13951400 "reserveInfo[data_es]=" + data_es + "&" +
13961401 "reserveInfo[recording]=" + recording;
13971402
1398-// System.out.println("PostData=[" + postData + "]");
1403+ if (getDebug())
1404+ System.out.println("PostData=[" + postData + "]");
1405+
13991406 return postData;
14001407 }
14011408
@@ -1997,7 +2004,7 @@ public class PlugIn_RecDBR_T2007 extends HDDRecorderUtils implements HDDRecorder
19972004
19982005 String copycount = t.getHidden_params().get("copycount");
19992006 if (copycount != null)
2000- detail += "コピー回数:" + copycount + "回\n";
2007+ detail += "コピー回数:" + (copycount.equals("1") ? AbsTitleListView.MOVEONLY : copycount + "回") + "\n";
20012008
20022009 // detail += "CONTENT ID:" + t.getContentId() + "\n";
20032010
--- a/TinyBannavi/src/tainavi/plugintv/PlugIn_CSPTVKingdom110.java
+++ b/TinyBannavi/src/tainavi/plugintv/PlugIn_CSPTVKingdom110.java
@@ -60,6 +60,8 @@ public class PlugIn_CSPTVKingdom110 extends PlugIn_TVPTVKingdom implements TVPro
6060 private final String ERRID = "[ERROR]"+MSGID;
6161 private final String DBGID = "[DEBUG]"+MSGID;
6262
63+ private final String PROGCACHE_PREFIX = "TVK_CS_";
64+
6365
6466 /*******************************************************************************
6567 * 部品
@@ -76,6 +78,10 @@ public class PlugIn_CSPTVKingdom110 extends PlugIn_TVPTVKingdom implements TVPro
7678 ******************************************************************************/
7779 @Override
7880 public boolean loadProgram(String areaCode, boolean force) {
81+ setCacheFileOnly(true);
82+
83+ if (!force && loadFromProgCache(PROGCACHE_PREFIX + areaCode))
84+ return true;
7985
8086 // 入れ物を空にする
8187 newplist = new ArrayList<ProgList>();
@@ -104,6 +110,9 @@ public class PlugIn_CSPTVKingdom110 extends PlugIn_TVPTVKingdom implements TVPro
104110 pcenter.clear();
105111 pcenter = newplist;
106112 newplist = null;
113+
114+ saveToProgCache(PROGCACHE_PREFIX + areaCode);
115+
107116 return true;
108117 }
109118
@@ -147,6 +156,8 @@ public class PlugIn_CSPTVKingdom110 extends PlugIn_TVPTVKingdom implements TVPro
147156 else if ( f.exists() == false ) {
148157 return false;
149158 }
159+
160+ setCacheFileOnly(false);
150161 }
151162
152163 if (response == null){
--- a/TinyBannavi/src/tainavi/plugintv/PlugIn_CSPtheTelevisionD.java
+++ b/TinyBannavi/src/tainavi/plugintv/PlugIn_CSPtheTelevisionD.java
@@ -39,7 +39,7 @@ public class PlugIn_CSPtheTelevisionD extends PlugIn_TVPtheTelevision implements
3939
4040 //
4141 public boolean loadProgram(String areaCode, boolean force) {
42-
42+ setCacheFileOnly(true);
4343 // 新しい入れ物(トップ)を用意する
4444 newplist = new ArrayList<ProgList>();
4545
--- a/TinyBannavi/src/tainavi/plugintv/PlugIn_TVPDimora.java
+++ b/TinyBannavi/src/tainavi/plugintv/PlugIn_TVPDimora.java
@@ -90,6 +90,7 @@ public class PlugIn_TVPDimora extends TVProgramUtils implements TVProgram,Clonea
9090
9191 @Override
9292 public boolean loadProgram(String areaCode, boolean force) {
93+ setCacheFileOnly(true);
9394
9495 // 入れ物を空にする
9596 newplist = new ArrayList<ProgList>();
@@ -275,6 +276,8 @@ public class PlugIn_TVPDimora extends TVProgramUtils implements TVProgram,Clonea
275276 else{
276277 reportProgress(ERRID+"番組表(キャッシュ)の保存に失敗しました: "+targetCache);
277278 }
279+
280+ setCacheFileOnly(false);
278281 }
279282 else{
280283 reportProgress(ERRID+"番組表(オンライン)の取得に失敗しました" + targetOnline);
--- a/TinyBannavi/src/tainavi/plugintv/PlugIn_TVPTVKingdom.java
+++ b/TinyBannavi/src/tainavi/plugintv/PlugIn_TVPTVKingdom.java
@@ -65,6 +65,7 @@ public class PlugIn_TVPTVKingdom extends TVProgramUtils implements TVProgram,Clo
6565 private final String ERRID = "[ERROR]"+MSGID;
6666 private final String DBGID = "[DEBUG]"+MSGID;
6767
68+ private final String PROGCACHE_PREFIX = "TVK_";
6869
6970 /*******************************************************************************
7071 * 部品
@@ -98,6 +99,11 @@ public class PlugIn_TVPTVKingdom extends TVProgramUtils implements TVProgram,Clo
9899
99100 @Override
100101 public boolean loadProgram(String areaCode, boolean force) {
102+ setCacheFileOnly(true);
103+
104+ if (!force && loadFromProgCache(PROGCACHE_PREFIX + areaCode)){
105+ return true;
106+ }
101107
102108 // 入れ物を空にする
103109 newplist = new ArrayList<ProgList>();
@@ -241,6 +247,9 @@ public class PlugIn_TVPTVKingdom extends TVProgramUtils implements TVProgram,Clo
241247 pcenter.clear();
242248 pcenter = newplist;
243249 newplist = null;
250+
251+ saveToProgCache(PROGCACHE_PREFIX + areaCode);
252+
244253 return true;
245254 }
246255
@@ -273,6 +282,7 @@ public class PlugIn_TVPTVKingdom extends TVProgramUtils implements TVProgram,Clo
273282 return false;
274283 }
275284
285+ setCacheFileOnly(false);
276286 reportProgress(String.format("%s (オンライン)を取得しました: %s",getTVProgramId(), target));
277287 // 連続アクセス規制よけ
278288 CommonUtils.milSleep(accessWait);
--- a/TinyBannavi/src/tainavi/plugintv/PlugIn_TVPtheTelevision.java
+++ b/TinyBannavi/src/tainavi/plugintv/PlugIn_TVPtheTelevision.java
@@ -82,6 +82,7 @@ public class PlugIn_TVPtheTelevision extends TVProgramUtils implements TVProgram
8282 ******************************************************************************/
8383
8484 public boolean loadProgram(String areaCode, boolean force) {
85+ setCacheFileOnly(true);
8586
8687 // 入れ物を空にする
8788 newplist.clear();
@@ -152,6 +153,7 @@ public class PlugIn_TVPtheTelevision extends TVProgramUtils implements TVProgram
152153 }
153154
154155 reportProgress(MSGID+"(オンライン)を取得しました: ("+counter+"/"+counterMax+") "+pl.Center+" "+url);
156+ setCacheFileOnly(false);
155157 }
156158 else if (f.exists()) {
157159 // キャッシュファイルの読み込み