source: orange/orange/OrangeCanvas/orngCanvas.pyw @ 7735:22867997305f

Revision 7735:22867997305f, 47.8 KB checked in by ales_erjavec <ales.erjavec@…>, 3 years ago (diff)

Added updateWidgetRegistry method (ensures the settingsWidgetTabs? is consistent with widgetRegistry).

Line 
1# Author: Gregor Leban (gregor.leban@fri.uni-lj.si)
2# Description:
3#    main file, that creates the MDI environment
4
5# This module has to be imported first because it takes care of the system PATH variable
6# Namely, it throws out the MikTeX directories which contain an incompatible Qt .dll's
7import orngEnviron, orngAddOns
8
9from PyQt4.QtCore import *
10from PyQt4.QtGui import *
11   
12import sys, os, cPickle, orngRegistry, OWGUI
13import orngTabs, orngDoc, orngDlgs, orngOutput, orngHelp, OWReport
14import  user, orngMisc
15
16RedR = False
17product = "Red R" if RedR else "Orange"
18
19
20class OrangeCanvasDlg(QMainWindow):
21    def __init__(self, app, parent=None, flags=0):
22        QMainWindow.__init__(self, parent)
23        self.debugMode = 1        # print extra output for debuging
24        self.setWindowTitle("%s Canvas" % product)
25        self.windows = []    # list of id for windows in Window menu
26        self.recentDocs = []
27        self.iconNameToIcon = {}
28        self.toolbarIconSizeList = [16, 32, 40, 48, 60]
29        self.schemeIconSizeList = [32, 40, 48]
30        self.widgetsToolBar = None
31        self.originalPalette = QApplication.palette()
32
33        self.__dict__.update(orngEnviron.directoryNames)
34               
35        self.defaultPic = os.path.join(self.picsDir, "Unknown.png")
36        self.defaultBackground = os.path.join(self.picsDir, "frame.png")
37        canvasPicsDir = os.path.join(self.canvasDir, "icons")
38        self.file_new = os.path.join(canvasPicsDir, "doc.png")
39        self.outputPix = os.path.join(canvasPicsDir, "output.png")
40        self.file_open = os.path.join(canvasPicsDir, "open.png")
41        self.file_save = os.path.join(canvasPicsDir, "save.png")
42        if RedR:
43            self.reload_pic = os.path.join(canvasPicsDir, "update1.png")
44        self.text_icon = os.path.join(canvasPicsDir, "text.png")
45        self.file_print = os.path.join(canvasPicsDir, "print.png")
46        self.file_exit = os.path.join(canvasPicsDir, "exit.png")
47        canvasIconName = os.path.join(canvasPicsDir, "CanvasIcon.png")
48        if os.path.exists(canvasIconName):
49            self.setWindowIcon(QIcon(canvasIconName))
50           
51        self.settings = {}
52        if RedR:
53            self.settings['svnSettings'] = {}
54            self.settings['versionNumber'] = 'Version1.0'
55        self.menuSaveSettingsID = -1
56        self.menuSaveSettings = 1
57
58        self.loadSettings()
59        if RedR:
60            import updateRedR
61            self.settings['svnSettings'], self.settings['versionNumber'] = updateRedR.start(self.settings['svnSettings'], self.settings['versionNumber'])
62           
63#        self.widgetSelectedColor = QColor(*self.settings["widgetSelectedColor"])
64#        self.widgetActiveColor = QColor(*self.settings["widgetActiveColor"])
65#        self.lineColor = QColor(*self.settings["lineColor"])
66
67        # output window
68        self.output = orngOutput.OutputWindow(self)
69        self.output.catchException(1)
70        self.output.catchOutput(1)
71       
72        self.updateWidgetRegistry()
73
74        # create error and warning icons
75        informationIconName = os.path.join(canvasPicsDir, "information.png")
76        warningIconName = os.path.join(canvasPicsDir, "warning.png")
77        errorIconName = os.path.join(canvasPicsDir, "error.png")
78        if os.path.exists(errorIconName) and os.path.exists(warningIconName) and os.path.exists(informationIconName):
79            self.errorIcon = QPixmap(errorIconName)
80            self.warningIcon = QPixmap(warningIconName)
81            self.informationIcon = QPixmap(informationIconName)
82            self.widgetIcons = {"Info": self.informationIcon, "Warning": self.warningIcon, "Error": self.errorIcon}
83        else:
84            self.errorIcon = None
85            self.warningIcon = None
86            self.informationIcon = None
87            self.widgetIcons = None
88            print "Unable to load all necessary icons. Please reinstall Orange."
89
90        self.setStatusBar(MyStatusBar(self))
91       
92        self.updateStyle()
93       
94        # create toolbar
95        self.toolbar = self.addToolBar("Toolbar")
96        self.toolbar.setOrientation(Qt.Horizontal)
97#        self.toolbar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
98        if not self.settings.get("showToolbar", True):
99            self.toolbar.hide()
100       
101        # create a schema
102        self.schema = orngDoc.SchemaDoc(self)
103        self.setCentralWidget(self.schema)
104        self.schema.setFocus()
105
106        self.toolbar.addAction(QIcon(self.file_open), "Open schema", self.menuItemOpen)
107#        self.toolbar.addAction(QIcon(self.style().standardIcon(QStyle.SP_FileIcon)), "Open schema", self.menuItemOpen)
108        self.toolSave = self.toolbar.addAction(QIcon(self.file_save), "Save schema", self.menuItemSave)
109#        self.toolSave = self.toolbar.addAction(QIcon(self.style().standardIcon(QStyle.SP_DialogSaveButton)), "Save schema", self.menuItemSave)
110        if RedR:
111            self.toolReloadWidgets = self.toolbar.addAction(QIcon(self.reload_pic), "Reload Widgets", self.reloadWidgets)
112        self.toolbar.addSeparator()
113        self.toolbar.addAction(QIcon(self.file_print), "Print", self.menuItemPrinter)
114        self.toolbar.addSeparator()
115        w = QWidget()
116        w.setLayout(QHBoxLayout())
117       
118        items = ["Tool box", "Tree view", "Tree view (no icons)", "Tabs without labels", "Tabs with labels"]
119        ind = max(len(items) - 1, self.settings["widgetListType"])
120        self.widgetListTypeCB = OWGUI.comboBox(w, self.settings, "widgetListType", label="Style:", orientation="horizontal", items=items, callback=self.createWidgetsToolbar, debuggingEnabled=0)
121        self.widgetListTypeCB.setFocusPolicy(Qt.TabFocus)
122        self.toolbar.addWidget(w)
123       
124        self.toolbar.addSeparator()
125
126        w = QWidget()
127        w.setLayout(QHBoxLayout())
128        items = ["%d x %d" % (v, v) for v in self.toolbarIconSizeList]
129        self.settings["toolbarIconSize"] = min(len(items) - 1, self.settings["toolbarIconSize"])
130        cb = OWGUI.comboBoxWithCaption(w, self.settings, "toolbarIconSize", "Icon size:", items=items, tooltip="Set the size of the widget icons in the toolbar, tool box, and tree view area", callback=self.createWidgetsToolbar, debuggingEnabled=0)
131        cb.setFocusPolicy(Qt.TabFocus)
132       
133        self.toolbar.addWidget(w)
134       
135        self.freezeAction = self.toolbar.addAction("Freeze signals")
136        self.freezeAction.setCheckable(True)
137        self.freezeAction.setIcon(QIcon(self.style().standardIcon(QStyle.SP_MediaPause))) #self.schema_pause))
138       
139        def toogleSchemaFreeze(freeze):
140            self.freezeAction.setIcon(QIcon(self.style().standardIcon(QStyle.SP_MediaPlay if freeze else QStyle.SP_MediaPause))) #self.schema_pause))
141            self.schema.setFreeze(freeze)
142           
143        self.connect(self.freezeAction, SIGNAL("toggled(bool)"), toogleSchemaFreeze) #lambda bool: self.schema.setFreeze(bool))
144       
145        # Restore geometry before calling createWidgetsToolbar.
146        # On Mac OSX with unified title bar the canvas can move up on restarts
147        state = self.settings.get("CanvasMainWindowGeometry", None)
148        if state is not None:
149            state = self.restoreGeometry(QByteArray(state))
150            width, height = self.width(), self.height()
151       
152        if not state:
153            width, height = self.settings.get("canvasWidth", 700), self.settings.get("canvasHeight", 600)
154
155        # center window in the desktop
156        # on multiheaded desktops it it does not fit
157       
158        desktop = qApp.desktop()
159        space = desktop.availableGeometry(self)
160        geometry, frame = self.geometry(), self.frameGeometry()
161       
162        #Fit the frame size to fit in space
163        width = min(space.width() - (frame.width() - geometry.width()), geometry.width())
164        height = min(space.height() - (frame.height() - geometry.height()), geometry.height())
165       
166        self.resize(width, height)
167       
168        self.addToolBarBreak()
169        orngTabs.constructCategoriesPopup(self)
170        self.createWidgetsToolbar()
171        self.readShortcuts()
172       
173        def addOnRefreshCallback():
174            self.updateWidgetRegistry()
175            orngTabs.constructCategoriesPopup(self)
176            self.createWidgetsToolbar()
177        orngAddOns.addOnRefreshCallback.append(addOnRefreshCallback)
178
179        # create menu
180        self.initMenu()
181        self.readRecentFiles()
182
183       
184       
185        #move to center if frame not fully contained in space
186        if not space.contains(self.frameGeometry()):
187            x = max(0, space.width() / 2 - width / 2)
188            y = max(0, space.height() / 2 - height / 2)
189           
190            self.move(x, y)
191
192        self.helpWindow = orngHelp.HelpWindow(self)
193        self.reportWindow = OWReport.ReportWindow()
194        self.reportWindow.widgets = self.schema.widgets
195        self.reportWindow.saveDir = self.settings["reportsDir"]
196       
197
198        # did Orange crash the last time we used it? If yes, you will find a temSchema.tmp file
199        if not RedR:
200            if os.path.exists(os.path.join(self.canvasSettingsDir, "tempSchema.tmp")):
201                mb = QMessageBox('%s Canvas' % product, "Your previous %s Canvas session was not closed successfully.\nYou can choose to reload your unsaved work or start a new session.\n\nIf you choose 'Reload', the links will be disabled to prevent reoccurence of the crash.\nYou can enable them by clicking Options/Enable all links." % product, QMessageBox.Information, QMessageBox.Ok | QMessageBox.Default, QMessageBox.Cancel | QMessageBox.Escape, QMessageBox.NoButton)
202                mb.setButtonText(QMessageBox.Ok, "Reload")
203                mb.setButtonText(QMessageBox.Cancel, "New schema")
204                if mb.exec_() == QMessageBox.Ok:
205                    self.schema.loadDocument(os.path.join(self.canvasSettingsDir, "tempSchema.tmp"), freeze=1)
206       
207        if self.schema.widgets == [] and len(sys.argv) > 1 and os.path.exists(sys.argv[-1]) and os.path.splitext(sys.argv[-1])[1].lower() == ".ows":
208            self.schema.loadDocument(sys.argv[-1])
209       
210        # show message box if no numpy
211        qApp.processEvents()
212        try:
213            import numpy
214        except:
215            if QMessageBox.warning(self, '%s Canvas' % product, 'Several widgets now use numpy module, \nthat is not yet installed on this computer. \nDo you wish to download it?', QMessageBox.Ok | QMessageBox.Default, QMessageBox.Cancel | QMessageBox.Escape) == QMessageBox.Ok:
216                import webbrowser
217                webbrowser.open("http://sourceforge.net/projects/numpy/")
218
219    def updateWidgetRegistry(self):
220        """ Update the widget registry and add new category tabs to the
221        settings dict. 
222        """
223        # The default Widget tabs order
224        if not self.settings.has_key("WidgetTabs") or self.settings["WidgetTabs"] == []:
225            f = open(os.path.join(self.canvasDir, "WidgetTabs.txt"), "r")
226            defaultTabs = [c for c in [line.split("#")[0].strip() for line in f.readlines()] if c!=""]
227            for i in xrange(len(defaultTabs)-1,0,-1):
228                if defaultTabs[i] in defaultTabs[0:i]:
229                    del defaultTabs[i]
230            self.settings["WidgetTabs"] = [(name, Qt.Checked) for name in defaultTabs] + [("Prototypes", Qt.Unchecked)]
231           
232        widgetTabList = self.settings["WidgetTabs"]
233        self.widgetRegistry = orngRegistry.readCategories()
234       
235        extraTabs = [(name, 1) for name in self.widgetRegistry.keys() if name not in [tab for (tab, s) in widgetTabList]]
236        extraTabs = sorted(extraTabs)
237       
238        # Keep Prototypes as last in list
239        if widgetTabList[-1][0] == "Prototypes":
240            widgetTabList = widgetTabList[: -1] + extraTabs + widgetTabList[-1 :]
241        else:
242            widgetTabList = widgetTabList + extraTabs
243        self.settings["WidgetTabs"] = widgetTabList
244           
245    def createWidgetsToolbar(self):
246        if self.widgetsToolBar:
247            self.settings["showWidgetToolbar"] = self.widgetsToolBar.isVisible()
248            if isinstance(self.widgetsToolBar, QToolBar):
249                self.removeToolBar(self.widgetsToolBar)
250            elif isinstance(self.widgetsToolBar, orngTabs.WidgetToolBox):
251                self.settings["toolboxWidth"] = self.widgetsToolBar.toolbox.width()
252                self.removeDockWidget(self.widgetsToolBar)
253            elif isinstance(self.widgetsToolBar, orngTabs.WidgetTree):
254                self.settings["toolboxWidth"] = self.widgetsToolBar.treeWidget.width()
255                self.removeDockWidget(self.widgetsToolBar)
256           
257        if self.settings["widgetListType"] == 0:
258            self.tabs = self.widgetsToolBar = orngTabs.WidgetToolBox(self, self.widgetRegistry)
259            self.addDockWidget(Qt.LeftDockWidgetArea, self.widgetsToolBar)
260        elif self.settings["widgetListType"] in [1, 2]:
261            self.tabs = self.widgetsToolBar = orngTabs.WidgetTree(self, self.widgetRegistry)
262            self.addDockWidget(Qt.LeftDockWidgetArea, self.widgetsToolBar)
263        else:
264            if sys.platform == "darwin":
265                self.setUnifiedTitleAndToolBarOnMac(False)   
266            self.widgetsToolBar = self.addToolBar("Widgets")
267            self.insertToolBarBreak(self.widgetsToolBar)
268            self.tabs = orngTabs.WidgetTabs(self, self.widgetRegistry, self.widgetsToolBar)
269            self.widgetsToolBar.addWidget(self.tabs)
270           
271        if sys.platform == "darwin":
272            self.setUnifiedTitleAndToolBarOnMac(self.settings["widgetListType"] in [0, 1, 2] and self.settings["style"].lower() == "macintosh (aqua)")
273
274        # find widgets and create tab with buttons
275        self.tabs.createWidgetTabs(self.settings["WidgetTabs"], self.widgetRegistry, self.widgetDir, self.picsDir, self.defaultPic)
276        if not self.settings.get("showWidgetToolbar", True):
277            self.widgetsToolBar.hide()
278
279    def readShortcuts(self):
280        self.widgetShortcuts = {}
281        shfn = os.path.join(self.canvasSettingsDir, "shortcuts.txt")
282        if os.path.exists(shfn):
283            for t in file(shfn).readlines():
284                key, info = [x.strip() for x in t.split(":")]
285                if len(info) == 0: continue
286                if info[0] == "(" and info[-1] == ")":
287                    cat, widgetName = eval(info)            # new style of shortcuts are of form F: ("Data", "File")
288                else:
289                    cat, widgetName = info.split(" - ")   # old style of shortcuts are of form F: Data - File
290                if self.widgetRegistry.has_key(cat) and self.widgetRegistry[cat].has_key(widgetName):
291                    self.widgetShortcuts[key] = self.widgetRegistry[cat][widgetName]
292
293
294    def initMenu(self):
295        self.menuRecent = QMenu("Recent Schemas", self)
296
297        self.menuFile = QMenu("&File", self)
298        self.menuFile.addAction("New Scheme", self.menuItemNewScheme, QKeySequence.New)
299        self.menuFile.addAction(QIcon(self.file_open), "&Open...", self.menuItemOpen, QKeySequence.Open)
300        self.menuFile.addAction(QIcon(self.file_open), "&Open and Freeze...", self.menuItemOpenFreeze)
301        if RedR:
302            self.menuFile.addAction("Import Schema", self.importSchema)
303        if os.path.exists(os.path.join(self.canvasSettingsDir, "lastSchema.tmp")):
304            self.menuFile.addAction("Reload Last Schema", self.menuItemOpenLastSchema, Qt.CTRL + Qt.Key_R)
305        #self.menuFile.addAction( "&Clear", self.menuItemClear)
306        self.menuFile.addSeparator()
307        self.menuReportID = self.menuFile.addAction("&Report", self.menuItemReport, Qt.CTRL + Qt.ALT + Qt.Key_R)
308        self.menuFile.addSeparator()
309        self.menuSaveID = self.menuFile.addAction(QIcon(self.file_save), "&Save", self.menuItemSave, QKeySequence.Save)
310        self.menuSaveAsID = self.menuFile.addAction("Save &as...", self.menuItemSaveAs)
311        if not RedR:
312            self.menuFile.addAction("&Save as Application (Tabs)...", self.menuItemSaveAsAppTabs)
313            self.menuFile.addAction("&Save as Application (Buttons)...", self.menuItemSaveAsAppButtons)
314        self.menuFile.addSeparator()
315        self.menuFile.addAction(QIcon(self.file_print), "&Print Schema / Save image", self.menuItemPrinter, QKeySequence.Print)
316        self.menuFile.addSeparator()
317        self.menuFile.addMenu(self.menuRecent)
318        self.menuFile.addSeparator()
319        self.menuFile.addAction("E&xit", self.close, Qt.CTRL + Qt.Key_Q)
320
321        self.menuOptions = QMenu("&Options", self)
322        self.menuOptions.addAction("Enable All Links", self.menuItemEnableAll, Qt.CTRL + Qt.Key_E)
323        self.menuOptions.addAction("Disable All Links", self.menuItemDisableAll, Qt.CTRL + Qt.Key_D)
324        self.menuOptions.addSeparator()
325        self.menuOptions.addAction("Show Output Window", self.menuItemShowOutputWindow)
326        self.menuOptions.addAction("Clear Output Window", self.menuItemClearOutputWindow)
327        self.menuOptions.addAction("Save Output Text...", self.menuItemSaveOutputWindow)
328        if RedR:
329            self.menuOptions.addAction("Set to debug mode", self.setDebugMode)
330       
331        # uncomment this only for debugging
332#        self.menuOptions.addSeparator()
333#        self.menuOptions.addAction("Dump widget variables", self.dumpVariables)
334
335        self.menuOptions.addSeparator()
336#        self.menuOptions.addAction( "Channel preferences",  self.menuItemPreferences)
337        #self.menuOptions.addSeparator()
338        self.menuOptions.addAction("&Customize Shortcuts", self.menuItemEditWidgetShortcuts)
339        self.menuOptions.addAction("&Delete Widget Settings", self.menuItemDeleteWidgetSettings)
340        self.menuOptions.addSeparator()
341        self.menuOptions.addAction(sys.platform == "darwin" and "&Preferences..." or "Canvas &Options...", self.menuItemCanvasOptions)
342        self.menuOptions.addAction("&Add-ons...", self.menuItemAddOns)
343
344        localHelp = 0
345        self.menuHelp = QMenu("&Help", self)
346        if os.path.exists(os.path.join(self.orangeDir, r"doc/reference/default.htm")): self.menuHelp.addAction("Orange Help", self.menuOpenLocalOrangeHelp)
347        if os.path.exists(os.path.join(self.orangeDir, r"doc/catalog/index.html")): self.menuHelp.addAction("Orange Widget Catalog", self.menuOpenLocalWidgetCatalog)
348        if os.path.exists(os.path.join(self.orangeDir, r"doc/canvas/default.htm")): self.menuHelp.addAction("Orange Canvas Help", self.menuOpenLocalCanvasHelp)
349
350        self.menuHelp.addAction("Orange Online Widget Catalog", self.menuOpenOnlineOrangeHelp)
351        #self.menuHelp.addAction("Orange Canvas Online Help", self.menuOpenOnlineCanvasHelp)
352
353        if os.path.exists(os.path.join(self.orangeDir, r"updateOrange.py")):
354            self.menuHelp.addSeparator()
355            self.menuHelp.addAction("Check for updates", self.menuCheckForUpdates)
356           
357        self.menuHelp.addSeparator()
358        self.menuHelp.addAction("About Orange", self.menuItemAboutOrange)
359
360        # widget popup menu
361        self.widgetPopup = QMenu("Widget", self)
362        self.openActiveWidgetAction = self.widgetPopup.addAction("Open", self.schema.canvasView.openActiveWidget)
363        self.widgetPopup.addSeparator()
364        self.renameActiveWidgetAction = rename = self.widgetPopup.addAction("&Rename", self.schema.canvasView.renameActiveWidget, Qt.Key_F2)
365        self.removeActiveWidgetAction = delete = self.widgetPopup.addAction("Remove", self.schema.canvasView.removeActiveWidget, Qt.Key_Delete)
366        if sys.platform != "darwin":
367            delete.setShortcuts([Qt.Key_Delete, Qt.CTRL + Qt.Key_Backspace, Qt.CTRL + Qt.Key_Delete])
368        else:
369            delete.setShortcuts([Qt.CTRL + Qt.Key_Backspace, Qt.Key_Delete, Qt.CTRL + Qt.Key_Delete])
370        self.widgetPopup.addSeparator()
371        self.helpActiveWidgetAction = self.widgetPopup.addAction("Help", self.schema.canvasView.helpOnActiveWidget, Qt.Key_F1)
372        self.widgetPopup.setEnabled(0)
373       
374        if sys.platform == "darwin":
375            self.windowPopup = QMenu("Window", self)
376            self.windowPopup.addAction("Minimize", self.showMinimized, Qt.CTRL + Qt.Key_M)
377            self.windowPopup.addAction("Zoom", self.showMaximized, 0)
378
379        self.menuBar = QMenuBar(self)
380        self.menuBar.addMenu(self.menuFile)
381        self.menuBar.addMenu(self.menuOptions)
382        self.menuBar.addMenu(self.widgetPopup)
383       
384        if hasattr(self, "windowPopup"):
385            self.menuBar.addMenu(self.windowPopup)
386           
387        self.menuBar.addMenu(self.menuHelp)
388       
389        self.setMenuBar(self.menuBar)
390       
391    def setDebugMode(self):   # RedR specific
392        if self.output.debugMode:
393            self.output.debugMode = 0
394        else:
395            self.output.debugMode = 1
396    def importSchema(self):   # RedR specific
397        name = QFileDialog.getOpenFileName(self, "Import File", self.settings["saveSchemaDir"], "Orange Widget Scripts (*.ows)")
398        if name.isEmpty():
399            return
400        self.schema.clear()
401        self.schema.loadDocument(str(name), freeze = 0, importBlank = 1)
402        self.addToRecentMenu(str(name))
403   
404    def openSchema(self, filename):
405        if self.schema.isSchemaChanged() and self.schema.widgets:
406            ret = QMessageBox.warning(self, "Orange Canvas", "Changes to your present schema are not saved.\nSave them?",
407                                      QMessageBox.Save | QMessageBox.Discard | QMessageBox.Cancel, QMessageBox.Save)
408            if ret == QMessageBox.Save:
409                self.schema.saveDocument()
410            elif ret == QMessageBox.Cancel:
411                return
412        self.schema.clear()
413        dirname = os.path.dirname(filename)
414        os.chdir(dirname)
415        self.schema.loadDocument(filename)
416       
417    def menuItemOpen(self):
418        name = QFileDialog.getOpenFileName(self, "Open Orange Schema", self.settings["saveSchemaDir"], "Orange Widget Scripts (*.ows)")
419        if name.isEmpty():
420            return
421        self.schema.clear()
422        dirname = os.path.dirname(str(name))
423        os.chdir(dirname)
424        self.schema.loadDocument(str(name), freeze=0)
425        self.addToRecentMenu(str(name))
426
427    def menuItemOpenFreeze(self):
428        name = QFileDialog.getOpenFileName(self, "Open Orange Schema", self.settings["saveSchemaDir"], "Orange Widget Scripts (*.ows)")
429        if name.isEmpty():
430            return
431        self.schema.clear()
432        dirname = os.path.dirname(str(name))
433        os.chdir(dirname)
434        self.schema.loadDocument(str(name), freeze=1)
435        self.addToRecentMenu(str(name))
436
437    def menuItemOpenLastSchema(self):
438        fullName = os.path.join(self.canvasSettingsDir, "lastSchema.tmp")
439        if os.path.exists(fullName):
440            self.schema.loadDocument(fullName)
441
442    def menuItemReport(self):
443        self.schema.reportAll()
444       
445    def menuItemSave(self):
446        self.schema.saveDocument()
447       
448    def menuItemSaveAs(self):
449        self.schema.saveDocumentAs()
450
451    def menuItemSaveAsAppButtons(self):
452        self.schema.saveDocumentAsApp(asTabs=0)
453
454    def menuItemSaveAsAppTabs(self):
455        self.schema.saveDocumentAsApp(asTabs=1)
456
457    def menuItemPrinter(self):
458        try:
459            import OWDlgs
460            sizeDlg = OWDlgs.OWChooseImageSizeDlg(self.schema.canvas, defaultName=self.schema.schemaName or "schema", parent=self)
461            sizeDlg.exec_()
462        except:
463            print "Missing file 'OWDlgs.py'. This file should be in OrangeWidgets folder. Unable to print/save image."
464       
465
466    def readRecentFiles(self):
467        self.menuRecent.clear()
468        if not self.settings.has_key("RecentFiles"): return
469        recentDocs = self.settings["RecentFiles"]
470
471        # remove missing recent files
472        for i in range(len(recentDocs) - 1, -1, -1):
473            if not os.path.exists(recentDocs[i]):
474                recentDocs.remove(recentDocs[i])
475
476        recentDocs = recentDocs[:9]
477        self.settings["RecentFiles"] = recentDocs
478
479        for i in range(len(recentDocs)):
480            shortName = "&" + str(i + 1) + " " + os.path.basename(recentDocs[i])
481            self.menuRecent.addAction(shortName, lambda ind=i: self.openRecentFile(ind + 1))
482
483    def openRecentFile(self, index):
484        if len(self.settings["RecentFiles"]) >= index:
485            self.schema.clear()
486            name = self.settings["RecentFiles"][index - 1]
487            dirname = os.path.dirname(name)
488            os.chdir(dirname)
489            self.schema.loadDocument(name)
490            self.addToRecentMenu(name)
491
492    def addToRecentMenu(self, name):
493        recentDocs = []
494        if self.settings.has_key("RecentFiles"):
495            recentDocs = self.settings["RecentFiles"]
496
497        # convert to a valid file name
498        name = os.path.realpath(name)
499
500        if name in recentDocs:
501            recentDocs.remove(name)
502        recentDocs.insert(0, name)
503
504        if len(recentDocs) > 5:
505            recentDocs.remove(recentDocs[5])
506        self.settings["RecentFiles"] = recentDocs
507        self.readRecentFiles()
508
509    def menuItemSelectAll(self):
510        return
511
512    def updateSnapToGrid(self):
513        if self.settings["snapToGrid"]:
514            for widget in self.schema.widgets:
515                widget.setCoords(widget.x(), widget.y())
516            self.schema.canvas.update()
517
518    def menuItemEnableAll(self):
519        self.schema.enableAllLines()
520
521    def menuItemDisableAll(self):
522        self.schema.disableAllLines()
523
524    def menuItemSaveSettings(self):
525        self.menuSaveSettings = not self.menuSaveSettings
526        self.menuOptions.setItemChecked(self.menuSaveSettingsID, self.menuSaveSettings)
527
528    def menuItemNewScheme(self):
529        self.schema.clear()
530
531    def dumpVariables(self):
532        self.schema.dumpWidgetVariables()
533
534    def menuItemShowOutputWindow(self):
535        self.output.show()
536        self.output.raise_()
537        self.output.activateWindow()
538
539    def menuItemClearOutputWindow(self):
540        self.output.textOutput.clear()
541        self.statusBar().showMessage("")
542
543    def menuItemSaveOutputWindow(self):
544        qname = QFileDialog.getSaveFileName(self, "Save Output To File", self.canvasSettingsDir + "/Output.html", "HTML Document (*.html)")
545        if qname.isEmpty(): return
546        name = str(qname)
547
548        text = str(self.output.textOutput.toHtml())
549        #text = text.replace("</nobr>", "</nobr><br>")
550
551        file = open(name, "wt")
552        file.write(text)
553        file.close()
554
555
556    def menuItemShowToolbar(self):
557        self.settings["showToolbar"] = not self.settings.get("showToolbar", True)
558        if self.settings["showToolbar"]: self.toolbar.show()
559        else: self.toolbar.hide()
560
561    def menuItemShowWidgetToolbar(self):
562        self.settings["showWidgetToolbar"] = not self.settings.get("showWidgetToolbar", True)
563        if self.settings["showWidgetToolbar"]: self.widgetsToolBar.show()
564        else: self.widgetsToolBar.hide()
565
566
567    def menuItemEditWidgetShortcuts(self):
568        dlg = orngDlgs.WidgetShortcutDlg(self, self)
569        if dlg.exec_() == QDialog.Accepted:
570            self.widgetShortcuts = dict([(y, x) for x, y in dlg.invDict.items()])
571            shf = file(os.path.join(self.canvasSettingsDir, "shortcuts.txt"), "wt")
572            for k, widgetInfo in self.widgetShortcuts.items():
573                shf.write("%s: %s\n" % (k, (widgetInfo.category, widgetInfo.name)))
574
575    def menuItemDeleteWidgetSettings(self):
576        if QMessageBox.warning(self, 'Orange Canvas', 'Delete all settings?\nNote that for a complete reset there should be no open schema with any widgets.', QMessageBox.Ok | QMessageBox.Default, QMessageBox.Cancel | QMessageBox.Escape) == QMessageBox.Ok:
577            if os.path.exists(self.widgetSettingsDir):
578                for f in os.listdir(self.widgetSettingsDir):
579                    if os.path.splitext(f)[1].lower() == ".ini":
580                        os.remove(os.path.join(self.widgetSettingsDir, f))
581
582    def menuOpenLocalOrangeHelp(self):
583        import webbrowser
584        webbrowser.open("file:///" + os.path.join(self.orangeDir, "doc/reference/default.htm"))
585
586    def menuOpenLocalWidgetCatalog(self):
587        import webbrowser
588        webbrowser.open("file:///" + os.path.join(self.orangeDir, "doc/catalog/index.html"))
589
590    def menuOpenLocalCanvasHelp(self):
591        import webbrowser
592        webbrowser.open(os.path.join(self.orangeDir, "doc/canvas/default.htm"))
593
594    def menuOpenOnlineOrangeHelp(self):
595        import webbrowser
596        webbrowser.open("http://www.ailab.si/orange/doc/catalog")
597
598    def menuOpenOnlineCanvasHelp(self):
599        import webbrowser
600        #webbrowser.open("http://www.ailab.si/orange/orangeCanvas") # to be added on the web
601        webbrowser.open("http://www.ailab.si/orange")
602
603    def menuCheckForUpdates(self):
604        import updateOrange
605        self.updateDlg = updateOrange.updateOrangeDlg(None)#, Qt.WA_DeleteOnClose)
606
607    def menuItemAboutOrange(self):
608        dlg = orngDlgs.AboutDlg(self)
609        dlg.exec_()
610
611
612## to see the signals you have to call: self.output.catchException(0); self.output.catchOutput(0)
613## and run orngCanvas.pyw from command line using "python.exe orngCanvas.pyw"
614#    def event(self, e):
615#        eventDict = dict([(0, "None"), (130, "AccessibilityDescription"), (119, "AccessibilityHelp"), (86, "AccessibilityPrepare"), (114, "ActionAdded"), (113, "ActionChanged"), (115, "ActionRemoved"), (99, "ActivationChange"), (121, "ApplicationActivated"), (122, "ApplicationDeactivated"), (36, "ApplicationFontChange"), (37, "ApplicationLayoutDirectionChange"), (38, "ApplicationPaletteChange"), (35, "ApplicationWindowIconChange"), (68, "ChildAdded"), (69, "ChildPolished"), (71, "ChildRemoved"), (40, "Clipboard"), (19, "Close"), (82, "ContextMenu"), (52, "DeferredDelete"), (60, "DragEnter"), (62, "DragLeave"), (61, "DragMove"), (63, "Drop"), (98, "EnabledChange"), (10, "Enter"), (150, "EnterEditFocus"), (124, "EnterWhatsThisMode"), (116, "FileOpen"), (8, "FocusIn"), (9, "FocusOut"), (97, "FontChange"), (159, "GraphicsSceneContextMenu"), (164, "GraphicsSceneDragEnter"), (166, "GraphicsSceneDragLeave"), (165, "GraphicsSceneDragMove"), (167, "GraphicsSceneDrop"), (163, "GraphicsSceneHelp"), (160, "GraphicsSceneHoverEnter"), (162, "GraphicsSceneHoverLeave"), (161, "GraphicsSceneHoverMove"), (158, "GraphicsSceneMouseDoubleClick"), (155, "GraphicsSceneMouseMove"), (156, "GraphicsSceneMousePress"), (157, "GraphicsSceneMouseRelease"), (168, "GraphicsSceneWheel"), (18, "Hide"), (27, "HideToParent"), (127, "HoverEnter"), (128, "HoverLeave"), (129, "HoverMove"), (96, "IconDrag"), (101, "IconTextChange"), (83, "InputMethod"), (6, "KeyPress"), (7, "KeyRelease"), (89, "LanguageChange"), (90, "LayoutDirectionChange"), (76, "LayoutRequest"), (11, "Leave"), (151, "LeaveEditFocus"), (125, "LeaveWhatsThisMode"), (88, "LocaleChange"), (153, "MenubarUpdated"), (43, "MetaCall"), (102, "ModifiedChange"), (4, "MouseButtonDblClick"), (2, "MouseButtonPress"), (3, "MouseButtonRelease"), (5, "MouseMove"), (109, "MouseTrackingChange"), (13, "Move"), (12, "Paint"), (39, "PaletteChange"), (131, "ParentAboutToChange"), (21, "ParentChange"), (75, "Polish"), (74, "PolishRequest"), (123, "QueryWhatsThis"), (14, "Resize"), (117, "Shortcut"), (51, "ShortcutOverride"), (17, "Show"), (26, "ShowToParent"), (50, "SockAct"), (112, "StatusTip"), (100, "StyleChange"), (87, "TabletMove"), (92, "TabletPress"), (93, "TabletRelease"), (171, "TabletEnterProximity"), (172, "TabletLeaveProximity"), (1, "Timer"), (120, "ToolBarChange"), (110, "ToolTip"), (78, "UpdateLater"), (77, "UpdateRequest"), (111, "WhatsThis"), (118, "WhatsThisClicked"), (31, "Wheel"), (132, "WinEventAct"), (24, "WindowActivate"), (103, "WindowBlocked"), (25, "WindowDeactivate"), (34, "WindowIconChange"), (105, "WindowStateChange"), (33, "WindowTitleChange"), (104, "WindowUnblocked"), (126, "ZOrderChange"), (169, "KeyboardLayoutChange"), (170, "DynamicPropertyChange")])
616#        if eventDict.has_key(e.type()):
617#            print str(self.windowTitle()), eventDict[e.type()]
618#        return QMainWindow.event(self, e)
619
620
621    def menuItemCanvasOptions(self):
622        dlg = orngDlgs.CanvasOptionsDlg(self, self)
623
624        if dlg.exec_() == QDialog.Accepted:
625            if self.settings["snapToGrid"] != dlg.settings["snapToGrid"]:
626                self.updateSnapToGrid()
627
628            if self.settings["widgetListType"] != dlg.settings["widgetListType"]:
629                self.settings["widgetListType"] = dlg.settings["widgetListType"]
630                self.createWidgetsToolbar()
631                self.widgetListTypeCB.setCurrentIndex(self.settings["widgetListType"])
632            self.settings.update(dlg.settings)
633            self.updateStyle()
634           
635#            self.widgetSelectedColor = dlg.selectedWidgetIcon.color
636#            self.widgetActiveColor   = dlg.activeWidgetIcon.color
637#            self.lineColor           = dlg.lineIcon.color
638           
639            # update settings in widgets in current documents
640            for widget in self.schema.widgets:
641                widget.instance._useContexts = self.settings["useContexts"]
642                widget.instance._owInfo = self.settings["owInfo"]
643                widget.instance._owWarning = self.settings["owWarning"]
644                widget.instance._owError = self.settings["owError"]
645                widget.instance._owShowStatus = self.settings["owShow"]
646                widget.instance.updateStatusBarState()
647                widget.resetWidgetSize()
648                widget.updateWidgetState()
649               
650            # update tooltips for lines in all documents
651            for line in self.schema.lines:
652                line.showSignalNames = self.settings["showSignalNames"]
653                line.updateTooltip()
654           
655            self.schema.canvasView.repaint()
656       
657#            import orngEnviron, orngRegistry
658#            if dlg.toAdd != []:
659#                for (name, dir) in dlg.toAdd:
660#                    orngEnviron.registerAddOn(name, dir)
661           
662#            if dlg.toRemove != []:
663#                for (catName, cat) in dlg.toRemove:
664#                    addonsToRemove = set()
665#                    for widget in cat.values():
666#                        addonDir = widget.directory
667#                        while os.path.split(addonDir)[1] in ["prototypes", "widgets"]:
668#                            addonDir = os.path.split(addonDir)[0]
669#                        addonName = os.path.split(addonDir)[1]
670#                        addonsToRemove.add( (addonName, addonDir) )
671#                    for addonToRemove in addonsToRemove:
672#                        orngEnviron.registerAddOn(add=False, *addonToRemove)
673#           
674#            if dlg.toAdd != [] or dlg.toRemove != []:
675#                self.widgetRegistry = orngRegistry.readCategories()
676
677            # save tab order settings
678            newTabList = [(str(dlg.tabOrderList.item(i).text()), int(dlg.tabOrderList.item(i).checkState())) for i in range(dlg.tabOrderList.count())]
679            if newTabList != self.settings["WidgetTabs"]:
680                self.settings["WidgetTabs"] = newTabList
681                self.createWidgetsToolbar()
682                orngTabs.constructCategoriesPopup(self)
683
684    def menuItemAddOns(self):
685        dlg = orngDlgs.AddOnManagerDialog(self, self)
686        if dlg.exec_() == QDialog.Accepted:
687            for (id, addOn) in dlg.addOnsToRemove.items():
688                try:
689                    addOn.uninstall(refresh=False)
690                    if id in dlg.addOnsToAdd.items():
691                        orngAddOns.installAddOnFromRepo(dlg.addOnsToAdd[id], globalInstall=False, refresh=False)
692                        del dlg.addOnsToAdd[id]
693                except Exception, e:
694                    print "Problem %s add-on %s: %s" % ("upgrading" if id in dlg.addOnsToAdd else "removing", addOn.name, e)
695            for (id, addOn) in dlg.addOnsToAdd.items():
696                if id.startswith("registered:"):
697                    try:
698                        orngAddOns.registerAddOn(addOn.name, addOn.directory, refresh=False, systemWide=False)
699                    except Exception, e:
700                        print "Problem registering add-on %s: %s" % (addOn.name, e)
701                else:
702                    try:
703                        orngAddOns.installAddOnFromRepo(dlg.addOnsToAdd[id], globalInstall=False, refresh=False)
704                    except Exception, e:
705                        print "Problem installing add-on %s: %s" % (addOn.name, e)
706            if len(dlg.addOnsToAdd)+len(dlg.addOnsToRemove)>0:
707                orngAddOns.refreshAddOns(reloadPath=True)
708               
709                   
710
711    def updateStyle(self):
712        QApplication.setStyle(QStyleFactory.create(self.settings["style"]))
713#        qApp.setStyleSheet(" QDialogButtonBox { button-layout: 0; }")       # we want buttons to go in the "windows" direction (Yes, No, Cancel)
714        if self.settings["useDefaultPalette"]:
715            QApplication.setPalette(qApp.style().standardPalette())
716        else:
717            QApplication.setPalette(self.originalPalette)
718
719
720    def setStatusBarEvent(self, text):
721        if text == "" or text == None:
722            self.statusBar().showMessage("")
723            return
724        elif text == "\n": return
725        text = str(text)
726        text = text.replace("<nobr>", ""); text = text.replace("</nobr>", "")
727        text = text.replace("<b>", ""); text = text.replace("</b>", "")
728        text = text.replace("<i>", ""); text = text.replace("</i>", "")
729        text = text.replace("<br>", ""); text = text.replace("&nbsp", "")
730        self.statusBar().showMessage("Last event: " + str(text), 5000)
731
732    # Loads settings from the widget's .ini file
733    def loadSettings(self):
734        self.settings = {"widgetListType": 4, "iconSize": "40 x 40", "toolbarIconSize": 2, "toolboxWidth": 200, 'schemeIconSize': 1,
735                       "snapToGrid": 1, "writeLogFile": 1, "dontAskBeforeClose": 0, "saveWidgetsPosition": 1,
736#                       "widgetSelectedColor": (0, 255, 0), "widgetActiveColor": (0, 0, 255), "lineColor": (0, 255, 0),
737                       "reportsDir": self.defaultReportsDir, "saveSchemaDir": self.canvasSettingsDir, "saveApplicationDir": self.canvasSettingsDir,
738                       "showSignalNames": 1, "useContexts": 1, "enableCanvasDropShadows": 0,
739                       "canvasWidth": 700, "canvasHeight": 600, "useDefaultPalette": 0,
740                       "focusOnCatchException": 1, "focusOnCatchOutput": 0, "printOutputInStatusBar": 1, "printExceptionInStatusBar": 1,
741                       "outputVerbosity": 0, "synchronizeHelp": 1,
742                       "ocShow": 1, "owShow": 0, "ocInfo": 1, "owInfo": 1, "ocWarning": 1, "owWarning": 1, "ocError": 1, "owError": 1,
743                       }
744        if RedR:
745            self.setting.update({"svnSettings": None, "versionNumber": "Version0"})
746        try:
747            filename = os.path.join(self.canvasSettingsDir, "orngCanvas.ini")
748            self.settings.update(cPickle.load(open(filename, "rb")))
749        except:
750            pass
751
752        if not self.settings.has_key("style"):
753            items = [str(n) for n in QStyleFactory.keys()]
754            lowerItems = [str(n).lower() for n in QStyleFactory.keys()]
755            if sys.platform == "darwin" and qVersion() < "4.6": #On Mac OSX full aqua style isn't supported until Qt 4.6
756                currStyle = "cleanlooks"
757            else:
758                currStyle = str(qApp.style().objectName()).lower()
759            self.settings.setdefault("style", items[lowerItems.index(currStyle)])
760
761
762    # Saves settings to this widget's .ini file
763    def saveSettings(self):
764        filename = os.path.join(self.canvasSettingsDir, "orngCanvas.ini")
765        file = open(filename, "wb")
766        if self.settings["widgetListType"] == 1:        # tree view
767            self.settings["treeItemsOpenness"] = dict([(key, self.tabs.tabDict[key].isExpanded()) for key in self.tabs.tabDict.keys()])
768        cPickle.dump(self.settings, file)
769        file.close()
770
771    def closeEvent(self, ce):
772        # save the current width of the toolbox, if we are using it
773        if isinstance(self.widgetsToolBar, orngTabs.WidgetToolBox):
774            self.settings["toolboxWidth"] = self.widgetsToolBar.toolbox.width()
775        self.settings["showWidgetToolbar"] = self.widgetsToolBar.isVisible()
776        self.settings["showToolbar"] = self.toolbar.isVisible()
777        self.settings["reportsDir"] = self.reportWindow.saveDir
778
779        closed = self.schema.close()
780        if closed:
781            self.canvasIsClosing = 1        # output window (and possibly report window also) will check this variable before it will close the window
782            self.output.logFile.close()
783            self.output.hide()
784           
785            ce.accept()
786           
787            self.helpWindow.close()
788            self.reportWindow.close()
789        else:
790            ce.ignore()
791       
792        self.reportWindow.removeTemp()
793       
794        size = self.geometry().size()
795        self.settings["canvasWidth"] = size.width()
796        self.settings["canvasHeight"] = size.height()
797        self.settings["CanvasMainWindowGeometry"] = str(self.saveGeometry())
798       
799        self.saveSettings()
800       
801
802    def setCaption(self, caption=""):
803        if caption:
804            caption = caption.split(".")[0]
805            self.setWindowTitle(caption + " - %s Canvas" % product)
806        else:
807            self.setWindowTitle("%s Canvas" % product)
808   
809    def getWidgetIcon(self, widgetInfo):
810        if self.iconNameToIcon.has_key(widgetInfo.icon):
811            return self.iconNameToIcon[widgetInfo.icon]
812       
813        iconNames = self.getFullWidgetIconName(widgetInfo)
814        iconBackgrounds = self.getFullIconBackgroundName(widgetInfo)
815        icon = QIcon()
816        if len(iconNames) == 1:
817            iconSize = QPixmap(iconNames[0]).width()
818            iconBackgrounds = [name for name in iconBackgrounds if QPixmap(name).width() == iconSize]
819        for name, back in zip(iconNames, iconBackgrounds):
820            image = QPixmap(back).toImage()
821            painter = QPainter(image)
822            painter.drawPixmap(0, 0, QPixmap(name))
823            painter.end()
824            icon.addPixmap(QPixmap.fromImage(image))
825        if iconNames != [self.defaultPic]:
826            self.iconNameToIcon[widgetInfo.icon] = icon
827        return icon
828           
829   
830    def getFullWidgetIconName(self, widgetInfo):
831        iconName = widgetInfo.icon
832        names = []
833        name, ext = os.path.splitext(iconName)
834        for num in [16, 32, 40, 48, 60]:
835            names.append("%s_%d%s" % (name, num, ext))
836           
837        widgetDir = str(widgetInfo.directory)  #os.path.split(self.getFileName())[0]
838        fullPaths = []
839        for paths in [(self.widgetDir, widgetInfo.category), (self.widgetDir,), (self.picsDir,), tuple(), (widgetDir,), (widgetDir, "icons")]:
840            for name in names + [iconName]:
841                fname = os.path.join(*paths + (name,))
842                if os.path.exists(fname):
843                    fullPaths.append(fname)
844            if len(fullPaths) > 1 and fullPaths[-1].endswith(iconName):
845                fullPaths.pop()     # if we have the new icons we can remove the default icon
846            if fullPaths != []:
847                return fullPaths
848        return [self.defaultPic]
849   
850    def getFullIconBackgroundName(self, widgetInfo):
851        widgetDir = str(widgetInfo.directory)
852        fullPaths = []
853        for paths in [(widgetDir, "icons"), (self.widgetDir, widgetInfo.category, "icons"), (self.widgetDir, "icons"), (self.picsDir,), tuple(), (widgetDir,), (widgetDir, "icons")]:
854            for name in ["background_%d.png" % num for num in [16, 32, 40, 48, 60]]:
855                fname = os.path.join(*paths + (name,))
856#                print fname
857                if os.path.exists(fname):
858                    fullPaths.append(fname)
859            if fullPaths != []:
860                return fullPaths   
861        return [self.defaultBackground]
862   
863class MyStatusBar(QStatusBar):
864    def __init__(self, parent):
865        QStatusBar.__init__(self, parent)
866        self.parentWidget = parent
867
868    def mouseDoubleClickEvent(self, ev):
869        self.parentWidget.menuItemShowOutputWindow()
870       
871       
872class OrangeQApplication(QApplication):
873    def __init__(self, *args):
874        QApplication.__init__(self, *args)
875       
876    #QFileOpenEvent are Mac OSX only
877    if sys.platform == "darwin":
878        def event(self, event):
879            if event.type() == QEvent.FileOpen:
880                file = str(event.file())
881                def send():
882                    if hasattr(qApp, "canvasDlg"):
883                        qApp.canvasDlg.openSchema(file)
884                    else:
885                        QTimer.singleShot(100, send)
886                send()
887            return QApplication.event(self, event)
888       
889#    def notify(self, receiver, event):
890#        eventDict = {0: 'None', 1: 'Timer', 2: 'MouseButtonPress', 3: 'MouseButtonRelease', 4: 'MouseButtonDblClick', 5: 'MouseMove', 6: 'KeyPress', 7: 'KeyRelease', 8: 'FocusIn', 9: 'FocusOut', 10: 'Enter', 11: 'Leave', 12: 'Paint', 13: 'Move', 14: 'Resize', 17: 'Show', 18: 'Hide', 19: 'Close', 21: 'ParentChange', 24: 'WindowActivate', 25: 'WindowDeactivate', 26: 'ShowToParent', 27: 'HideToParent', 31: 'Wheel', 33: 'WindowTitleChange', 34: 'WindowIconChange', 35: 'ApplicationWindowIconChange', 36: 'ApplicationFontChange', 37: 'ApplicationLayoutDirectionChange', 38: 'ApplicationPaletteChange', 39: 'PaletteChange', 40: 'Clipboard', 43: 'MetaCall', 50: 'SockAct', 51: 'ShortcutOverride', 52: 'DeferredDelete', 60: 'DragEnter', 61: 'DragMove', 62: 'DragLeave', 63: 'Drop', 68: 'ChildAdded', 69: 'ChildPolished', 70: 'ChildInserted', 71: 'ChildRemoved', 74: 'PolishRequest', 75: 'Polish', 76: 'LayoutRequest', 77: 'UpdateRequest', 78: 'UpdateLater', 82: 'ContextMenu', 83: 'InputMethod', 86: 'AccessibilityPrepare', 87: 'TabletMove', 88: 'LocaleChange', 89: 'LanguageChange', 90: 'LayoutDirectionChange', 92: 'TabletPress', 93: 'TabletRelease', 94: 'OkRequest', 96: 'IconDrag', 97: 'FontChange', 98: 'EnabledChange', 99: 'ActivationChange', 100: 'StyleChange', 101: 'IconTextChange', 102: 'ModifiedChange', 103: 'WindowBlocked', 104: 'WindowUnblocked', 105: 'WindowStateChange', 109: 'MouseTrackingChange', 110: 'ToolTip', 111: 'WhatsThis', 112: 'StatusTip', 113: 'ActionChanged', 114: 'ActionAdded', 115: 'ActionRemoved', 116: 'FileOpen', 117: 'Shortcut', 118: 'WhatsThisClicked', 119: 'AccessibilityHelp', 120: 'ToolBarChange', 121: 'ApplicationActivate', 122: 'ApplicationDeactivate', 123: 'QueryWhatsThis', 124: 'EnterWhatsThisMode', 125: 'LeaveWhatsThisMode', 126: 'ZOrderChange', 127: 'HoverEnter', 128: 'HoverLeave', 129: 'HoverMove', 130: 'AccessibilityDescription', 131: 'ParentAboutToChange', 132: 'WinEventAct', 150: 'EnterEditFocus', 151: 'LeaveEditFocus', 153: 'MenubarUpdated', 155: 'GraphicsSceneMouseMove', 156: 'GraphicsSceneMousePress', 157: 'GraphicsSceneMouseRelease', 158: 'GraphicsSceneMouseDoubleClick', 159: 'GraphicsSceneContextMenu', 160: 'GraphicsSceneHoverEnter', 161: 'GraphicsSceneHoverMove', 162: 'GraphicsSceneHoverLeave', 163: 'GraphicsSceneHelp', 164: 'GraphicsSceneDragEnter', 165: 'GraphicsSceneDragMove', 166: 'GraphicsSceneDragLeave', 167: 'GraphicsSceneDrop', 168: 'GraphicsSceneWheel', 169: 'KeyboardLayoutChange', 170: 'DynamicPropertyChange', 171: 'TabletEnterProximity', 172: 'TabletLeaveProximity', 173: 'NonClientAreaMouseMove', 174: 'NonClientAreaMouseButtonPress', 175: 'NonClientAreaMouseButtonRelease', 176: 'NonClientAreaMouseButtonDblClick', 177: 'MacSizeChange', 178: 'ContentsRectChange', 181: 'GraphicsSceneResize', 182: 'GraphicsSceneMove', 183: 'CursorChange', 184: 'ToolTipChange', 186: 'GrabMouse', 187: 'UngrabMouse', 188: 'GrabKeyboard', 189: 'UngrabKeyboard'}
891#        import time
892#        try:
893#            if str(receiver.windowTitle()) != "":
894#                print time.strftime("%H:%M:%S"), "%15s" % str(receiver.windowTitle()) + ": ",      # print only events for QWidget classes and up
895#                if eventDict.has_key(event.type()):
896#                    print eventDict[event.type()]
897#                else:
898#                    print "unknown event name (" + str(event.type()) + ")"
899#        except:
900#            pass
901#            #print str(receiver.objectName()),
902#               
903#        return QApplication.notify(self, receiver, event)
904
905
906def main(argv=None):
907    if argv == None:
908        argv = sys.argv
909
910    app = OrangeQApplication(sys.argv)
911    dlg = OrangeCanvasDlg(app)
912    qApp.canvasDlg = dlg
913    dlg.show()
914    for arg in sys.argv[1:]:
915        if arg == "-reload":
916            dlg.menuItemOpenLastSchema()
917    app.exec_()
918    app.closeAllWindows()
919
920if __name__ == "__main__":
921    sys.exit(main())
Note: See TracBrowser for help on using the repository browser.