~dpm/qreator/snap

« back to all changes in this revision

Viewing changes to qreator/QreatorWindow.py

  • Committer: David Planella
  • Date: 2012-05-28 10:23:55 UTC
  • mfrom: (61.1.17 qreator-arb)
  • Revision ID: david.planella@ubuntu.com-20120528102355-nt15wc6cmk42rr7t
Merged new features and extras packaging from the lp:app-review-packaging branch

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
# -*- Mode: Python; coding: utf-8; indent-tabs-mode: nil; tab-width: 4 -*-
2
2
### BEGIN LICENSE
3
3
# Copyright (C) 2012 David Planella <david.planella@ubuntu.com>
4
 
# This program is free software: you can redistribute it and/or modify it 
5
 
# under the terms of the GNU General Public License version 3, as published 
 
4
# This program is free software: you can redistribute it and/or modify it
 
5
# under the terms of the GNU General Public License version 3, as published
6
6
# by the Free Software Foundation.
7
 
8
 
# This program is distributed in the hope that it will be useful, but 
9
 
# WITHOUT ANY WARRANTY; without even the implied warranties of 
10
 
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR 
 
7
#
 
8
# This program is distributed in the hope that it will be useful, but
 
9
# WITHOUT ANY WARRANTY; without even the implied warranties of
 
10
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11
11
# PURPOSE.  See the GNU General Public License for more details.
12
 
13
 
# You should have received a copy of the GNU General Public License along 
 
12
#
 
13
# You should have received a copy of the GNU General Public License along
14
14
# with this program.  If not, see <http://www.gnu.org/licenses/>.
15
15
### END LICENSE
16
16
 
17
 
import gettext
18
 
from gettext import gettext as _
19
 
gettext.textdomain('qreator')
20
 
 
21
17
import cairo
22
18
import math
23
 
from gi.repository import Gtk, Gdk  # pylint: disable=E0611
 
19
from gi.repository import Gtk, Gdk, GdkPixbuf  # pylint: disable=E0611
24
20
from gi.repository import GtkChamplain, Clutter, Champlain
25
21
from gi.repository import NetworkManager, NMClient
26
22
import logging
27
23
logger = logging.getLogger('qreator')
28
24
 
 
25
from qreator_lib.i18n import _
29
26
from qreator_lib import Window
30
 
 
31
 
import Geoclue
 
27
from qreator_lib.helpers import get_media_file as get_media_file
 
28
 
 
29
import sys
 
30
sys.path.insert(0, "/usr/share/software-center/")
 
31
import softwarecenter.db.database
 
32
import defer
 
33
 
32
34
from QRCode import QRCode as QRCode
33
35
from QRCode import QRCodeOutput as QRCodeOutput
34
36
 
35
37
COL_DESC = 0
36
38
COL_PIXBUF = 1
37
 
COL_ID = 2
38
 
COL_CALLBACK = 3
 
39
COL_CALLBACK = 2
39
40
 
40
41
PAGE_NEW = 0
41
42
#PAGE_HISTORY = 1
43
44
PAGE_ABOUT = 1
44
45
PAGE_QR = 2
45
46
 
46
 
POS_PROVIDER = 'Ubuntu GeoIP'
47
 
 
48
47
 
49
48
# See qreator_lib.Window.py for more details about how this class works
50
49
class QreatorWindow(Window):
66
65
        # Initialize the Cairo surface that will contain the QR code
67
66
        self.surface = None
68
67
 
69
 
        # Initialize the icon view widget
70
 
        self.ui.iconview1.set_text_column(COL_DESC)
71
 
        self.ui.iconview1.set_pixbuf_column(COL_PIXBUF)
72
 
 
73
68
        # Hide the notebook tabs
74
69
        self.ui.notebook1.set_show_tabs(False)
75
70
 
81
76
        # a Glade bug they are otherwise not marked as translatable)
82
77
        self.ui.entryURL.set_placeholder_text(_('[URL]'))
83
78
        self.ui.entrySSID.set_placeholder_text(
84
 
            _('[Network SSID - expand for autodetection]'))
85
 
        self.ui.entryPassword.set_placeholder_text(_('[Password]'))
 
79
            _('[Network identifier - expand for autodetection]'))
 
80
        self.ui.entryPassword.set_placeholder_text(_('[Network password]'))
86
81
 
87
82
        # Initialize about dialog
88
83
        about = Gtk.AboutDialog()
89
84
        about.set_program_name("Qreator")
