diff --git a/cocoa/inter/app.py b/cocoa/inter/app.py index 51768c74..be331357 100644 --- a/cocoa/inter/app.py +++ b/cocoa/inter/app.py @@ -1,7 +1,7 @@ import logging 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 class DupeGuruView(FairwareView): @@ -17,8 +17,7 @@ class PyDupeGuruBase(PyFairware): install_exception_hook() install_cocoa_logger() patch_threaded_job_performer() - appdata = proxy.getAppdataPath() - self.model = modelclass(self, appdata) + self.model = modelclass(self) #---Sub-proxies def detailsPanel(self) -> pyref: @@ -144,14 +143,6 @@ class PyDupeGuruBase(PyFairware): self.model.options['copymove_dest_type'] = copymove_dest_type #--- model --> view - @dontwrap - def open_path(self, path): - proxy.openPath_(str(path)) - - @dontwrap - def reveal_path(self, path): - proxy.revealPath_(str(path)) - @dontwrap def ask_yes_no(self, prompt): return self.callback.askYesNoWithPrompt_(prompt) diff --git a/cocoalib/cocoa/inter.py b/cocoalib/cocoa/inter.py index 625f2c5f..e140d26a 100644 --- a/cocoalib/cocoa/inter.py +++ b/cocoalib/cocoa/inter.py @@ -294,10 +294,6 @@ class PyBaseApp(PyGUIObject): def set_default(self, key_name, value): proxy.setPrefValue_value_(key_name, value) - @dontwrap - def open_url(self, url): - proxy.openURL_(url) - @dontwrap def show_message(self, msg): self.callback.showMessage_(msg) diff --git a/core/app.py b/core/app.py index e72313cc..096b7fca 100644 --- a/core/app.py +++ b/core/app.py @@ -25,6 +25,7 @@ from hscommon.util import (delete_if_empty, first, escape, nonone, format_time_d rem_file_ext) from hscommon.trans import tr from hscommon.plat import ISWINDOWS +from hscommon import desktop from . import directories, results, scanner, export, fs from .gui.deletion_options import DeletionOptions @@ -123,8 +124,6 @@ class DupeGuru(RegistrableApplication, Broadcaster): Instance of :mod:`meta-gui ` table listing the results from :attr:`results` """ #--- View interface - # open_path(path) - # reveal_path(path) # ask_yes_no(prompt) --> bool # show_results_window() # show_problem_dialog() @@ -135,13 +134,13 @@ class DupeGuru(RegistrableApplication, Broadcaster): PROMPT_NAME = "dupeGuru" 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): logging.getLogger().setLevel(logging.DEBUG) logging.debug("Debug mode enabled") RegistrableApplication.__init__(self, view, appid=1) Broadcaster.__init__(self) - self.appdata = appdata + self.appdata = desktop.special_folder_path(desktop.SpecialFolder.AppData) if not op.exists(self.appdata): os.makedirs(self.appdata) self.directories = directories.Directories() @@ -440,7 +439,7 @@ class DupeGuru(RegistrableApplication, Broadcaster): def export_to_xhtml(self): colnames, rows = self._get_export_data() export_path = export.export_to_xhtml(colnames, rows) - self.view.open_path(export_path) + desktop.open_path(export_path) def export_to_csv(self): 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): return for dupe in self.selected_dupes: - self.view.open_path(dupe.path) + desktop.open_path(dupe.path) def purge_ignore_list(self): 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): if self.selected_dupes: - self.view.reveal_path(self.selected_dupes[0].path) + desktop.reveal_path(self.selected_dupes[0].path) def save(self): if not op.exists(self.appdata): diff --git a/core/gui/problem_dialog.py b/core/gui/problem_dialog.py index d458c022..9271ae83 100644 --- a/core/gui/problem_dialog.py +++ b/core/gui/problem_dialog.py @@ -6,6 +6,8 @@ # which should be included with this package. The terms are also available at # http://www.hardcoded.net/licenses/bsd_license +from hscommon import desktop + from .problem_table import ProblemTable class ProblemDialog: @@ -20,7 +22,7 @@ class ProblemDialog: def reveal_selected_dupe(self): 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): self._selected_dupe = dupe diff --git a/core_me/app.py b/core_me/app.py index eb9124da..a49499ea 100644 --- a/core_me/app.py +++ b/core_me/app.py @@ -16,8 +16,8 @@ class DupeGuru(DupeGuruBase): METADATA_TO_READ = ['size', 'mtime', 'duration', 'bitrate', 'samplerate', 'title', 'artist', 'album', 'genre', 'year', 'track', 'comment'] - def __init__(self, view, appdata): - DupeGuruBase.__init__(self, view, appdata) + def __init__(self, view): + DupeGuruBase.__init__(self, view) self.scanner = scanner.ScannerME() self.directories.fileclasses = [fs.MusicFile] diff --git a/core_pe/app.py b/core_pe/app.py index 05b871b2..05927096 100644 --- a/core_pe/app.py +++ b/core_pe/app.py @@ -18,8 +18,8 @@ class DupeGuru(DupeGuruBase): NAME = __appname__ METADATA_TO_READ = ['size', 'mtime', 'dimensions', 'exif_timestamp'] - def __init__(self, view, appdata): - DupeGuruBase.__init__(self, view, appdata) + def __init__(self, view): + DupeGuruBase.__init__(self, view) self.scanner = ScannerPE() self.scanner.cache_path = op.join(self.appdata, 'cached_pictures.db') diff --git a/core_se/app.py b/core_se/app.py index 42d80d9b..cacd2e7d 100644 --- a/core_se/app.py +++ b/core_se/app.py @@ -14,8 +14,8 @@ class DupeGuru(DupeGuruBase): NAME = __appname__ METADATA_TO_READ = ['size', 'mtime'] - def __init__(self, view, appdata): - DupeGuruBase.__init__(self, view, appdata) + def __init__(self, view): + DupeGuruBase.__init__(self, view) self.directories.fileclasses = [fs.File] self.directories.folderclass = fs.Folder diff --git a/hscommon/desktop.py b/hscommon/desktop.py new file mode 100644 index 00000000..ea5d707f --- /dev/null +++ b/hscommon/desktop.py @@ -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!") diff --git a/hscommon/reg.py b/hscommon/reg.py index 3b5a57e0..98e84d56 100644 --- a/hscommon/reg.py +++ b/hscommon/reg.py @@ -9,6 +9,7 @@ import re from hashlib import md5 +from . import desktop from .trans import trget tr = trget('hscommon') @@ -47,7 +48,6 @@ class RegistrableApplication: # setup_as_registered() # show_message(msg) # show_demo_nag(prompt) - # open_url(url) PROMPT_NAME = "" DEMO_LIMITATION = "" @@ -154,13 +154,13 @@ class RegistrableApplication: pass def contribute(self): - self.view.open_url("http://open.hardcoded.net/contribute/") + desktop.open_url("http://open.hardcoded.net/contribute/") 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): - self.view.open_url("http://open.hardcoded.net/about/") + desktop.open_url("http://open.hardcoded.net/about/") @property def should_show_fairware_reminder(self): diff --git a/qt/base/app.py b/qt/base/app.py index 01de41aa..f4d6b378 100644 --- a/qt/base/app.py +++ b/qt/base/app.py @@ -7,7 +7,6 @@ # http://www.hardcoded.net/licenses/bsd_license import sys -import os import os.path as op 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.plat import ISLINUX +from hscommon import desktop from qtlib.about_box import AboutBox from qtlib.recent import Recent from qtlib.reg import Registration -from qtlib.util import createActions, getAppData +from qtlib.util import createActions from qtlib.progress_window import ProgressWindow from . import platform @@ -46,7 +46,7 @@ class DupeGuru(QObject): QObject.__init__(self) self.prefs = self.PREFERENCES_CLASS() self.prefs.load() - self.model = self.MODELCLASS(view=self, appdata=getAppData()) + self.model = self.MODELCLASS(view=self) self._setup() self.prefsChanged.emit(self.prefs) @@ -154,7 +154,7 @@ class DupeGuru(QObject): def openDebugLogTriggered(self): debugLogPath = op.join(self.model.appdata, 'debug.log') - self.open_path(debugLogPath) + desktop.open_path(debugLogPath) def preferencesTriggered(self): self.preferences_dialog.load() @@ -181,15 +181,6 @@ class DupeGuru(QObject): QDesktopServices.openUrl(url) #--- 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): return self.prefs.get_value(key) @@ -212,10 +203,6 @@ class DupeGuru(QObject): def ask_yes_no(self, prompt): return self.confirm('', prompt) - def open_url(self, url): - url = QUrl(url) - QDesktopServices.openUrl(url) - def show_results_window(self): self.showResultsWindow()