Fix bug on song saving

Add new screen for Plugin status
Add new presentation plugin code
This commit is contained in:
Tim Bentley 2009-08-13 21:02:38 +01:00
parent a684ecaa1e
commit 10ba1db5f3
7 changed files with 548 additions and 4 deletions

View File

@ -86,18 +86,22 @@ class PluginManager(object):
__import__(modulename, globals(), locals(), []) __import__(modulename, globals(), locals(), [])
except ImportError, e: except ImportError, e:
log.error(u'Failed to import module %s on path %s for reason %s', modulename, path, e.args[0]) log.error(u'Failed to import module %s on path %s for reason %s', modulename, path, e.args[0])
self.plugin_classes = Plugin.__subclasses__() plugin_classes = Plugin.__subclasses__()
self.plugins = [] self.plugins = []
self.plugin_list=[]
plugin_objects = [] plugin_objects = []
for p in self.plugin_classes: for p in plugin_classes:
try: try:
plugin = p(self.plugin_helpers) plugin = p(self.plugin_helpers)
log.debug(u'loaded plugin %s with helpers', unicode(p)) log.debug(u'loaded plugin %s with helpers', unicode(p))
log.debug(u'Plugin: %s', unicode(p)) log.debug(u'Plugin: %s', unicode(p))
pList = {u'name': plugin.name, u'version':plugin.version, u'status': u'Inactive'}
if plugin.check_pre_conditions(): if plugin.check_pre_conditions():
log.debug(u'Appending %s ', unicode(p)) log.debug(u'Appending %s ', unicode(p))
plugin_objects.append(plugin) plugin_objects.append(plugin)
eventmanager.register(plugin) eventmanager.register(plugin)
pList[u'status'] = u'Active'
self.plugin_list.append(pList)
except TypeError: except TypeError:
log.error(u'loaded plugin %s has no helpers', unicode(p)) log.error(u'loaded plugin %s has no helpers', unicode(p))
self.plugins = sorted(plugin_objects, self.order_by_weight) self.plugins = sorted(plugin_objects, self.order_by_weight)

View File

@ -27,6 +27,7 @@ from generaltab import GeneralTab
from themestab import ThemesTab from themestab import ThemesTab
from about import AboutForm from about import AboutForm
from alertform import AlertForm from alertform import AlertForm
from plugindialoglistform import PluginForm
from settingsform import SettingsForm from settingsform import SettingsForm
from servicemanager import ServiceManager from servicemanager import ServiceManager
from thememanager import ThemeManager from thememanager import ThemeManager

View File

