1
+ # Mantid Repository : https://github.com/mantidproject/mantid
2
+ #
1
3
# Copyright © 2017 ISIS Rutherford Appleton Laboratory UKRI,
2
4
# NScD Oak Ridge National Laboratory, European Spallation Source,
3
5
# Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
4
6
# SPDX - License - Identifier: GPL - 3.0 +
5
7
import os
6
8
7
-
9
+ # --- Logger and ConfigService Setup ---
8
10
try :
9
11
from mantid .kernel import Logger
10
12
from mantid .kernel import ConfigService
11
-
12
13
except ImportError :
13
14
print ("Warning: Mantid Kernel (Logger/ConfigService) not found, using basic print/dummy." )
14
15
@@ -28,17 +29,18 @@ def information(self, msg):
28
29
def error (self , msg ):
29
30
print (f"ERROR [{ self ._name } ]: { msg } " )
30
31
31
- class ConfigService :
32
+ class ConfigService : # Dummy for environments without Mantid
32
33
@staticmethod
33
34
def Instance ():
34
35
class DummyInstance :
35
36
def getString (self , key , pathAbsolute = True ):
36
- return None # Default to None
37
+ return None
37
38
38
39
return DummyInstance ()
39
40
40
41
41
42
log = Logger ("HelpWindowModel" )
43
+ # --------------------------------------
42
44
43
45
from qtpy .QtCore import QUrl # noqa: E402
44
46
from qtpy .QtWebEngineCore import QWebEngineUrlRequestInterceptor , QWebEngineUrlRequestInfo # noqa: E402
@@ -80,89 +82,132 @@ class HelpWindowModel:
80
82
MODE_ONLINE = "Online Docs"
81
83
82
84
def __init__ (self , online_base = "https://docs.mantidproject.org/" ):
83
- local_docs_path_from_config = None
85
+ # Store raw online base early, needed for fallback logic below
86
+ self ._raw_online_base = online_base .rstrip ("/" )
87
+
88
+ # --- Step 1: Attempt to get local path from ConfigService ---
89
+ local_docs_path_from_config = None # Default if lookup fails or path is empty
84
90
try :
91
+ # ConfigService is imported at the top level now
85
92
config_service = ConfigService .Instance ()
86
- raw_path = config_service .getString ("docs.html.root" , True )
87
- if raw_path :
93
+ raw_path = config_service .getString ("docs.html.root" , True ) # pathAbsolute=True
94
+ if raw_path : # Only assign if not empty
88
95
local_docs_path_from_config = raw_path
89
96
log .debug (f"Retrieved 'docs.html.root' from ConfigService: '{ local_docs_path_from_config } '" )
90
97
else :
91
98
log .debug ("'docs.html.root' property is empty or not found in ConfigService." )
92
-
93
99
except Exception as e :
94
- log .error (f"Error retrieving 'docs.html.root' from ConfigService: { e } " )
100
+ # Catch potential errors during ConfigService interaction
101
+ # This includes cases where the dummy ConfigService might be used
102
+ log .error (f"Error retrieving 'docs.html.root' from ConfigService: { e } . Defaulting to online mode." )
103
+ # local_docs_path_from_config remains None
95
104
96
- self ._raw_online_base = online_base .rstrip ("/" )
97
- self ._is_local = False
98
- self ._mode_string = self .MODE_ONLINE
99
- self ._base_url = self ._raw_online_base
100
- self ._version_string = None
101
- self ._determine_mode_and_base_url (local_docs_path_from_config )
105
+ # --- Step 2: Determine final mode and set ALL related state variables ---
106
+ # This method now sets _is_local, _mode_string, _base_url, _version_string
107
+ self ._determine_mode_and_set_state (local_docs_path_from_config )
102
108
103
- def _determine_mode_and_base_url (self , local_docs_path ):
109
+ def _determine_mode_and_set_state (self , local_docs_path ):
104
110
"""
105
- Sets the internal state (_is_local, _mode_string, _base_url, _version_string)
106
- based on the validity of the provided local_docs_path.
111
+ Sets the final operational state (_is_local, _mode_string, _base_url, _version_string)
112
+ based *only* on the validity of the provided local_docs_path argument, which is the
113
+ result of the ConfigService lookup (can be a path string or None).
107
114
"""
108
- log .debug (f"Determining mode with local_docs_path='{ local_docs_path } '" )
115
+ log .debug (f"Determining final mode and state with local_docs_path='{ local_docs_path } '" )
116
+
117
+ # Check if the path from config is valid and points to an existing directory
109
118
if local_docs_path and os .path .isdir (local_docs_path ):
119
+ # --- Configure for LOCAL/OFFLINE Mode ---
120
+ log .debug ("Valid local docs path found. Configuring for Offline Mode." )
110
121
self ._is_local = True
111
122
self ._mode_string = self .MODE_OFFLINE
112
- abs_local_path = os .path .abspath (local_docs_path )
123
+ abs_local_path = os .path .abspath (local_docs_path ) # Ensure absolute
124
+ # Base URL for local files needs 'file:///' prefix and correct path format
113
125
self ._base_url = QUrl .fromLocalFile (abs_local_path ).toString ()
114
- self ._version_string = None
115
- log .debug (f"Using { self ._mode_string } from { self ._base_url } " )
126
+ self ._version_string = None # Version string not applicable for local docs mode
127
+ log .debug (f"Final state: Mode='{ self ._mode_string } ', Base URL='{ self ._base_url } '" )
128
+
116
129
else :
117
- if local_docs_path :
130
+ # --- Configure for ONLINE Mode ---
131
+ # Log reason if applicable
132
+ if local_docs_path : # Path was provided but invalid
118
133
log .warning (
119
- f"Local docs path '{ local_docs_path } ' from ConfigService ('docs.html.root') is invalid or not found. Falling back to online docs ." # noqa: E501
134
+ f"Local docs path '{ local_docs_path } ' from ConfigService ('docs.html.root') is invalid or not found. Falling back to Online Mode ." # noqa: E501
120
135
)
121
- else :
122
- log .debug ("No valid local docs path found from ConfigService. Using online docs ." )
136
+ else : # Path was None (not found in config or error during lookup)
137
+ log .debug ("No valid local docs path found from ConfigService. Configuring for Online Mode ." )
123
138
124
139
self ._is_local = False
125
140
self ._mode_string = self .MODE_ONLINE
126
- self ._version_string = getMantidVersionString ()
127
141
142
+ # Attempt to get versioned URL for online mode
143
+ self ._version_string = getMantidVersionString () # Might return None
144
+
145
+ # Set final base URL based on online path and version string
128
146
if self ._version_string :
129
147
base_online = self ._raw_online_base
130
148
if base_online .endswith ("/stable" ):
131
149
base_online = base_online [: - len ("/stable" )]
150
+ # Avoid double versioning if base_online already has it
132
151
if self ._version_string not in base_online :
133
152
self ._base_url = f"{ base_online .rstrip ('/' )} /{ self ._version_string } "
134
- log .debug (f"Using { self . _mode_string } (Version: { self . _version_string } ) from { self ._base_url } " )
135
- else :
153
+ log .debug (f"Using versioned online URL: { self ._base_url } " )
154
+ else : # Use provided base as-is (likely includes 'stable' or version)
136
155
self ._base_url = self ._raw_online_base
137
- log .debug (f"Using { self . _mode_string } (Using provided base URL, possibly stable/latest ): { self ._base_url } " )
138
- else :
156
+ log .debug (f"Using provided online base URL (version/stable implied ): { self ._base_url } " )
157
+ else : # No version string found, use raw online base
139
158
self ._base_url = self ._raw_online_base
140
- log .debug (f"Using { self ._mode_string } (Version: Unknown/Stable) from { self ._base_url } " )
159
+ log .debug (f"Using default online base URL (version unknown): { self ._base_url } " )
160
+
161
+ log .debug (f"Final state: Mode='{ self ._mode_string } ', Base URL='{ self ._base_url } ', Version='{ self ._version_string } '" )
141
162
163
+ # --- Getter methods remain the same ---
142
164
def is_local_docs_mode (self ):
165
+ """
166
+ :return: True if using local docs, False otherwise. Based on state set during init.
167
+ """
143
168
return self ._is_local
144
169
145
170
def get_mode_string (self ):
171
+ """
172
+ :return: User-friendly string indicating the mode ("Offline Docs" or "Online Docs").
173
+ """
146
174
return self ._mode_string
147
175
148
176
def get_base_url (self ):
177
+ """
178
+ :return: The determined base URL (either file:///path/ or https://docs...[/version]/) with trailing slash.
179
+ """
180
+ # Ensure trailing slash for correct relative URL joining
149
181
return self ._base_url .rstrip ("/" ) + "/"
150
182
183
+ # --- URL building methods use the state set during init ---
151
184
def build_help_url (self , relative_url ):
185
+ """
186
+ Returns a QUrl pointing to the determined doc source for the given relative URL.
187
+ """
152
188
if not relative_url or not relative_url .lower ().endswith ((".html" , ".htm" )):
153
189
relative_url = "index.html"
190
+
154
191
relative_url = relative_url .lstrip ("/" )
155
- base = self .get_base_url ()
192
+ base = self .get_base_url () # Uses the final URL determined during init
156
193
full_url_str = f"{ base } { relative_url } "
194
+
157
195
url = QUrl (full_url_str )
158
196
if not url .isValid ():
159
197
log .warning (f"Constructed invalid URL: { full_url_str } from base '{ base } ' and relative '{ relative_url } '" )
160
198
return url
161
199
162
200
def get_home_url (self ):
201
+ """
202
+ Return the 'home' page URL (index.html) based on the determined mode/base URL.
203
+ """
163
204
return self .build_help_url ("index.html" )
164
205
206
+ # --- Interceptor creation uses the state set during init ---
165
207
def create_request_interceptor (self ):
208
+ """
209
+ Return an appropriate request interceptor based on the determined mode (_is_local).
210
+ """
166
211
if self ._is_local :
167
212
log .debug ("Using LocalRequestInterceptor." )
168
213
return LocalRequestInterceptor ()
0 commit comments