90
 
        about.set_copyright("Copyright (c) 2012 David Planella\n" +
91
 
                            "http://about.me/david.planella")
 
85
        about.set_copyright(
 
86
            "Copyright (c) 2012 David Planella" +
 
87
            "\nhttp://about.me/david.planella")
92
88
        about.set_website("https://launchpad.net/qreator")
93
 
        #about.set_logo(GdkPixbuf.Pixbuf.new_from_file(
94
 
        #                    get_media_file("qreator-192.png")))
95
89
 
96
 
        about.set_version('12.05')
97
 
        about.set_authors(['David Planella <david.planella@ubuntu.com>',
98
 
                           'Michael Hall <mhall119@ubuntu.com>'])
99
 
        #about.set_comments(_('Create your own QR codes'))
100
 
        about.set_license(_('Distributed under the GPL v3 license.\n' +
101
 
                'http://www.opensource.org/licenses/gpl-3.0.html'))
 
90
        about.set_version('12.05.4')
 
91
        about.set_authors([
 
92
            'David Planella <david.planella@ubuntu.com>',
 
93
            'Michael Hall <mhall119@ubuntu.com>',
 
94
            'Andrew Starr-Bochicchio <andrewsomething@ubuntu.com >',
 
95
            ])
 
96
        about.set_license(_('Distributed under the GPL v3 license.') +
 
97
                '\nhttp://www.opensource.org/licenses/gpl-3.0.html')
102
98
 
103
99
        about.set_translator_credits(_("translator-credits"))
104
100
 
105
101
        box = builder.get_object("about_box")
106
102
        about.vbox.reparent(box)
107
103
 
108
 
        self.qr_code_placeholder = 'qreator'
 
104
        # Get rid of the 'Close' button
 
105
        for button in about.action_area.get_children():
 
106
            if button.get_property('label') == 'gtk-close':
 
107
                button.destroy()
 
108
 
 
109
        # Initialize the Software Center apps autocompletion
 
110
        self.softwarecenterapps = None
 
111
 
 
112
        self.usc_apps_complete = Complete()
 
113
 
 
114
        self.usc_apps_complete.set_hexpand(True)
 
115
        self.usc_apps_complete.connect("changed",
 
116
                                    self.on_usc_apps_complete_changed, None)
 
117
 
 
118
        #self.get_softwarecenterapps()
 
119
        #self.on_get_softwarecenterapps()
 
120
        deferred = defer.defer(self.get_softwarecenterapps)
 
121
        deferred.add_callback(self.on_get_softwarecenterapps)
 
122
 
 
123
        self.ui.qr_app.attach(self.usc_apps_complete, 1, 0, 1, 1)
 
124
 
 
125
        # Load the background texture
 
126
        self.texture = cairo.ImageSurface.create_from_png(
 
127
                                                get_media_file("pattern.png"))
 
128
 
 
129
        # Set up the QR types shown in the main icon view
 
130
        self.ui.qr_types_view.set_text_column(COL_DESC)
 
131
        self.ui.qr_types_view.set_pixbuf_column(COL_PIXBUF)
 
132
 
 
133
        self.qr_types = [
 
134
            {'desc': _('URL'),
 
135
                'icon': GdkPixbuf.Pixbuf.new_from_file(get_media_file(
 
136
                            'url.png')),
 
137
                'callback': 'on_qr_url_clicked'},
 
138
            {'desc': _('Text'),
 
139
                'icon': GdkPixbuf.Pixbuf.new_from_file(get_media_file(
 
140
                            'text.png')),
 
141
                'callback': 'on_qr_text_clicked'},
 
142
            {'desc': _('Geolocation'),
 
143
                'icon': GdkPixbuf.Pixbuf.new_from_file(get_media_file(
 
144
                            'location.png')),
 
145
                'callback': 'on_qr_location_clicked'},
 
146
            {'desc': _('Wifi network'),
 
147
                'icon': GdkPixbuf.Pixbuf.new_from_file(get_media_file(
 
148
                            'wifi.png')),
 
149
                'callback': 'on_qr_wifi_clicked'},
 
150
            {'desc': _('Ubuntu Software Center app'),
 
151
                'icon': GdkPixbuf.Pixbuf.new_from_file(get_media_file(
 
152
                            'softwarecentre.png')),
 
153
                'callback': 'on_qr_softwarecenterapp_clicked'},
 
154
        ]
 
155
 
 
156
        self.qr_types_store = Gtk.ListStore(str, GdkPixbuf.Pixbuf, str)
 
