plugins.py
Go to the documentation of this file.
00001 #!/bin/env python
00002 
00003 from bwi_tools import getImageFileLocationFromMapFile as getImageFileLocation, loadMapFromFile
00004 from python_qt_binding.QtCore import Qt
00005 from python_qt_binding.QtGui import QFrame, QHBoxLayout, QImage, QLabel, QMessageBox, QPainter, QPushButton, \
00006                                     QVBoxLayout, QWidget
00007 from qt_gui.plugin import Plugin
00008 
00009 from .location_function import LocationFunction
00010 from .door_function import DoorFunction
00011 from .object_function import ObjectFunction
00012 from .utils import clearLayoutAndFixHeight, \
00013                    getDoorsFileLocationFromDataDirectory, \
00014                    getLocationsFileLocationFromDataDirectory, \
00015                    getObjectsFileLocationFromDataDirectory
00016 
00017 import rospy
00018 
00019 class MapImage(QLabel):
00020 
00021     def __init__(self, map_image_location, parent=None):
00022         super(MapImage, self).__init__(parent)
00023 
00024         # Image
00025         self.setFixedHeight(700)
00026         self.setFixedWidth(1300)
00027         self.setObjectName("map_image")
00028 
00029         # Set defaults to handle mouse events, as if these are not setup and a user clicks on the image, then all future
00030         # mouse events are ignored.
00031         self.enableDefaultMouseHooks()
00032 
00033         map_image = QImage(map_image_location)
00034         self.map_image = map_image.scaled(1300, 700, Qt.KeepAspectRatio)
00035 
00036         # Create a pixmap for the overlay. This will be modified by functions to change what is being displayed 
00037         # on the screen.
00038         self.overlay_image = QImage(self.map_image.size(), QImage.Format_ARGB32_Premultiplied) 
00039         self.overlay_image.fill(Qt.transparent)
00040 
00041         self.update()
00042 
00043     def defaultMouseHandler(self, event):
00044         # Do nothing.
00045         pass
00046 
00047     def enableDefaultMouseHooks(self):
00048         self.mousePressEvent = self.defaultMouseHandler
00049         self.mouseMoveEvent = self.defaultMouseHandler
00050         self.mouseReleaseEvent = self.defaultMouseHandler
00051 
00052     def paintEvent(self, event):
00053         painter = QPainter(self)
00054         painter.drawImage(event.rect(), self.map_image, event.rect())
00055         painter.drawImage(event.rect(), self.overlay_image, event.rect())
00056         painter.end()
00057 
00058 class LogicalMarkerPlugin(Plugin):
00059 
00060     def __init__(self, context):
00061         super(LogicalMarkerPlugin, self).__init__(context)
00062 
00063         # Create an image for the original map. This will never change.
00064         try:
00065             self.map_yaml_file_str = rospy.get_param("~map_file")
00066             self.data_directory = rospy.get_param("~data_directory")
00067         except KeyError:
00068             rospy.logfatal("~map_file and ~data_directory need to be set to use the logical marker")
00069             return
00070 
00071         map_image_location = getImageFileLocation(self.map_yaml_file_str)
00072         map = loadMapFromFile(self.map_yaml_file_str)
00073         locations_file = getLocationsFileLocationFromDataDirectory(self.data_directory)
00074         doors_file = getDoorsFileLocationFromDataDirectory(self.data_directory)
00075         objects_file = getObjectsFileLocationFromDataDirectory(self.data_directory)
00076 
00077         # Give QObjects reasonable names
00078         self.setObjectName('LogicalMarkerPlugin')
00079 
00080         # Create QWidget
00081         self.master_widget = QWidget()
00082         self.master_layout = QVBoxLayout(self.master_widget)
00083 
00084         # Main Functions - Doors, Locations, Objects
00085         self.function_layout = QHBoxLayout()
00086         self.master_layout.addLayout(self.function_layout)
00087         self.function_buttons = []
00088         self.current_function = None
00089         for button_text in ['Locations', 'Doors', 'Objects']:
00090             button = QPushButton(button_text, self.master_widget)
00091             button.clicked[bool].connect(self.handle_function_button)
00092             button.setCheckable(True)
00093             self.function_layout.addWidget(button)
00094             self.function_buttons.append(button)
00095         self.function_layout.addStretch(1)
00096 
00097         self.master_layout.addWidget(self.get_horizontal_line())
00098 
00099         # Subfunction toolbar
00100         self.subfunction_layout = QHBoxLayout()
00101         clearLayoutAndFixHeight(self.subfunction_layout)
00102         self.master_layout.addLayout(self.subfunction_layout)
00103         self.current_subfunction = None
00104 
00105         self.master_layout.addWidget(self.get_horizontal_line())
00106 
00107         self.image = MapImage(map_image_location, self.master_widget)
00108         self.master_layout.addWidget(self.image)
00109 
00110         self.master_layout.addWidget(self.get_horizontal_line())
00111 
00112         # Configuration toolbar
00113         self.configuration_layout = QHBoxLayout()
00114         clearLayoutAndFixHeight(self.configuration_layout)
00115         self.master_layout.addLayout(self.configuration_layout)
00116 
00117         # Add a stretch at the bottom.
00118         self.master_layout.addStretch(1)
00119 
00120         self.master_widget.setObjectName('LogicalMarkerPluginUI')
00121         if context.serial_number() > 1:
00122             self.master_widget.setWindowTitle(self.master_widget.windowTitle() + (' (%d)' % context.serial_number()))
00123         context.add_widget(self.master_widget)
00124 
00125 
00126         # Activate the functions
00127         self.functions = {}
00128         self.functions['Locations'] = LocationFunction(locations_file,
00129                                                        map,
00130                                                        self.master_widget, 
00131                                                        self.subfunction_layout, 
00132                                                        self.configuration_layout,
00133                                                        self.image)
00134         self.functions['Doors'] = DoorFunction(doors_file,
00135                                                map,
00136                                                self.functions['Locations'],
00137                                                self.master_widget, 
00138                                                self.subfunction_layout, 
00139                                                self.configuration_layout,
00140                                                self.image)
00141         self.functions['Objects'] = ObjectFunction(objects_file,
00142                                                    map,
00143                                                    self.functions['Locations'],
00144                                                    self.master_widget, 
00145                                                    self.subfunction_layout, 
00146                                                    self.configuration_layout,
00147                                                    self.image)
00148     def construct_layout(self):
00149         pass
00150 
00151     def get_horizontal_line(self):
00152         """
00153         http://stackoverflow.com/questions/5671354/how-to-programmatically-make-a-horizontal-line-in-qt
00154         """
00155         hline = QFrame()
00156         hline.setFrameShape(QFrame.HLine)
00157         hline.setFrameShadow(QFrame.Sunken)
00158         return hline
00159 
00160     def handle_function_button(self):
00161         source = self.sender()
00162 
00163         if source.text() == self.current_function:
00164             source.setChecked(True)
00165             return
00166 
00167         # Depress all other buttons.
00168         for button in self.function_buttons:
00169             if button != source:
00170                 button.setChecked(False)
00171 
00172         if self.current_function is not None:
00173             self.functions[self.current_function].deactivateFunction()
00174         self.current_function = source.text()
00175 
00176         # Clear all subfunction buttons.
00177         clearLayoutAndFixHeight(self.subfunction_layout)
00178 
00179         if self.current_function is not None:
00180             self.functions[self.current_function].activateFunction()
00181 
00182     def shutdown_plugin(self):
00183         modified = False
00184         for function in self.functions:
00185             if self.functions[function].isModified():
00186                 modified = True
00187         if modified:
00188             ret = QMessageBox.warning(self.master_widget, "Save",
00189                         "The logical map has been modified.\n"
00190                         "Do you want to save your changes?",
00191                         QMessageBox.Save | QMessageBox.Discard)
00192             if ret == QMessageBox.Save:
00193                 for function in self.functions:
00194                     self.functions[function].saveConfiguration()
00195 
00196     def save_settings(self, plugin_settings, instance_settings):
00197         pass
00198 
00199     def restore_settings(self, plugin_settings, instance_settings):
00200         pass


bwi_planning_common
Author(s): Piyush Khandelwal
autogenerated on Thu Jun 6 2019 17:57:32