123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254 |
- ########################################################################
- # Searx-Qt - Lightweight desktop application for Searx.
- # Copyright (C) 2020-2022 CYBERDEViL
- #
- # This file is part of Searx-Qt.
- #
- # Searx-Qt is free software: you can redistribute it and/or modify
- # it under the terms of the GNU General Public License as published by
- # the Free Software Foundation, either version 3 of the License, or
- # (at your option) any later version.
- #
- # Searx-Qt is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License
- # along with this program. If not, see <https://www.gnu.org/licenses/>.
- #
- ########################################################################
- from PyQt5.QtCore import QSettings, QStandardPaths, QFile
- from searxqt.models.instances import InstancesModelTypes
- from searxqt import PROFILES_PATH, SETTINGS_PATH
- from searxqt.core import log
- from searxqt.version import __version__
- class ProfileItem:
- def __init__(
- self,
- id_='',
- name='',
- type_=InstancesModelTypes.NotDefined,
- preset=None
- ):
- """
- @param id_: Unique profile id
- @type id: str
- @param name: Profile name
- @type name: str
- @param type_: Profile type
- @type type_: InstancesModelTypes.*
- @param preset: This is only used for new profiles, it is the key of the
- defaults preset that should be loaded.
- @type preset: None or str
- """
- self.id = id_
- self.name = name
- self.type = type_
- self.preset = preset
- def serialize(self):
- return {
- 'id': self.id,
- 'name': self.name,
- 'type': self.type
- }
- def deserialize(self, data):
- self.id = data['id']
- self.name = data['name']
- self.type = int(data['type'])
- class Profiles:
- def __init__(self):
- self._currentProfile = ProfileItem()
- self._profiles = {
- # list with searxqt.models.profiles.ProfileItem's
- 'profiles': [],
- # str: profile id
- 'default': None
- }
- def __contains__(self, profile):
- return bool(profile in self._profiles['profiles'])
- def __len__(self):
- return len(self._profiles['profiles'])
- def __getitem__(self, index):
- return self._profiles['profiles'][index]
- def add(self, profile):
- """ Add profile to this object. This will not save profiles.conf!
- @param profile: ProfileItem to add.
- @type profile: ProfileItem
- """
- self._profiles['profiles'].append(profile)
- def remove(self, profile):
- """ Remove profile from this object. This will not save profiles.conf!
- @param profile: ProfileItem to remove.
- @type profile: ProfileItem
- """
- self._profiles['profiles'].remove(profile)
- def current(self):
- """ Returns current profile
- @rtype: ProfileItem
- """
- return self._currentProfile
- def default(self):
- """ Returns the default profile
- @rtype: ProfileItem or None when not set.
- """
- return self._profiles['default']
- def setDefault(self, profile):
- """
- @param profile: ProfileItem to set as default.
- @type profile: ProfileItem or None to unset.
- """
- self._profiles['default'] = profile
- def loadProfiles(self, settings):
- """ Load profiles.conf
- """
- self._profiles['default'] = None
- default = settings.value('default', '', str)
- if default != '':
- self._profiles['default'] = ProfileItem()
- self._profiles['default'].deserialize(default)
- # Deserialize profiles
- self._profiles['profiles'].clear()
- for profile in settings.value('profiles', list(), list):
- item = ProfileItem(profile['id'], profile['name'], profile['type'])
- self._profiles['profiles'].append(item)
- def saveProfiles(self):
- settings = self.settings()
- if self._profiles['default'] is not None:
- settings.setValue('default', self._profiles['default'].serialize())
- else:
- settings.setValue('default', '')
- # Store searx-qt version (for backward compatibility)
- settings.setValue('version', __version__)
- # Serialize profiles
- profiles = []
- for profile in self._profiles['profiles']:
- profiles.append(profile.serialize())
- settings.setValue('profiles', profiles)
- def getActiveProfiles(self, settings):
- """ Returns a list with active profile id's
- """
- return settings.value('active', list(), list)
- def profileActive(self, profile):
- """ Check if profile is active or not. This will re-read the
- profiles.conf file.
- @rtype: bool
- """
- settings = self.settings()
- return bool(profile.id in self.getActiveProfiles(settings))
- def profileExists(self, profile):
- """ Check if profile is still present in profiles.conf. This will
- re-read the profiles.conf file. It however won't store the read
- data in this object.
- @rtype: bool
- """
- settings = self.settings()
- profiles = settings.value('profiles', list(), list)
- for p in profiles:
- if p['id'] == profile.id:
- return True
- return False
- def settings(self):
- return QSettings(SETTINGS_PATH, 'profiles')
- def releaseAll(self):
- """ Release active profiles. This may be wanted after a crash of
- searx-qt or the system. User must make sure to close all other
- instances of searx-qt first.
- """
- settings = self.settings()
- settings.remove('active')
- def setProfile(self, settings, profile):
- """ Sets current profile active (also stores it to profiles.conf).
- @type settings: QSettings
- @type profile: ProfileItem
- """
- # Read a list of active profile id's
- activeProfiles = self.getActiveProfiles(settings)
- if self._currentProfile.id in activeProfiles:
- # Remove old profile id from active profiles
- activeProfiles.remove(self._currentProfile.id)
- # Append current profile id to the active profiles list
- if profile.id:
- activeProfiles.append(profile.id)
- # Store the changes
- settings.setValue('active', activeProfiles)
- self._currentProfile = profile
- def removeProfileFiles(self, profileIds):
- """ Removes all profile files for given profile ID's.
- @param profileIds: List with unique profile ID's
- @type profileIds: list
- """
- for profileId in profileIds:
- self.removeProfileFile(profileId)
- def removeProfileFile(self, profileId):
- """ Remove profile file for given profile ID.
- @param profileId: Unique profile id
- @type profileId: str
- """
- # Locate full file-path
- confFilePath = QStandardPaths.locate(
- QStandardPaths.ConfigLocation,
- f"{PROFILES_PATH}{profileId}.conf",
- QStandardPaths.LocateFile
- )
- # confFilePath may be a empty string, this means the file wasn't
- # found. This can happen when the profile has never loaded and saved.
- if confFilePath:
- log.debug(f"Trying to remove: {confFilePath}", self)
- confFile = QFile(confFilePath)
- if confFile.remove():
- log.debug(f"Removed {confFilePath}", self)
- return True
- else:
- log.error(f"Could not remove {confFilePath}", self)
- return False
- def names(self):
- """ Returns all profile names in a list.
- @rtype: list
- """
- return [profile.name for profile in self._profiles['profiles']]
|