Files
docview/docs/design/04-ui-navigation.md
2026-09-21 13:41:40 +09:00

25 KiB

04 画面・操作設計

1. 設計方針

本文を中心にしたデスクトップGUIとし、アプリの周辺表示に等幅文字・細い区切り線・キーボード中心の操作を使う。PDFの紙面は文字端末に置き換えず、原文の色・文字・図形を保持して描画する。

R01〜R14は提供要件、R15は「デスクトップGUIで、見た目とキーボード操作をTUI風にする」という確定補足に対応する。本書の具体的なキー割当、初期レイアウト、タイムアウトは設計提案であり、利用者から指定された固定値ではない。要件一覧は01、位置・能力・コマンドのデータ契約は05、設定スキーマは06に置く。

初期版は1ウィンドウ・1アクティブ文書とする。ファイルはOSの選択画面、起動引数のローカルパス、ドラッグ&ドロップから開ける。Qt Quick側がUIとキーモードを管理し、PDFiumの表示結果とQt WebEngineの文書内容へ操作を振り分ける。文書内スクリプトにアプリのキー操作を管理させない。

2. 画面構成

2.1 初期画面

文書未選択時は、中央に「Ctrl+O: 文書を開く」「?: 操作一覧」の2項目を表示する。メニューバー、ツールバー、常時表示の装飾ボタンは置かない。OSのウィンドウ枠は通常どおり使用する。画面の余白、文字、区切り線は設定テーマの色を使う。

2.2 閲覧画面

┌─ 目次 ─────────┬──────────────────────────────────────┐
│  第1章          │                                      │
│  > 第2章        │      原文どおりの文書描画領域          │
│    2.1          │                                      │
│    2.2          │                                      │
├─ ページ一覧 ────┤                                      │
│  12             │                                      │
│ >13             │                                      │
│  14             │                                      │
├────────────────┴──────────────────────────────────────┤
│ book.pdf  13 / 248  125%                      内容       │
└───────────────────────────────────────────────────────┘

図はすべての領域を表示した例。初期値では文書領域と1行のステータス行だけを表示し、目次とページ一覧は隠す。目次とページ一覧は独立に表示・非表示を切り替えられる。両方を表示した場合は左側の上下に配置し、片方だけなら左側の高さ全体を使う。各幅・高さの下限を確保し、小さいウィンドウではパネルを自動的に増やさない。

  • 文書領域: PDFのページは連続縦スクロールを初期値とする。ページの背景色や埋込フォントは文書どおりに描く。アプリのテーマを変更しても文書の色を勝手に反転しない。
  • 目次パネル: 項目を階層表示する。現在位置を含む最も近い項目を示す「現在位置」と、キーボードで選択中の行を示す「選択位置」を区別する。選択を動かすだけで本文を移動させない。
  • ページ一覧パネル: PDFは実ページ番号の一覧を基本とする。ページラベルがある場合は「付録-3(実ページ 213)」のように表示できる。サムネイルは必須にせず、将来追加候補とする。HTMLには表示しない。固定レイアウトEPUBではspine項目のページ一覧、リフローEPUBではpage-listがあれば出版物由来のページ参照、なければspine由来の章一覧を表示する。見出しは「ページ一覧」「出版物のページ」「章一覧」と内容に合わせる。
  • ステータス行: ファイル名、位置、ズーム倍率、フォーカス領域を簡潔に表示する。PDFは実ページ番号/総ページ数、HTMLは見出し名または「文書」、EPUBは章位置を表示する。HTMLやリフローEPUBに固定総ページ数を捏造しない。非表示にできる。
  • 通知: 文書読込中・エラー・利用できない操作は短い通知として表示する。通常の閲覧時に通知領域の高さを占有しない。自動消去される通知と、明示的な対処を要するエラーを区別する。

ページ一覧・目次が提供されない文書で対応キーを押した場合は「この文書にはページ一覧がありません」等を表示する。空のパネルを常設しない。マウスによるスクロール、リンク選択、パネル操作も可能とするが、主要操作はすべてキーボードで到達できる。