@ -23,7 +23,8 @@ import logging
from PyQt4 import QtCore, QtGui from PyQt4 import QtCore, QtGui
from openlp.core.ui import AboutForm, SettingsForm, AlertForm, \ from openlp.core.ui import AboutForm, SettingsForm, AlertForm, \
ServiceManager, ThemeManager, MainDisplay, SlideController ServiceManager, ThemeManager, MainDisplay, SlideController, \
PluginForm
from openlp.core.lib import translate, Plugin, MediaManagerItem, \ from openlp.core.lib import translate, Plugin, MediaManagerItem, \
SettingsTab, EventManager, RenderManager, PluginConfig, \ SettingsTab, EventManager, RenderManager, PluginConfig, \
SettingsManager, PluginManager, EventType SettingsManager, PluginManager, EventType
@ -203,6 +204,14 @@ class Ui_MainWindow(object):
QtGui.QIcon.Normal, QtGui.QIcon.Off) QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.ToolsAlertItem.setIcon(AlertIcon) self.ToolsAlertItem.setIcon(AlertIcon)
self.ToolsAlertItem.setObjectName(u'ToolsAlertItem') self.ToolsAlertItem.setObjectName(u'ToolsAlertItem')
self.PluginItem = QtGui.QAction(MainWindow)
PluginIcon = QtGui.QIcon()
PluginIcon.addPixmap(QtGui.QPixmap(u':/tools/tools_alert.png'),
QtGui.QIcon.Normal, QtGui.QIcon.Off)
self.PluginItem.setIcon(AlertIcon)
self.PluginItem.setObjectName(u'PluginItem')
self.HelpDocumentationItem = QtGui.QAction(MainWindow) self.HelpDocumentationItem = QtGui.QAction(MainWindow)
ContentsIcon = QtGui.QIcon() ContentsIcon = QtGui.QIcon()
ContentsIcon.addPixmap(QtGui.QPixmap(u':/system/system_help_contents.png'), ContentsIcon.addPixmap(QtGui.QPixmap(u':/system/system_help_contents.png'),
@ -264,6 +273,7 @@ class Ui_MainWindow(object):
self.OptionsMenu.addSeparator() self.OptionsMenu.addSeparator()
self.OptionsMenu.addAction(self.OptionsSettingsItem) self.OptionsMenu.addAction(self.OptionsSettingsItem)
self.ToolsMenu.addAction(self.ToolsAlertItem) self.ToolsMenu.addAction(self.ToolsAlertItem)
self.ToolsMenu.addAction(self.PluginItem)
self.ToolsMenu.addSeparator() self.ToolsMenu.addSeparator()
self.ToolsMenu.addAction(self.ToolsAddToolItem) self.ToolsMenu.addAction(self.ToolsAddToolItem)
self.HelpMenu.addAction(self.HelpDocumentationItem) self.HelpMenu.addAction(self.HelpDocumentationItem)
@ -362,6 +372,12 @@ class Ui_MainWindow(object):
self.ToolsAlertItem.setStatusTip( self.ToolsAlertItem.setStatusTip(
translate(u'mainWindow', u'Show an alert message')) translate(u'mainWindow', u'Show an alert message'))
self.ToolsAlertItem.setShortcut(translate(u'mainWindow', u'F7')) self.ToolsAlertItem.setShortcut(translate(u'mainWindow', u'F7'))
self.PluginItem.setText(translate(u'mainWindow', u'&Plugin'))
self.PluginItem.setStatusTip(
translate(u'mainWindow', u'List the Plugins'))
self.PluginItem.setShortcut(translate(u'mainWindow', u'F8'))
self.HelpDocumentationItem.setText( self.HelpDocumentationItem.setText(
translate(u'mainWindow', u'&User Guide')) translate(u'mainWindow', u'&User Guide'))
self.HelpAboutItem.setText(translate(u'mainWindow', u'&About')) self.HelpAboutItem.setText(translate(u'mainWindow', u'&About'))
@ -408,6 +424,7 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
self.mainDisplay = MainDisplay(self, screens) self.mainDisplay = MainDisplay(self, screens)
self.generalConfig = PluginConfig(u'General') self.generalConfig = PluginConfig(u'General')
self.alertForm = AlertForm(self) self.alertForm = AlertForm(self)
self.pluginForm = PluginForm(self)
self.aboutForm = AboutForm() self.aboutForm = AboutForm()
self.settingsForm = SettingsForm(self.screenList, self) self.settingsForm = SettingsForm(self.screenList, self)
# Set up the path with plugins # Set up the path with plugins
@ -441,6 +458,8 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
QtCore.SIGNAL(u'triggered()'), self.onHelpAboutItemClicked) QtCore.SIGNAL(u'triggered()'), self.onHelpAboutItemClicked)
QtCore.QObject.connect(self.ToolsAlertItem, QtCore.QObject.connect(self.ToolsAlertItem,
QtCore.SIGNAL(u'triggered()'), self.onToolsAlertItemClicked) QtCore.SIGNAL(u'triggered()'), self.onToolsAlertItemClicked)
QtCore.QObject.connect(self.PluginItem,
QtCore.SIGNAL(u'triggered()'), self.onPluginItemClicked)
QtCore.QObject.connect(self.OptionsSettingsItem, QtCore.QObject.connect(self.OptionsSettingsItem,
QtCore.SIGNAL(u'triggered()'), self.onOptionsSettingsItemClicked) QtCore.SIGNAL(u'triggered()'), self.onOptionsSettingsItemClicked)
#warning cyclic dependency #warning cyclic dependency
@ -514,6 +533,13 @@ class MainWindow(QtGui.QMainWindow, Ui_MainWindow):
""" """
self.alertForm.exec_() self.alertForm.exec_()
def onPluginItemClicked(self):
"""
Show the Plugin form
"""
self.pluginForm.load()
self.pluginForm.exec_()
def onOptionsSettingsItemClicked(self): def onOptionsSettingsItemClicked(self):
""" """
Show the Settings dialog Show the Settings dialog

