# -*- Mode: Python; coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4
##
## Copyright (C) 2011-2012 Async Open Source <http://www.async.com.br>
## All rights reserved
##
## 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; either version 2 of the License, or
## (at your option) any later version.
##
## 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., or visit: http://www.gnu.org/.
##
## Author(s): Stoq Team <stoq-devel@async.com.br>
##
import logging
import json
import urlparse
import gtk
import webkit
from stoqlib.api import api
from stoqlib.lib.dateutils import localdate
from stoqlib.gui.base.dialogs import run_dialog
from stoqlib.gui.editors.paymenteditor import get_dialog_for_payment
from stoqlib.gui.utils.openbrowser import open_browser
log = logging.getLogger(__name__)
USER_AGENT = ("Mozilla/5.0 (X11; Linux x86_64) "
"AppleWebKit/535.4+ (KHTML, like Gecko) "
"Version/5.0 Safari/535.4+ Stoq")
# urlparse.urlparse() requires you to register your custom url
# scheme to be able to use result.query
[docs]def register_scheme(scheme):
for method in filter(lambda s: s.startswith('uses_'), dir(urlparse)):
getattr(urlparse, method).append(scheme)
register_scheme('stoq')
[docs]class WebView(gtk.ScrolledWindow):
def __init__(self):
gtk.ScrolledWindow.__init__(self)
self.set_shadow_type(gtk.SHADOW_ETCHED_IN)
self._view = webkit.WebView()
settings = self._view.props.settings
settings.props.enable_developer_extras = True
settings.props.user_agent = USER_AGENT
settings.props.enable_default_context_menu = False
self._view.get_web_inspector().connect(
'inspect-web-view',
self._on_inspector__inspect_web_view)
self._view.connect(
'navigation-policy-decision-requested',
self._on_view__navigation_policy_decision_requested)
self.add(self._view)
self._view.show()
def _dialog_payment_details(self, id):
from stoqlib.domain.payment.payment import Payment
store = api.new_store()
payment = store.get(Payment, id)
dialog_class = get_dialog_for_payment(payment)
retval = run_dialog(dialog_class, self.app, store, payment)
if store.confirm(retval):
self.refresh()
store.close()
def _dialog_purchase(self, id):
from stoqlib.domain.purchase import PurchaseOrder
from stoqlib.gui.dialogs.purchasedetails import PurchaseDetailsDialog
store = api.new_store()
purchase = store.get(PurchaseOrder, id)
retval = run_dialog(PurchaseDetailsDialog, self.app, store, purchase)
if store.confirm(retval):
self.refresh()
store.close()
def _dialog_call(self, id):
from stoqlib.domain.person import Calls
from stoqlib.gui.editors.callseditor import CallsEditor
store = api.new_store()
model = store.get(Calls, id)
retval = run_dialog(CallsEditor, self.app, store, model, None, None)
if store.confirm(retval):
self.refresh()
store.close()
def _dialog_client(self, id):
from stoqlib.domain.person import Client
from stoqlib.gui.dialogs.clientdetails import ClientDetailsDialog
with api.new_store() as store:
model = store.get(Client, id)
run_dialog(ClientDetailsDialog, self.app, store, model)
def _dialog_work_order(self, id):
from stoqlib.domain.workorder import WorkOrder
from stoqlib.gui.editors.workordereditor import WorkOrderEditor
with api.new_store() as store:
model = store.get(WorkOrder, id)
user = api.get_current_user(store)
visual_mode = not user.profile.check_app_permission(u'services')
run_dialog(WorkOrderEditor, self.app, store, model,
visual_mode=visual_mode)
def _show_search_by_date(self, date, app_name):
y, m, d = map(int, date.split('-'))
date = localdate(y, m, d).date()
self.app.window.hide_app(empty=True)
shell_app = self.app.window.run_application(
app_name, refresh=False)
shell_app.search_for_date(date)
def _show_in_payments_by_date(self, date):
self._show_search_by_date(date, u'receivable')
def _show_out_payments_by_date(self, date):
self._show_search_by_date(date, u'payable')
def _show_purchases_by_date(self, date):
self._show_search_by_date(date, u'purchase')
def _show_work_orders_by_date(self, date):
self._show_search_by_date(date, u'services')
def _show_client_birthdays_by_date(self, date):
from stoqlib.gui.search.personsearch import ClientSearch
with api.new_store() as store:
y, m, d = map(int, date.split('-'))
date = localdate(y, m, d).date()
run_dialog(ClientSearch, self.app, store, birth_date=date)
def _show_client_calls_by_date(self, date):
from stoqlib.gui.search.callsearch import ClientCallsSearch
store = api.new_store()
y, m, d = map(int, date.split('-'))
date = localdate(y, m, d).date()
run_dialog(ClientCallsSearch, self.app, store, date=date)
store.close()
def _uri_run_dialog(self, result, kwargs):
path = result.path
if path == '/payment':
self._dialog_payment_details(**kwargs)
elif path == '/purchase':
self._dialog_purchase(**kwargs)
elif path == '/call':
self._dialog_call(**kwargs)
elif path == '/birthday':
self._dialog_client(**kwargs)
elif path == '/workorder':
self._dialog_work_order(**kwargs)
else:
raise NotImplementedError(path)
def _uri_show(self, result, kwargs):
path = result.path
if path == '/in-payments-by-date':
self._show_in_payments_by_date(**kwargs)
elif path == '/out-payments-by-date':
self._show_out_payments_by_date(**kwargs)
elif path == '/purchases-by-date':
self._show_purchases_by_date(**kwargs)
elif path == '/work-orders-by-date':
self._show_work_orders_by_date(**kwargs)
elif path == '/client-calls-by-date':
self._show_client_calls_by_date(**kwargs)
elif path == '/client-birthdays-by-date':
self._show_client_birthdays_by_date(**kwargs)
else:
raise NotImplementedError(path)
def _uri_self(self, result, kwargs):
self.web_open_uri(kwargs)
def _parse_stoq_uri(self, uri):
result = urlparse.urlparse(uri)
kwargs = {}
for arg in result.query.split(','):
k, v = arg.split('=', 1)
kwargs[k] = v
if result.hostname == 'dialog':
self._uri_run_dialog(result, kwargs)
elif result.hostname == 'show':
self._uri_show(result, kwargs)
elif result.hostname == 'self':
self._uri_self(result, kwargs)
else:
raise NotImplementedError(result.hostname)
def _policy_decision(self, uri, policy):
if uri.startswith('file:///'):
policy.use()
elif uri.startswith('http://localhost'):
policy.use()
elif uri.startswith('stoq://'):
policy.ignore()
self._parse_stoq_uri(uri)
else:
open_browser(uri, self.get_screen())
def _create_view_for_inspector(self, introspector_view):
window = gtk.Window()
window.set_size_request(800, 600)
sw = gtk.ScrolledWindow()
window.add(sw)
view = webkit.WebView()
sw.add(introspector_view)
window.show_all()
return view
#
# Callbacks
#
def _on_inspector__inspect_web_view(self, inspector, view):
return self._create_view_for_inspector(view)
def _on_view__navigation_policy_decision_requested(self, view, frame,
request, action,
policy):
self._policy_decision(request.props.uri, policy)
#
# Public API
#
[docs] def refresh(self):
pass
[docs] def get_view(self):
return self._view
[docs] def print_(self):
self._view.execute_script('window.print()')
[docs] def load_uri(self, uri):
log.info("Loading uri: %s" % (uri, ))
self._view.load_uri(uri)
[docs] def load_string(self, html, mime_type='text/html',
encoding='utf-8'):
log.info("Loading html: %r" % (html, ))
self._view.load_string(html, mime_type, encoding, '')
[docs] def js_function_call(self, function, *args):
js_values = []
for arg in args:
if arg is True:
value = 'true'
elif arg is False:
value = 'false'
elif type(arg) in [str, int, float]:
value = repr(arg)
else:
value = json.dumps(arg)
js_values.append(value)
self._view.execute_script('%s(%s)' % (
function, ', '.join(js_values)))
[docs] def web_open_uri(self, kwargs):
pass
[docs]def show_html(html):
w = gtk.Window()
w.set_size_request(600, 400)
wv = WebView()
wv.load_string(html)
w.add(wv)
w.show_all()