source: orange/Orange/OrangeWidgets/OWWidget.py @ 11291:c5fb32b6d8a4

Revision 11291:c5fb32b6d8a4, 12.8 KB checked in by Ales Erjavec <ales.erjavec@…>, 15 months ago (diff)

Fixed/changed OWReport to work in the new interface.

Line 
1#
2# OWWidget.py
3# Orange Widget
4# A General Orange Widget, from which all the Orange Widgets are derived
5#
6
7from OWBaseWidget import *
8
9
10class OWWidget(OWBaseWidget):
11    def __init__(self, parent=None, signalManager=None, title="Orange Widget",
12                 wantGraph=False, wantStatusBar=False, savePosition=True,
13                 wantMainArea=1, noReport=False, showSaveGraph=1,
14                 resizingEnabled=1, wantStateInfoWidget=None,
15                 **args):
16        """
17        Initialization
18        Parameters:
19            title - The title of the\ widget, including a "&" (for shortcut in about box)
20            wantGraph - displays a save graph button or not
21        """
22
23        OWBaseWidget.__init__(self, parent, signalManager, title, savePosition=savePosition, resizingEnabled=resizingEnabled, **args)
24
25        self.setLayout(QVBoxLayout())
26        self.layout().setMargin(2)
27
28        self.topWidgetPart = OWGUI.widgetBox(self, orientation="horizontal", margin=0)
29        self.leftWidgetPart = OWGUI.widgetBox(self.topWidgetPart, orientation="vertical", margin=0)
30        if wantMainArea:
31            self.leftWidgetPart.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.MinimumExpanding))
32            self.leftWidgetPart.updateGeometry()
33            self.mainArea = OWGUI.widgetBox(self.topWidgetPart, orientation="vertical", sizePolicy=QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding), margin=0)
34            self.mainArea.layout().setMargin(4)
35            self.mainArea.updateGeometry()
36           
37        self.controlArea = OWGUI.widgetBox(self.leftWidgetPart, orientation="vertical", margin=4)# if wantMainArea else 1)
38
39        self.space = self.controlArea
40
41        self.buttonBackground = OWGUI.widgetBox(self.leftWidgetPart, orientation="horizontal", margin=4)# if wantMainArea else 1)
42        self.buttonBackground.hide()
43       
44        if wantGraph and showSaveGraph:
45            self.buttonBackground.show()
46            self.graphButton = OWGUI.button(self.buttonBackground, self, "&Save Graph")
47            self.graphButton.setAutoDefault(0)
48           
49        if wantStateInfoWidget is None:
50            wantStateInfoWidget = self._owShowStatus
51           
52        if wantStateInfoWidget:
53            # Widget for error, warnings, info.
54            self.widgetStateInfoBox = OWGUI.widgetBox(self.leftWidgetPart, "Widget state")
55            self.widgetStateInfo = OWGUI.widgetLabel(self.widgetStateInfoBox, "\n")
56            self.widgetStateInfo.setWordWrap(True)
57            self.widgetStateInfo.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
58            self.widgetStateInfo.setFixedHeight(self.widgetStateInfo.height())
59            self.widgetStateInfoBox.hide()
60                   
61            self.connect(self, SIGNAL("widgetStateChanged(QString, int, QString)"), self.updateWidgetStateInfo)
62       
63
64        self.__reportData = None
65        if not noReport and hasattr(self, "sendReport"):
66            self.buttonBackground.show()
67            self.reportButton = OWGUI.button(self.buttonBackground, self, "&Report", self.reportAndFinish, debuggingEnabled=0)
68            self.reportButton.setAutoDefault(0)
69
70        if wantStatusBar:
71            #self.widgetStatusArea = OWGUI.widgetBox(self, orientation = "horizontal", margin = 2)
72            self.widgetStatusArea = QFrame(self) 
73            self.statusBarIconArea = QFrame(self)
74            self.widgetStatusBar = QStatusBar(self) 
75           
76            self.layout().addWidget(self.widgetStatusArea)
77           
78            self.widgetStatusArea.setLayout(QHBoxLayout(self.widgetStatusArea))
79            self.widgetStatusArea.layout().addWidget(self.statusBarIconArea)
80            self.widgetStatusArea.layout().addWidget(self.widgetStatusBar)
81            self.widgetStatusArea.layout().setMargin(0)
82            self.widgetStatusArea.setFrameShape(QFrame.StyledPanel)
83                       
84            self.statusBarIconArea.setLayout(QHBoxLayout())
85            self.widgetStatusBar.setSizeGripEnabled(0) 
86            #self.statusBarIconArea.setFrameStyle (QFrame.Panel + QFrame.Sunken)
87            #self.widgetStatusBar.setFrameStyle (QFrame.Panel + QFrame.Sunken)
88            #self.widgetStatusBar.setSizePolicy(QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred))
89            #self.widgetStatusBar.setSizePolicy(QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Preferred))
90            #self.widgetStatusBar.updateGeometry()
91            #self.statusBarIconArea.setFixedSize(16*2,18)
92            self.statusBarIconArea.hide()
93           
94
95            # create pixmaps used in statusbar to show info, warning and error messages
96            #self._infoWidget, self._infoPixmap = self.createPixmapWidget(self.statusBarIconArea, os.path.join(self.widgetDir + "icons/triangle-blue.png"))
97            self._warningWidget = self.createPixmapWidget(self.statusBarIconArea, os.path.join(self.widgetDir + "icons/triangle-orange.png"))
98            self._errorWidget = self.createPixmapWidget(self.statusBarIconArea, os.path.join(self.widgetDir + "icons/triangle-red.png"))
99       
100       
101
102    # status bar handler functions
103    def createPixmapWidget(self, parent, iconName):
104        w = QLabel(parent)
105        parent.layout().addWidget(w)
106        w.setFixedSize(16, 16)
107        w.hide()
108        if os.path.exists(iconName):
109            w.setPixmap(QPixmap(iconName))
110        return w
111
112    def setState(self, stateType, id, text):
113        stateChanged = OWBaseWidget.setState(self, stateType, id, text)
114        if not stateChanged or not hasattr(self, "widgetStatusArea"):
115            return
116
117        iconsShown = 0
118        #for state, widget, icon, use in [("Info", self._infoWidget, self._owInfo), ("Warning", self._warningWidget, self._owWarning), ("Error", self._errorWidget, self._owError)]:
119        for state, widget, use in [("Warning", self._warningWidget, self._owWarning), ("Error", self._errorWidget, self._owError)]:
120            if not widget: continue
121            if use and self.widgetState[state] != {}:
122                widget.setToolTip("\n".join(self.widgetState[state].values()))
123                widget.show()
124                iconsShown = 1
125            else:
126                widget.setToolTip("")
127                widget.hide()
128
129        if iconsShown:
130            self.statusBarIconArea.show()
131        else:
132            self.statusBarIconArea.hide()
133
134        #if (stateType == "Info" and self._owInfo) or (stateType == "Warning" and self._owWarning) or (stateType == "Error" and self._owError):
135        if (stateType == "Warning" and self._owWarning) or (stateType == "Error" and self._owError):
136            if text:
137                self.setStatusBarText(stateType + ": " + text)
138            else:
139                self.setStatusBarText("")
140        self.updateStatusBarState()
141        #qApp.processEvents()
142       
143    def updateWidgetStateInfo(self, stateType, id, text):
144        html = self.widgetStateToHtml(self._owInfo, self._owWarning, self._owError)
145        if html:
146            self.widgetStateInfoBox.show()
147            self.widgetStateInfo.setText(html)
148            self.widgetStateInfo.setToolTip(html)
149        else:
150            if not self.widgetStateInfoBox.isVisible():
151                dHeight = - self.widgetStateInfoBox.height()
152            else:
153                dHeight = 0
154            self.widgetStateInfoBox.hide()
155            self.widgetStateInfo.setText("")
156            self.widgetStateInfo.setToolTip("")
157            width, height = self.width(), self.height() + dHeight
158            self.resize(width, height)
159#            QTimer.singleShot(1, lambda :self.resize(width, height))
160
161    def updateStatusBarState(self):
162        if not hasattr(self, "widgetStatusArea"):
163            return
164        if self._owShowStatus and (self.widgetState["Warning"] != {} or self.widgetState["Error"] != {}):
165            self.widgetStatusArea.show()
166        else:
167            self.widgetStatusArea.hide()
168
169    def setStatusBarText(self, text, timeout=5000):
170        if hasattr(self, "widgetStatusBar"):
171            self.widgetStatusBar.showMessage(" " + text, timeout)
172
173    def reportAndFinish(self):
174        self.sendReport()
175        self.finishReport()
176
177    def startReport(self, name=None):
178        if self.__reportData is not None:
179            print "Cannot open a new report when an old report is still active"
180            return False
181        self.reportName = name or self.windowTitle()
182        self.__reportData = ""
183        return True
184
185    def reportSection(self, title):
186        if self.__reportData is None:
187            self.startReport()
188        self.__reportData += "\n\n<h2>%s</h2>\n\n" % title
189
190    def reportSubsection(self, title):
191        if self.__reportData is None:
192            self.startReport()
193        self.__reportData += "\n\n  <h3>%s</h3>\n\n" % title
194
195    def reportList(self, items):
196        if self.__reportData is None:
197            self.startReport()
198        self.startReportList()
199        for item in items:
200            self.addToReportList(item)
201        self.finishReportList()
202
203    def getUniqueFileName(self, patt):
204        return OWReport.get_instance().getUniqueFileName(patt)
205
206    def getUniqueImageName(self, nm="img", ext=".png"):
207        return OWReport.get_instance().getUniqueFileName(nm + "%06i" + ext)
208
209    def reportImage(self, filenameOrFunc, *args):
210        if self.__reportData is None:
211            self.startReport()
212
213        if type(filenameOrFunc) in [str, unicode]:
214            self.__reportData += '    <IMG src="%s"/>\n' % filenameOrFunc
215        else:
216            sfn, ffn = self.getUniqueImageName()
217            filenameOrFunc(ffn, *args)
218            self.reportImage(sfn)
219
220    svg_type = "image/svg+xml"
221    def reportObject(self, type, data, **attrs):
222        if self.__reportData is None:
223            self.startReport()
224        self.__reportData += '<object type="%s" data="%s" %s></object>' % (type, data, " ".join('%s="%s"' % attr for attr in attrs.items()))
225
226    def startReportList(self):
227        if self.__reportData is None:
228            self.startReport()
229        self.__reportData += "    <UL>\n"
230
231    def addToReportList(self, item):
232        self.__reportData += "      <LI>%s</LI>\n" % item
233
234    def finishReportList(self):
235        self.__reportData += "    </UL>\n"
236
237    def reportSettings(self, sectionName="", settingsList=None, closeList=True):
238        if sectionName:
239            self.reportSection(sectionName)
240        elif self.__reportData is None:
241            self.startReport()
242        self.__reportData += "    <ul>%s</ul>\n" % "".join("<b>%s: </b>%s<br/>" % item for item in settingsList if item) 
243
244    def reportRaw(self, text):
245        if self.__reportData is None:
246            self.startReport()
247        self.__reportData += text
248
249    def prepareDataReport(self, data, listAttributes=True, exampleCount=True):
250        if data:
251            res = []
252            if exampleCount:
253                res.append(("Examples", str(len(data))))
254            if listAttributes:
255                if data.domain.attributes:
256                    res.append(("Attributes", "%i %s" % ( 
257                                len(data.domain.attributes), 
258                                 "(%s%s)" % (", ".join(x.name for foo, x in zip(xrange(30), data.domain.attributes)), "..." if len(data.domain.attributes) > 30 else "")
259                              )))
260                else:
261                    res.append(("Attributes", "0"))
262                metas = data.domain.getmetas()
263                if metas:
264                  if len(metas) <= 100:
265                      res.append(("Meta attributes", "%i (%s)" % (len(metas), ", ".join(x.name for x in metas.values()))))
266                  else:
267                      res.append(("Meta attributes", str(len(metas))))
268                res.append(("Class", data.domain.classVar.name if data.domain.classVar else "<none>"))
269            return res
270           
271    def reportData(self, settings, sectionName="Data", ifNone="None", listAttributes = True, exampleCount=True):
272        haveSettings = False
273        try:
274            haveSettings = isinstance(settings, list) and len(settings[0])==2
275        except:
276            pass
277        if not haveSettings:
278            settings = self.prepareDataReport(settings, listAttributes, exampleCount)
279        if not self.__reportData:
280            self.startReport()
281        if sectionName is not None:
282            self.reportSection(sectionName)
283        if settings:
284            self.reportSettings("", settings)
285        elif ifNone is not None:
286            self.reportRaw(ifNone)
287
288    def finishReport(self):
289        if self.__reportData is not None:
290            report = OWReport.get_instance()
291#            report(self.reportName, self.__reportData or "",
292#                   self.widgetId, self.windowIcon())
293            report.appendReport(self.reportName, self.__reportData,
294                                sender=self)
295            self.__reportData = None
296
297import OWReport
298
299if __name__ == "__main__":
300    a = QApplication(sys.argv)
301    ow = OWWidget()
302    ow.show()
303    a.exec_()
Note: See TracBrowser for help on using the repository browser.