View File

@ -0,0 +1,76 @@
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'plugindialoglistform.ui'
#
# Created: Thu Aug 13 05:52:06 2009
# by: PyQt4 UI code generator 4.5.4
#
# WARNING! All changes made in this file will be lost!
import logging
from PyQt4 import QtCore, QtGui
from openlp.core.lib import translate
class PluginForm(QtGui.QDialog):
global log
log = logging.getLogger(u'PluginForm')
def __init__(self, parent=None):
QtGui.QDialog.__init__(self, None)
self.parent = parent
self.setupUi(self)
log.debug(u'Defined')
def setupUi(self, PluginViewDialog):
PluginViewDialog.setObjectName("PluginViewDialog")
PluginViewDialog.resize(400, 393)
self.PluginViewList = QtGui.QTableWidget(PluginViewDialog)
self.PluginViewList.setGeometry(QtCore.QRect(20, 10, 371, 331))
self.PluginViewList.setObjectName("PluginViewList")
self.PluginViewList.setShowGrid(False)
self.PluginViewList.setGridStyle(QtCore.Qt.SolidLine)
self.PluginViewList.setSortingEnabled(False)
self.PluginViewList.setColumnCount(3)
item = QtGui.QTableWidgetItem()
self.PluginViewList.setHorizontalHeaderItem(0, item)
item = QtGui.QTableWidgetItem()
self.PluginViewList.setHorizontalHeaderItem(1, item)
item = QtGui.QTableWidgetItem()
self.PluginViewList.setHorizontalHeaderItem(2, item)
self.PluginViewList.horizontalHeader().setVisible(True)
self.PluginViewList.verticalHeader().setVisible(False)
self.ButtonBox = QtGui.QDialogButtonBox(PluginViewDialog)
self.ButtonBox.setGeometry(QtCore.QRect(220, 350, 170, 25))
self.ButtonBox.setStandardButtons(QtGui.QDialogButtonBox.Ok)
self.ButtonBox.setObjectName("ButtonBox")
self.retranslateUi(PluginViewDialog)
QtCore.QObject.connect(self.ButtonBox, QtCore.SIGNAL("accepted()"), PluginViewDialog.close)
QtCore.QMetaObject.connectSlotsByName(PluginViewDialog)
def retranslateUi(self, PluginViewDialog):
PluginViewDialog.setWindowTitle(QtGui.QApplication.translate("PluginViewDialog", "Plugin list", None, QtGui.QApplication.UnicodeUTF8))
self.PluginViewList.horizontalHeaderItem(0).setText(QtGui.QApplication.translate("PluginViewDialog", "Name", None, QtGui.QApplication.UnicodeUTF8))
self.PluginViewList.horizontalHeaderItem(1).setText(QtGui.QApplication.translate("PluginViewDialog", "Version", None, QtGui.QApplication.UnicodeUTF8))
self.PluginViewList.horizontalHeaderItem(2).setText(QtGui.QApplication.translate("PluginViewDialog", "Status", None, QtGui.QApplication.UnicodeUTF8))
def load(self):
"""
Load the plugin details into the screen
"""
for plugin in self.parent.plugin_manager.plugin_list:
row = self.PluginViewList.rowCount()
self.PluginViewList.setRowCount(row + 1)
item1 = QtGui.QTableWidgetItem(plugin[u'name'])
item1.setTextAlignment(QtCore.Qt.AlignVCenter)
item2 = QtGui.QTableWidgetItem(plugin[u'version'])
item2.setTextAlignment(QtCore.Qt.AlignVCenter)
item3 = QtGui.QTableWidgetItem(plugin[u'status'])
item3.setTextAlignment(QtCore.Qt.AlignVCenter)
self.PluginViewList.setItem(row, 0, item1)
self.PluginViewList.setItem(row, 1, item2)
self.PluginViewList.setItem(row, 2, item3)
self.PluginViewList.setRowHeight(row, 15)

