mirror of
https://github.com/arsenetar/dupeguru.git
synced 2024-11-19 13:29:03 +00:00
Refactoring: Created hscommon.desktop
This unit hosts previously awkward UI view methods which weren't related to the view itself, but to the current desktop environment. These functions are now at their appropriate place.
This commit is contained in:
parent
2fdfacb34e
commit
33d9569427
@ -1,7 +1,7 @@
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
from objp.util import pyref, dontwrap
|
from objp.util import pyref, dontwrap
|
||||||
from cocoa import install_exception_hook, install_cocoa_logger, patch_threaded_job_performer, proxy
|
from cocoa import install_exception_hook, install_cocoa_logger, patch_threaded_job_performer
|
||||||
from cocoa.inter import PyFairware, FairwareView
|
from cocoa.inter import PyFairware, FairwareView
|
||||||
|
|
||||||
class DupeGuruView(FairwareView):
|
class DupeGuruView(FairwareView):
|
||||||
@ -17,8 +17,7 @@ class PyDupeGuruBase(PyFairware):
|
|||||||
install_exception_hook()
|
install_exception_hook()
|
||||||
install_cocoa_logger()
|
install_cocoa_logger()
|
||||||
patch_threaded_job_performer()
|
patch_threaded_job_performer()
|
||||||
appdata = proxy.getAppdataPath()
|
self.model = modelclass(self)
|
||||||
self.model = modelclass(self, appdata)
|
|
||||||
|
|
||||||
#---Sub-proxies
|
#---Sub-proxies
|
||||||
def detailsPanel(self) -> pyref:
|
def detailsPanel(self) -> pyref:
|
||||||
@ -144,14 +143,6 @@ class PyDupeGuruBase(PyFairware):
|
|||||||
self.model.options['copymove_dest_type'] = copymove_dest_type
|
self.model.options['copymove_dest_type'] = copymove_dest_type
|
||||||
|
|
||||||
#--- model --> view
|
#--- model --> view
|
||||||
@dontwrap
|
|
||||||
def open_path(self, path):
|
|
||||||
proxy.openPath_(str(path))
|
|
||||||
|
|
||||||
@dontwrap
|
|
||||||
def reveal_path(self, path):
|
|
||||||
proxy.revealPath_(str(path))
|
|
||||||
|
|
||||||
@dontwrap
|
@dontwrap
|
||||||
def ask_yes_no(self, prompt):
|
def ask_yes_no(self, prompt):
|
||||||
return self.callback.askYesNoWithPrompt_(prompt)
|
return self.callback.askYesNoWithPrompt_(prompt)
|
||||||
|
@ -294,10 +294,6 @@ class PyBaseApp(PyGUIObject):
|
|||||||
def set_default(self, key_name, value):
|
def set_default(self, key_name, value):
|
||||||
proxy.setPrefValue_value_(key_name, value)
|
proxy.setPrefValue_value_(key_name, value)
|
||||||
|
|
||||||
@dontwrap
|
|
||||||
def open_url(self, url):
|
|
||||||
proxy.openURL_(url)
|
|
||||||
|
|
||||||
@dontwrap
|
@dontwrap
|
||||||
def show_message(self, msg):
|
def show_message(self, msg):
|
||||||
self.callback.showMessage_(msg)
|
self.callback.showMessage_(msg)
|
||||||
|
13
core/app.py
13
core/app.py
@ -25,6 +25,7 @@ from hscommon.util import (delete_if_empty, first, escape, nonone, format_time_d
|
|||||||
rem_file_ext)
|
rem_file_ext)
|
||||||
from hscommon.trans import tr
|
from hscommon.trans import tr
|
||||||
from hscommon.plat import ISWINDOWS
|
from hscommon.plat import ISWINDOWS
|
||||||
|
from hscommon import desktop
|
||||||
|
|
||||||
from . import directories, results, scanner, export, fs
|
from . import directories, results, scanner, export, fs
|
||||||
from .gui.deletion_options import DeletionOptions
|
from .gui.deletion_options import DeletionOptions
|
||||||
@ -123,8 +124,6 @@ class DupeGuru(RegistrableApplication, Broadcaster):
|
|||||||
Instance of :mod:`meta-gui <core.gui>` table listing the results from :attr:`results`
|
Instance of :mod:`meta-gui <core.gui>` table listing the results from :attr:`results`
|
||||||
"""
|
"""
|
||||||
#--- View interface
|
#--- View interface
|
||||||
# open_path(path)
|
|
||||||
# reveal_path(path)
|
|
||||||
# ask_yes_no(prompt) --> bool
|
# ask_yes_no(prompt) --> bool
|
||||||
# show_results_window()
|
# show_results_window()
|
||||||
# show_problem_dialog()
|
# show_problem_dialog()
|
||||||
@ -135,13 +134,13 @@ class DupeGuru(RegistrableApplication, Broadcaster):
|
|||||||
PROMPT_NAME = "dupeGuru"
|
PROMPT_NAME = "dupeGuru"
|
||||||
DEMO_LIMITATION = tr("will only be able to delete, move or copy 10 duplicates at once")
|
DEMO_LIMITATION = tr("will only be able to delete, move or copy 10 duplicates at once")
|
||||||
|
|
||||||
def __init__(self, view, appdata):
|
def __init__(self, view):
|
||||||
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")
|
||||||
RegistrableApplication.__init__(self, view, appid=1)
|
RegistrableApplication.__init__(self, view, appid=1)
|
||||||
Broadcaster.__init__(self)
|
Broadcaster.__init__(self)
|
||||||
self.appdata = appdata
|
self.appdata = desktop.special_folder_path(desktop.SpecialFolder.AppData)
|
||||||
if not op.exists(self.appdata):
|
if not op.exists(self.appdata):
|
||||||
os.makedirs(self.appdata)
|
os.makedirs(self.appdata)
|
||||||
self.directories = directories.Directories()
|
self.directories = directories.Directories()
|
||||||
@ -440,7 +439,7 @@ class DupeGuru(RegistrableApplication, Broadcaster):
|
|||||||
def export_to_xhtml(self):
|
def export_to_xhtml(self):
|
||||||
colnames, rows = self._get_export_data()
|
colnames, rows = self._get_export_data()
|
||||||
export_path = export.export_to_xhtml(colnames, rows)
|
export_path = export.export_to_xhtml(colnames, rows)
|
||||||
self.view.open_path(export_path)
|
desktop.open_path(export_path)
|
||||||
|
|
||||||
def export_to_csv(self):
|
def export_to_csv(self):
|
||||||
dest_file = self.view.select_dest_file(tr("Select a destination for your exported CSV"), 'csv')
|
dest_file = self.view.select_dest_file(tr("Select a destination for your exported CSV"), 'csv')
|
||||||
@ -557,7 +556,7 @@ class DupeGuru(RegistrableApplication, Broadcaster):
|
|||||||
if not self.view.ask_yes_no(MSG_MANY_FILES_TO_OPEN):
|
if not self.view.ask_yes_no(MSG_MANY_FILES_TO_OPEN):
|
||||||
return
|
return
|
||||||
for dupe in self.selected_dupes:
|
for dupe in self.selected_dupes:
|
||||||
self.view.open_path(dupe.path)
|
desktop.open_path(dupe.path)
|
||||||
|
|
||||||
def purge_ignore_list(self):
|
def purge_ignore_list(self):
|
||||||
self.scanner.ignore_list.Filter(lambda f,s:op.exists(f) and op.exists(s))
|
self.scanner.ignore_list.Filter(lambda f,s:op.exists(f) and op.exists(s))
|
||||||
@ -620,7 +619,7 @@ class DupeGuru(RegistrableApplication, Broadcaster):
|
|||||||
|
|
||||||
def reveal_selected(self):
|
def reveal_selected(self):
|
||||||
if self.selected_dupes:
|
if self.selected_dupes:
|
||||||
self.view.reveal_path(self.selected_dupes[0].path)
|
desktop.reveal_path(self.selected_dupes[0].path)
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
if not op.exists(self.appdata):
|
if not op.exists(self.appdata):
|
||||||
|
@ -6,6 +6,8 @@
|
|||||||
# which should be included with this package. The terms are also available at
|
# which should be included with this package. The terms are also available at
|
||||||
# http://www.hardcoded.net/licenses/bsd_license
|
# http://www.hardcoded.net/licenses/bsd_license
|
||||||
|
|
||||||
|
from hscommon import desktop
|
||||||
|
|
||||||
from .problem_table import ProblemTable
|
from .problem_table import ProblemTable
|
||||||
|
|
||||||
class ProblemDialog:
|
class ProblemDialog:
|
||||||
@ -20,7 +22,7 @@ class ProblemDialog:
|
|||||||
|
|
||||||
def reveal_selected_dupe(self):
|
def reveal_selected_dupe(self):
|
||||||
if self._selected_dupe is not None:
|
if self._selected_dupe is not None:
|
||||||
self.app.view.reveal_path(self._selected_dupe.path)
|
desktop.reveal_path(self._selected_dupe.path)
|
||||||
|
|
||||||
def select_dupe(self, dupe):
|
def select_dupe(self, dupe):
|
||||||
self._selected_dupe = dupe
|
self._selected_dupe = dupe
|
||||||
|
@ -16,8 +16,8 @@ class DupeGuru(DupeGuruBase):
|
|||||||
METADATA_TO_READ = ['size', 'mtime', 'duration', 'bitrate', 'samplerate', 'title', 'artist',
|
METADATA_TO_READ = ['size', 'mtime', 'duration', 'bitrate', 'samplerate', 'title', 'artist',
|
||||||
'album', 'genre', 'year', 'track', 'comment']
|
'album', 'genre', 'year', 'track', 'comment']
|
||||||
|
|
||||||
def __init__(self, view, appdata):
|
def __init__(self, view):
|
||||||
DupeGuruBase.__init__(self, view, appdata)
|
DupeGuruBase.__init__(self, view)
|
||||||
self.scanner = scanner.ScannerME()
|
self.scanner = scanner.ScannerME()
|
||||||
self.directories.fileclasses = [fs.MusicFile]
|
self.directories.fileclasses = [fs.MusicFile]
|
||||||
|
|
||||||
|
@ -18,8 +18,8 @@ class DupeGuru(DupeGuruBase):
|
|||||||
NAME = __appname__
|
NAME = __appname__
|
||||||
METADATA_TO_READ = ['size', 'mtime', 'dimensions', 'exif_timestamp']
|
METADATA_TO_READ = ['size', 'mtime', 'dimensions', 'exif_timestamp']
|
||||||
|
|
||||||
def __init__(self, view, appdata):
|
def __init__(self, view):
|
||||||
DupeGuruBase.__init__(self, view, appdata)
|
DupeGuruBase.__init__(self, view)
|
||||||
self.scanner = ScannerPE()
|
self.scanner = ScannerPE()
|
||||||
self.scanner.cache_path = op.join(self.appdata, 'cached_pictures.db')
|
self.scanner.cache_path = op.join(self.appdata, 'cached_pictures.db')
|
||||||
|
|
||||||
|
@ -14,8 +14,8 @@ class DupeGuru(DupeGuruBase):
|
|||||||
NAME = __appname__
|
NAME = __appname__
|
||||||
METADATA_TO_READ = ['size', 'mtime']
|
METADATA_TO_READ = ['size', 'mtime']
|
||||||
|
|
||||||
def __init__(self, view, appdata):
|
def __init__(self, view):
|
||||||
DupeGuruBase.__init__(self, view, appdata)
|
DupeGuruBase.__init__(self, view)
|
||||||
self.directories.fileclasses = [fs.File]
|
self.directories.fileclasses = [fs.File]
|
||||||
self.directories.folderclass = fs.Folder
|
self.directories.folderclass = fs.Folder
|
||||||
|
|
||||||
|
67
hscommon/desktop.py
Normal file
67
hscommon/desktop.py
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
# Created By: Virgil Dupras
|
||||||
|
# Created On: 2013-10-12
|
||||||
|
# Copyright 2013 Hardcoded Software (http://www.hardcoded.net)
|
||||||
|
#
|
||||||
|
# This software is licensed under the "BSD" License as described in the "LICENSE" file,
|
||||||
|
# which should be included with this package. The terms are also available at
|
||||||
|
# http://www.hardcoded.net/licenses/bsd_license
|
||||||
|
|
||||||
|
class SpecialFolder:
|
||||||
|
AppData = 1
|
||||||
|
Cache = 2
|
||||||
|
|
||||||
|
def open_url(url):
|
||||||
|
"""Open ``url`` with the default browser.
|
||||||
|
"""
|
||||||
|
_open_url(url)
|
||||||
|
|
||||||
|
def open_path(path):
|
||||||
|
"""Open ``path`` with its associated application.
|
||||||
|
"""
|
||||||
|
_open_path(str(path))
|
||||||
|
|
||||||
|
def reveal_path(path):
|
||||||
|
"""Open the folder containing ``path`` with the default file browser.
|
||||||
|
"""
|
||||||
|
_reveal_path(str(path))
|
||||||
|
|
||||||
|
def special_folder_path(special_folder):
|
||||||
|
"""Returns the path of ``special_folder``.
|
||||||
|
|
||||||
|
``special_folder`` is a SpecialFolder.* const.
|
||||||
|
"""
|
||||||
|
return _special_folder_path(special_folder)
|
||||||
|
|
||||||
|
try:
|
||||||
|
from cocoa import proxy
|
||||||
|
_open_url = proxy.openURL_
|
||||||
|
_open_path = proxy.openPath_
|
||||||
|
_reveal_path = proxy.revealPath_
|
||||||
|
|
||||||
|
def _special_folder_path(special_folder):
|
||||||
|
if special_folder == SpecialFolder.Cache:
|
||||||
|
return proxy.getCachePath()
|
||||||
|
else:
|
||||||
|
return proxy.getAppdataPath()
|
||||||
|
|
||||||
|
except ImportError:
|
||||||
|
try:
|
||||||
|
from PyQt4.QtCore import QUrl
|
||||||
|
from PyQt4.QtGui import QDesktopServices
|
||||||
|
import os.path as op
|
||||||
|
def _open_path(path):
|
||||||
|
url = QUrl.fromLocalFile(str(path))
|
||||||
|
QDesktopServices.openUrl(url)
|
||||||
|
|
||||||
|
def _reveal_path(path):
|
||||||
|
_open_path(op.dirname(str(path)))
|
||||||
|
|
||||||
|
def _special_folder_path(special_folder):
|
||||||
|
if special_folder == SpecialFolder.Cache:
|
||||||
|
qtfolder = QDesktopServices.CacheLocation
|
||||||
|
else:
|
||||||
|
qtfolder = QDesktopServices.DataLocation
|
||||||
|
return str(QDesktopServices.storageLocation(qtfolder))
|
||||||
|
|
||||||
|
except ImportError:
|
||||||
|
raise Exception("Can't setup desktop functions!")
|
@ -9,6 +9,7 @@
|
|||||||
import re
|
import re
|
||||||
from hashlib import md5
|
from hashlib import md5
|
||||||
|
|
||||||
|
from . import desktop
|
||||||
from .trans import trget
|
from .trans import trget
|
||||||
|
|
||||||
tr = trget('hscommon')
|
tr = trget('hscommon')
|
||||||
@ -47,7 +48,6 @@ class RegistrableApplication:
|
|||||||
# setup_as_registered()
|
# setup_as_registered()
|
||||||
# show_message(msg)
|
# show_message(msg)
|
||||||
# show_demo_nag(prompt)
|
# show_demo_nag(prompt)
|
||||||
# open_url(url)
|
|
||||||
|
|
||||||
PROMPT_NAME = "<undefined>"
|
PROMPT_NAME = "<undefined>"
|
||||||
DEMO_LIMITATION = "<undefined>"
|
DEMO_LIMITATION = "<undefined>"
|
||||||
@ -154,13 +154,13 @@ class RegistrableApplication:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def contribute(self):
|
def contribute(self):
|
||||||
self.view.open_url("http://open.hardcoded.net/contribute/")
|
desktop.open_url("http://open.hardcoded.net/contribute/")
|
||||||
|
|
||||||
def buy(self):
|
def buy(self):
|
||||||
self.view.open_url("http://www.hardcoded.net/purchase.htm")
|
desktop.open_url("http://www.hardcoded.net/purchase.htm")
|
||||||
|
|
||||||
def about_fairware(self):
|
def about_fairware(self):
|
||||||
self.view.open_url("http://open.hardcoded.net/about/")
|
desktop.open_url("http://open.hardcoded.net/about/")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def should_show_fairware_reminder(self):
|
def should_show_fairware_reminder(self):
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
# http://www.hardcoded.net/licenses/bsd_license
|
# http://www.hardcoded.net/licenses/bsd_license
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import os
|
|
||||||
import os.path as op
|
import os.path as op
|
||||||
|
|
||||||
from PyQt4.QtCore import QTimer, QObject, QCoreApplication, QUrl, QProcess, SIGNAL, pyqtSignal
|
from PyQt4.QtCore import QTimer, QObject, QCoreApplication, QUrl, QProcess, SIGNAL, pyqtSignal
|
||||||
@ -15,11 +14,12 @@ from PyQt4.QtGui import QDesktopServices, QFileDialog, QDialog, QMessageBox, QAp
|
|||||||
|
|
||||||
from hscommon.trans import trget
|
from hscommon.trans import trget
|
||||||
from hscommon.plat import ISLINUX
|
from hscommon.plat import ISLINUX
|
||||||
|
from hscommon import desktop
|
||||||
|
|
||||||
from qtlib.about_box import AboutBox
|
from qtlib.about_box import AboutBox
|
||||||
from qtlib.recent import Recent
|
from qtlib.recent import Recent
|
||||||
from qtlib.reg import Registration
|
from qtlib.reg import Registration
|
||||||
from qtlib.util import createActions, getAppData
|
from qtlib.util import createActions
|
||||||
from qtlib.progress_window import ProgressWindow
|
from qtlib.progress_window import ProgressWindow
|
||||||
|
|
||||||
from . import platform
|
from . import platform
|
||||||
@ -46,7 +46,7 @@ class DupeGuru(QObject):
|
|||||||
QObject.__init__(self)
|
QObject.__init__(self)
|
||||||
self.prefs = self.PREFERENCES_CLASS()
|
self.prefs = self.PREFERENCES_CLASS()
|
||||||
self.prefs.load()
|
self.prefs.load()
|
||||||
self.model = self.MODELCLASS(view=self, appdata=getAppData())
|
self.model = self.MODELCLASS(view=self)
|
||||||
self._setup()
|
self._setup()
|
||||||
self.prefsChanged.emit(self.prefs)
|
self.prefsChanged.emit(self.prefs)
|
||||||
|
|
||||||
@ -154,7 +154,7 @@ class DupeGuru(QObject):
|
|||||||
|
|
||||||
def openDebugLogTriggered(self):
|
def openDebugLogTriggered(self):
|
||||||
debugLogPath = op.join(self.model.appdata, 'debug.log')
|
debugLogPath = op.join(self.model.appdata, 'debug.log')
|
||||||
self.open_path(debugLogPath)
|
desktop.open_path(debugLogPath)
|
||||||
|
|
||||||
def preferencesTriggered(self):
|
def preferencesTriggered(self):
|
||||||
self.preferences_dialog.load()
|
self.preferences_dialog.load()
|
||||||
@ -181,15 +181,6 @@ class DupeGuru(QObject):
|
|||||||
QDesktopServices.openUrl(url)
|
QDesktopServices.openUrl(url)
|
||||||
|
|
||||||
#--- model --> view
|
#--- model --> view
|
||||||
@staticmethod
|
|
||||||
def open_path(path):
|
|
||||||
url = QUrl.fromLocalFile(str(path))
|
|
||||||
QDesktopServices.openUrl(url)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def reveal_path(path):
|
|
||||||
DupeGuru.open_path(path[:-1])
|
|
||||||
|
|
||||||
def get_default(self, key):
|
def get_default(self, key):
|
||||||
return self.prefs.get_value(key)
|
return self.prefs.get_value(key)
|
||||||
|
|
||||||
@ -212,10 +203,6 @@ class DupeGuru(QObject):
|
|||||||
def ask_yes_no(self, prompt):
|
def ask_yes_no(self, prompt):
|
||||||
return self.confirm('', prompt)
|
return self.confirm('', prompt)
|
||||||
|
|
||||||
def open_url(self, url):
|
|
||||||
url = QUrl(url)
|
|
||||||
QDesktopServices.openUrl(url)
|
|
||||||
|
|
||||||
def show_results_window(self):
|
def show_results_window(self):
|
||||||
self.showResultsWindow()
|
self.showResultsWindow()
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user