214 lines
6.0 KiB
Python
214 lines
6.0 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
Copyright (C) 2012 Fabio Erculiani
|
|
|
|
Authors:
|
|
Fabio Erculiani
|
|
|
|
This program 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; version 3.
|
|
|
|
This program 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, write to the Free Software Foundation, Inc.,
|
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
"""
|
|
import os
|
|
import subprocess
|
|
import shlex
|
|
try:
|
|
import ConfigParser as configparser
|
|
except ImportError:
|
|
import configparser
|
|
|
|
from gi.repository import GObject
|
|
|
|
from entropy.const import etpConst, const_convert_to_rawstring, \
|
|
const_isunicode
|
|
from entropy.core.settings.base import SystemSettings
|
|
from entropy.misc import ParallelTask
|
|
|
|
import entropy.tools
|
|
|
|
def build_application_store_url(app, sub_page):
|
|
"""
|
|
take rigo.models.application.Application object
|
|
and build up HTTP Entropy Application Store URL
|
|
pointing to exact Application page.
|
|
sub_page is used to load a specific part of the page,
|
|
for example "ugc" can be passed to load URL/ugc page.
|
|
"""
|
|
settings = SystemSettings()
|
|
details = app.get_details()
|
|
pkg_id, pkg_repo = details.pkg
|
|
branch = settings['repositories']['branch']
|
|
product = settings['repositories']['product']
|
|
url = "%s/show/%s,%s,%s,%s,%s,%s/%s" % (
|
|
etpConst['packages_website_url'],
|
|
details.pkgname,
|
|
pkg_id,
|
|
pkg_repo,
|
|
etpConst['currentarch'],
|
|
branch,
|
|
product,
|
|
sub_page)
|
|
return url
|
|
|
|
def build_register_url():
|
|
"""
|
|
Build User Account Registration Form URL.
|
|
"""
|
|
return os.path.join(etpConst['distro_website_url'], "register")
|
|
|
|
def open_url(url):
|
|
"""
|
|
Open the given URL using xdg-open
|
|
"""
|
|
def _open_url(url):
|
|
subprocess.call(["xdg-open", url])
|
|
task = ParallelTask(_open_url, url)
|
|
task.name = "UrlOpen"
|
|
task.daemon = True
|
|
task.start()
|
|
|
|
def get_output(args):
|
|
"""
|
|
Return the standard output and exit status generated by
|
|
args.
|
|
"""
|
|
read_end, write_end = None, None
|
|
exit_st = 1
|
|
output = ""
|
|
try:
|
|
read_end, write_end = os.pipe()
|
|
with os.fdopen(write_end, "w") as stdout:
|
|
exit_st = subprocess.call(
|
|
args, stdout=stdout)
|
|
# avoid blocking in case of no output
|
|
stdout.write("\n")
|
|
with os.fdopen(read_end, "r") as stdin:
|
|
output = stdin.read()
|
|
finally:
|
|
if read_end is not None:
|
|
try:
|
|
os.close(read_end)
|
|
except OSError:
|
|
pass
|
|
if write_end is not None:
|
|
try:
|
|
os.close(write_end)
|
|
except OSError:
|
|
pass
|
|
return exit_st, output
|
|
|
|
def _query_filetype(path):
|
|
"""
|
|
Query mime type of file path.
|
|
"""
|
|
exit_st, output = get_output(
|
|
["xdg-mime", "query", "filetype", path])
|
|
if exit_st != os.EX_OK:
|
|
return None
|
|
mime = output.split("\n")[0].strip()
|
|
if not mime:
|
|
return None
|
|
return mime
|
|
|
|
def _get_default_desktop(mime):
|
|
"""
|
|
Return default .desktop file for mimetype.
|
|
"""
|
|
exit_st, output = get_output(
|
|
["xdg-mime", "query", "default", mime])
|
|
if exit_st != os.EX_OK:
|
|
return None
|
|
desktop_name = output.split("\n")[0].strip()
|
|
if not desktop_name:
|
|
return None
|
|
return desktop_name
|
|
|
|
def open_editor(path):
|
|
"""
|
|
Open given path with the default editor and return
|
|
a subprocess.Popen object.
|
|
"""
|
|
mime = _query_filetype(path)
|
|
if mime is None:
|
|
return None
|
|
|
|
plain_mime = "text/plain"
|
|
desktop_name = _get_default_desktop(mime)
|
|
if not desktop_name:
|
|
if mime != plain_mime:
|
|
desktop_name = _get_default_desktop(
|
|
plain_mime)
|
|
if not desktop_name:
|
|
return None
|
|
|
|
xdg_data_dirs = os.getenv(
|
|
"XDG_DATA_DIRS",
|
|
"/usr/share").split(":")
|
|
desktop_path = None
|
|
for xdg_data_dir in xdg_data_dirs:
|
|
_desktop_path = os.path.join(
|
|
xdg_data_dir, "applications",
|
|
desktop_name)
|
|
if os.path.exists(_desktop_path) and \
|
|
os.path.isfile(_desktop_path):
|
|
desktop_path = _desktop_path
|
|
break
|
|
if desktop_path is None:
|
|
return None
|
|
|
|
parser = configparser.RawConfigParser()
|
|
read_files = parser.read([desktop_path])
|
|
if desktop_path not in read_files:
|
|
return None
|
|
exec_string = parser.get("Desktop Entry", "Exec")
|
|
# replace %F with %f
|
|
# replace %u with %f
|
|
# replace %U with %f
|
|
# as per:
|
|
# http://standards.freedesktop.org/desktop-entry-spec/latest
|
|
# and also handle %% (which is the escape for single %)
|
|
exec_string = exec_string.replace(" %F", " %f")
|
|
exec_string = exec_string.replace(" %U", " %f")
|
|
exec_string = exec_string.replace(" %u", " %f")
|
|
if " %f" in exec_string:
|
|
exec_string = exec_string.replace(
|
|
" %f", " \"" + path + "\"")
|
|
else:
|
|
exec_string += " \""
|
|
exec_string += path
|
|
exec_string += "\""
|
|
# shlex split() wants raw string
|
|
exec_string = const_convert_to_rawstring(exec_string)
|
|
args = shlex.split(exec_string)
|
|
proc = subprocess.Popen(args)
|
|
return proc
|
|
|
|
def escape_markup(text):
|
|
"""
|
|
Escape markup text to use with GTK3 widgets.
|
|
After escaping, text is converted to raw string
|
|
from unicode. brrr...
|
|
"""
|
|
return \
|
|
GObject.markup_escape_text(
|
|
prepare_markup(text))
|
|
|
|
def prepare_markup(text):
|
|
"""
|
|
Convert text to raw bytestring to make GTK3 happy.
|
|
"""
|
|
if const_isunicode(text):
|
|
return \
|
|
const_convert_to_rawstring(
|
|
text, from_enctype=etpConst['conf_encoding'])
|
|
return text
|