[#2098] Add function to highlight the torrent folder/file
* Will show/highlight a file path in system file manager. *nix uses dbus with an xdg_open fallback. * [GTKUI] Open Folder still opens the download location but now shows the torrent data file/folder * [GTKUI] Files_tab now has a second menu item 'Show' to show a file's location * The open_file and show_file functions now use timestamps on *nix so that windows open in front, this fixes recent desktop changes that prevent windows randomly stealing focus. * Removed utf8 decode for Windows. All paths should be unicode string, any resulting errors should be traced to source and corrected.
This commit is contained in:
parent
670cd21685
commit
c5f7eeaacb
|
@ -1,38 +1,11 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# common.py
|
||||
# Copyright (C) 2007,2008 Andrew Resch <andrewresch@gmail.com>
|
||||
#
|
||||
# Copyright (C) 2007, 2008 Andrew Resch <andrewresch@gmail.com>
|
||||
# This file is part of Deluge and is licensed under GNU General Public License 3.0, or later, with
|
||||
# the additional special exception to link portions of this program with the OpenSSL library.
|
||||
# See LICENSE for more details.
|
||||
#
|
||||
# Deluge is free software.
|
||||
#
|
||||
# You may 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.
|
||||
#
|
||||
# deluge 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 deluge. If not, write to:
|
||||
# The Free Software Foundation, Inc.,
|
||||
# 51 Franklin Street, Fifth Floor
|
||||
# Boston, MA 02110-1301, USA.
|
||||
#
|
||||
# In addition, as a special exception, the copyright holders give
|
||||
# permission to link the code of portions of this program with the OpenSSL
|
||||
# library.
|
||||
# You must obey the GNU General Public License in all respects for all of
|
||||
# the code used other than OpenSSL. If you modify file(s) with this
|
||||
# exception, you may extend this exception to your version of the file(s),
|
||||
# but you are not obligated to do so. If you do not wish to do so, delete
|
||||
# this exception statement from your version. If you delete this exception
|
||||
# statement from all source files in the program, then also delete it here.
|
||||
#
|
||||
#
|
||||
|
||||
|
||||
"""Common functions for various parts of Deluge to use."""
|
||||
|
||||
|
@ -48,6 +21,14 @@ import gettext
|
|||
import locale
|
||||
import base64
|
||||
import urllib
|
||||
import urlparse
|
||||
|
||||
try:
|
||||
import dbus
|
||||
bus = dbus.SessionBus()
|
||||
dbus_fileman = bus.get_object("org.freedesktop.FileManager1", "/org/freedesktop/FileManager1")
|
||||
except:
|
||||
dbus_fileman = None
|
||||
|
||||
from deluge.error import InvalidPathError
|
||||
|
||||
|
@ -223,20 +204,51 @@ def resource_filename(module, path):
|
|||
)
|
||||
|
||||
|
||||
def open_file(path):
|
||||
"""
|
||||
Opens a file or folder using the system configured program
|
||||
def open_file(path, timestamp=None):
|
||||
"""Opens a file or folder using the system configured program.
|
||||
|
||||
:param path: the path to the file or folder to open
|
||||
:type path: string
|
||||
Args:
|
||||
path (str): The path to the file or folder to open.
|
||||
timestamp (int, optional): An event request timestamp.
|
||||
|
||||
"""
|
||||
if windows_check():
|
||||
os.startfile(path.decode("utf8"))
|
||||
os.startfile(path)
|
||||
elif osx_check():
|
||||
subprocess.Popen(["open", "%s" % path])
|
||||
subprocess.Popen(["open", path])
|
||||
else:
|
||||
subprocess.Popen(["xdg-open", "%s" % path])
|
||||
if timestamp is None:
|
||||
timestamp = int(time.time())
|
||||
env = os.environ.copy()
|
||||
env["DESKTOP_STARTUP_ID"] = "%s-%u-%s-xdg_open_TIME%d" % \
|
||||
(os.path.basename(sys.argv[0]), os.getpid(), os.uname()[1], timestamp)
|
||||
subprocess.Popen(["xdg-open", "%s" % path], env=env)
|
||||
|
||||
|
||||
def show_file(path, timestamp=None):
|
||||
"""Shows (highlights) a file or folder using the system configured file manager.
|
||||
|
||||
Args:
|
||||
path (str): The path to the file or folder to show.
|
||||
timestamp (int, optional): An event request timestamp.
|
||||
|
||||
"""
|
||||
if windows_check():
|
||||
subprocess.Popen(["explorer", "/select,", path])
|
||||
elif osx_check():
|
||||
subprocess.Popen(["open", "-R", path])
|
||||
else:
|
||||
if timestamp is None:
|
||||
timestamp = int(time.time())
|
||||
startup_id = "%s_%u_%s-dbus_TIME%d" % (os.path.basename(sys.argv[0]), os.getpid(), os.uname()[1], timestamp)
|
||||
if dbus_fileman:
|
||||
paths = [urlparse.urljoin("file:", urllib.pathname2url(utf8_encoded(path)))]
|
||||
dbus_fileman.ShowItems(paths, startup_id, dbus_interface="org.freedesktop.FileManager1")
|
||||
else:
|
||||
env = os.environ.copy()
|
||||
env["DESKTOP_STARTUP_ID"] = startup_id.replace("dbus", "xdg-open")
|
||||
# No option in xdg to highlight a file so just open parent folder.
|
||||
subprocess.Popen(["xdg-open", os.path.dirname(path.rstrip("/"))], env=env)
|
||||
|
||||
|
||||
def open_url_in_browser(url):
|
||||
|
|
|
@ -197,6 +197,7 @@ class FilesTab(Tab):
|
|||
|
||||
self.localhost_widgets = [
|
||||
builder.get_object("menuitem_open_file"),
|
||||
builder.get_object("menuitem_show_file"),
|
||||
builder.get_object("menuitem3")
|
||||
]
|
||||
|
||||
|
@ -215,6 +216,7 @@ class FilesTab(Tab):
|
|||
|
||||
component.get("MainWindow").connect_signals({
|
||||
"on_menuitem_open_file_activate": self._on_menuitem_open_file_activate,
|
||||
"on_menuitem_show_file_activate": self._on_menuitem_show_file_activate,
|
||||
"on_menuitem_donotdownload_activate": self._on_menuitem_donotdownload_activate,
|
||||
"on_menuitem_normal_activate": self._on_menuitem_normal_activate,
|
||||
"on_menuitem_high_activate": self._on_menuitem_high_activate,
|
||||
|
@ -319,8 +321,7 @@ class FilesTab(Tab):
|
|||
self.torrent_id = None
|
||||
|
||||
def _on_row_activated(self, tree, path, view_column):
|
||||
if client.is_localhost:
|
||||
component.get("SessionProxy").get_torrent_status(self.torrent_id, ["save_path", "files"]).addCallback(self._on_open_file)
|
||||
self._on_menuitem_open_file_activate()
|
||||
|
||||
def get_file_path(self, row, path=""):
|
||||
if not row:
|
||||
|
@ -339,7 +340,21 @@ class FilesTab(Tab):
|
|||
path = self.get_file_path(select).split("/")
|
||||
filepath = os.path.join(status["save_path"], *path)
|
||||
log.debug("Open file '%s'", filepath)
|
||||
deluge.common.open_file(filepath)
|
||||
timestamp = gtk.get_current_event_time()
|
||||
deluge.common.open_file(filepath, timestamp=timestamp)
|
||||
|
||||
def _on_show_file(self, status):
|
||||
paths = self.listview.get_selection().get_selected_rows()[1]
|
||||
selected = []
|
||||
for path in paths:
|
||||
selected.append(self.treestore.get_iter(path))
|
||||
|
||||
for select in selected:
|
||||
path = self.get_file_path(select).split("/")
|
||||
filepath = os.path.join(status["save_path"], *path)
|
||||
log.debug("Show file '%s'", filepath)
|
||||
timestamp = gtk.get_current_event_time()
|
||||
deluge.common.show_file(filepath, timestamp=timestamp)
|
||||
|
||||
## The following 3 methods create the folder/file view in the treeview
|
||||
def prepare_file_store(self, files):
|
||||
|
@ -525,7 +540,14 @@ class FilesTab(Tab):
|
|||
return True
|
||||
|
||||
def _on_menuitem_open_file_activate(self, menuitem):
|
||||
self._on_row_activated(None, None, None)
|
||||
if client.is_localhost:
|
||||
component.get("SessionProxy").get_torrent_status(
|
||||
self.torrent_id, ["save_path", "files"]).addCallback(self._on_open_file)
|
||||
|
||||
def _on_menuitem_show_file_activate(self, menuitem):
|
||||
if client.is_localhost:
|
||||
component.get("SessionProxy").get_torrent_status(
|
||||
self.torrent_id, ["save_path", "files"]).addCallback(self._on_show_file)
|
||||
|
||||
def _set_file_priorities_on_user_change(self, selected, priority):
|
||||
"""Sets the file priorities in the core. It will change the selected
|
||||
|
|
|
@ -46,6 +46,17 @@
|
|||
<signal name="activate" handler="on_menuitem_open_file_activate" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImageMenuItem" id="menuitem_show_file">
|
||||
<property name="label" translatable="yes">_Show</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_stock">True</property>
|
||||
<signal name="activate" handler="on_menuitem_show_file_activate" swapped="no"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparatorMenuItem" id="menuitem3">
|
||||
<property name="visible">True</property>
|
||||
|
|
|
@ -326,10 +326,12 @@ class MenuBar(component.Component):
|
|||
log.debug("on_menuitem_open_folder")
|
||||
|
||||
def _on_torrent_status(status):
|
||||
deluge.common.open_file(status["save_path"])
|
||||
timestamp = gtk.get_current_event_time()
|
||||
path = os.path.join(status["save_path"], status["files"][0]["path"].split('/')[0])
|
||||
deluge.common.show_file(path, timestamp=timestamp)
|
||||
for torrent_id in component.get("TorrentView").get_selected_torrents():
|
||||
component.get("SessionProxy").get_torrent_status(
|
||||
torrent_id, ["save_path"]).addCallback(_on_torrent_status)
|
||||
torrent_id, ["save_path", "files"]).addCallback(_on_torrent_status)
|
||||
|
||||
def on_menuitem_move_activate(self, data=None):
|
||||
log.debug("on_menuitem_move_activate")
|
||||
|
|
Loading…
Reference in New Issue