2.3 読込と異常時

  1. 文書を開く操作から、OS標準のファイル選択を表示する。
  2. ファイル確定後、読込状態を即座に表示する。目次や総ページ数の確定を待ってから初めて画面を更新する実装にしない。
  3. 最初に必要なページ・章を表示し、他ページや目次は準備できた時点で反映する。
  4. 読込が失敗した場合は、対象名、原因の分類、利用者が可能な対処を示す。内部例外・スタックトレースは画面に出さない。
  5. 既存文書から別文書への切替では、新文書の最低限の表示準備が完了するまで旧文書を保持する。失敗時は旧文書へ戻る。

PDFパスワード入力等の文字入力が必要な画面は、閲覧キーを奪わない専用ダイアログにする。対応暗号方式・パスワード保持方針は03・07に従う。

3. 操作状態とフォーカス

Vimの通常モードに相当する閲覧操作を採用するが、文書編集用の挿入モード・ビジュアルモードは作らない。

状態 入力の扱い 遷移・終了
内容閲覧 文書用キー、リンクのTab移動、マウススクロール パネルへフォーカス移動、ファイル選択等
目次フォーカス 行移動・階層開閉・選択確定 Enterで本文へ移動して内容に戻る、Escで内容へ戻る
ページ一覧フォーカス 行移動・選択確定 Enterで対象へ移動して内容に戻る、Escで内容へ戻る
キー列待機 g、z、[、]、Ctrl+W、数値カウントの後続を待つ 完成で実行、Escで破棄、期限切れで破棄
操作一覧表示 スクロール・閉じる操作のみ Escまたは?で閉じて元のフォーカスへ戻る
コマンド入力 :から入力欄を表示し、文字入力・IME・左右移動・削除を優先 Enterで検証して実行、Escで取消して元のフォーカスへ戻る
ダイアログ/文字入力 OS標準の編集操作とIMEを優先 確定・取消で元のフォーカスへ戻る
読込中 UIは応答し、不要になった読込の取消または別文書選択を可能にする 成功、失敗、取消

3.1 キー処理の優先順位

  1. OSまたはネイティブダイアログが占有する操作。
  2. IMEの変換・確定、ダイアログ内の文字入力と標準編集操作。
  3. 最前面にある操作一覧等の一時表示。
  4. 現在のフォーカス領域に限定された割当。
  5. アプリ共通割当。

Ctrl+O等の共通操作も、文字入力中・IME変換中に無条件で横取りしない。少なくとも isComposing 相当の状態にあるキーイベントは閲覧コマンドへ配送しない。コマンド入力、ファイル選択、パスワード入力、OSの標準ダイアログでは、j、k、数字、?等を通常の文字として入力できる。

3.2 フォーカス規則

  • 文書を開き終えたときは内容にフォーカスする。
  • パネルを表示しても直ちに本文位置やフォーカスを変更しない。
  • フォーカス中のパネルを隠した場合は内容に戻す。
  • Ctrl+Wの後にwを押すと「内容→目次→ページ一覧→内容」の順に循環する。非表示領域は飛ばす。
  • リンクの Tab / Shift+Tab は内容領域内のリンクを順に選択する。リンクがない場合は本文位置を変えず、内容にフォーカスを残す。パネル間の移動は専用キーで行う。
  • PDF内・HTML内・EPUB内の読取専用文書要素は、アプリの通常操作モードを勝手に切り替えない。フォーム記入や文書内スクリプトによるキーフックは設けない。
  • フォーカス枠、選択行、現在位置は色だけに依存せず、線・記号・濃淡で区別する。

4. 既定キーバインド案

キー表記は論理キー名を使う。Shiftを要する大文字は別のキーとして扱い、日本語配列/英語配列で文字を入力する物理キーが異なっても、設定上は ?、+ 等の文字で識別する。OSが予約するキーは上書きできない場合があるため、設定チェックと操作一覧で知らせる。

4.1 内容領域

