profiles.py 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. ########################################################################
  2. # Searx-qt - Lightweight desktop application for SearX.
  3. # Copyright (C) 2020 CYBERDEViL
  4. #
  5. # This file is part of Searx-qt.
  6. #
  7. # Searx-qt is free software: you can redistribute it and/or modify
  8. # it under the terms of the GNU General Public License as published by
  9. # the Free Software Foundation, either version 3 of the License, or
  10. # (at your option) any later version.
  11. #
  12. # Searx-qt is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU General Public License
  18. # along with this program. If not, see <https://www.gnu.org/licenses/>.
  19. #
  20. ########################################################################
  21. from PyQt5.QtCore import QSettings, QStandardPaths, QFile
  22. from searxqt.models.instances import InstancesModelTypes
  23. from searxqt import PROFILES_PATH, SETTINGS_PATH
  24. class ProfileItem(tuple):
  25. def __init__(self, data=None):
  26. """
  27. @param data:
  28. @type data: tuple (id, name, type)
  29. """
  30. tuple.__init__(self)
  31. self.id = ''
  32. self.name = ''
  33. self.type = InstancesModelTypes.NotDefined
  34. if data:
  35. self.id = data[0]
  36. self.name = data[1]
  37. self.type = data[2]
  38. def __new__(cls, data=('', '')):
  39. return super(ProfileItem, cls).__new__(cls, tuple(data))
  40. class Profiles:
  41. def __init__(self):
  42. self._currentProfile = ProfileItem()
  43. self._profiles = {
  44. # list with searxqt.models.profiles.ProfileItem's
  45. 'profiles': [],
  46. # str: profile id
  47. 'default': ProfileItem()
  48. }
  49. def __contains__(self, profile):
  50. return bool(profile in self._profiles['profiles'])
  51. def __len__(self):
  52. return len(self._profiles['profiles'])
  53. def __getitem__(self, index):
  54. return self._profiles['profiles'][index]
  55. def add(self, profile):
  56. """ Add profile to this object. This will not save profiles.conf!
  57. @param profile: ProfileItem to add.
  58. @type profile: ProfileItem
  59. """
  60. self._profiles['profiles'].append(profile)
  61. def remove(self, profile):
  62. """ Remove profile from this object. This will not save profiles.conf!
  63. @param profile: ProfileItem to remove.
  64. @type profile: ProfileItem
  65. """
  66. self._profiles['profiles'].remove(profile)
  67. def current(self):
  68. """ Returns current profile
  69. @rtype: ProfileItem
  70. """
  71. return self._currentProfile
  72. def default(self):
  73. """ Returns the default profile
  74. @rtype: ProfileItem
  75. """
  76. return self._profiles['default']
  77. def setDefault(self, profile):
  78. """
  79. @param profile: ProfileItem to set as default.
  80. @type profile: ProfileItem
  81. """
  82. self._profiles['default'] = profile
  83. def loadProfiles(self, settings):
  84. """ Load profiles.conf
  85. """
  86. self._profiles = {
  87. # list with searxqt.models.profiles.ProfileItem's
  88. 'profiles': settings.value('profiles', list(), list),
  89. # str: profile id
  90. 'default': settings.value(
  91. 'default', ProfileItem(), ProfileItem
  92. )
  93. }
  94. def getActiveProfiles(self, settings):
  95. """ Returns a list with active profile id's
  96. """
  97. return settings.value('active', list(), list)
  98. def profileActive(self, profile):
  99. """ Check if profile is active or not. This will re-read the
  100. profiles.conf file.
  101. @rtype: bool
  102. """
  103. settings = self.settings()
  104. return bool(profile.id in self.getActiveProfiles(settings))
  105. def profileExists(self, profile):
  106. """ Check if profile is still present in profiles.conf. This will
  107. re-read the profiles.conf file. It however won't store the read
  108. data in this object.
  109. @rtype: bool
  110. """
  111. settings = self.settings()
  112. profiles = settings.value('profiles', list(), list)
  113. for p in profiles:
  114. if p.id == profile.id:
  115. return True
  116. return False
  117. def settings(self):
  118. return QSettings(SETTINGS_PATH, 'profiles')
  119. def releaseAll(self):
  120. """ Release active profiles. This may be wanted after a crash of
  121. searx-qt or the system. User must make sure to close all other
  122. instances of searx-qt first.
  123. """
  124. settings = self.settings()
  125. settings.remove('active')
  126. def setProfile(self, settings, profile):
  127. """ Sets current profile active (also stores it to profiles.conf).
  128. @type settings: QSettings
  129. @type profile: ProfileItem
  130. """
  131. # Read a list of active profile id's
  132. activeProfiles = self.getActiveProfiles(settings)
  133. if self._currentProfile.id in activeProfiles:
  134. # Remove current profile id from active profiles
  135. activeProfiles.remove(self._currentProfile.id)
  136. # Append current profile id to the active profiles list
  137. if profile.id:
  138. activeProfiles.append(profile.id)
  139. # Store the changes
  140. settings.setValue('active', activeProfiles)
  141. self._currentProfile = profile
  142. def saveProfiles(self):
  143. settings = self.settings()
  144. settings.setValue('profiles', self._profiles['profiles'])
  145. settings.setValue('default', self._profiles['default'])
  146. def removeProfileFiles(self, profileIds):
  147. """ Removes all profile files for given profile ID's.
  148. @param profileIds: List with unique profile ID's
  149. @type profileIds: list
  150. """
  151. for profileId in profileIds:
  152. self.removeProfileFile(profileId)
  153. def removeProfileFile(self, profileId):
  154. """ Remove profile file for given profile ID.
  155. @param profileId: Unique profile id
  156. @type profileId: str
  157. """
  158. # Locate full file-path
  159. confFilePath = QStandardPaths.locate(
  160. QStandardPaths.ConfigLocation,
  161. f"{PROFILES_PATH}{profileId}.conf",
  162. QStandardPaths.LocateFile
  163. )
  164. # confFilePath may be a empty string, this means the file wasn't
  165. # found. This can happen when the profile has never loaded and saved.
  166. if confFilePath:
  167. print(f"Trying to remove: {confFilePath}")
  168. confFile = QFile(confFilePath)
  169. if confFile.remove():
  170. print(f"Removed {confFilePath}")
  171. return True
  172. else:
  173. print(f"Could not remove {confFilePath}")
  174. return False
  175. def names(self):
  176. """ Returns all profile names in a list.
  177. @rtype: list
  178. """
  179. return [profile.name for profile in self._profiles['profiles']]