1#!/usr/bin/env python 2 3 4############################################################################# 5## 6## Copyright (C) 2013 Riverbank Computing Limited. 7## Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). 8## All rights reserved. 9## 10## This file is part of the examples of PyQt. 11## 12## $QT_BEGIN_LICENSE:BSD$ 13## You may use this file under the terms of the BSD license as follows: 14## 15## "Redistribution and use in source and binary forms, with or without 16## modification, are permitted provided that the following conditions are 17## met: 18## * Redistributions of source code must retain the above copyright 19## notice, this list of conditions and the following disclaimer. 20## * Redistributions in binary form must reproduce the above copyright 21## notice, this list of conditions and the following disclaimer in 22## the documentation and/or other materials provided with the 23## distribution. 24## * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor 25## the names of its contributors may be used to endorse or promote 26## products derived from this software without specific prior written 27## permission. 28## 29## THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 30## "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 31## LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 32## A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 33## OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 34## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 35## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 36## DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 37## THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 38## (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 39## OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." 40## $QT_END_LICENSE$ 41## 42############################################################################# 43 44 45import sys 46 47from PyQt5.QtCore import (pyqtProperty, pyqtSignal, Q_CLASSINFO, 48 QCoreApplication, QDate, QObject, QTime, QUrl) 49from PyQt5.QtGui import QColor 50from PyQt5.QtQml import (qmlAttachedPropertiesObject, qmlRegisterType, 51 QQmlComponent, QQmlEngine, QQmlListProperty) 52 53 54QML = b''' 55import People 1.0 56import QtQuick 2.0 57 58BirthdayParty { 59 onPartyStarted: console.log("This party started rockin' at " + time); 60 61 host: Boy { 62 name: "Bob Jones" 63 shoe { size: 12; color: "white"; brand: "Nike"; price: 90.0 } 64 } 65 66 Boy { 67 name: "Leo Hodges" 68 BirthdayParty.rsvp: "2009-07-06" 69 shoe { size: 10; color: "black"; brand: "Reebok"; price: 59.95 } 70 } 71 72 Boy { 73 name: "Jack Smith" 74 shoe { size: 8; color: "blue"; brand: "Puma"; price: 19.95 } 75 } 76 77 Girl { 78 name: "Anne Brown" 79 BirthdayParty.rsvp: "2009-07-01" 80 shoe.size: 7 81 shoe.color: "red" 82 shoe.brand: "Marc Jacobs" 83 shoe.price: 699.99 84 } 85} 86''' 87 88 89class ShoeDescription(QObject): 90 def __init__(self, parent=None): 91 super(ShoeDescription, self).__init__(parent) 92 93 self._size = 0 94 self._color = QColor() 95 self._brand = '' 96 self._price = 0.0 97 98 @pyqtProperty(int) 99 def size(self): 100 return self._size 101 102 @size.setter 103 def size(self, size): 104 self._size = size 105 106 @pyqtProperty(QColor) 107 def color(self): 108 return self._color 109 110 @color.setter 111 def color(self, color): 112 self._color = color 113 114 @pyqtProperty(str) 115 def brand(self): 116 return self._brand 117 118 @brand.setter 119 def brand(self, brand): 120 self._brand = brand 121 122 @pyqtProperty(float) 123 def price(self): 124 return self._price 125 126 @price.setter 127 def price(self, price): 128 self._price = price 129 130 131class Person(QObject): 132 def __init__(self, parent=None): 133 super(Person, self).__init__(parent) 134 135 self._name = '' 136 self._shoe = ShoeDescription() 137 138 @pyqtProperty(str) 139 def name(self): 140 return self._name 141 142 @name.setter 143 def name(self, name): 144 self._name = name 145 146 @pyqtProperty(ShoeDescription) 147 def shoe(self): 148 return self._shoe 149 150 151class Boy(Person): 152 pass 153 154 155class Girl(Person): 156 pass 157 158 159class BirthdayPartyAttached(QObject): 160 def __init__(self, parent): 161 super(BirthdayPartyAttached, self).__init__(parent) 162 163 self._rsvp = QDate() 164 165 @pyqtProperty(QDate) 166 def rsvp(self): 167 return self._rsvp 168 169 @rsvp.setter 170 def rsvp(self, rsvp): 171 self._rsvp = rsvp 172 173 174class BirthdayParty(QObject): 175 Q_CLASSINFO('DefaultProperty', 'guests') 176 177 partyStarted = pyqtSignal(QTime, arguments=['time']) 178 179 def __init__(self, parent=None): 180 super(BirthdayParty, self).__init__(parent) 181 182 self._host = None 183 self._guests = [] 184 185 @pyqtProperty(Person) 186 def host(self): 187 return self._host 188 189 @host.setter 190 def host(self, host): 191 self._host = host 192 193 @pyqtProperty(QQmlListProperty) 194 def guests(self): 195 return QQmlListProperty(Person, self, self._guests) 196 197 def startParty(self): 198 self.partyStarted.emit(QTime.currentTime()) 199 200 201app = QCoreApplication(sys.argv) 202 203qmlRegisterType(BirthdayPartyAttached) 204qmlRegisterType(BirthdayParty, "People", 1, 0, "BirthdayParty", 205 attachedProperties=BirthdayPartyAttached) 206qmlRegisterType(ShoeDescription) 207qmlRegisterType(Person) 208qmlRegisterType(Boy, "People", 1, 0, "Boy") 209qmlRegisterType(Girl, "People", 1, 0, "Girl") 210 211engine = QQmlEngine() 212 213component = QQmlComponent(engine) 214component.setData(QML, QUrl()) 215 216party = component.create() 217 218if party is not None and party.host is not None: 219 print("\"%s\" is having a birthday!" % party.host.name) 220 221 if isinstance(party.host, Boy): 222 print("He is inviting:") 223 else: 224 print("She is inviting:") 225 226 for guest in party.guests: 227 attached = qmlAttachedPropertiesObject(BirthdayParty, guest, False) 228 229 if attached is not None: 230 rsvpDate = attached.property('rsvp') 231 else: 232 rsvpDate = QDate() 233 234 if rsvpDate.isNull(): 235 print(" \"%s\" RSVP date: Hasn't RSVP'd" % guest.name) 236 else: 237 print(" \"%s\" RSVP date: %s" % (guest.name, rsvpDate.toString())) 238 239 party.startParty() 240else: 241 for e in component.errors(): 242 print("Error:", e.toString()); 243