キー 動作 境界・備考
j / k 小さく下/上へスクロール 設定可能な移動量。キーリピートに対応
h / l 横方向にスクロール 横の余りがない場合は何もしない
Ctrl+D / Ctrl+U 表示領域の半分だけ進む/戻る PDFは下/上。HTML/EPUBは書字方向に沿った読書軸を使う
Ctrl+F / Ctrl+B 表示領域のほぼ1画面分進む/戻る 読書軸に沿って移動し、少量の重なりを残す
gg / G 文書の先頭/末尾へ EPUBは読書順序の先頭/末尾。パネルでは先頭/末行
数字G PDFの指定実ページへ 例: 42G。HTML/EPUBでは利用不可と通知
J / K 次/前のPDF実ページへ PDFのみ。移動先ページの先頭へ
]] / [[ 次/前の見出しへ 見出し情報がある場合のみ
]c / [c 次/前のEPUB章へ EPUBのspine順に移動。非linear項目は通常順送りから除外
+ / - 拡大/縮小 PDFは表示倍率、HTML/リフローEPUBはズーム。原文は変更しない
= 幅に合わせる PDFまたは固定レイアウトに適用。リフロー形式では標準倍率へ戻す
Tab / Shift+Tab 次/前のリンクを選ぶ リンク数が多い場合もスクロール位置を選択先へ追従
Enter 選択リンクを実行 文書内移動・別文書/外部リンクの扱いは基盤仕様に従う
Esc 未完成のキー列またはリンク選択を解除。読込・索引待機中は要求を取り消す 文字入力/IMEの取消を優先し、文書自体は閉じない

このキー案では Ctrl+F をVim流の画面送りに使う。追加提案である本文検索は / で開始する。原要件を満たす基本操作と、検索・位置復元等の補助機能を区別する。

4.2 目次・ページ一覧

キー 目次 ページ一覧
j / k 次/前の可視行 次/前の行
h 展開中なら折りたたみ、そうでなければ親へ 何もしない
l 子があれば展開、展開済みなら最初の子へ 何もしない
gg / G 先頭/末尾の可視行 先頭/末尾の行
Ctrl+D / Ctrl+U 半画面分の行を移動 同左
Enter 選択項目へ移動 選択ページへ移動
Esc 内容へフォーカスを戻す 同左

4.3 共通操作

キー 動作
Ctrl+O 文書を開く
t 目次の表示/非表示を切り替える
p ページ一覧の表示/非表示を切り替える
zs ステータス行の表示/非表示を切り替える
Ctrl+W w 表示中の領域間でフォーカスを移す
: コマンド入力欄を表示する
? 現在の設定を反映した操作一覧を表示する

t、p、J、Kには文書リーダー独自の役割を割り当てる。Vimの完全互換ではないことを操作一覧で示す。q単押しで終了する操作は誤操作を避けて既定に含めず、OS標準のウィンドウ終了を使う。

4.4 キー列と設定検証

  • 接頭辞待機の既定値は800 msとする設計提案。06に従い200〜3,000 msへ変更でき、0は無期限待機とする。
  • 単一キーと、そのキーを接頭辞とする長いキー列を同じ有効コンテキストへ割り当てた場合はエラーにする。例: g と gg の併存は不可。
  • 同じ有効コンテキストで同じキーを複数動作へ割り当てる設定は拒否する。共通割当と領域別割当で同じキー列がある場合は領域別を優先する。利用者設定は(mode, context, keys)が一致する既定定義を置換する。異なる長さの接頭辞衝突は、同時に有効なcontext間でも拒否する。
  • 設定変更はファイル全体の構文・値・キー衝突検証が成功した後、一括で適用する。失敗時は最後に有効だった設定を維持し、行番号と修正可能な理由を表示する。
  • 数字は内容領域のPDFページ指定にのみ使い、先行ゼロを除き1以上の整数に制限する。入力中の数字は必要時だけ通知する。末尾が G 以外または期限切れなら入力列を破棄して、直前キーを別のコマンドとして勝手に実行しない。
  • フォーカス変更、文書切替、ダイアログ表示時は未完成キー列を破棄する。
  • リピートイベントで接頭辞待機を何重にも作らない。j等の連続スクロールはリピートを受け付けるが、パネル表示切替は長押しで点滅しない。

5. 形式別の位置と移動

5.1 PDF

  • 内部のページ番号は0始まり、利用者向けの実ページ番号は1始まりとし、変換箇所を位置型の境界へ限定する。
  • 42G はラベル「42」ではなく42枚目を開く。ページラベルと実ページが異なる場合は、ステータスと一覧に両方を表示する。
  • 現在ページは、文書表示領域の中央線に交わるページを基本とする。中央線がページ間の余白にある場合は近いページ、同距離なら前のページとする。これにより、ページ端で次/前操作が不安定になることを避ける。
  • 次/前ページは現在ページ番号に±1を適用し、移動先ページの上端へ移動する。末尾・先頭ではその位置にとどまり、短く境界を通知する。
  • PDFの目次は文書内のアウトライン情報を利用する。構造タグのH/H1〜H6から有効なページ位置を取得できる場合は、これを見出しジャンプへ用いる。構造タグの有効な見出しがない場合は、文書内宛先を持つアウトラインを代わりに用い、表示名を「目次項目移動」とする。構造タグ由来の見出しとアウトライン由来の項目は共通位置型へ変換しても、情報源の種別を保存する。両方を単純に併合して同一の項目へ二度移動させない。文字サイズ推定・OCRによる見出し生成は行わない。
  • ズーム変更時は、表示領域の中心にある文書上の点をできる限り保持する。異なる大きさや回転を持つページへ移動しても、そのページ固有の幾何情報を尊重する。

5.2 HTMLとZIP HTML

  • 通常HTMLはそのファイルを入口とする。ZIP HTMLは現在表示するHTMLを基準に相対URLを解決する。CSS内の参照はそのCSS自身の場所を基準とする。入口が複数ある場合・存在しない場合の選択規則は基盤仕様に従う。
  • h1〜h6 と有効なARIA見出しをDOM順で収集して見出し移動を提供する。display:none等で表示されない要素は対象外とする。見出し文言が空の場合は「見出し(レベルN)」と表示する。
  • HTMLの目次は、明示的な文書内目次のリンク構造が認識可能な場合にそれを採用する。認識不能でも見出しから作成した見出し一覧を利用できる。この一覧を著者作成の目次と混同しないようにラベルを区別する。
  • ZIP内の別HTMLへのリンクは同じ出版物コンテキストで開く。ページ一覧をファイル一覧として流用しない。HTMLを開いた順を「章順」として推定しない。
  • gg / G は現在のHTMLリソースの先頭/末尾である。ZIP全体の先頭/末尾とは解釈しない。
  • リフロー・ズーム変更後は、先頭可視要素とその要素内の相対位置を基準に位置を回復する。DOMに安定した位置がない場合はスクロール比率へフォールバックする。

5.3 EPUB

  • 章の通常移動はパッケージのspine順に従う。目次の表示順から章の読書順を推定しない。
  • リフロー形式は表示領域と作者の書字方向に従って組版する。横書きの通常文書は縦スクロール、日本語縦書き等はwriting-modeとdirectionに合った読書軸を使う。j/kとh/lは物理方向、半画面/1画面移動は読書方向に対応する。次/前章は次/前の通常読書対象spine項目の先頭へ移動する。
  • 目次はEPUB 3のnavigation document、EPUB 2はNCXを利用する。両方ある場合の優先順位はEPUB基盤仕様で固定する。
  • EPUB内の h1〜h6 と有効なARIA見出しを見出しジャンプの対象とする。章境界を越える見出し移動は、次/前の通常読書対象spine項目の最初/最後の有効見出しへ移る。先読みは必要最小限とし、全章を描画してから読書開始する構成にしない。
  • 章単位の位置と章内アンカーを持ち、画面幅の変更でページ数が変わっても同じ箇所に留まる。EPUB page-listのページ番号は書籍が提供した参照であり、現在の画面分割数ではない。
  • 固定レイアウトはそのviewportと読み方向を尊重する。日本語縦書き・RTLを含め、作者のCSSと出版物の方向情報を使う。固定レイアウトとリフロー文書では倍率・幅合わせの意味を分ける。

5.4 見出し移動の共通定義

「次の見出し」は現在の読書位置より後ろにある最初の有効な見出し、「前の見出し」は現在の読書位置より前にある最後の有効な見出しとする。同一の目的地へ重複する見出しは一度にまとめる。見出しの先頭ぴったりにいる場合、その見出しを再選択しない。PDFで見出しのページだけが確定し座標が確定しない場合は、precision=pageとしてページ先頭へ移動し、その精度を表示する。確定していない位置を正確な見出し位置と扱わない。目的地が不正な目次項目は選択時に理由を示し、他の目次項目まで使えなくしない。

6. コマンド契約と文字入力

設定ファイル、キー入力、コマンド入力は同じコマンドIDへ解決する。コマンド入力欄は必要時だけ最下部に現れ、ステータス行が非表示でも利用できる。入力中は等幅文字で : と文字列、エラーがあればその理由を示す。

ID 既定キー/文字列 引数・適用対象
file.open Ctrl+O、:open 引数なしはファイル選択。:open "path" は指定ローカルパスを開く
app.quit :q 終了。OS標準の終了操作も使用可
operation.cancel 読込/索引待機中のEsc、:cancel 現在の待機要求を取り消す。新文書のコミット前なら旧文書へ戻る。文字入力/IMEの取消が優先
document.root.choose :root 単独HTMLの許可フォルダーをOSの選択画面で指定。新root内へ資源を再解決
document.info :info 形式、検出した制限、欠落資源、エラー詳細を表示
history.clear :history clear 保存した履歴・位置を件数確認後に消去。補助機能
scroll.down / scroll.up j / k 内容領域の縦スクロール
scroll.left / scroll.right h / l 内容領域の横スクロール
scroll.half_down / scroll.half_up Ctrl+D / Ctrl+U 表示領域の半分
scroll.page_down / scroll.page_up Ctrl+F / Ctrl+B 表示領域のほぼ全体
nav.document_start / nav.document_end gg / G 形式別に定める文書範囲
nav.page 数字G、:page N 1始まりのPDF実ページ番号。範囲外はエラー、暗黙に末尾へ丸めない
nav.page_next / nav.page_previous J / K PDFのみ
nav.heading_next / nav.heading_previous ]] / [[ 有効な見出しまたは代替目次項目がある文書
nav.chapter_next / nav.chapter_previous ]c / [c EPUBのみ
panel.toc.toggle t、:toctoggle 目次または見出し一覧の表示を切り替える
panel.pages.toggle p、:pagestoggle 利用可能なページ/章一覧の表示を切り替える
panel.status.toggle zs、:statusbar ステータス行の表示を切り替える
focus.next Ctrl+W w 表示中の領域を循環
zoom.in / zoom.out + / - 現在位置を保持して拡大/縮小
zoom.fit_width = 固定ページでは幅合わせ、リフローでは標準倍率
view.rotate :rotate 90、:rotate -90 PDFの表示回転のみ。原本へ保存しない
command.open : コマンド入力状態へ移行
config.reload :reload 06で定義する検証と一括再読込
help.toggle ?、:help 現在のキー設定に対応する操作一覧
nav.back / nav.forward Alt+Left / Alt+Right 同一文書コンテキスト内の明示的なジャンプ履歴
search.open / 本文検索の入力欄。補助機能の提案
search.next / search.previous n / N 検索結果。補助機能の提案

nav.back / nav.forward は目次・リンク・指定ページ等のジャンプを戻す。小さなスクロールのすべてを履歴へ積まない。新しい文書を開くことと、同じZIP内HTMLへの移動は、文書コンテキストの境界によって区別する。

コマンドの引数はアプリ内パーサーで処理し、シェルへ渡さない。パスは空白を含む場合に二重引用符で囲み、Windowsのバックスラッシュは文字どおり扱う。シェル変数、ワイルドカード、!による外部コマンド実行は展開しない。未知のコマンド、引数不足、余分な引数は入力欄に理由を表示し、文書状態を変更しない。IME確定のEnterはコマンド実行と兼用せず、変換確定後のEnterで実行する。

7. 補助機能の提案

本文検索、読書位置の再開、最近使った文書は原要件の独立した追加提案である。実装順の判断により削減できる。これらを省略してもR01〜R15の試験を省略しない。

  • 本文検索: /で検索欄を開く。入力中はIMEと文字編集を優先する。Enterで検索し、n/Nで結果を移動する。PDFの既存テキストとHTML/EPUBの表示テキストを対象とし、画像へOCRを適用しない。検索処理は取消可能にし、結果なしと文字情報なしを区別する。
  • 読書位置の再開: 文書を閉じる前の論理位置・倍率をローカル保存し、同じ文書を開いたときに回復する。原文の変更やウィンドウ幅の違いによる復元精度の低下を考慮し、保存先と識別方式は05・06に従う。HTML/リフローEPUBの画面上のページ数を永続キーにしない。
  • 最近使った文書: 初期画面の追加表示として設定で有効化できる。初期画面を履歴の大量表示で埋めない。消去機能と保存上限を持ち、原本を変更しない。

8. UI実装前の確認項目

Qt QuickとQt WebEngineの間のフォーカス、IMEのcompositionイベント、日本語/英語キーボード配列、Wayland/X11、Windowsの表示スケール差を実機で確認する。PDFのアウトラインと構造タグ由来の見出し位置は出典を区別して保持する。これらは実装開始時の技術検証対象とする。