mirror of
https://github.com/arsenetar/dupeguru.git
synced 2025-03-09 21:24:36 +00:00
Add portable mode
If settings.ini is present next to the executable, will run in portable mode. This results in settings, data, and cache all being in same folder as dupeGuru.
This commit is contained in:
parent
d62b13bcdb
commit
be10b462fc
@ -126,13 +126,13 @@ class DupeGuru(Broadcaster):
|
|||||||
|
|
||||||
PICTURE_CACHE_TYPE = "sqlite" # set to 'shelve' for a ShelveCache
|
PICTURE_CACHE_TYPE = "sqlite" # set to 'shelve' for a ShelveCache
|
||||||
|
|
||||||
def __init__(self, view):
|
def __init__(self, view, portable=False):
|
||||||
if view.get_default(DEBUG_MODE_PREFERENCE):
|
if view.get_default(DEBUG_MODE_PREFERENCE):
|
||||||
logging.getLogger().setLevel(logging.DEBUG)
|
logging.getLogger().setLevel(logging.DEBUG)
|
||||||
logging.debug("Debug mode enabled")
|
logging.debug("Debug mode enabled")
|
||||||
Broadcaster.__init__(self)
|
Broadcaster.__init__(self)
|
||||||
self.view = view
|
self.view = view
|
||||||
self.appdata = desktop.special_folder_path(desktop.SpecialFolder.AppData, appname=self.NAME)
|
self.appdata = desktop.special_folder_path(desktop.SpecialFolder.AppData, appname=self.NAME, portable=portable)
|
||||||
if not op.exists(self.appdata):
|
if not op.exists(self.appdata):
|
||||||
os.makedirs(self.appdata)
|
os.makedirs(self.appdata)
|
||||||
self.app_mode = AppMode.Standard
|
self.app_mode = AppMode.Standard
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
# http://www.gnu.org/licenses/gpl-3.0.html
|
# http://www.gnu.org/licenses/gpl-3.0.html
|
||||||
|
|
||||||
import time
|
import time
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
from hscommon.util import format_time_decimal
|
from hscommon.util import format_time_decimal
|
||||||
|
|
||||||
@ -58,3 +60,7 @@ def fix_surrogate_encoding(s, encoding="utf-8"):
|
|||||||
return s.encode(encoding, "replace").decode(encoding)
|
return s.encode(encoding, "replace").decode(encoding)
|
||||||
else:
|
else:
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
|
||||||
|
def executable_folder():
|
||||||
|
return os.path.dirname(os.path.abspath(sys.argv[0]))
|
||||||
|
@ -30,7 +30,7 @@ def reveal_path(path):
|
|||||||
_reveal_path(str(path))
|
_reveal_path(str(path))
|
||||||
|
|
||||||
|
|
||||||
def special_folder_path(special_folder, appname=None):
|
def special_folder_path(special_folder, appname=None, portable=False):
|
||||||
"""Returns the path of ``special_folder``.
|
"""Returns the path of ``special_folder``.
|
||||||
|
|
||||||
``special_folder`` is a SpecialFolder.* const. The result is the special folder for the current
|
``special_folder`` is a SpecialFolder.* const. The result is the special folder for the current
|
||||||
@ -38,7 +38,7 @@ def special_folder_path(special_folder, appname=None):
|
|||||||
|
|
||||||
You can override the application name with ``appname``. This argument is ingored under Qt.
|
You can override the application name with ``appname``. This argument is ingored under Qt.
|
||||||
"""
|
"""
|
||||||
return _special_folder_path(special_folder, appname)
|
return _special_folder_path(special_folder, appname, portable=portable)
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -54,7 +54,7 @@ try:
|
|||||||
_open_path = proxy.openPath_
|
_open_path = proxy.openPath_
|
||||||
_reveal_path = proxy.revealPath_
|
_reveal_path = proxy.revealPath_
|
||||||
|
|
||||||
def _special_folder_path(special_folder, appname=None):
|
def _special_folder_path(special_folder, appname=None, portable=False):
|
||||||
if special_folder == SpecialFolder.Cache:
|
if special_folder == SpecialFolder.Cache:
|
||||||
base = proxy.getCachePath()
|
base = proxy.getCachePath()
|
||||||
else:
|
else:
|
||||||
@ -68,6 +68,9 @@ except ImportError:
|
|||||||
try:
|
try:
|
||||||
from PyQt5.QtCore import QUrl, QStandardPaths
|
from PyQt5.QtCore import QUrl, QStandardPaths
|
||||||
from PyQt5.QtGui import QDesktopServices
|
from PyQt5.QtGui import QDesktopServices
|
||||||
|
from qtlib.util import getAppData
|
||||||
|
from core.util import executable_folder
|
||||||
|
from hscommon.plat import ISWINDOWS
|
||||||
|
|
||||||
def _open_url(url):
|
def _open_url(url):
|
||||||
QDesktopServices.openUrl(QUrl(url))
|
QDesktopServices.openUrl(QUrl(url))
|
||||||
@ -79,12 +82,15 @@ except ImportError:
|
|||||||
def _reveal_path(path):
|
def _reveal_path(path):
|
||||||
_open_path(op.dirname(str(path)))
|
_open_path(op.dirname(str(path)))
|
||||||
|
|
||||||
def _special_folder_path(special_folder, appname=None):
|
def _special_folder_path(special_folder, appname=None, portable=False):
|
||||||
if special_folder == SpecialFolder.Cache:
|
if special_folder == SpecialFolder.Cache:
|
||||||
qtfolder = QStandardPaths.CacheLocation
|
if ISWINDOWS and portable:
|
||||||
|
folder = op.join(executable_folder(), "cache")
|
||||||
|
else:
|
||||||
|
folder = QStandardPaths.standardLocations(QStandardPaths.CacheLocation)[0]
|
||||||
else:
|
else:
|
||||||
qtfolder = QStandardPaths.DataLocation
|
folder = getAppData(portable)
|
||||||
return QStandardPaths.standardLocations(qtfolder)[0]
|
return folder
|
||||||
|
|
||||||
except ImportError:
|
except ImportError:
|
||||||
# We're either running tests, and these functions don't matter much or we're in a really
|
# We're either running tests, and these functions don't matter much or we're in a really
|
||||||
@ -97,5 +103,5 @@ except ImportError:
|
|||||||
def _reveal_path(path):
|
def _reveal_path(path):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def _special_folder_path(special_folder, appname=None):
|
def _special_folder_path(special_folder, appname=None, portable=False):
|
||||||
return "/tmp"
|
return "/tmp"
|
||||||
|
@ -52,7 +52,7 @@ class DupeGuru(QObject):
|
|||||||
# Enable tabs instead of separate floating windows for each dialog
|
# Enable tabs instead of separate floating windows for each dialog
|
||||||
# Could be passed as an argument to this class if we wanted
|
# Could be passed as an argument to this class if we wanted
|
||||||
self.use_tabs = True
|
self.use_tabs = True
|
||||||
self.model = DupeGuruModel(view=self)
|
self.model = DupeGuruModel(view=self, portable=self.prefs.portable)
|
||||||
self._setup()
|
self._setup()
|
||||||
|
|
||||||
# --- Private
|
# --- Private
|
||||||
|
@ -29,6 +29,7 @@ class Preferences(PreferencesBase):
|
|||||||
self.language = get("Language", self.language)
|
self.language = get("Language", self.language)
|
||||||
if not self.language and trans.installed_lang:
|
if not self.language and trans.installed_lang:
|
||||||
self.language = trans.installed_lang
|
self.language = trans.installed_lang
|
||||||
|
self.portable = get("Portable", False)
|
||||||
|
|
||||||
self.tableFontSize = get("TableFontSize", self.tableFontSize)
|
self.tableFontSize = get("TableFontSize", self.tableFontSize)
|
||||||
self.reference_bold_font = get("ReferenceBoldFont", self.reference_bold_font)
|
self.reference_bold_font = get("ReferenceBoldFont", self.reference_bold_font)
|
||||||
@ -138,6 +139,7 @@ class Preferences(PreferencesBase):
|
|||||||
set_("DestinationType", self.destination_type)
|
set_("DestinationType", self.destination_type)
|
||||||
set_("CustomCommand", self.custom_command)
|
set_("CustomCommand", self.custom_command)
|
||||||
set_("Language", self.language)
|
set_("Language", self.language)
|
||||||
|
set_("Portable", self.portable)
|
||||||
|
|
||||||
set_("TableFontSize", self.tableFontSize)
|
set_("TableFontSize", self.tableFontSize)
|
||||||
set_("ReferenceBoldFont", self.reference_bold_font)
|
set_("ReferenceBoldFont", self.reference_bold_font)
|
||||||
|
@ -12,6 +12,7 @@ from PyQt5.QtWidgets import QDockWidget
|
|||||||
from hscommon.trans import trget
|
from hscommon.trans import trget
|
||||||
from hscommon.util import tryint
|
from hscommon.util import tryint
|
||||||
from hscommon.plat import ISWINDOWS
|
from hscommon.plat import ISWINDOWS
|
||||||
|
from core.util import executable_folder
|
||||||
|
|
||||||
from os import path as op
|
from os import path as op
|
||||||
|
|
||||||
@ -68,18 +69,25 @@ def adjust_after_deserialization(v):
|
|||||||
return v
|
return v
|
||||||
|
|
||||||
|
|
||||||
def createQSettings():
|
def create_qsettings():
|
||||||
# Create a QSettings instance with the correct arguments.
|
# Create a QSettings instance with the correct arguments.
|
||||||
# On windows use an ini file in the AppDataLocation instead of registry if possible as it
|
config_location = op.join(executable_folder(), "settings.ini")
|
||||||
# makes it easier for a user to clear it out when there are issues.
|
if op.isfile(config_location):
|
||||||
if ISWINDOWS:
|
settings = QSettings(config_location, QSettings.IniFormat)
|
||||||
Locations = QStandardPaths.standardLocations(QStandardPaths.AppDataLocation)
|
settings.setValue("Portable", True)
|
||||||
if Locations:
|
elif ISWINDOWS:
|
||||||
return QSettings(op.join(Locations[0], "settings.ini"), QSettings.IniFormat)
|
# On windows use an ini file in the AppDataLocation instead of registry if possible as it
|
||||||
|
# makes it easier for a user to clear it out when there are issues.
|
||||||
|
locations = QStandardPaths.standardLocations(QStandardPaths.AppDataLocation)
|
||||||
|
if locations:
|
||||||
|
settings = QSettings(op.join(locations[0], "settings.ini"), QSettings.IniFormat)
|
||||||
else:
|
else:
|
||||||
return QSettings()
|
settings = QSettings()
|
||||||
|
settings.setValue("Portable", False)
|
||||||
else:
|
else:
|
||||||
return QSettings()
|
settings = QSettings()
|
||||||
|
settings.setValue("Portable", False)
|
||||||
|
return settings
|
||||||
|
|
||||||
|
|
||||||
# About QRect conversion:
|
# About QRect conversion:
|
||||||
@ -93,7 +101,7 @@ class Preferences(QObject):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
QObject.__init__(self)
|
QObject.__init__(self)
|
||||||
self.reset()
|
self.reset()
|
||||||
self._settings = createQSettings()
|
self._settings = create_qsettings()
|
||||||
|
|
||||||
def _load_values(self, settings, get):
|
def _load_values(self, settings, get):
|
||||||
pass
|
pass
|
||||||
|
@ -12,6 +12,7 @@ import os.path as op
|
|||||||
import os
|
import os
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
from core.util import executable_folder
|
||||||
from hscommon.util import first
|
from hscommon.util import first
|
||||||
|
|
||||||
from PyQt5.QtCore import QStandardPaths
|
from PyQt5.QtCore import QStandardPaths
|
||||||
@ -88,8 +89,11 @@ def setAccelKeys(menu):
|
|||||||
action.setText(newtext)
|
action.setText(newtext)
|
||||||
|
|
||||||
|
|
||||||
def getAppData():
|
def getAppData(portable=False):
|
||||||
return QStandardPaths.standardLocations(QStandardPaths.DataLocation)[0]
|
if portable:
|
||||||
|
return op.join(executable_folder(), "data")
|
||||||
|
else:
|
||||||
|
return QStandardPaths.standardLocations(QStandardPaths.AppDataLocation)[0]
|
||||||
|
|
||||||
|
|
||||||
class SysWrapper(io.IOBase):
|
class SysWrapper(io.IOBase):
|
||||||
|
4
run.py
4
run.py
@ -16,7 +16,7 @@ from PyQt5.QtWidgets import QApplication
|
|||||||
from hscommon.trans import install_gettext_trans_under_qt
|
from hscommon.trans import install_gettext_trans_under_qt
|
||||||
from qtlib.error_report_dialog import install_excepthook
|
from qtlib.error_report_dialog import install_excepthook
|
||||||
from qtlib.util import setupQtLogging
|
from qtlib.util import setupQtLogging
|
||||||
from qtlib.preferences import createQSettings
|
from qtlib.preferences import create_qsettings
|
||||||
from qt import dg_rc # noqa: F401
|
from qt import dg_rc # noqa: F401
|
||||||
from qt.platform import BASE_PATH
|
from qt.platform import BASE_PATH
|
||||||
from core import __version__, __appname__
|
from core import __version__, __appname__
|
||||||
@ -53,7 +53,7 @@ def main():
|
|||||||
QCoreApplication.setApplicationName(__appname__)
|
QCoreApplication.setApplicationName(__appname__)
|
||||||
QCoreApplication.setApplicationVersion(__version__)
|
QCoreApplication.setApplicationVersion(__version__)
|
||||||
setupQtLogging()
|
setupQtLogging()
|
||||||
settings = createQSettings()
|
settings = create_qsettings()
|
||||||
lang = settings.value("Language")
|
lang = settings.value("Language")
|
||||||
locale_folder = op.join(BASE_PATH, "locale")
|
locale_folder = op.join(BASE_PATH, "locale")
|
||||||
install_gettext_trans_under_qt(locale_folder, lang)
|
install_gettext_trans_under_qt(locale_folder, lang)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user