Coverage for graphica/gui/dialog_dirs.py: 100.0%
70 statements
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-12 16:38 +0000
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-12 16:38 +0000
1"""ファイルダイアログを開く場所。用途ごとに前回選んだフォルダを覚え、まだ無ければ「ドキュメント」から開く。
3場所を渡さないと Qt は今の作業フォルダで開き、ショートカットから起動するとそれがアプリ本体のフォルダになる。
4作業中のプロジェクトの場所など、もっと適した場所があれば preferred_dir で渡す(在るときだけ使う)。
5"""
6import json
7import os
9from PySide6.QtCore import QStandardPaths
11from graphica.gui import app_settings, notify
13# 用途(覚えるフォルダの単位)
14PROJECT = 'project' # プロジェクトを開く・保存する
15DATA = 'data' # データを読み込む
16EXPORT = 'export' # 図・スクリプト・レポートを書き出す
17TABLE = 'table' # データ表(CSV・Excel)を書き出す
18TEMPLATE = 'template' # 書式テンプレート
19OTHER = 'other' # 設定の書き出し・診断情報・プラグインなど
22def documents_dir():
23 path = QStandardPaths.writableLocation(QStandardPaths.StandardLocation.DocumentsLocation)
24 return path if path and os.path.isdir(path) else os.path.expanduser('~')
27def _remembered():
28 raw = app_settings.LAST_DIALOG_DIRS.read(app_settings.open_settings())
29 try:
30 value = json.loads(raw) if raw else {}
31 except (TypeError, ValueError):
32 return {}
33 return value if isinstance(value, dict) else {}
36def start_dir(purpose, preferred_dir=None):
37 """preferred_dir が在ればそこ、無ければその用途で前回選んだフォルダ、それも無ければ「ドキュメント」。"""
38 for candidate in (preferred_dir, _remembered().get(purpose)):
39 if candidate and os.path.isdir(candidate):
40 return os.path.normpath(candidate)
41 return os.path.normpath(documents_dir())
44def start_path(purpose, file_name='', preferred_dir=None):
45 directory = start_dir(purpose, preferred_dir)
46 return os.path.normpath(os.path.join(directory, file_name) if file_name else directory)
49def remember(purpose, path):
50 """選んだファイルのフォルダ(フォルダならそのもの)を、その用途の次の開き先にする。"""
51 if not path:
52 return
53 directory = path if os.path.isdir(path) else os.path.dirname(path)
54 if not directory:
55 return
56 remembered = _remembered()
57 if remembered.get(purpose) == directory:
58 return
59 remembered[purpose] = directory
60 app_settings.LAST_DIALOG_DIRS.write(app_settings.open_settings(), json.dumps(remembered, ensure_ascii=False))
63def get_save_file_name(parent, purpose, title, file_name, file_filter, preferred_dir=None):
64 path, selected_filter = notify.get_save_file_name(
65 parent, title, start_path(purpose, file_name, preferred_dir), file_filter)
66 remember(purpose, path)
67 return path, selected_filter
70def get_open_file_name(parent, purpose, title, file_filter, preferred_dir=None):
71 path, selected_filter = notify.get_open_file_name(parent, title, start_dir(purpose, preferred_dir), file_filter)
72 remember(purpose, path)
73 return path, selected_filter
76def get_open_file_names(parent, purpose, title, file_filter, preferred_dir=None):
77 paths, selected_filter = notify.get_open_file_names(parent, title, start_dir(purpose, preferred_dir), file_filter)
78 if paths:
79 remember(purpose, paths[0])
80 return paths, selected_filter
83def get_existing_directory(parent, purpose, title, preferred_dir=None):
84 path = notify.get_existing_directory(parent, title, start_dir(purpose, preferred_dir))
85 remember(purpose, path)
86 return path
89# --- 作業中のものに合わせた場所 ---
91def project_dir(app):
92 """保存したプロジェクトのフォルダ。まだ保存していなければ None。"""
93 path = getattr(app, '_current_project_path', None)
94 return os.path.dirname(path) if path else None
97def project_stem(app):
98 path = getattr(app, '_current_project_path', None)
99 return os.path.splitext(os.path.basename(path))[0] if path else ''
102def data_source_dir(app):
103 """読み込んだデータファイルのうち、最初に見つかったもののフォルダ(データの隣にプロジェクトを置けるように)。"""
104 for dataset in getattr(app.project, 'datasets', []):
105 source = getattr(dataset, 'source_file', None)
106 if source and os.path.isdir(os.path.dirname(source)):
107 return os.path.dirname(source)
108 return None
111def output_dir(app):
112 """書き出しの場所: 保存したプロジェクトのフォルダ、無ければ読み込んだデータのフォルダ。"""
113 return project_dir(app) or data_source_dir(app)