1+ # Mantid Repository : https://github.com/mantidproject/mantid
2+ #
13# Copyright © 2017 ISIS Rutherford Appleton Laboratory UKRI,
24# NScD Oak Ridge National Laboratory, European Spallation Source,
35# Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
46# SPDX - License - Identifier: GPL - 3.0 +
57import os
68
7-
9+ # --- Logger and ConfigService Setup ---
810try :
911 from mantid .kernel import Logger
1012 from mantid .kernel import ConfigService
11-
1213except ImportError :
1314 print ("Warning: Mantid Kernel (Logger/ConfigService) not found, using basic print/dummy." )
1415
@@ -28,17 +29,18 @@ def information(self, msg):
2829 def error (self , msg ):
2930 print (f"ERROR [{ self ._name } ]: { msg } " )
3031
31- class ConfigService :
32+ class ConfigService : # Dummy for environments without Mantid
3233 @staticmethod
3334 def Instance ():
3435 class DummyInstance :
3536 def getString (self , key , pathAbsolute = True ):
36- return None # Default to None
37+ return None
3738
3839 return DummyInstance ()
3940
4041
4142log = Logger ("HelpWindowModel" )
43+ # --------------------------------------
4244
4345from qtpy .QtCore import QUrl # noqa: E402
4446from qtpy .QtWebEngineCore import QWebEngineUrlRequestInterceptor , QWebEngineUrlRequestInfo # noqa: E402
@@ -80,89 +82,132 @@ class HelpWindowModel:
8082 MODE_ONLINE = "Online Docs"
8183
8284 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
8490 try :
91+ # ConfigService is imported at the top level now
8592 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
8895 local_docs_path_from_config = raw_path
8996 log .debug (f"Retrieved 'docs.html.root' from ConfigService: '{ local_docs_path_from_config } '" )
9097 else :
9198 log .debug ("'docs.html.root' property is empty or not found in ConfigService." )
92-
9399 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
95104
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 )
102108
103- def _determine_mode_and_base_url (self , local_docs_path ):
109+ def _determine_mode_and_set_state (self , local_docs_path ):
104110 """
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).
107114 """
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
109118 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." )
110121 self ._is_local = True
111122 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
113125 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+
116129 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
118133 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
120135 )
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 ." )
123138
124139 self ._is_local = False
125140 self ._mode_string = self .MODE_ONLINE
126- self ._version_string = getMantidVersionString ()
127141
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
128146 if self ._version_string :
129147 base_online = self ._raw_online_base
130148 if base_online .endswith ("/stable" ):
131149 base_online = base_online [: - len ("/stable" )]
150+ # Avoid double versioning if base_online already has it
132151 if self ._version_string not in base_online :
133152 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)
136155 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
139158 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 } '" )
141162
163+ # --- Getter methods remain the same ---
142164 def is_local_docs_mode (self ):
165+ """
166+ :return: True if using local docs, False otherwise. Based on state set during init.
167+ """
143168 return self ._is_local
144169
145170 def get_mode_string (self ):
171+ """
172+ :return: User-friendly string indicating the mode ("Offline Docs" or "Online Docs").
173+ """
146174 return self ._mode_string
147175
148176 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
149181 return self ._base_url .rstrip ("/" ) + "/"
150182
183+ # --- URL building methods use the state set during init ---
151184 def build_help_url (self , relative_url ):
185+ """
186+ Returns a QUrl pointing to the determined doc source for the given relative URL.
187+ """
152188 if not relative_url or not relative_url .lower ().endswith ((".html" , ".htm" )):
153189 relative_url = "index.html"
190+
154191 relative_url = relative_url .lstrip ("/" )
155- base = self .get_base_url ()
192+ base = self .get_base_url () # Uses the final URL determined during init
156193 full_url_str = f"{ base } { relative_url } "
194+
157195 url = QUrl (full_url_str )
158196 if not url .isValid ():
159197 log .warning (f"Constructed invalid URL: { full_url_str } from base '{ base } ' and relative '{ relative_url } '" )
160198 return url
161199
162200 def get_home_url (self ):
201+ """
202+ Return the 'home' page URL (index.html) based on the determined mode/base URL.
203+ """
163204 return self .build_help_url ("index.html" )
164205
206+ # --- Interceptor creation uses the state set during init ---
165207 def create_request_interceptor (self ):
208+ """
209+ Return an appropriate request interceptor based on the determined mode (_is_local).
210+ """
166211 if self ._is_local :
167212 log .debug ("Using LocalRequestInterceptor." )
168213 return LocalRequestInterceptor ()
0 commit comments