157
        # ^ desc, icon, callback ^
 
158
        self.qr_types_store.set_sort_column_id(COL_DESC,
 
159
                                               Gtk.SortType.ASCENDING)
 
160
        self.ui.qr_types_view.set_model(self.qr_types_store)
 
161
        self.fill_qr_types_store()
 
162
 
 
163
        self.curr_height = 0
 
164
        self.curr_width = 0
 
165
 
 
166
        # Add an initial text, so that there is an initial QR code
 
167
        self.qr_code_placeholder = 'http://launchpad.net/qreator'
 
168
 
 
169
    def fill_qr_types_store(self):
 
170
        self.qr_types_store.clear()
 
171
 
 
172
        for qr_type in self.qr_types:
 
173
            self.qr_types_store.append([qr_type['desc'],
 
174
                                        qr_type['icon'],
 
175
                                        qr_type['callback']])
 
176
 
 
177
    def on_qreator_window_check_resize(self, widget):
 
178
        '''We need this function to fix the issue described at
 
179
        http://bit.ly/LW94BO whereby the number of columns of the icon view
 
180
        widget stays fixed at the number set for the initial width of the
 
181
        window'''
 
182
        # Get the new size
 
183
        new_width = widget.get_size()[0]
 
184
        new_height = widget.get_size()[1]
 
185
        # If the size has changed...
 
186
        if(new_width != self.curr_width or new_height != self.curr_height):
 
187
            # Remember new size
 
188
            self.curr_width = new_width
 
189
            self.curr_height = new_height
 
190
            # and refill iconviews with icons to adjust columns number
 
191
            self.fill_qr_types_store()
109
192
 
110
193
    def on_entryText_changed(self, widget, data=None):