View File

@ -0,0 +1,329 @@
# -*- coding: utf-8 -*-
# vim: autoindent shiftwidth=4 expandtab textwidth=80 tabstop=4 softtabstop=4
"""
OpenLP - Open Source Lyrics Projection
Copyright (c) 2008 Raoul Snyman
Portions copyright (c) 2008-2009 Martin Thompson, Tim Bentley
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place, Suite 330, Boston, MA 02111-1307 USA
"""
# OOo API documentation:
# http://api.openoffice.org/docs/common/ref/com/sun/star/presentation/XSlideShowController.html
# http://docs.go-oo.org/sd/html/classsd_1_1SlideShow.html
# http://www.oooforum.org/forum/viewtopic.phtml?t=5252
# http://wiki.services.openoffice.org/wiki/Documentation/DevGuide/Working_with_Presentations
# http://mail.python.org/pipermail/python-win32/2008-January/006676.html
import os , subprocess
import time
import uno
from PyQt4 import QtCore, QtGui
from openlp.core.lib import OpenLPToolbar, translate
from openlp.core.ui.slidecontroller import MasterToolbar
class impressToolbar(MasterToolbar):
def __init__(self):
self.startOpenoffice()
self.isLive = True
def createResolver(self):
self.localContext = uno.getComponentContext()
self.resolver = self.localContext.ServiceManager.createInstanceWithContext(u'com.sun.star.bridge.UnoUrlResolver', self.localContext)
try:
self.ctx = self.resolver.resolve(u'uno:socket,host=localhost,port=2002;urp;StarOffice.ComponentContext')
except:
return False
return True
def buildEnvironment(self):
self.smgr = self.ctx.ServiceManager
self.desktop = self.smgr.createInstanceWithContext( "com.sun.star.frame.Desktop", self.ctx )
self.model = self.desktop.getCurrentComponent()
text = self.model.Text
cursor = text.createTextCursor()
text.insertString(cursor, "Hello world", 0)
self.ctx.ServiceManager
self.createApp()
if self._sm == None:
# start OO here
# Create output log file
time.sleep(10)
self.createApp()
def startOpenoffice(self):
cmd = u'openoffice.org -nologo -norestore -invisible -minimized -impress' + u'"' + u'-accept=socket,host=localhost,port=2002;urp;'+ u'"'
retval = subprocess.Popen(cmd, shell=True)
self.oopid = retval.pid
def checkOoPid(self):
if os.name == u'nt':
import win32api
handle = win32api.OpenProcess(PROCESS_TERMINATE, False, self.oopid)
#todo need some code here
return True
elif os.name == u'mac':
pass
else:
procfile = open("/proc/%d/stat" %(self.oopid))
file = procfile.readline().split()[1]
print file
if file == u'(soffice)' or file == u'(openoffice.org)':
return True
return False
def createApp(self):
try:
self._app = self._sm.createInstance( "com.sun.star.frame.Desktop" )
print "started"
except:
print "oops"
self._sm = None
self._app = None
return
def getApp(self):
if self._app == None:
self.createApp()
if self._app == None:
return None
return self._app
app = property(getApp)
def quit(self):
self._app.Terminate()
self._app = None
self._sm = None
def defineToolbar(self):
# Controller toolbar
self.Toolbar = OpenLPToolbar(self)
sizeToolbarPolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Fixed,
QtGui.QSizePolicy.Fixed)
sizeToolbarPolicy.setHorizontalStretch(0)
sizeToolbarPolicy.setVerticalStretch(0)
sizeToolbarPolicy.setHeightForWidth(
self.Toolbar.sizePolicy().hasHeightForWidth())
self.Toolbar.setSizePolicy(sizeToolbarPolicy)
if self.isLive:
self.Toolbar.addToolbarButton(u'First Slide',
u':/slides/slide_first.png',
translate(u'SlideController', u'Move to first'),
self.onSlideSelectedFirst)
self.Toolbar.addToolbarButton(u'Previous Slide',
u':/slides/slide_previous.png',
translate(u'SlideController', u'Move to previous'),
self.onSlideSelectedPrevious)
self.Toolbar.addToolbarButton(u'Next Slide',
u':/slides/slide_next.png',
translate(u'SlideController', u'Move to next'),
self.onSlideSelectedNext)
if self.isLive:
self.Toolbar.addToolbarButton(u'Last Slide',
u':/slides/slide_last.png',
translate(u'SlideController', u'Move to last'),
self.onSlideSelectedLast)
self.Toolbar.addSeparator()
self.Toolbar.addToolbarButton(u'Close Screen',
u':/slides/slide_close.png',
translate(u'SlideController', u'Close Screen'),
self.onBlankScreen)
def serviceLoaded(self):
"""
method to allow toolbars to know when the service item
is fully in place
"""
pass
def onSlideSelectedFirst(self):
"""
Go to the first slide.
"""
self.PreviewListWidget.selectRow(0)
self.onSlideSelected()
def onSlideSelectedNext(self):
"""
Go to the next slide.
"""
row = self.PreviewListWidget.currentRow() + 1
if row == self.PreviewListWidget.rowCount():
row = 0
self.PreviewListWidget.selectRow(row)
self.onSlideSelected()
def onSlideSelectedPrevious(self):
"""
Go to the previous slide.
"""
row = self.PreviewListWidget.currentRow() - 1
if row == -1:
row = self.PreviewListWidget.rowCount() - 1
self.PreviewListWidget.selectRow(row)
self.onSlideSelected()
def onSlideSelectedLast(self):
"""
Go to the last slide.
"""
self.PreviewListWidget.selectRow(self.PreviewListWidget.rowCount() - 1)
self.onSlideSelected()
def onBlankScreen(self):
"""
Blank the screen.
"""
self.mainDisplay.blankDisplay()
def onSlideSelected(self):
"""
Generate the preview when you click on a slide.
if this is the Live Controller also display on the screen
"""
row = self.PreviewListWidget.currentRow()
if row > -1 and row < self.PreviewListWidget.rowCount():
label = self.PreviewListWidget.cellWidget(row, 0)
smallframe = label.pixmap()
frame = self.serviceitem.frames[row][u'image']
self.SlidePreview.setPixmap(smallframe)
if self.isLive:
self.mainDisplay.frameView(frame)
def addServiceItem(self, serviceitem, slideno = 1):
"""
Loads a ServiceItem into the system from plugins
Display the first slide
"""
log.debug(u'add Service Item')
# serviceitem.render()
# self.addServiceManagerItem(serviceitem, 0)
def addServiceManagerItem(self, serviceitem, slideno):
"""
Loads a ServiceItem into the system from ServiceManager
Display the slide number passed
"""
log.debug(u'add Service Manager Item')
# self.PreviewListWidget.clear()
# self.PreviewListWidget.setRowCount(0)
# self.serviceitem = serviceitem
# framenumber = 0
# for frame in self.serviceitem.frames:
# self.PreviewListWidget.setRowCount(self.PreviewListWidget.rowCount() + 1)
# pixmap = QtGui.QPixmap.fromImage(frame[u'image'])
# item = QtGui.QTableWidgetItem()
# label = QtGui.QLabel()
# label.setMargin(15)
# label.setScaledContents(True)
# width = 300
# height = width * pixmap.height() / pixmap.width()
# label.setPixmap(pixmap)
# self.PreviewListWidget.setCellWidget(framenumber, 0,label)
# self.PreviewListWidget.setItem( framenumber, 0, item)
# self.PreviewListWidget.setRowHeight(framenumber, height)
# self.PreviewListWidget.setColumnWidth(0, width)
# framenumber += 1
# if slideno > self.PreviewListWidget.rowCount():
# self.PreviewListWidget.selectRow(self.PreviewListWidget.rowCount())
# else:
# self.PreviewListWidget.selectRow(slideno)
# self.onSlideSelected()
# self.serviceLoaded()
class ImpressCOMPres(object):
def __init__(self, oooApp, filename):
self.oooApp = oooApp
self.filename = filename
self.open()
def getPres(self):
if self._pres == None:
self.open()
return self._pres
pres = property(getPres)
def open(self):
self.comp = self.oooApp.app.loadComponentFromURL(u'file:///' + self.filename, '_blank', 0, [])
self.presdoc = self.comp.getPresentation()
self.presdoc.start()
self._pres = self.presdoc.getController()
def close(self):
self.pres.deactivate()
self.presdoc.end()
self.comp.dispose()
self._pres = None
self.presdoc = None
self.comp = None
def isActive(self):
return self.pres.isRunning() and self.pres.isActive()
def resume(self):
return self.pres.resume()
def pause(self):
return self.pres.pause()
def blankScreen(self):
self.pres.blankScreen(0)
def stop(self):
self.pres.deactivate()
# self.presdoc.end()
def go(self):
self.pres.activate()
# self.presdoc.start()
def getSlideNumber(self):
return self.pres.getCurrentSlideIndex
def setSlideNumber(self, slideno):
self.pres.gotoSlideIndex(slideno)
slideNumber = property(getSlideNumber, setSlideNumber)
def nextStep(self):
self.pres.gotoNextEffect()
def prevStep(self):
self.pres.gotoPreviousSlide()
def moveWindow(self, top, height, left, width):
# position the window somehow
pass
class ImpressCOMSlide(object):
def __init__(self, pres, index):
self.pres = pres
self.slide = pres.getSlideByIndex(index)
def preview(self):
if self.preview == None:
# get a slide somehow
pass
return self.preview
if __name__ == '__main__':
ooo = Openoffice()
ooo.createResolver()
#show = ImpressCOMPres(ooo, u'/home/timali/test1.odp')
#show.go()
#show.resume()
#show.nextStep()

