1#############################################################################
2##
3## Copyright (C) 2013 Riverbank Computing Limited.
4## Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
5## All rights reserved.
6##
7## This file is part of the examples of PyQt.
8##
9## $QT_BEGIN_LICENSE:LGPL$
10## Commercial Usage
11## Licensees holding valid Qt Commercial licenses may use this file in
12## accordance with the Qt Commercial License Agreement provided with the
13## Software or, alternatively, in accordance with the terms contained in
14## a written agreement between you and Nokia.
15##
16## GNU Lesser General Public License Usage
17## Alternatively, this file may be used under the terms of the GNU Lesser
18## General Public License version 2.1 as published by the Free Software
19## Foundation and appearing in the file LICENSE.LGPL included in the
20## packaging of this file.  Please review the following information to
21## ensure the GNU Lesser General Public License version 2.1 requirements
22## will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23##
24## In addition, as a special exception, Nokia gives you certain additional
25## rights.  These rights are described in the Nokia Qt LGPL Exception
26## version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27##
28## GNU General Public License Usage
29## Alternatively, this file may be used under the terms of the GNU
30## General Public License version 3.0 as published by the Free Software
31## Foundation and appearing in the file LICENSE.GPL included in the
32## packaging of this file.  Please review the following information to
33## ensure the GNU General Public License version 3.0 requirements will be
34## met: http://www.gnu.org/copyleft/gpl.html.
35##
36## If you have questions regarding the use of this file, please contact
37## Nokia at qt-info@nokia.com.
38## $QT_END_LICENSE$
39##
40#############################################################################
41
42
43from xml.dom.minidom import parseString
44
45from PyQt5.QtCore import QRectF, QRegExp, Qt
46from PyQt5.QtGui import QImage
47
48from colors import Colors
49from demoitem import DemoItem
50from demoitemanimation import DemoItemAnimation
51from demotextitem import DemoTextItem
52from headingitem import HeadingItem
53from imageitem import ImageItem
54
55
56class ExampleContent(DemoItem):
57    def __init__(self, name, parent=None):
58        super(ExampleContent, self).__init__(parent)
59
60        # Prevent a circular import.
61        from menumanager import MenuManager
62        self._menu_manager = MenuManager.instance()
63
64        self.name = name
65        self.heading = None
66        self.description = None
67        self.screenshot = None
68
69        self._prepared = False
70
71    def prepare(self):
72        if not self._prepared:
73            self.createContent()
74            self._prepared = True
75
76    def animationStopped(self, id):
77        if id == DemoItemAnimation.ANIM_OUT:
78            # Free up some memory.
79            self.heading = None
80            self.description = None
81            self.screenshot = None
82            self._prepared = False
83
84    def loadDescription(self):
85        contents = self._menu_manager.getHtml(self.name).data().decode('utf8')
86        if contents == '':
87            paragraphs = []
88        else:
89            exampleDoc = parseString(contents)
90            paragraphs = exampleDoc.getElementsByTagName('p')
91
92        if len(paragraphs) < 1:
93            Colors.debug("- ExampleContent.loadDescription(): Could not load description:", self._menu_manager.info[self.name].get('docfile'))
94
95        description = Colors.contentColor + "Could not load description. Ensure that the documentation for Qt is built."
96        for p in paragraphs:
97            description = self.extractTextFromParagraph(p)
98            if self.isSummary(description):
99                break
100
101        return Colors.contentColor + description
102
103    def isSummary(self, text):
104        re = QRegExp("(In )?((The|This) )?(%s )?.*(tutorial|example|demo|application)" % self.name, Qt.CaseInsensitive)
105
106        return ('[' not in text) and (re.indexIn(text) >= 0)
107
108    def extractTextFromParagraph(self, parentNode):
109        description = ''
110        node = parentNode.firstChild
111
112        while node is not None:
113            if node.nodeType == node.TEXT_NODE:
114                description += Colors.contentColor + node.nodeValue
115            elif node.hasChildNodes():
116                if node.nodeName == 'b':
117                    beginTag = '<b>'
118                    endTag = '</b>'
119                elif node.nodeName == 'a':
120                    beginTag = Colors.contentColor
121                    endTag = '</font>'
122                elif node.nodeName == 'i':
123                    beginTag = '<i>'
124                    endTag = '</i>'
125                elif node.nodeName == 'tt':
126                    beginTag = '<tt>'
127                    endTag = '</tt>'
128                else:
129                    beginTag = endTag = ''
130
131                description += beginTag + self.extractTextFromParagraph(node) + endTag
132
133            node = node.nextSibling
134
135        return description
136
137    def createContent(self):
138        # Create the items.
139        self.heading = HeadingItem(self.name, self)
140        self.description = DemoTextItem(self.loadDescription(),
141                Colors.contentFont(), Colors.heading, 500, self)
142        imgHeight = 340 - int(self.description.boundingRect().height()) + 50
143        self.screenshot = ImageItem(QImage.fromData(self._menu_manager.getImage(self.name)), 550, imgHeight, self)
144
145        # Place the items on screen.
146        self.heading.setPos(0, 3)
147        self.description.setPos(0, self.heading.pos().y() + self.heading.boundingRect().height() + 10)
148        self.screenshot.setPos(0, self.description.pos().y() + self.description.boundingRect().height() + 10)
149
150    def boundingRect(self):
151        return QRectF(0, 0, 500, 100)
152