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

1"""ファイルダイアログを開く場所。用途ごとに前回選んだフォルダを覚え、まだ無ければ「ドキュメント」から開く。 

2 

3場所を渡さないと Qt は今の作業フォルダで開き、ショートカットから起動するとそれがアプリ本体のフォルダになる。 

4作業中のプロジェクトの場所など、もっと適した場所があれば preferred_dir で渡す(在るときだけ使う)。 

5""" 

6import json 

7import os 

8 

9from PySide6.QtCore import QStandardPaths 

10 

11from graphica.gui import app_settings, notify 

12 

13# 用途(覚えるフォルダの単位) 

14PROJECT = 'project' # プロジェクトを開く・保存する 

15DATA = 'data' # データを読み込む 

16EXPORT = 'export' # 図・スクリプト・レポートを書き出す 

17TABLE = 'table' # データ表(CSV・Excel)を書き出す 

18TEMPLATE = 'template' # 書式テンプレート 

19OTHER = 'other' # 設定の書き出し・診断情報・プラグインなど 

20 

21 

22def documents_dir(): 

23 path = QStandardPaths.writableLocation(QStandardPaths.StandardLocation.DocumentsLocation) 

24 return path if path and os.path.isdir(path) else os.path.expanduser('~') 

25 

26 

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 {} 

34 

35 

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()) 

42 

43 

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) 

47 

48 

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)) 

61 

62 

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 

68 

69 

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 

74 

75 

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 

81 

82 

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 

87 

88 

89# --- 作業中のものに合わせた場所 --- 

90 

91def project_dir(app): 

92 """保存したプロジェクトのフォルダ。まだ保存していなければ None。""" 

93 path = getattr(app, '_current_project_path', None) 

94 return os.path.dirname(path) if path else None 

95 

96 

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 '' 

100 

101 

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 

109 

110 

111def output_dir(app): 

112 """書き出しの場所: 保存したプロジェクトのフォルダ、無ければ読み込んだデータのフォルダ。""" 

113 return project_dir(app) or data_source_dir(app)