View File

@ -356,7 +356,7 @@ class EditSongForm(QtGui.QDialog, Ui_EditSongDialog):
self.processTitle() self.processTitle()
self.songmanager.save_song(self.song) self.songmanager.save_song(self.song)
if self.title_change: if self.title_change:
self.eventmanager.post_event(Event(EventType.LoadSongList), u'EditSongForm') self.eventmanager.post_event(Event(EventType.LoadSongList, u'EditSongForm'))
self.close() self.close()
def processLyrics(self): def processLyrics(self):

View File

@ -0,0 +1,108 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PluginViewDialog</class>
<widget class="QWidget" name="PluginViewDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>393</height>
</rect>
</property>
<property name="windowTitle">
<string>Plugin list</string>
</property>
<widget class="QTableWidget" name="PluginViewList">
<property name="geometry">
<rect>
<x>20</x>
<y>10</y>
<width>371</width>
<height>331</height>
</rect>
</property>
<property name="showGrid">
<bool>false</bool>
</property>
<property name="gridStyle">
<enum>Qt::SolidLine</enum>
</property>
<property name="rowCount">
<number>1</number>
</property>
<attribute name="horizontalHeaderVisible">
<bool>true</bool>
</attribute>
<attribute name="horizontalHeaderShowSortIndicator" stdset="0">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
<row/>
<column>
<property name="text">
<string>Name</string>
</property>
</column>
<column>
<property name="text">
<string>Version</string>
</property>
</column>
<column>
<property name="text">
<string>Status</string>
</property>
</column>
<item row="0" column="0">
<property name="text">
<string>qqq</string>
</property>
</item>
<item row="0" column="1">
<property name="text">
<string>aaa</string>
</property>
</item>
<item row="0" column="2">
<property name="text">
<string>ccc</string>
</property>
</item>
</widget>
<widget class="QDialogButtonBox" name="ButtonBox">
<property name="geometry">
<rect>
<x>220</x>
<y>350</y>
<width>170</width>
<height>25</height>
</rect>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Ok</set>
</property>
</widget>
</widget>
<resources/>
<connections>
<connection>
<sender>ButtonBox</sender>
<signal>accepted()</signal>
<receiver>PluginViewDialog</receiver>
<slot>close()</slot>
<hints>
<hint type="sourcelabel">
<x>370</x>
<y>364</y>
</hint>
<hint type="destinationlabel">
<x>460</x>
<y>367</y>
</hint>
</hints>
</connection>
</connections>
</ui>