111
194
        self.update_qr_code(widget.get_text(widget.get_start_iter(),
155
238
        for ssid in ssids:
156
239
            self.ui.comboboxtextSSID.append_text(ssid)
157
240
 
 
241
    def on_qr_softwarecenterapp_clicked(self):
 
242
        # We're now loading the UI for the Software Center app QR type
 
243
        self._hide_children(self.ui.qr_input)
 
244
        self.ui.qr_app.show_all()
 
245
 
158
246
    def on_qr_text_clicked(self):
159
247
        # Initialize multi-line text entry
160
248
        textbuffer = self.ui.entryText.get_buffer()
201
289
 
202
290
        self.ui.qr_location.show_all()
203
291
 
204
 
    def on_iconview1_item_activated(self, widget, item):
 
292
    def on_qr_types_view_item_activated(self, widget, item):
205
293
        '''Loads the UI for the appropriate QR type'''
206
294
 
207
295
        model = widget.get_model()
263
351
        self.qr_code_placeholder = text
264
352
        self.ui.qr_drawingarea.queue_draw()
265
353
 
 
354
    def on_usc_apps_complete_changed(self, widget, data=None):
 
355
        USC_APPS_BASE_URL = 'https://apps.ubuntu.com/cat/applications/'
 
356
        self.update_qr_code(USC_APPS_BASE_URL + widget.get_text())
 
357
 
266
358
    def on_entryURL_changed(self, widget, data=None):
267
359
        self.update_url_qr_code(www=widget.get_text())
268
360
 
353
445
 
354
446
        # Fill the rounded rectangle with a linear gradient
355
447
        lg = cairo.LinearGradient(0.0, 0.0, 500.0, 500.0)
356
 
        lg.add_color_stop_rgba(0, 1, 1, 1, 1)
357
 
        lg.add_color_stop_rgba(1, 0.678, 0.678, 0.678, 1)
 
448
        lg.add_color_stop_rgba(0, 0.27, 0.27, 0.27, 1)  # 1,1,1 is white
 
449
        lg.add_color_stop_rgba(1, 0.22, 0.22, 0.22, 1)
358
450
 
359
451
        ctx.set_source(lg)
360
452
        ctx.fill()
361
453
 
 
454
        # Load a texture and overlay it to the gradient, tiled
 
455
        pattern = cairo.SurfacePattern(self.texture)
 
456
        pattern.set_extend(cairo.EXTEND_REPEAT)
 
457
        ctx.set_source(pattern)
 
458
        ctx.paint()
 
459
 
362
460
        ## Create the QR code
363
461
        qr_code = QRCode()
364
462
        self.surface = qr_code.encode(text, QRCodeOutput.CAIRO_SURFACE)
374
472
        # Render the image
375
473
        ctx.paint()
376
474
 
 
475
    def get_softwarecenterapps(self):
 
476
        print 'Task STARTED!'
 
477
        db = softwarecenter.db.database.StoreDatabase()
 
478
        db._aptcache.open()
 
479
        db.open(use_axi=False, use_agent=False)
 
480
        apps = []
 
481
        for doc in db:
 
482
            app = db.get_application(doc)
 
483
            appdetails = app.get_details(db)
 
484
            appinfo = App(app.appname, app.pkgname, appdetails.icon)
 
485
            apps.append(appinfo)
 
486
        self.softwarecenterapps = apps
 
487
        return apps
 
488
 
 
489
    def on_get_softwarecenterapps(self, result):
 
490
        print 'Task FINISHED!'
 
491
        self.usc_apps_complete.add(self.softwarecenterapps)
 
492
 
377
493
 
378
494
def get_current_location():
379
495
    '''Gets the current location from geolocation via IP (only method
380
496
       currently supported)'''
381
 
 
382
 
    location = Geoclue.DiscoverLocation()
383
 
    location.init()
384
 
    location.set_position_provider(POS_PROVIDER)
385
 
    position = location.get_location_info()
 
497
    #import Geoclue
 
498
    #POS_PROVIDER = 'Ubuntu GeoIP'
 
499
    #location = Geoclue.DiscoverLocation()
 
500
    #location.init()
 
501
    #location.set_position_provider(POS_PROVIDER)
 
502
    #position = location.get_location_info()
 
503
 
 
504
    import dbus
 
505
    bus = dbus.SessionBus()
 
506
    geoclue = bus.get_object(
 
507
        'org.freedesktop.Geoclue.Providers.UbuntuGeoIP',
 
508
        '/org/freedesktop/Geoclue/Providers/UbuntuGeoIP')
 
509
    position_info = geoclue.GetPosition(
 
510
        dbus_interface='org.freedesktop.Geoclue.Position')
 
511
 
 
512
    position = {}
 
513
    position['timestamp'] = position_info[1]
 
514
    position['latitude'] = position_info[2]
 
515
    position['longitude'] = position_info[3]
 
516
    position['altitude'] = position_info[4]
386
517
 
387
518
    return position['latitude'], position['longitude']
388
519
 
398
529
                ssids.append(ap.get_ssid())
399
530
 
400
531
    return ssids
 
532
 
 
533
 
 
534
class App(object):
 
535
    def __init__(self, name, package, icon):
 
536
        self.name = name
 
537
        self.package = package
 
538
        self.icon = icon
 
539
 
 
540
 
 
541
class Complete(Gtk.Entry):
 
542
    '''a class to autocomplete'''
 
543
 
 
544
    def __init__(self, apps=None):
 
545
        Gtk.Entry.__init__(self)
 
546
        self.completion = Gtk.EntryCompletion()
 
547
        self.set_completion(self.completion)
 
548
        self.model = Gtk.ListStore(str, GdkPixbuf.Pixbuf, str)
 
549
        self.completion.set_model(self.model)
 
550
        self.completion_img = Gtk.CellRendererPixbuf()
 
551
        self.completion.pack_start(self.completion_img, True)
 
552
        self.completion.add_attribute(self.completion_img, "pixbuf", 1)
 
553
        self.completion.set_text_column(0)
 
554
        self.completion.set_popup_set_width(False)
 
555
        self.completion.set_inline_completion(True)
 
556
        self.icons = Gtk.IconTheme.get_default()
 
557
        self.icons.append_search_path("/usr/share/app-install/icons/")
 
558
 
 
559
        if apps:
 
560
            self.add(apps)
 
561
        else:
 
562
            self.set_placeholder_text(
 
563
                _('[Wait a few seconds to enable autocompletion...]'))
 
564
 
 
565
    def add(self, apps):
 
566
        for app in apps:
 
567
            self._remember(app)
 
568
        self.set_placeholder_text(
 
569
                _('[Type the name of an app]'))
 
570
 
 
571
    def _remember(self, app):
 
572
        '''add a value to the list of strings to suggest'''
 
573
        try:
 
574
            icon = self.icons.load_icon(
 
575
                "{0}".format(app.icon),
 
576
                16, Gtk.IconLookupFlags.USE_BUILTIN)
 
577
        except:
 
578
            icon = self.icons.load_icon(
 
579
                "stock_not",
 
580
                16, Gtk.IconLookupFlags.USE_BUILTIN)
 
581
        self.model.append([app.package, icon, app.name])