def __init__(self, scene, x, y, caption, answers, done_cb, parent=None): self.w = 0 self.h = 0 super(DialogItem, self).__init__(scene, x, y, parent=parent) self.sp = self.m2pix(0.01) self.done_cb = done_cb self.fixed = False self.desc = DescItem(scene, 0, 0, self) self.desc.set_content(caption) self.items = [] self.w = (len(answers) + 1) * self.sp for answer in answers: btn = ButtonItem(self.scene(), 0, 0, answer, self, self.answer_cb) self.items.append(btn) self.w += btn._width() y = self.sp self._place_childs_horizontally(y, self.sp, [self.desc]) y += self.desc._height() + self.sp self._place_childs_horizontally(y, self.sp, self.items) y += self.items[0]._height() y += self.sp self.h = y self.update() self.setZValue(300)
def __init__(self, scene, x, y, w, data, item_selected_cb=None, parent=None): self.w = 100 self.h = 100 self.sp = 0 self.item_selected_cb = item_selected_cb super(ListItem, self).__init__(scene, x, y, parent) self.w = self.m2pix(w) self.h = self.m2pix(0.2) self.sp = self.m2pix(0.005) self.items = [] self.middle_item_idx = 0 self.selected_item_idx = None for d in data: self.items.append(ButtonItem(self.scene(), 0, 0, d, self, self.item_clicked_cb, width=w, push_button=True)) rospack = rospkg.RosPack() icons_path = rospack.get_path('art_projected_gui') + '/icons/' self.up_btn = ButtonItem(self.scene(), 0, 0, translate( "ProgramItem", "Up"), self, self.up_btn_cb, width=w, image_path=icons_path + "arrow-up.svg") self.down_btn = ButtonItem(self.scene(), 0, 0, translate( "ProgramItem", "Down"), self, self.down_btn_cb, width=w, image_path=icons_path + "arrow-down.svg") self.up_btn.setPos(0, 0) self.down_btn.setPos(0, self.h - self.down_btn.boundingRect().height()) self.set_current_idx(min(1, len(self.items) - 1)) self.update()
def __init__(self, scene, x, y, caption, answers, done_cb, parent=None): self.w = 0 self.h = 0 super(DialogItem, self).__init__(scene, x, y, parent=parent) self.sp = self.m2pix(0.01) self.done_cb = done_cb self.fixed = False self.desc = DescItem(scene, 0, 0, self) self.desc.set_content(caption, color=QtCore.Qt.white) self.items = [] for answer in answers: btn = ButtonItem(self.scene(), 0, 0, answer, self, self.answer_cb) self.items.append(btn) self.w = max(self.desc.boundingRect().width(), sum(btn.boundingRect().width() for btn in self.items)) + 2 * self.sp y = self.sp self._place_childs_horizontally(y, self.sp, [self.desc]) y += self.desc._height() + self.sp self._place_childs_horizontally(y, self.sp, self.items) y += self.items[0]._height() y += self.sp self.h = y self.setFlag(QtGui.QGraphicsItem.ItemIsMovable, True) self.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, True) self.update() self.setZValue(300)
def set_prog(self, prog, template): self.prog = prog self.template = template self.items = [] self.active_item = None cnt = 0 max_w = 0 # TODO Handle program groups - create ProgramGroupItem class and allow switching between groups. For now, let's assume that there will always be just one group for pitem in self.prog.blocks[0].items: if self.template: # to make sure that template is 'clear' pitem.object = "" del pitem.pick_polygon.polygon.points[:] pitem.place_pose.pose.position.x = 0 pitem.place_pose.pose.position.y = 0 pitem.place_pose.pose.position.z = 0 # TODO how to place items easily? using some layout?? self.items.append(ProgramItemItem(self.scene(), self.rpm, 0, 0, pitem, self, self.item_selected_cb)) if len(self.items) < 2: self.items[-1].setPos(30, 20) else: self.items[-1].setPos(30, 10 + self.items[-2].y() + self.items[-2].h) if self.items[-1].w > max_w: max_w = self.items[-1].w cnt += 1 # set first item as active if (self.active_item is None) and self.items[-1].item_req_learning(): self.set_active(self.items[-1]) # if pitem.type in self.items_req_learning: # if self.active_item is None: self.active_item = pitem self.btn = ButtonItem(self.scene(), self.rpm, 0, 0, translate("ProgramItem", "Start"), self, self.btn_clicked) self.btn.setPos(10, 5 + cnt * 50) self.btn.set_enabled(False) # TODO najit max. sirku itemu a tomu prizpusobit sirku programu self.h = 20 + cnt * 50 + 30 self.w = max_w + 40 self.update()
def __init__(self, scene, x, y, w, data, item_selected_cb=None, parent=None): self.w = 100 self.h = 100 self.sp = 0 self.item_selected_cb = item_selected_cb super(ListItem, self).__init__(scene, x, y, parent=parent) self.w = self.m2pix(w) self.h = self.m2pix(0.2) self.sp = self.m2pix(0.005) self.items = [] self.middle_item_idx = 0 self.selected_item_idx = None for d in data: self.items.append(ButtonItem(self.scene(), 0, 0, d, self, self.item_clicked_cb, width=w, push_button=True)) # TODO down_btn is not properly aligned self.up_btn = ButtonItem(self.scene(), 0, 0, "", self, self.up_btn_cb, width=w / 2 - 0.005 / 2, image_path=icons_path + "arrow-up.svg") self.down_btn = ButtonItem(self.scene(), 0, 0, "", self, self.down_btn_cb, width=w / 2 - 0.005 / 2, image_path=icons_path + "arrow-down.svg") self.up_btn.setPos(0, self.h - self.down_btn.boundingRect().height()) self.down_btn.setPos(self.up_btn.boundingRect().width() + self.sp, self.h - self.down_btn.boundingRect().height()) self.set_current_idx(min(1, len(self.items) - 1)) self.update()
def __init__(self, scene, x, y, program_headers, learned_dict, selected_program_id=None, program_selected_cb=None): self.w = 100 self.h = 100 self.program_headers = program_headers self.learned_dict = learned_dict self.program_selected_cb = program_selected_cb super(ProgramListItem, self).__init__(scene, x, y) self.w = self.m2pix(0.2) self.h = self.m2pix(0.25) self.fixed = False self.setZValue(100) data = [] self.map_from_idx_to_program_id = {} self.map_from_program_id_to_idx = {} for ph in self.program_headers: data.append("ID: " + str(ph.id) + "\nName: " + ph.name) idx = len(data) - 1 self.map_from_idx_to_program_id[idx] = ph.id self.map_from_program_id_to_idx[ph.id] = idx self.list = ListItem(scene, 0, 0, 0.2 - 2 * 0.005, data, self.item_selected_cb, parent=self) for idx in range(0, len(data)): if not self.learned_dict[self.map_from_idx_to_program_id[idx]]: self.list.items[idx].set_background_color(QtCore.Qt.red) self.run_btn = ButtonItem(scene, 0, 0, translate("ProgramItem", "Run"), self, self.run_btn_cb) self.edit_btn = ButtonItem(scene, 0, 0, translate("ProgramItem", "Edit"), self, self.edit_btn_cb) self.template_btn = ButtonItem(scene, 0, 0, translate("ProgramItem", "Template"), self, self.template_btn_cb) self.run_btn.set_enabled(False) self.edit_btn.set_enabled(False) self.template_btn.set_enabled(False) if selected_program_id is not None: self.list.set_current_idx( self.map_from_program_id_to_idx[selected_program_id]) sp = self.m2pix(0.005) h = 50 self.list.setPos(sp, h) h += self.list._height() h += 2 * sp self._place_childs_horizontally( h, sp, [self.run_btn, self.edit_btn, self.template_btn]) h += self.run_btn._height() h += 3 * sp self.h = h self.update()
class ProgramListItem(Item): def __init__(self, scene, x, y, program_headers, learned_dict, selected_program_id=None, program_selected_cb=None): self.w = 100 self.h = 100 self.program_headers = program_headers self.learned_dict = learned_dict self.program_selected_cb = program_selected_cb super(ProgramListItem, self).__init__(scene, x, y) self.w = self.m2pix(0.2) self.h = self.m2pix(0.25) self.fixed = False self.setZValue(100) data = [] self.map_from_idx_to_program_id = {} self.map_from_program_id_to_idx = {} for ph in self.program_headers: data.append("ID: " + str(ph.id) + "\nName: " + ph.name) idx = len(data) - 1 self.map_from_idx_to_program_id[idx] = ph.id self.map_from_program_id_to_idx[ph.id] = idx self.list = ListItem(scene, 0, 0, 0.2 - 2 * 0.005, data, self.item_selected_cb, parent=self) for idx in range(0, len(data)): if not self.learned_dict[self.map_from_idx_to_program_id[idx]]: self.list.items[idx].set_background_color(QtCore.Qt.red) self.run_btn = ButtonItem(scene, 0, 0, translate("ProgramItem", "Run"), self, self.run_btn_cb) self.edit_btn = ButtonItem(scene, 0, 0, translate("ProgramItem", "Edit"), self, self.edit_btn_cb) self.template_btn = ButtonItem(scene, 0, 0, translate("ProgramItem", "Template"), self, self.template_btn_cb) self.run_btn.set_enabled(False) self.edit_btn.set_enabled(False) self.template_btn.set_enabled(False) if selected_program_id is not None: self.list.set_current_idx( self.map_from_program_id_to_idx[selected_program_id]) sp = self.m2pix(0.005) h = 50 self.list.setPos(sp, h) h += self.list._height() h += 2 * sp self._place_childs_horizontally( h, sp, [self.run_btn, self.edit_btn, self.template_btn]) h += self.run_btn._height() h += 3 * sp self.h = h self.update() def item_selected_cb(self): if self.list.selected_item_idx is None: self.run_btn.set_enabled(False) self.edit_btn.set_enabled(False) self.template_btn.set_enabled(False) else: pid = self.map_from_idx_to_program_id[self.list.selected_item_idx] self.run_btn.setEnabled(self.learned_dict[pid]) self.edit_btn.set_enabled(True) self.template_btn.set_enabled(True) def get_current_header(self): return self.program_headers[self.list.selected_item_idx] def run_btn_cb(self, btn): if self.program_selected_cb is not None: self.program_selected_cb(self.get_current_header().id, run=True) def edit_btn_cb(self, btn): if self.program_selected_cb is not None: self.program_selected_cb(self.get_current_header().id) def template_btn_cb(self, btn): if self.program_selected_cb is not None: self.program_selected_cb(self.get_current_header().id, template=True) def boundingRect(self): return QtCore.QRectF(0, 0, self.w, self.h) def paint(self, painter, option, widget): if not self.scene(): return painter.setClipRect(option.exposedRect) painter.setRenderHint(QtGui.QPainter.Antialiasing) font = QtGui.QFont('Arial', 14) painter.setFont(font) painter.setPen(QtCore.Qt.white) sp = self.m2pix(0.01) painter.drawText(sp, 2 * sp, translate("ProgramListItem", "Program list")) pen = QtGui.QPen() pen.setStyle(QtCore.Qt.NoPen) painter.setPen(pen) painter.setBrush(QtCore.Qt.gray) painter.setOpacity(0.5) painter.drawRoundedRect(QtCore.QRect(0, 0, self.w, self.h), 5.0, 5.0)
class ListItem(Item): def __init__(self, scene, x, y, w, data, item_selected_cb=None, parent=None): self.w = 100 self.h = 100 self.sp = 0 self.item_selected_cb = item_selected_cb super(ListItem, self).__init__(scene, x, y, parent=parent) self.w = self.m2pix(w) self.h = self.m2pix(0.2) self.sp = self.m2pix(0.005) self.items = [] self.middle_item_idx = 0 self.selected_item_idx = None for d in data: self.items.append(ButtonItem(self.scene(), 0, 0, d, self, self.item_clicked_cb, width=w, push_button=True)) # TODO down_btn is not properly aligned self.up_btn = ButtonItem(self.scene(), 0, 0, "", self, self.up_btn_cb, width=w / 2 - 0.005 / 2, image_path=icons_path + "arrow-up.svg") self.down_btn = ButtonItem(self.scene(), 0, 0, "", self, self.down_btn_cb, width=w / 2 - 0.005 / 2, image_path=icons_path + "arrow-down.svg") self.up_btn.setPos(0, self.h - self.down_btn.boundingRect().height()) self.down_btn.setPos(self.up_btn.boundingRect().width() + self.sp, self.h - self.down_btn.boundingRect().height()) self.set_current_idx(min(1, len(self.items) - 1)) self.update() def item_clicked_cb(self, btn): if not self.isEnabled(): return if not btn.pressed: self.selected_item_idx = None else: self.selected_item_idx = self.items.index(btn) for i in range(0, len(self.items)): if i != self.selected_item_idx: self.items[i].set_pressed(False) self.set_current_idx(self.selected_item_idx) if self.item_selected_cb is not None: self.item_selected_cb() def get_current_idx(self): return self.middle_item_idx def set_current_idx(self, idx, select=False): if select: self.selected_item_idx = idx self.middle_item_idx = max(idx, min(1, len(self.items) - 1)) for it in self.items: it.setVisible(False) if select: it.set_pressed(False) displayed = [self.middle_item_idx] # selected item is always vertically centered self.items[self.middle_item_idx].setPos( 0, (self.h - self.items[self.middle_item_idx].boundingRect().height()) / 2) self.items[self.middle_item_idx].setVisible(True) if select: self.items[self.selected_item_idx].set_pressed(True) # how much vert. space is used vspace = self.items[self.middle_item_idx].boundingRect().height() # fill space above middle item for idx in range(self.middle_item_idx - 1, -1, -1): h = self.items[idx].boundingRect().height() y = self.items[idx + 1].y() - self.sp - h if y < 0: break self.items[idx].setPos(0, y) self.items[idx].setVisible(True) displayed.append(idx) vspace += self.sp + h displayed.append(idx) # fill space below middle item for idx in range(self.middle_item_idx + 1, len(self.items)): h = self.items[idx].boundingRect().height() y = self.items[idx - 1].y() + self.items[idx - 1].boundingRect().height() + self.sp if y + h > self.down_btn.y(): break self.items[idx].setPos(0, y) self.items[idx].setVisible(True) vspace += self.sp + h displayed.append(idx) if self.isEnabled(): self.up_btn.set_enabled(min(displayed) > 0) self.down_btn.set_enabled(max(displayed) < len(self.items) - 1) def up_btn_cb(self, btn): if self.middle_item_idx > 0: self.set_current_idx(self.middle_item_idx - 1) def down_btn_cb(self, btn): if self.middle_item_idx < len(self.items) - 1: self.set_current_idx(self.middle_item_idx + 1) def boundingRect(self): return QtCore.QRectF(0, 0, self.w, self.h) def paint(self, painter, option, widget): pass
class ListItem(Item): def __init__(self, scene, x, y, w, data, item_selected_cb=None, parent=None): self.w = 100 self.h = 100 self.sp = 0 self.item_selected_cb = item_selected_cb super(ListItem, self).__init__(scene, x, y, parent) self.w = self.m2pix(w) self.h = self.m2pix(0.2) self.sp = self.m2pix(0.005) self.items = [] self.middle_item_idx = 0 self.selected_item_idx = None for d in data: self.items.append(ButtonItem(self.scene(), 0, 0, d, self, self.item_clicked_cb, width=w, push_button=True)) rospack = rospkg.RosPack() icons_path = rospack.get_path('art_projected_gui') + '/icons/' self.up_btn = ButtonItem(self.scene(), 0, 0, translate( "ProgramItem", "Up"), self, self.up_btn_cb, width=w, image_path=icons_path + "arrow-up.svg") self.down_btn = ButtonItem(self.scene(), 0, 0, translate( "ProgramItem", "Down"), self, self.down_btn_cb, width=w, image_path=icons_path + "arrow-down.svg") self.up_btn.setPos(0, 0) self.down_btn.setPos(0, self.h - self.down_btn.boundingRect().height()) self.set_current_idx(min(1, len(self.items) - 1)) self.update() def item_clicked_cb(self, btn): if not self.isEnabled(): return if not btn.pressed: self.selected_item_idx = None else: self.selected_item_idx = self.items.index(btn) for i in range(0, len(self.items)): if i != self.selected_item_idx: self.items[i].set_pressed(False) self.set_current_idx(self.selected_item_idx) if self.item_selected_cb is not None: self.item_selected_cb() def get_current_idx(self): return self.middle_item_idx def set_current_idx(self, idx, select=False): if select: self.selected_item_idx = idx self.middle_item_idx = max(idx, min(1, len(self.items) - 1)) if self.isEnabled(): if self.middle_item_idx == min(1, len(self.items) - 1): self.up_btn.set_enabled(False) else: self.up_btn.set_enabled(True) if (idx < len(self.items) - 2): self.down_btn.set_enabled(True) else: self.down_btn.set_enabled(False) for it in self.items: it.setVisible(False) if select: it.set_pressed(False) # selected item is always vertically centered self.items[self.middle_item_idx].setPos( 0, (self.h - self.items[self.middle_item_idx].boundingRect().height()) / 2) self.items[self.middle_item_idx].setVisible(True) if select: self.items[self.middle_item_idx].set_pressed(True) # how much vert. space is used vspace = self.items[self.middle_item_idx].boundingRect().height() # fill space above selected item for idx in range(self.middle_item_idx - 1, -1, -1): h = self.items[idx].boundingRect().height() y = self.items[idx + 1].y() - self.sp - h if y < self.up_btn.y() + self.up_btn.boundingRect().height(): break self.items[idx].setPos(0, y) self.items[idx].setVisible(True) vspace += self.sp + h # fill space below selected item for idx in range(self.middle_item_idx + 1, len(self.items)): h = self.items[idx].boundingRect().height() y = self.items[idx - 1].y() + self.items[idx - 1].boundingRect().height() + self.sp if y + h > self.down_btn.y(): break self.items[idx].setPos(0, y) self.items[idx].setVisible(True) vspace += self.sp + h def up_btn_cb(self, btn): if self.middle_item_idx > 0: self.set_current_idx(self.middle_item_idx - 1) def down_btn_cb(self, btn): if self.middle_item_idx < len(self.items) - 1: self.set_current_idx(self.middle_item_idx + 1) def boundingRect(self): return QtCore.QRectF(0, 0, self.w, self.h) def paint(self, painter, option, widget): pass
def __init__(self, scene, x, y, program_helper, instruction, ih, done_cb=None, item_switched_cb=None, learning_request_cb=None, pause_cb=None, cancel_cb=None, stopped=False, visualize=False, v_visualize_cb=None, v_back_cb=None, vis_pause_cb=None, vis_stop_cb=None, vis_replay_cb=None, vis_back_to_blocks_cb=None): self.w = 100 self.h = 100 self.instruction = instruction self.ih = ih self.done_cb = done_cb self.item_switched_cb = item_switched_cb self.learning_request_cb = learning_request_cb self.pause_cb = pause_cb self.cancel_cb = cancel_cb self.readonly = False self.stopped = stopped # variables for HoloLens visualization self.visualize = visualize self.visualization_paused = False # callbacks for visualization buttons self.v_visualize_cb = v_visualize_cb self.v_back_cb = v_back_cb self.vis_pause_cb = vis_pause_cb self.vis_stop_cb = vis_stop_cb self.vis_replay_cb = vis_replay_cb self.vis_back_to_blocks_cb = vis_back_to_blocks_cb super(ProgramItem, self).__init__(scene, x, y) self.title = DescItem(self.scene(), 0, 0, self) # TODO it should take coords given to __init__ self.title.setPos(QtCore.QPointF(self.m2pix(0.01), self.m2pix(0.01))) self.w = self.m2pix(0.2) self.h = self.m2pix(0.25) self.sp = self.m2pix(0.005) self.ph = program_helper self.block_id = None self.item_id = None self.block_learned = False self.program_learned = False # block "view" self.block_finished_btn = ButtonItem(self.scene(), 0, 0, "BTN", self, self.block_finished_btn_cb, image_path=icons_path + "back.svg") self.block_edit_btn = ButtonItem(self.scene(), 0, 0, "BTN", self, self.block_edit_btn_cb, image_path=icons_path + "edit.svg") self.block_on_success_btn = ButtonItem(self.scene(), 0, 0, "BTN", self, self.block_on_success_btn_cb, image_path=icons_path + "success.svg") self.block_on_failure_btn = ButtonItem(self.scene(), 0, 0, "BTN", self, self.block_on_failure_btn_cb, image_path=icons_path + "failure.svg") # block "view" when in visualization self.program_visualize_btn = ButtonItem( self.scene(), 0, 0, translate("ProgramItem", "Visualize Program"), self, self.program_visualize_btn_cb) self.block_visualize_btn = ButtonItem( self.scene(), 0, 0, translate("ProgramItem", "Visualize Block"), self, self.block_visualize_btn_cb) self.block_back_btn = ButtonItem(self.scene(), 0, 0, translate("ProgramItem", "Back"), self, self.block_back_btn_cb) bdata = [] self.blocks_map = {} # map from indexes (key) to block_id (value) self.blocks_map_rev = {} for i in range(len(self.ph.get_program().blocks)): bmsg = self.ph.get_program().blocks[i] bdata.append( translate("ProgramItem", "Block %1\n%2\nSuccess: %3, failure: %4").arg( bmsg.id).arg(bmsg.name).arg(bmsg.on_success).arg( bmsg.on_failure)) idx = len(bdata) - 1 self.blocks_map[idx] = bmsg.id self.blocks_map_rev[bmsg.id] = idx self.blocks_list = ListItem(self.scene(), 0, 0, 0.2 - 2 * 0.005, bdata, self.block_selected_cb, parent=self) for k, v in self.blocks_map.iteritems(): self._update_block(v) y = self.title.mapToParent(self.title.boundingRect().bottomLeft()).y() self.blocks_list.setPos(self.sp, y) y += self.blocks_list._height() + self.sp if visualize: self._place_childs_horizontally(y, self.sp, [ self.program_visualize_btn, self.block_visualize_btn, self.block_back_btn ]) y += self.block_visualize_btn._height() + self.sp self.block_back_btn.set_enabled(True) self.block_visualize_btn.set_enabled(False) self.program_visualize_btn.set_enabled(True) # hide edit block buttons group_visible( (self.block_finished_btn, self.block_edit_btn, self.block_on_failure_btn, self.block_on_success_btn), False) else: self._place_childs_horizontally(y, self.sp, [ self.block_edit_btn, self.block_on_success_btn, self.block_on_failure_btn, self.block_finished_btn ]) y += self.block_finished_btn._height() + self.sp group_enable((self.block_edit_btn, self.block_on_failure_btn, self.block_on_success_btn), False) # hide visualization block buttons group_visible((self.block_visualize_btn, self.program_visualize_btn, self.block_back_btn), False) self.h = y # items "view" self.item_edit_btn = ButtonItem(self.scene(), 0, 0, translate("ProgramItem", "Ed"), self, self.item_edit_btn_cb, image_path=icons_path + "edit.svg") self.item_run_btn = ButtonItem(self.scene(), 0, 0, "BTN", self, self.item_run_btn_cb, image_path=icons_path + "run.svg") self.item_on_success_btn = ButtonItem(self.scene(), 0, 0, "BTN", self, self.item_on_success_btn_cb, image_path=icons_path + "success.svg") self.item_on_failure_btn = ButtonItem(self.scene(), 0, 0, "BTN", self, self.item_on_failure_btn_cb, image_path=icons_path + "failure.svg") self.item_finished_btn = ButtonItem(self.scene(), 0, 0, "BTN", self, self.item_finished_btn_cb, image_path=icons_path + "back.svg") self.items_list = None group_visible((self.item_finished_btn, self.item_run_btn, self.item_on_success_btn, self.item_on_failure_btn, self.item_edit_btn), False) # readonly (program running) "view" self.pr_pause_btn = ButtonItem(self.scene(), 0, 0, "BTN", self, self.pr_pause_btn_cb, image_path=icons_path + "pause.svg") if self.stopped: self.pr_pause_btn.set_image(icons_path + "run.svg") self.pr_cancel_btn = ButtonItem(self.scene(), 0, 0, "BTN", self, self.pr_cancel_btn_cb, image_path=icons_path + "stop.svg") group_visible((self.pr_pause_btn, self.pr_cancel_btn), False) # buttons for HoloLens visualization self.vis_pause_btn = ButtonItem(self.scene(), 0, 0, translate("ProgramItem", "Resume"), self, self.vis_pause_btn_cb) # quick hack .. init button with 'Resume' caption and switch back to # 'Pause' to keep the button large enough for text switching if not self.visualization_paused: self.vis_pause_btn.set_caption(translate("ProgramItem", "Pause")) self.vis_stop_btn = ButtonItem(self.scene(), 0, 0, translate("ProgramItem", "Stop"), self, self.vis_stop_btn_cb) self.vis_replay_btn = ButtonItem(self.scene(), 0, 0, translate("ProgramItem", "Replay"), self, self.vis_replay_btn_cb) self.vis_back_btn = ButtonItem( self.scene(), 0, 0, translate("ProgramItem", "Back to blocks"), self, self.vis_back_btn_cb) group_visible((self.vis_pause_btn, self.vis_stop_btn, self.vis_replay_btn, self.vis_back_btn), False) self.fixed = False self.editing_item = False self.edit_request = False self.run_request = False self.setFlag(QtGui.QGraphicsItem.ItemIsMovable, True) self.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, True) self.setZValue(100) self._update_learned() self.update() if self.item_switched_cb: self.item_switched_cb(None, None, blocks=True)
class ProgramItem(Item): def __init__(self, scene, x, y, program_helper, instruction, ih, done_cb=None, item_switched_cb=None, learning_request_cb=None, pause_cb=None, cancel_cb=None, stopped=False, visualize=False, v_visualize_cb=None, v_back_cb=None, vis_pause_cb=None, vis_stop_cb=None, vis_replay_cb=None, vis_back_to_blocks_cb=None): self.w = 100 self.h = 100 self.instruction = instruction self.ih = ih self.done_cb = done_cb self.item_switched_cb = item_switched_cb self.learning_request_cb = learning_request_cb self.pause_cb = pause_cb self.cancel_cb = cancel_cb self.readonly = False self.stopped = stopped # variables for HoloLens visualization self.visualize = visualize self.visualization_paused = False # callbacks for visualization buttons self.v_visualize_cb = v_visualize_cb self.v_back_cb = v_back_cb self.vis_pause_cb = vis_pause_cb self.vis_stop_cb = vis_stop_cb self.vis_replay_cb = vis_replay_cb self.vis_back_to_blocks_cb = vis_back_to_blocks_cb super(ProgramItem, self).__init__(scene, x, y) self.title = DescItem(self.scene(), 0, 0, self) # TODO it should take coords given to __init__ self.title.setPos(QtCore.QPointF(self.m2pix(0.01), self.m2pix(0.01))) self.w = self.m2pix(0.2) self.h = self.m2pix(0.25) self.sp = self.m2pix(0.005) self.ph = program_helper self.block_id = None self.item_id = None self.block_learned = False self.program_learned = False # block "view" self.block_finished_btn = ButtonItem(self.scene(), 0, 0, "BTN", self, self.block_finished_btn_cb, image_path=icons_path + "back.svg") self.block_edit_btn = ButtonItem(self.scene(), 0, 0, "BTN", self, self.block_edit_btn_cb, image_path=icons_path + "edit.svg") self.block_on_success_btn = ButtonItem(self.scene(), 0, 0, "BTN", self, self.block_on_success_btn_cb, image_path=icons_path + "success.svg") self.block_on_failure_btn = ButtonItem(self.scene(), 0, 0, "BTN", self, self.block_on_failure_btn_cb, image_path=icons_path + "failure.svg") # block "view" when in visualization self.program_visualize_btn = ButtonItem( self.scene(), 0, 0, translate("ProgramItem", "Visualize Program"), self, self.program_visualize_btn_cb) self.block_visualize_btn = ButtonItem( self.scene(), 0, 0, translate("ProgramItem", "Visualize Block"), self, self.block_visualize_btn_cb) self.block_back_btn = ButtonItem(self.scene(), 0, 0, translate("ProgramItem", "Back"), self, self.block_back_btn_cb) bdata = [] self.blocks_map = {} # map from indexes (key) to block_id (value) self.blocks_map_rev = {} for i in range(len(self.ph.get_program().blocks)): bmsg = self.ph.get_program().blocks[i] bdata.append( translate("ProgramItem", "Block %1\n%2\nSuccess: %3, failure: %4").arg( bmsg.id).arg(bmsg.name).arg(bmsg.on_success).arg( bmsg.on_failure)) idx = len(bdata) - 1 self.blocks_map[idx] = bmsg.id self.blocks_map_rev[bmsg.id] = idx self.blocks_list = ListItem(self.scene(), 0, 0, 0.2 - 2 * 0.005, bdata, self.block_selected_cb, parent=self) for k, v in self.blocks_map.iteritems(): self._update_block(v) y = self.title.mapToParent(self.title.boundingRect().bottomLeft()).y() self.blocks_list.setPos(self.sp, y) y += self.blocks_list._height() + self.sp if visualize: self._place_childs_horizontally(y, self.sp, [ self.program_visualize_btn, self.block_visualize_btn, self.block_back_btn ]) y += self.block_visualize_btn._height() + self.sp self.block_back_btn.set_enabled(True) self.block_visualize_btn.set_enabled(False) self.program_visualize_btn.set_enabled(True) # hide edit block buttons group_visible( (self.block_finished_btn, self.block_edit_btn, self.block_on_failure_btn, self.block_on_success_btn), False) else: self._place_childs_horizontally(y, self.sp, [ self.block_edit_btn, self.block_on_success_btn, self.block_on_failure_btn, self.block_finished_btn ]) y += self.block_finished_btn._height() + self.sp group_enable((self.block_edit_btn, self.block_on_failure_btn, self.block_on_success_btn), False) # hide visualization block buttons group_visible((self.block_visualize_btn, self.program_visualize_btn, self.block_back_btn), False) self.h = y # items "view" self.item_edit_btn = ButtonItem(self.scene(), 0, 0, translate("ProgramItem", "Ed"), self, self.item_edit_btn_cb, image_path=icons_path + "edit.svg") self.item_run_btn = ButtonItem(self.scene(), 0, 0, "BTN", self, self.item_run_btn_cb, image_path=icons_path + "run.svg") self.item_on_success_btn = ButtonItem(self.scene(), 0, 0, "BTN", self, self.item_on_success_btn_cb, image_path=icons_path + "success.svg") self.item_on_failure_btn = ButtonItem(self.scene(), 0, 0, "BTN", self, self.item_on_failure_btn_cb, image_path=icons_path + "failure.svg") self.item_finished_btn = ButtonItem(self.scene(), 0, 0, "BTN", self, self.item_finished_btn_cb, image_path=icons_path + "back.svg") self.items_list = None group_visible((self.item_finished_btn, self.item_run_btn, self.item_on_success_btn, self.item_on_failure_btn, self.item_edit_btn), False) # readonly (program running) "view" self.pr_pause_btn = ButtonItem(self.scene(), 0, 0, "BTN", self, self.pr_pause_btn_cb, image_path=icons_path + "pause.svg") if self.stopped: self.pr_pause_btn.set_image(icons_path + "run.svg") self.pr_cancel_btn = ButtonItem(self.scene(), 0, 0, "BTN", self, self.pr_cancel_btn_cb, image_path=icons_path + "stop.svg") group_visible((self.pr_pause_btn, self.pr_cancel_btn), False) # buttons for HoloLens visualization self.vis_pause_btn = ButtonItem(self.scene(), 0, 0, translate("ProgramItem", "Resume"), self, self.vis_pause_btn_cb) # quick hack .. init button with 'Resume' caption and switch back to # 'Pause' to keep the button large enough for text switching if not self.visualization_paused: self.vis_pause_btn.set_caption(translate("ProgramItem", "Pause")) self.vis_stop_btn = ButtonItem(self.scene(), 0, 0, translate("ProgramItem", "Stop"), self, self.vis_stop_btn_cb) self.vis_replay_btn = ButtonItem(self.scene(), 0, 0, translate("ProgramItem", "Replay"), self, self.vis_replay_btn_cb) self.vis_back_btn = ButtonItem( self.scene(), 0, 0, translate("ProgramItem", "Back to blocks"), self, self.vis_back_btn_cb) group_visible((self.vis_pause_btn, self.vis_stop_btn, self.vis_replay_btn, self.vis_back_btn), False) self.fixed = False self.editing_item = False self.edit_request = False self.run_request = False self.setFlag(QtGui.QGraphicsItem.ItemIsMovable, True) self.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, True) self.setZValue(100) self._update_learned() self.update() if self.item_switched_cb: self.item_switched_cb(None, None, blocks=True) def _update_title(self): color = QtCore.Qt.white if self.items_list is not None: if not self.block_learned and not self.readonly: color = QtCore.Qt.red self.title.set_content(translate( "ProgramItem", "Program %1, block %2").arg( self.ph.get_program_id()).arg(self.block_id), scale=1.2, color=color) else: if not self.program_learned and not self.readonly: color = QtCore.Qt.red self.title.set_content(translate("ProgramItem", "Program %1").arg( self.ph.get_program_id()), scale=1.2, color=color) def pr_pause_btn_cb(self, btn): if self.pause_cb is not None: ret = self.pause_cb() if ret: # set disabled and wait for state update self.set_enabled(False) def pr_cancel_btn_cb(self, btn): if self.cancel_cb is not None: ret = self.cancel_cb() if ret: # set disabled and wait for state update self.set_enabled(False) def vis_pause_btn_cb(self, btn): # callback which notifies HoloLens that pause/resume button was hit if self.vis_pause_cb is not None: self.vis_pause_cb(self.visualization_paused) # if visualization is paused .. then resume it - e.g. hit RESUME button if self.visualization_paused: self.visualization_paused = False self.vis_pause_btn.set_caption(translate("ProgramItem", "Pause")) # or visualization is running .. then pause it - e.g. hit PAUSE button else: self.visualization_paused = True self.vis_pause_btn.set_caption(translate("ProgramItem", "Resume")) def vis_stop_btn_cb(self, btn): # callback which notifies HoloLens that stop button was hit if self.vis_stop_cb is not None: self.vis_stop_cb() # make sure that visualization is not paused and handle it's button caption properly if self.visualization_paused: self.visualization_paused = False self.vis_pause_btn.set_caption(translate("ProgramItem", "Pause")) group_enable((self.vis_stop_btn, self.vis_pause_btn), False) group_enable((self.vis_replay_btn, self.vis_back_btn), True) def vis_replay_btn_cb(self, btn): # callback which notifies HoloLens that replay button was hit if self.vis_replay_cb is not None: self.vis_replay_cb() group_enable((self.vis_stop_btn, self.vis_pause_btn), True) group_enable((self.vis_replay_btn, self.vis_back_btn), False) def vis_back_btn_cb(self, btn): # callback which notifies HoloLens that visualization ended if self.vis_back_to_blocks_cb is not None: self.vis_back_to_blocks_cb() # go back to blocks view from visualization group_visible((self.block_visualize_btn, self.program_visualize_btn, self.block_back_btn, self.blocks_list), True) self.block_back_btn.set_enabled(True) self.program_visualize_btn.set_enabled(True) self.show_visualization_buttons(False) self.block_selected_cb( ) # TODO extract method to set buttons to proper state self.blocks_list.setEnabled(True) self.scene().removeItem(self.items_list) self.items_list = None self.item_id = None if self.item_switched_cb is not None: self.item_switched_cb(*self.cid) self.update() def _update_learned(self): if self.block_id is not None: self.block_learned = self.ph.block_learned(self.block_id) self.program_learned = self.ph.program_learned() self._update_title() def set_readonly(self, readonly): self.readonly = readonly if self.readonly: if self.items_list is not None: self.items_list.setVisible(True) self.items_list.setEnabled(False) self.blocks_list.set_enabled(False, True) group_visible( (self.block_finished_btn, self.block_edit_btn, self.block_on_failure_btn, self.block_on_success_btn), False) group_enable((self.pr_pause_btn, self.pr_cancel_btn), True) else: # TODO pass self.update() def set_program_btns_enabled(self, state): group_enable((self.pr_pause_btn, self.pr_cancel_btn), state) def set_active(self, block_id, item_id): # print "set_active", block_id, item_id old_block_id = self.block_id self.block_id = block_id self.item_id = item_id if old_block_id != self.block_id and item_id is not None: # remove old list first self.scene().removeItem(self.items_list) self.items_list = None # init new one self._init_items_list() if self.item_id is not None: self.items_list.set_current_idx(self.items_map_rev[self.item_id], select=True) self._handle_item_btns() group_visible( (self.block_finished_btn, self.block_edit_btn, self.block_on_failure_btn, self.block_on_success_btn, self.block_visualize_btn, self.program_visualize_btn, self.block_back_btn, self.blocks_list), False) else: self.blocks_list.set_current_idx( self.blocks_map_rev[self.block_id], select=True) self._update_title() def get_text_for_item(self, block_id, item_id): item = self.ph.get_item_msg(block_id, item_id) text = str(item.id) text += " | " # TODO deal with long strings if item.name: text += item.name else: text += self.ih[item.type].gui.learn.NAME if len(item.ref_id) > 0: if self.ph.item_has_nothing_to_set(block_id, item_id): text += translate("ProgramItem", " (copy of %1)").arg(item.ref_id[0]) # else: # text += translate("ProgramItem", " (refers to %1)").arg(', '.join(str(x) for x in item.ref_id)) if item.type in self.ih.properties.using_object: (obj, ref_id) = self.ph.get_object(block_id, item_id) text += "\n" if self.ph.is_object_set(block_id, item_id): obj_txt = obj[0] else: obj_txt = "??" text += translate("ProgramItem", " Object type: %1").arg(obj_txt) if ref_id != item_id: text += translate("ProgramItem", " (same as in %1)").arg(ref_id) # instruction-specific additional text # TODO it should use different class when running? text += self.ih[item.type].gui.learn.get_text(self.ph, block_id, item_id) text += "\n" text += translate("ProgramItem", " Success: %1, failure: %2").arg( item.on_success).arg(item.on_failure) return text def show_visualization_buttons(self, buttons_visible): """Shows or hides buttons for visualization mode for HoloLens""" group_visible((self.vis_pause_btn, self.vis_stop_btn, self.vis_replay_btn, self.vis_back_btn), buttons_visible) def _init_items_list(self): idata = [] self.items_map = {} # map from indexes (key) to item_id (value) self.items_map_rev = {} bmsg = self.ph.get_block_msg(self.block_id) for i in range(len(bmsg.items)): item_id = bmsg.items[i].id idata.append(self.get_text_for_item(self.block_id, item_id)) self.items_map[i] = item_id self.items_map_rev[item_id] = i self.items_list = ListItem(self.scene(), 0, 0, 0.2 - 2 * 0.005, idata, self.item_selected_cb, parent=self) for k, v in self.items_map.iteritems(): if self.ph.get_item_msg( self.block_id, v).type in self.ih.properties.runnable_during_learning: self._update_item(self.block_id, v) else: self.items_list.items[k].set_enabled(False) y = self.title.mapToParent( self.title.boundingRect().bottomLeft()).y() + self.sp self.items_list.setPos(self.sp, y) y += self.items_list._height() + self.sp # in running state if self.readonly: self.items_list.setEnabled(False) self._place_childs_horizontally( y, self.sp, [self.pr_pause_btn, self.pr_cancel_btn]) y += self.pr_pause_btn._height() + 3 * self.sp pr = (self.pr_pause_btn, self.pr_cancel_btn) group_enable(pr, True) group_visible((self.item_finished_btn, self.item_run_btn, self.item_on_success_btn, self.item_on_failure_btn, self.item_edit_btn), False) self.show_visualization_buttons(False) # going to HoloLens visualization elif self.visualize: self.items_list.setEnabled(False) self._place_childs_horizontally( y, self.sp, [self.vis_pause_btn, self.vis_stop_btn, self.vis_replay_btn]) y += self.vis_back_btn._height() + self.sp self._place_childs_horizontally(y, self.sp, [self.vis_back_btn]) y += self.vis_back_btn._height() + 3 * self.sp self.show_visualization_buttons(True) group_enable((self.vis_pause_btn, self.vis_stop_btn), True) self.vis_back_btn.set_enabled(False) group_visible((self.pr_pause_btn, self.pr_cancel_btn), False) group_visible((self.item_run_btn, self.item_on_success_btn, self.item_on_failure_btn, self.item_edit_btn), False) # in learning state else: btns = (self.item_edit_btn, self.item_run_btn, self.item_on_success_btn, self.item_on_failure_btn, self.item_finished_btn) self._place_childs_horizontally(y, self.sp, btns) y += max(btn._height() for btn in btns) y += self.sp group_visible((self.item_finished_btn, self.item_run_btn, self.item_on_success_btn, self.item_on_failure_btn, self.item_edit_btn), True) self.item_finished_btn.setEnabled(True) group_enable((self.item_run_btn, self.item_on_failure_btn, self.item_on_success_btn, self.item_on_failure_btn), False) group_visible((self.pr_pause_btn, self.pr_cancel_btn), False) self.show_visualization_buttons(False) self.h = y self._update_title() self.update() if self.item_switched_cb: self.item_switched_cb(self.block_id, self.item_id, blocks=False) def block_edit_btn_cb(self, btn): group_visible((self.block_finished_btn, self.block_edit_btn, self.item_on_success_btn, self.block_on_failure_btn, self.block_on_success_btn, self.blocks_list), False) self._init_items_list() def block_visualize_btn_cb(self, btn): group_visible((self.block_visualize_btn, self.program_visualize_btn, self.block_back_btn, self.blocks_list), False) # callback which notifies HoloLens that visualization started if self.v_visualize_cb is not None: self.v_visualize_cb(visualize_whole_program=False) self._init_items_list() def program_visualize_btn_cb(self, btn): group_visible((self.block_visualize_btn, self.program_visualize_btn, self.block_back_btn, self.blocks_list), False) # callback which notifies HoloLens that visualization started if self.v_visualize_cb is not None: self.v_visualize_cb(visualize_whole_program=True) self.block_id = self.ph.get_first_block_id() self._init_items_list() # go back from block view visualization into main menu def block_back_btn_cb(self, btn): group_visible((self.block_visualize_btn, self.program_visualize_btn, self.block_back_btn), False) # callback which notifies HoloLens that visualization ended if self.v_back_cb is not None: self.v_back_cb() def block_selected_cb(self): if self.blocks_list.selected_item_idx is not None: self.block_id = self.blocks_map[self.blocks_list.selected_item_idx] self.block_on_failure_btn.set_enabled( self.ph.get_block_on_failure(self.block_id) != 0) self.block_on_success_btn.set_enabled( self.ph.get_block_on_success(self.block_id) != 0) self.block_edit_btn.set_enabled(True) self.block_visualize_btn.set_enabled(True) if self.item_switched_cb: self.item_switched_cb(self.block_id, None, blocks=True) self._update_learned() else: self.block_id = None self.item_id = None self.block_edit_btn.set_enabled(False) self.block_on_failure_btn.set_enabled(False) self.block_on_success_btn.set_enabled(False) self.block_visualize_btn.set_enabled(False) if self.item_switched_cb is not None: self.item_switched_cb(self.block_id, None, blocks=True) @property def cid(self): """Shortcut for accessing program item""" return self.block_id, self.item_id def _handle_item_btns(self): # print ("_handle_item_btns, self.editing_item: " + str(self.editing_item)) if not self.editing_item: of = self.ph.get_id_on_failure(*self.cid) os = self.ph.get_id_on_success(*self.cid) self.item_on_failure_btn.set_enabled( of[0] != 0 and not (of[0] == self.block_id and of[1] == self.item_id)) self.item_on_success_btn.set_enabled( os[0] != 0 and not (os[0] == self.block_id and os[1] == self.item_id)) self.item_run_btn.set_enabled(self._item_runnable()) self.item_edit_btn.set_enabled(self._item_editable()) else: self.item_edit_btn.set_enabled(True) self.item_edit_btn.set_image(icons_path + "save.svg") group_enable((self.item_finished_btn, self.items_list), False) self.item_run_btn.set_enabled(False) group_visible((self.pr_cancel_btn, self.pr_pause_btn), False) def _item_runnable(self): if self.ph.item_requires_learning(*self.cid): return self.ph.item_learned(*self.cid) return self.ph.get_item_msg( *self.cid).type in self.ih.properties.runnable_during_learning def _item_editable(self): if not self.ph.item_requires_learning(*self.cid): return False if self.ph.item_takes_params_from_ref( *self.cid) and not self.ph.ref_params_learned(*self.cid): return False if self.ph.get_item_type(*self.cid) in self.ih.properties.place | self.ih.properties.ref_to_pick and not \ self.ph.ref_pick_learned(*self.cid)[0]: return False return True def item_selected_cb(self): # print ("self.items_list.selected_item_idx", self.items_list.selected_item_idx) if self.items_list.selected_item_idx is not None: self.item_id = self.items_map[self.items_list.selected_item_idx] self._handle_item_btns() self._update_learned() else: self.item_id = None group_enable((self.item_run_btn, self.item_on_success_btn, self.item_on_failure_btn, self.item_edit_btn), False) if self.item_switched_cb is not None: self.item_switched_cb(*self.cid) def block_on_failure_btn_cb(self, btn): self.set_active(self.ph.get_block_on_failure(self.block_id), None) def block_on_success_btn_cb(self, btn): self.set_active(self.ph.get_block_on_success(self.block_id), None) def block_finished_btn_cb(self, btn): if self.done_cb is not None: self.done_cb() def item_finished_btn_cb(self, btn): # go back to blocks view group_visible((self.block_finished_btn, self.block_edit_btn, self.block_on_failure_btn, self.block_on_success_btn, self.blocks_list), True) group_visible((self.item_finished_btn, self.item_run_btn, self.item_on_success_btn, self.item_on_failure_btn, self.item_edit_btn), False) self.block_selected_cb( ) # TODO extract method to set buttons to proper state self.blocks_list.setEnabled(True) self.block_finished_btn.setEnabled(True) self.scene().removeItem(self.items_list) self.items_list = None self.item_id = None if self.item_switched_cb is not None: self.item_switched_cb(*self.cid) self._update_title() self.update() def item_on_failure_btn_cb(self, btn): of = self.ph.get_id_on_failure(*self.cid) self.set_active(*of) if self.item_switched_cb is not None: self.item_switched_cb(*of) def item_on_success_btn_cb(self, btn): of = self.ph.get_id_on_success(*self.cid) self.set_active(*of) if self.item_switched_cb is not None: self.item_switched_cb(*of) def item_run_btn_cb(self, btn): self.run_request = True self.set_enabled(False) self.learning_request_cb(LearningRequestGoal.EXECUTE_ITEM) def item_edit_btn_cb(self, btn): self.edit_request = True # call action / disable all, wait for result (callback), enable editing if not self.editing_item: self.learning_request_cb(LearningRequestGoal.GET_READY) else: self.learning_request_cb(LearningRequestGoal.DONE) self.set_enabled(False) def learning_request_result(self, success): self.set_enabled(True) # TODO no success, no editing if self.edit_request: self.edit_request = False if not self.editing_item: self.editing_item = True self.item_edit_btn.set_image(icons_path + "save.svg") group_enable( (self.item_finished_btn, self.items_list, self.item_on_failure_btn, self.item_on_success_btn), False) else: self.editing_item = False self.item_edit_btn.set_image(icons_path + "edit.svg") group_enable((self.item_finished_btn, self.items_list), True) self._update_learned() self._handle_item_btns() elif self.run_request: self.run_request = False if self.item_switched_cb is not None: self.item_switched_cb(self.block_id, self.item_id, not self.editing_item) def boundingRect(self): return QtCore.QRectF(0, 0, self.w, self.h) def set_place_pose(self, place): msg = self.get_current_item() assert len(msg.pose) > 0 msg.pose[0].pose.position.x = place.position[0] msg.pose[0].pose.position.y = place.position[1] msg.pose[0].pose.position.z = place.position[2] msg.pose[0].pose.orientation = conversions.a2q(place.quaternion) self._update_item() ''' Method which saves place poses of all objects (in the grid) into the ProgramItem message. ''' def set_place_poses(self, poses): msg = self.get_current_item() poses_count = len(poses) msg_poses_count = len(msg.pose) # TODO nemel by byt pocet objektu v gridu spis fixni (dany strukturou programu)? if poses_count > msg_poses_count: for i in range(poses_count - msg_poses_count): ps = PoseStamped() msg.pose.append(ps) elif poses_count < msg_poses_count: for i in range(msg_poses_count - poses_count): msg.pose.pop() for i, pose in enumerate(poses): pos = pose.get_pos() msg.pose[i].pose.position.x = pos[0] msg.pose[i].pose.position.y = pos[1] msg.pose[i].pose.orientation = conversions.yaw2quaternion( pose.rotation()) self._update_item() def set_pose(self, ps): msg = self.get_current_item() assert len(msg.pose) > 0 msg.pose[0] = ps self._update_item() def update_pose(self, ps, idx): msg = self.get_current_item() msg.pose[idx] = ps self._update_item() def clear_poses(self): for ps in self.get_current_item().pose: ps.pose = Pose() self._update_item() def get_poses_count(self): msg = self.get_current_item() return len(msg.pose) def set_object(self, obj): msg = self.get_current_item() assert len(msg.object) > 0 msg.object[0] = obj self._update_item() def set_polygon(self, pts): msg = self.get_current_item() assert len(msg.polygon) > 0 del msg.polygon[0].polygon.points[:] for pt in pts: msg.polygon[0].polygon.points.append(Point32(pt[0], pt[1], 0)) self._update_item() ''' Method which saves 4 points forming a grid into the ProgramItem message. ''' def set_place_grid(self, pts): msg = self.get_current_item() assert len(msg.polygon) > 0 del msg.polygon[0].polygon.points[:] for pt in pts: msg.polygon[0].polygon.points.append(Point32(pt[0], pt[1], 0)) self._update_item() def _update_block(self, block_id): idx = self.blocks_map_rev[block_id] if self.ph.block_learned(block_id): self.blocks_list.items[idx].set_background_color() else: self.blocks_list.items[idx].set_background_color(QtCore.Qt.red) def _update_item(self, block_id=None, item_id=None): if block_id is None: block_id = self.block_id # need to update all items in block as there might be various dependencies (ref_id) for idx, item_id in self.items_map.iteritems(): if self.ph.item_learned(block_id, item_id) or \ (self.ph.get_item_msg(block_id, item_id).type in self.ih.properties.runnable_during_learning and not self.ih.requires_learning(self.ph.get_item_msg(block_id, item_id).type)): self.items_list.items[idx].set_background_color() else: self.items_list.items[idx].set_background_color(QtCore.Qt.red) self.items_list.items[idx].set_caption( self.get_text_for_item(block_id, item_id)) self._update_block(block_id) def get_current_item(self): if self.block_id is not None and self.item_id is not None: return self.ph.get_item_msg(*self.cid) return None def paint(self, painter, option, widget): if not self.scene(): return painter.setClipRect(option.exposedRect) painter.setRenderHint(QtGui.QPainter.Antialiasing) pen = QtGui.QPen() pen.setStyle(QtCore.Qt.NoPen) painter.setPen(pen) painter.setBrush(QtCore.Qt.gray) painter.setOpacity(0.5) painter.drawRoundedRect(QtCore.QRect(0, 0, self.w, self.h), 5.0, 5.0)
def __init__( self, scene, x, y, program_headers, learned_dict, selected_program_id=None, program_selected_cb=None, program_selection_changed_cb=None): self.w = 100 self.h = 100 self.program_headers = program_headers self.learned_dict = learned_dict self.program_selected_cb = program_selected_cb self.program_selection_changed_cb = program_selection_changed_cb super(ProgramListItem, self).__init__(scene, x, y) self.w = self.m2pix(0.2) self.h = self.m2pix(0.25) self.fixed = False self.setZValue(100) title = DescItem(self.scene(), 0, 0, self) title.set_content(translate("ProgramListItem", "Program list"), 1.2) title.setPos(QtCore.QPointF(self.m2pix(0.01), self.m2pix(0.01))) # TODO it should take coords given to __init__ data = [] self.map_from_idx_to_program_id = {} self.map_from_program_id_to_idx = {} self.program_headers.sort(key=lambda p: p.id) for ph in self.program_headers: data.append("Program " + str(ph.id) + "\n" + ph.name) idx = len(data) - 1 self.map_from_idx_to_program_id[idx] = ph.id self.map_from_program_id_to_idx[ph.id] = idx self.list = ListItem(scene, 0, 0, 0.2 - 2 * 0.005, data, self.item_selected_cb, parent=self) for idx in range(0, len(data)): if not self.learned_dict[self.map_from_idx_to_program_id[idx]]: self.list.items[idx].set_background_color(QtCore.Qt.red) rospack = rospkg.RosPack() icons_path = rospack.get_path('art_projected_gui') + '/icons/' self.run_btn = ButtonItem(scene, 0, 0, "BTN", self, self.run_btn_cb, image_path=icons_path + "run.svg") self.edit_btn = ButtonItem(scene, 0, 0, "BTN", self, self.edit_btn_cb, image_path=icons_path + "edit.svg") self.template_btn = ButtonItem(scene, 0, 0, "BTN", self, self.template_btn_cb, image_path=icons_path + "template.svg") self.visualize_btn = ButtonItem(scene, 0, 0, "BTN", self, self.visualize_btn_cb, image_path=icons_path + "visualize.svg") self.run_btn.set_enabled(False) self.edit_btn.set_enabled(False) self.template_btn.set_enabled(False) self.visualize_btn.set_enabled(False) if selected_program_id is not None: self.list.set_current_idx(self.map_from_program_id_to_idx[selected_program_id]) sp = self.m2pix(0.005) # h = title.mapToParent(title.boundingRect().bottomLeft()).y() + sp h = 0 self.list.setPos(sp, h) h += self.list._height() h += 2 * sp btns = (self.run_btn, self.edit_btn, self.template_btn, self.visualize_btn) self._place_childs_horizontally(h, sp, btns) h += self.run_btn._height() h += 3 * sp self.h = h self.setFlag(QtGui.QGraphicsItem.ItemIsMovable, True) self.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, True) self.update()
class ProgramListItem(Item): def __init__( self, scene, x, y, program_headers, learned_dict, selected_program_id=None, program_selected_cb=None, program_selection_changed_cb=None): self.w = 100 self.h = 100 self.program_headers = program_headers self.learned_dict = learned_dict self.program_selected_cb = program_selected_cb self.program_selection_changed_cb = program_selection_changed_cb super(ProgramListItem, self).__init__(scene, x, y) self.w = self.m2pix(0.2) self.h = self.m2pix(0.25) self.fixed = False self.setZValue(100) title = DescItem(self.scene(), 0, 0, self) title.set_content(translate("ProgramListItem", "Program list"), 1.2) title.setPos(QtCore.QPointF(self.m2pix(0.01), self.m2pix(0.01))) # TODO it should take coords given to __init__ data = [] self.map_from_idx_to_program_id = {} self.map_from_program_id_to_idx = {} self.program_headers.sort(key=lambda p: p.id) for ph in self.program_headers: data.append("Program " + str(ph.id) + "\n" + ph.name) idx = len(data) - 1 self.map_from_idx_to_program_id[idx] = ph.id self.map_from_program_id_to_idx[ph.id] = idx self.list = ListItem(scene, 0, 0, 0.2 - 2 * 0.005, data, self.item_selected_cb, parent=self) for idx in range(0, len(data)): if not self.learned_dict[self.map_from_idx_to_program_id[idx]]: self.list.items[idx].set_background_color(QtCore.Qt.red) rospack = rospkg.RosPack() icons_path = rospack.get_path('art_projected_gui') + '/icons/' self.run_btn = ButtonItem(scene, 0, 0, "BTN", self, self.run_btn_cb, image_path=icons_path + "run.svg") self.edit_btn = ButtonItem(scene, 0, 0, "BTN", self, self.edit_btn_cb, image_path=icons_path + "edit.svg") self.template_btn = ButtonItem(scene, 0, 0, "BTN", self, self.template_btn_cb, image_path=icons_path + "template.svg") self.visualize_btn = ButtonItem(scene, 0, 0, "BTN", self, self.visualize_btn_cb, image_path=icons_path + "visualize.svg") self.run_btn.set_enabled(False) self.edit_btn.set_enabled(False) self.template_btn.set_enabled(False) self.visualize_btn.set_enabled(False) if selected_program_id is not None: self.list.set_current_idx(self.map_from_program_id_to_idx[selected_program_id]) sp = self.m2pix(0.005) # h = title.mapToParent(title.boundingRect().bottomLeft()).y() + sp h = 0 self.list.setPos(sp, h) h += self.list._height() h += 2 * sp btns = (self.run_btn, self.edit_btn, self.template_btn, self.visualize_btn) self._place_childs_horizontally(h, sp, btns) h += self.run_btn._height() h += 3 * sp self.h = h self.setFlag(QtGui.QGraphicsItem.ItemIsMovable, True) self.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, True) self.update() def item_selected_cb(self): if self.list.selected_item_idx is None: self.run_btn.set_enabled(False) self.edit_btn.set_enabled(False) self.template_btn.set_enabled(False) self.visualize_btn.set_enabled(False) if self.program_selection_changed_cb: self.program_selection_changed_cb(None) else: pid = self.map_from_idx_to_program_id[self.list.selected_item_idx] self.run_btn.setEnabled(self.learned_dict[pid]) for ph in self.program_headers: if ph.id == pid: self.edit_btn.set_enabled(not ph.readonly) break self.template_btn.set_enabled(True) self.visualize_btn.set_enabled(True) if self.program_selection_changed_cb: self.program_selection_changed_cb(ph.id, ro=ph.readonly, learned=self.learned_dict[ph.id]) def get_current_header(self): return self.program_headers[self.list.selected_item_idx] def run_btn_cb(self, btn): if self.program_selected_cb is not None: self.program_selected_cb(self.get_current_header().id, run=True) def edit_btn_cb(self, btn): if self.program_selected_cb is not None: self.program_selected_cb(self.get_current_header().id) def visualize_btn_cb(self, btn): if self.program_selected_cb is not None: self.program_selected_cb(self.get_current_header().id, visualize=True) def template_btn_cb(self, btn): if self.program_selected_cb is not None: self.program_selected_cb(self.get_current_header().id, template=True) def boundingRect(self): return QtCore.QRectF(0, 0, self.w, self.h) def paint(self, painter, option, widget): if not self.scene(): return painter.setClipRect(option.exposedRect) painter.setRenderHint(QtGui.QPainter.Antialiasing) pen = QtGui.QPen() pen.setStyle(QtCore.Qt.NoPen) painter.setPen(pen) painter.setBrush(QtCore.Qt.gray) painter.setOpacity(0.5) painter.drawRoundedRect(QtCore.QRect(0, 0, self.w, self.h), 5.0, 5.0)
def __init__(self, scene, x, y, program_helper, done_cb=None, item_switched_cb=None, learning_request_cb=None, pause_cb=None, cancel_cb=None, stopped=False): self.w = 100 self.h = 100 self.done_cb = done_cb self.item_switched_cb = item_switched_cb self.learning_request_cb = learning_request_cb self.pause_cb = pause_cb self.cancel_cb = cancel_cb self.readonly = False self.stopped = stopped super(ProgramItem, self).__init__(scene, x, y) self.w = self.m2pix(0.2) self.h = self.m2pix(0.25) self.sp = self.m2pix(0.005) self.ph = program_helper self.block_id = None self.item_id = None self.block_learned = False self.program_learned = False # block "view" self.block_finished_btn = ButtonItem(self.scene(), 0, 0, translate("ProgramItem", "Done"), self, self.block_finished_btn_cb) self.block_edit_btn = ButtonItem(self.scene(), 0, 0, translate("ProgramItem", "Edit"), self, self.block_edit_btn_cb) self.block_on_failure_btn = ButtonItem( self.scene(), 0, 0, translate("ProgramItem", "On fail"), self, self.block_on_failure_btn) bdata = [] self.blocks_map = {} # map from indexes (key) to block_id (value) self.blocks_map_rev = {} for i in range(len(self.ph.get_program().blocks)): bmsg = self.ph.get_program().blocks[i] bdata.append( translate("ProgramItem", "Block %1\n%2").arg(bmsg.id).arg(bmsg.name)) idx = len(bdata) - 1 self.blocks_map[idx] = bmsg.id self.blocks_map_rev[bmsg.id] = idx self.blocks_list = ListItem(self.scene(), 0, 0, 0.2 - 2 * 0.005, bdata, self.block_selected_cb, parent=self) for k, v in self.blocks_map.iteritems(): self._update_block(v) y = 50 self.blocks_list.setPos(self.sp, y) y += self.blocks_list._height() + self.sp self._place_childs_horizontally(y, self.sp, [ self.block_finished_btn, self.block_edit_btn, self.block_on_failure_btn ]) y += self.block_finished_btn._height() + self.sp group_enable((self.block_edit_btn, self.block_on_failure_btn), False) self.h = y # items "view" self.item_edit_btn = ButtonItem(self.scene(), 0, 0, translate("ProgramItem", "Edit"), self, self.item_edit_btn_cb) self.item_run_btn = ButtonItem(self.scene(), 0, 0, translate("ProgramItem", "Run"), self, self.item_run_btn_cb) self.item_on_success_btn = ButtonItem(self.scene(), 0, 0, translate("ProgramItem", "On S"), self, self.item_on_success_btn_cb) self.item_on_failure_btn = ButtonItem(self.scene(), 0, 0, translate("ProgramItem", "On F"), self, self.item_on_failure_btn_cb) self.item_finished_btn = ButtonItem( self.scene(), 0, 0, translate("ProgramItem", "Back to blocks"), self, self.item_finished_btn_cb) self.items_list = None group_visible((self.item_finished_btn, self.item_run_btn, self.item_on_success_btn, self.item_on_failure_btn, self.item_edit_btn), False) # readonly (program running) "view" self.pr_pause_btn = ButtonItem(self.scene(), 0, 0, translate("ProgramItem", "Pause"), self, self.pr_pause_btn_cb) if self.stopped: self.pr_pause_btn.set_caption(translate("ProgramItem", "Resume")) self.pr_cancel_btn = ButtonItem(self.scene(), 0, 0, translate("ProgramItem", "Stop"), self, self.pr_cancel_btn_cb) group_visible((self.pr_pause_btn, self.pr_cancel_btn), False) self.fixed = False self.editing_item = False self.edit_request = False self.run_request = False self.setFlag(QtGui.QGraphicsItem.ItemIsMovable, True) self.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, True) self.setZValue(100) self._update_learned() self.update() if self.item_switched_cb: self.item_switched_cb(None, None, blocks=True)
class ProgramItem(Item): def __init__(self, scene, x, y, program_helper, done_cb=None, item_switched_cb=None, learning_request_cb=None, pause_cb=None, cancel_cb=None, stopped=False): self.w = 100 self.h = 100 self.done_cb = done_cb self.item_switched_cb = item_switched_cb self.learning_request_cb = learning_request_cb self.pause_cb = pause_cb self.cancel_cb = cancel_cb self.readonly = False self.stopped = stopped super(ProgramItem, self).__init__(scene, x, y) self.w = self.m2pix(0.2) self.h = self.m2pix(0.25) self.sp = self.m2pix(0.005) self.ph = program_helper self.block_id = None self.item_id = None self.block_learned = False self.program_learned = False # block "view" self.block_finished_btn = ButtonItem(self.scene(), 0, 0, translate("ProgramItem", "Done"), self, self.block_finished_btn_cb) self.block_edit_btn = ButtonItem(self.scene(), 0, 0, translate("ProgramItem", "Edit"), self, self.block_edit_btn_cb) self.block_on_failure_btn = ButtonItem( self.scene(), 0, 0, translate("ProgramItem", "On fail"), self, self.block_on_failure_btn) bdata = [] self.blocks_map = {} # map from indexes (key) to block_id (value) self.blocks_map_rev = {} for i in range(len(self.ph.get_program().blocks)): bmsg = self.ph.get_program().blocks[i] bdata.append( translate("ProgramItem", "Block %1\n%2").arg(bmsg.id).arg(bmsg.name)) idx = len(bdata) - 1 self.blocks_map[idx] = bmsg.id self.blocks_map_rev[bmsg.id] = idx self.blocks_list = ListItem(self.scene(), 0, 0, 0.2 - 2 * 0.005, bdata, self.block_selected_cb, parent=self) for k, v in self.blocks_map.iteritems(): self._update_block(v) y = 50 self.blocks_list.setPos(self.sp, y) y += self.blocks_list._height() + self.sp self._place_childs_horizontally(y, self.sp, [ self.block_finished_btn, self.block_edit_btn, self.block_on_failure_btn ]) y += self.block_finished_btn._height() + self.sp group_enable((self.block_edit_btn, self.block_on_failure_btn), False) self.h = y # items "view" self.item_edit_btn = ButtonItem(self.scene(), 0, 0, translate("ProgramItem", "Edit"), self, self.item_edit_btn_cb) self.item_run_btn = ButtonItem(self.scene(), 0, 0, translate("ProgramItem", "Run"), self, self.item_run_btn_cb) self.item_on_success_btn = ButtonItem(self.scene(), 0, 0, translate("ProgramItem", "On S"), self, self.item_on_success_btn_cb) self.item_on_failure_btn = ButtonItem(self.scene(), 0, 0, translate("ProgramItem", "On F"), self, self.item_on_failure_btn_cb) self.item_finished_btn = ButtonItem( self.scene(), 0, 0, translate("ProgramItem", "Back to blocks"), self, self.item_finished_btn_cb) self.items_list = None group_visible((self.item_finished_btn, self.item_run_btn, self.item_on_success_btn, self.item_on_failure_btn, self.item_edit_btn), False) # readonly (program running) "view" self.pr_pause_btn = ButtonItem(self.scene(), 0, 0, translate("ProgramItem", "Pause"), self, self.pr_pause_btn_cb) if self.stopped: self.pr_pause_btn.set_caption(translate("ProgramItem", "Resume")) self.pr_cancel_btn = ButtonItem(self.scene(), 0, 0, translate("ProgramItem", "Stop"), self, self.pr_cancel_btn_cb) group_visible((self.pr_pause_btn, self.pr_cancel_btn), False) self.fixed = False self.editing_item = False self.edit_request = False self.run_request = False self.setFlag(QtGui.QGraphicsItem.ItemIsMovable, True) self.setFlag(QtGui.QGraphicsItem.ItemIsSelectable, True) self.setZValue(100) self._update_learned() self.update() if self.item_switched_cb: self.item_switched_cb(None, None, blocks=True) def pr_pause_btn_cb(self, btn): if self.pause_cb is not None: ret = self.pause_cb() if ret: # set disabled and wait for state update self.set_enabled(False) def pr_cancel_btn_cb(self, btn): if self.cancel_cb is not None: ret = self.cancel_cb() if ret: # set disabled and wait for state update self.set_enabled(False) def _update_learned(self): if self.block_id is not None: self.block_learned = self.ph.block_learned(self.block_id) self.program_learned = self.ph.program_learned() def set_readonly(self, readonly): self.readonly = readonly if self.readonly: if self.items_list is not None: self.items_list.setVisible(True) self.items_list.setEnabled(False) self.blocks_list.set_enabled(False, True) group_visible((self.block_finished_btn, self.block_edit_btn, self.block_on_failure_btn), False) group_enable((self.pr_pause_btn, self.pr_cancel_btn), True) else: # TODO pass self.update() def set_program_btns_enabled(self, state): group_enable((self.pr_pause_btn, self.pr_cancel_btn), state) def set_active(self, block_id, item_id): old_block_id = self.block_id self.block_id = block_id self.item_id = item_id if old_block_id != self.block_id: self._init_items_list() self.items_list.set_current_idx(self.items_map_rev[self.item_id], select=True) self._handle_item_btns() if self.item_id is not None: group_visible((self.block_finished_btn, self.block_edit_btn, self.block_on_failure_btn), False) def get_text_for_item(self, block_id, item_id): item = self.ph.get_item_msg(block_id, item_id) text = str(item.id) text += " | " if item.type == ProgIt.GET_READY: text += translate("ProgramItem", "GET_READY").toUpper() elif item.type == ProgIt.WAIT_FOR_USER: text += translate("ProgramItem", "WAIT_FOR_USER").toUpper() elif item.type == ProgIt.WAIT_UNTIL_USER_FINISHES: text += translate("ProgramItem", "WAIT_UNTIL_USER_FINISHES").toUpper() elif item.type == ProgIt.PICK_FROM_POLYGON: text += translate("ProgramItem", "PICK_FROM_POLYGON").toUpper() elif item.type == ProgIt.PICK_FROM_FEEDER: text += translate("ProgramItem", "PICK_FROM_FEEDER").toUpper() elif item.type == ProgIt.PLACE_TO_POSE: text += translate("ProgramItem", "PLACE_TO_POSE").toUpper() text += ' ' + translate("ProgramItem", "object from step %1").toUpper().arg( item.ref_id[0]) elif item.type == ProgIt.PLACE_TO_GRID: text += translate("ProgramItem", "PLACE_TO_GRID").toUpper() elif item.type == ProgIt.DRILL_POINTS: text += translate("ProgramItem", "DRILL POINTS").toUpper() if len(item.ref_id) > 0: if self.ph.item_has_nothing_to_set(block_id, item_id): text += translate("ProgramItem", " (copy of %1)").arg(item.ref_id[0]) # else: # text += translate("ProgramItem", " (refers to %1)").arg(', '.join(str(x) for x in item.ref_id)) if item.type in self.ph.ITEMS_USING_OBJECT: (obj, ref_id) = self.ph.get_object(block_id, item_id) text += "\n" if self.ph.is_object_set(block_id, item_id): obj_txt = obj[0] else: obj_txt = "??" text += translate("ProgramItem", " Object type: %1").arg(obj_txt) if ref_id != item_id: text += translate("ProgramItem", " (same as in %1)").arg(ref_id) if item.type == ProgIt.DRILL_POINTS: ps, ref_id = self.ph.get_pose(block_id, item_id) ps_learned = 0.0 for i in range(len(ps)): if self.ph.is_pose_set(block_id, item_id, i): ps_learned += 1 text += translate("ProgramItem", " learned poses: %1/%2").arg(ps_learned).arg( len(ps)) if item.type == ProgIt.PICK_FROM_FEEDER: text += "\n" if self.ph.is_pose_set(block_id, item_id): text += translate("ProgramItem", " Pose stored.") else: text += translate("ProgramItem", " Pose has to be set.") text += "\n" text += translate("ProgramItem", " Success: %1, failure: %2").arg( item.on_success).arg(item.on_failure) return text def _init_items_list(self): idata = [] self.items_map = {} # map from indexes (key) to item_id (value) self.items_map_rev = {} bmsg = self.ph.get_block_msg(self.block_id) for i in range(len(bmsg.items)): item_id = bmsg.items[i].id idata.append(self.get_text_for_item(self.block_id, item_id)) self.items_map[i] = item_id self.items_map_rev[item_id] = i self.items_list = ListItem(self.scene(), 0, 0, 0.2 - 2 * 0.005, idata, self.item_selected_cb, parent=self) for k, v in self.items_map.iteritems(): if self.ph.item_requires_learning(self.block_id, v): self._update_item(self.block_id, v) else: self.items_list.items[k].set_enabled(False) y = 50 self.items_list.setPos(self.sp, y) y += self.items_list._height() + self.sp if not self.readonly: self._place_childs_horizontally(y, self.sp, [ self.item_edit_btn, self.item_run_btn, self.item_on_success_btn, self.item_on_failure_btn ]) y += self.item_finished_btn._height() + self.sp self._place_childs_horizontally(y, self.sp, [self.item_finished_btn]) y += self.item_finished_btn._height() + 3 * self.sp group_visible((self.item_finished_btn, self.item_run_btn, self.item_on_success_btn, self.item_on_failure_btn, self.item_edit_btn), True) self.item_finished_btn.setEnabled(True) group_enable((self.item_run_btn, self.item_on_failure_btn, self.item_on_success_btn, self.item_on_failure_btn), False) group_visible((self.pr_pause_btn, self.pr_cancel_btn), False) else: self.items_list.setEnabled(False) self._place_childs_horizontally( y, self.sp, [self.pr_pause_btn, self.pr_cancel_btn]) y += self.pr_pause_btn._height() + 3 * self.sp pr = (self.pr_pause_btn, self.pr_cancel_btn) group_enable(pr, True) group_visible((self.item_finished_btn, self.item_run_btn, self.item_on_success_btn, self.item_on_failure_btn, self.item_edit_btn), False) self.h = y self.update() if self.item_switched_cb: self.item_switched_cb(self.block_id, None, blocks=False) def block_edit_btn_cb(self, btn): group_visible((self.block_finished_btn, self.block_edit_btn, self.item_on_success_btn, self.block_on_failure_btn, self.blocks_list), False) self._init_items_list() def block_selected_cb(self): if self.blocks_list.selected_item_idx is not None: self.block_id = self.blocks_map[self.blocks_list.selected_item_idx] if self.ph.get_block_on_failure(self.block_id) != 0: self.block_on_failure_btn.set_enabled(True) else: self.block_on_failure_btn.set_enabled(False) self.block_edit_btn.set_enabled(True) if self.item_switched_cb: self.item_switched_cb(self.block_id, None, blocks=True) self._update_learned() else: self.block_id = None self.item_id = None self.block_edit_btn.set_enabled(False) self.block_on_failure_btn.set_enabled(False) if self.item_switched_cb is not None: self.item_switched_cb(self.block_id, None, blocks=True) def _handle_item_btns(self): # print ("_handle_item_btns, self.editing_item: " + str(self.editing_item)) if not self.editing_item: of = self.ph.get_id_on_failure(self.block_id, self.item_id) os = self.ph.get_id_on_success(self.block_id, self.item_id) self.item_on_failure_btn.set_enabled( of[0] != 0 and not (of[0] == self.block_id and of[1] == self.item_id)) self.item_on_success_btn.set_enabled( os[0] != 0 and not (os[0] == self.block_id and os[1] == self.item_id)) if self.ph.item_requires_learning( self.block_id, self.item_id) and self.ph.item_learned( self.block_id, self.item_id): self.item_run_btn.set_enabled(True) else: self.item_run_btn.set_enabled(False) # TODO place pose with object through ref_id - disable Edit when object is not set self.item_edit_btn.set_enabled( self.ph.item_requires_learning(self.block_id, self.item_id) and not self.ph.item_has_nothing_to_set( self.block_id, self.item_id)) else: self.item_edit_btn.set_enabled(True) self.item_edit_btn.set_caption(translate("ProgramItem", "Done")) group_enable((self.item_finished_btn, self.items_list), False) self.item_run_btn.set_enabled(False) group_visible((self.pr_cancel_btn, self.pr_pause_btn), False) def item_selected_cb(self): # print ("self.items_list.selected_item_idx", self.items_list.selected_item_idx) if self.items_list.selected_item_idx is not None: self.item_id = self.items_map[self.items_list.selected_item_idx] self._handle_item_btns() self._update_learned() else: self.item_id = None group_enable((self.item_run_btn, self.item_on_success_btn, self.item_on_failure_btn, self.item_edit_btn), False) if self.item_switched_cb is not None: self.item_switched_cb(self.block_id, self.item_id) def block_on_failure_btn(self, btn): self.set_active( *self.ph.get_id_on_failure(self.block_id, self.item_id)) def block_finished_btn_cb(self, btn): if self.done_cb is not None: self.done_cb() def item_finished_btn_cb(self, btn): # go back to blocks view group_visible((self.block_finished_btn, self.block_edit_btn, self.block_on_failure_btn, self.blocks_list), True) group_visible((self.item_finished_btn, self.item_run_btn, self.item_on_success_btn, self.item_on_failure_btn, self.item_edit_btn), False) self.block_selected_cb( ) # TODO extract method to set buttons to proper state self.blocks_list.setEnabled(True) self.block_finished_btn.setEnabled(True) self.scene().removeItem(self.items_list) self.items_list = None self.item_id = None if self.item_switched_cb is not None: self.item_switched_cb(self.block_id, self.item_id) self.update() def item_on_failure_btn_cb(self, btn): of = self.ph.get_id_on_failure(self.block_id, self.item_id) self.set_active(*of) if self.item_switched_cb is not None: self.item_switched_cb(*of) def item_on_success_btn_cb(self, btn): of = self.ph.get_id_on_success(self.block_id, self.item_id) self.set_active(*of) if self.item_switched_cb is not None: self.item_switched_cb(*of) def item_run_btn_cb(self, btn): self.run_request = True self.set_enabled(False) self.learning_request_cb(LearningRequestGoal.EXECUTE_ITEM) def item_edit_btn_cb(self, btn): self.edit_request = True # call action / disable all, wait for result (callback), enable editing if not self.editing_item: self.learning_request_cb(LearningRequestGoal.GET_READY) else: self.learning_request_cb(LearningRequestGoal.DONE) self.set_enabled(False) def learning_request_result(self, success): self.set_enabled(True) # TODO no success, no editing if self.edit_request: self.edit_request = False if not self.editing_item: self.editing_item = True self.item_edit_btn.set_caption(translate( "ProgramItem", "Done")) group_enable( (self.item_finished_btn, self.items_list, self.item_on_failure_btn, self.item_on_success_btn), False) else: self.editing_item = False self.item_edit_btn.set_caption(translate( "ProgramItem", "Edit")) group_enable((self.item_finished_btn, self.items_list), True) self._update_learned() self._handle_item_btns() elif self.run_request: self.run_request = False if self.item_switched_cb is not None: self.item_switched_cb(self.block_id, self.item_id, not self.editing_item) def boundingRect(self): return QtCore.QRectF(0, 0, self.w, self.h) def set_place_pose(self, place): msg = self.get_current_item() assert len(msg.pose) > 0 msg.pose[0].pose.position.x = place.position[0] msg.pose[0].pose.position.y = place.position[1] msg.pose[0].pose.position.z = place.position[2] msg.pose[0].pose.orientation = conversions.a2q(place.quaternion) self._update_item() ''' Method which saves place poses of all objects (in the grid) into the ProgramItem message. ''' def set_place_poses(self, poses): msg = self.get_current_item() poses_count = len(poses) msg_poses_count = len(msg.pose) # TODO nemel by byt pocet objektu v gridu spis fixni (dany strukturou programu)? if poses_count > msg_poses_count: for i in range(poses_count - msg_poses_count): ps = PoseStamped() msg.pose.append(ps) elif poses_count < msg_poses_count: for i in range(msg_poses_count - poses_count): msg.pose.pop() for i, pose in enumerate(poses): pos = pose.get_pos() msg.pose[i].pose.position.x = pos[0] msg.pose[i].pose.position.y = pos[1] msg.pose[i].pose.orientation = conversions.yaw2quaternion( pose.rotation()) self._update_item() def set_pose(self, ps): msg = self.get_current_item() assert len(msg.pose) > 0 msg.pose[0] = ps self._update_item() def update_pose(self, ps, idx): msg = self.get_current_item() msg.pose[idx] = ps self._update_item() def clear_poses(self): for ps in self.get_current_item().pose: ps.pose = Pose() self._update_item() def get_poses_count(self): msg = self.get_current_item() return len(msg.pose) def set_object(self, obj): msg = self.get_current_item() assert len(msg.object) > 0 msg.object[0] = obj self._update_item() def set_polygon(self, pts): msg = self.get_current_item() assert len(msg.polygon) > 0 del msg.polygon[0].polygon.points[:] for pt in pts: msg.polygon[0].polygon.points.append(Point32(pt[0], pt[1], 0)) self._update_item() ''' Method which saves 4 points forming a grid into the ProgramItem message. ''' def set_place_grid(self, pts): msg = self.get_current_item() assert len(msg.polygon) > 0 del msg.polygon[0].polygon.points[:] for pt in pts: msg.polygon[0].polygon.points.append(Point32(pt[0], pt[1], 0)) self._update_item() def _update_block(self, block_id): idx = self.blocks_map_rev[block_id] if self.ph.block_learned(block_id): self.blocks_list.items[idx].set_background_color() else: self.blocks_list.items[idx].set_background_color(QtCore.Qt.red) def _update_item(self, block_id=None, item_id=None): if block_id is None: block_id = self.block_id # need to update all items in block as there might be various dependencies (ref_id) for idx, item_id in self.items_map.iteritems(): if self.ph.item_learned(block_id, item_id): self.items_list.items[idx].set_background_color() else: self.items_list.items[idx].set_background_color(QtCore.Qt.red) self.items_list.items[idx].set_caption( self.get_text_for_item(block_id, item_id)) self._update_block(block_id) def get_current_item(self): if self.block_id is not None and self.item_id is not None: return self.ph.get_item_msg(self.block_id, self.item_id) return None def paint(self, painter, option, widget): if not self.scene(): return painter.setClipRect(option.exposedRect) painter.setRenderHint(QtGui.QPainter.Antialiasing) font = QtGui.QFont('Arial', 14) painter.setFont(font) painter.setPen(QtCore.Qt.white) # TODO measure text size / use label sp = self.m2pix(0.01) if self.items_list is not None: if not self.block_learned and not self.readonly: painter.setPen(QtCore.Qt.red) painter.drawText( sp, 2 * sp, translate("ProgramItem", "Program %1, block %2").arg( self.ph.get_program_id()).arg(self.block_id)) else: if not self.program_learned and not self.readonly: painter.setPen(QtCore.Qt.red) painter.drawText( sp, 2 * sp, translate("ProgramItem", "Program %1").arg(self.ph.get_program_id())) pen = QtGui.QPen() pen.setStyle(QtCore.Qt.NoPen) painter.setPen(pen) painter.setBrush(QtCore.Qt.gray) painter.setOpacity(0.5) painter.drawRoundedRect(QtCore.QRect(0, 0, self.w, self.h), 5.0, 5.0)
class ProgramItem(Item): def __init__(self, scene, x, y, program_helper, done_cb=None, item_switched_cb=None, learning_request_cb=None): self.w = 100 self.h = 100 self.done_cb = done_cb self.item_switched_cb = item_switched_cb self.learning_request_cb = learning_request_cb self.readonly = False super(ProgramItem, self).__init__(scene, x, y) self.w = self.m2pix(0.2) self.h = self.m2pix(0.25) self.sp = self.m2pix(0.005) self.ph = program_helper self.block_id = None self.item_id = None self.block_learned = False self.program_learned = False # block "view" self.block_finished_btn = ButtonItem(self.scene(), 0, 0, translate("ProgramItem", "Done"), self, self.block_finished_btn_cb) self.block_edit_btn = ButtonItem(self.scene(), 0, 0, translate("ProgramItem", "Edit"), self, self.block_edit_btn_cb) self.block_on_failure_btn = ButtonItem( self.scene(), 0, 0, translate("ProgramItem", "On fail"), self, self.block_on_failure_btn) bdata = [] self.blocks_map = {} # map from indexes (key) to block_id (value) self.blocks_map_rev = {} block_id = self.ph.get_first_block_id() while block_id != 0: bmsg = self.ph.get_block_msg(block_id) bdata.append("Block ID: " + str(block_id) + "\nName: " + bmsg.name) idx = len(bdata) - 1 self.blocks_map[idx] = block_id self.blocks_map_rev[block_id] = idx block_id = self.ph.get_block_on_success(block_id) # test for cycle if block_id in self.blocks_map_rev: break self.blocks_list = ListItem(self.scene(), 0, 0, 0.2 - 2 * 0.005, bdata, self.block_selected_cb, parent=self) for k, v in self.blocks_map.iteritems(): self._update_block(v) y = 50 self.blocks_list.setPos(self.sp, y) y += self.blocks_list._height() + self.sp self._place_childs_horizontally(y, self.sp, [ self.block_finished_btn, self.block_edit_btn, self.block_on_failure_btn ]) y += self.block_finished_btn._height() + self.sp group_enable((self.block_edit_btn, self.block_on_failure_btn), False) self.h = y self.update() # items "view" self.item_edit_btn = ButtonItem(self.scene(), 0, 0, translate("ProgramItem", "Edit"), self, self.item_edit_btn_cb) self.item_run_btn = ButtonItem(self.scene(), 0, 0, translate("ProgramItem", "Run"), self, self.item_run_btn_cb) self.item_on_failure_btn = ButtonItem( self.scene(), 0, 0, translate("ProgramItem", "On fail"), self, self.item_on_failure_btn_cb) self.item_finished_btn = ButtonItem( self.scene(), 0, 0, translate("ProgramItem", "Back to blocks"), self, self.item_finished_btn_cb) self.items_list = None group_visible((self.item_finished_btn, self.item_run_btn, self.item_on_failure_btn, self.item_edit_btn), False) # readonly (program running) "view" self.pr_pause_btn = ButtonItem(self.scene(), 0, 0, translate("ProgramItem", "Pause"), self, self.pr_pause_btn_cb) self.pr_repeat_btn = ButtonItem(self.scene(), 0, 0, translate("ProgramItem", "Repeat"), self, self.pr_repeat_btn_cb) self.pr_cancel_btn = ButtonItem(self.scene(), 0, 0, translate("ProgramItem", "Cancel"), self, self.pr_cancel_btn_cb) group_visible( (self.pr_pause_btn, self.pr_repeat_btn, self.pr_cancel_btn), False) self.fixed = False self.editing_item = False self.edit_request = False self.run_request = False self.setZValue(100) def pr_pause_btn_cb(self, btn): pass def pr_repeat_btn_cb(self, btn): pass def pr_cancel_btn_cb(self, btn): pass def _update_learned(self): self.block_learned = self.ph.block_learned(self.block_id) self.program_learned = self.ph.program_learned() def set_readonly(self, readonly): self.readonly = readonly if self.readonly: if self.items_list is not None: self.items_list.setVisible(True) self.items_list.setEnabled(False) self.blocks_list.set_enabled(False, True) group_visible((self.block_finished_btn, self.block_edit_btn, self.block_on_failure_btn), False) group_visible( (self.pr_pause_btn, self.pr_repeat_btn, self.pr_cancel_btn), True) else: # TODO pass self.update() def set_active(self, block_id, item_id): old_block_id = self.block_id self.block_id = block_id self.item_id = item_id if not self.readonly: self.set_readonly(True) if old_block_id != self.block_id: self._init_items_list() self.items_list.set_current_idx(self.items_map_rev[self.item_id], select=True) def get_text_for_item(self, block_id, item_id): item = self.ph.get_item_msg(block_id, item_id) text = "(" + str(item.id) + ") " if item.type == ProgIt.GET_READY: text += QtCore.QCoreApplication.translate("ProgramItem", "GET_READY") elif item.type == ProgIt.WAIT_FOR_USER: text += QtCore.QCoreApplication.translate("ProgramItem", "WAIT_FOR_USER") elif item.type == ProgIt.WAIT_UNTIL_USER_FINISHES: text += QtCore.QCoreApplication.translate( "ProgramItem", "WAIT_UNTIL_USER_FINISHES") elif item.type == ProgIt.PICK_FROM_POLYGON: text += QtCore.QCoreApplication.translate("ProgramItem", "PICK_FROM_POLYGON") if self.ph.is_object_set(block_id, item_id): text += "\n" + "object type=" + item.object[0] else: text += "\n" + "object type=??" elif item.type == ProgIt.PICK_FROM_FEEDER: text += QtCore.QCoreApplication.translate("ProgramItem", "PICK_FROM_FEEDER") if self.ph.is_pose_set(block_id, item_id): text += "\n" + "x=" + str( round(item.pose[0].pose.position.x, 2)) + ", y=" + str( round(item.pose[0].pose.position.y, 2)) + ", z=" + str( round(item.pose[0].pose.position.z, 2)) else: text += "\n" + "x=??, y=??, z=??" if self.ph.is_object_set(block_id, item_id): text += "\n" + "object type=" + item.object[0] else: text += "\n" + "object type=??" elif item.type == ProgIt.PICK_OBJECT_ID: text += QtCore.QCoreApplication.translate("ProgramItem", "PICK_OBJECT_ID") if self.ph.is_object_set(block_id, item_id): text += "\n" + "object ID=" + item.object[0] else: text += "\n" + "object ID=??" elif item.type == ProgIt.PLACE_TO_POSE: text += QtCore.QCoreApplication.translate("ProgramItem", "PLACE_TO_POSE") if self.ph.is_object_set(block_id, item.ref_id[0]): ref_item = self.ph.get_item_msg(block_id, item.ref_id[0]) text += "\n" + \ "object from (" + \ str(item.ref_id[0]) + ")=" + ref_item.object[0] else: text += "\n" + "object from (" + str(item.ref_id[0]) + ")=??" if self.ph.is_pose_set(block_id, item_id): text += "\n" + "x=" + str( round(item.pose[0].pose.position.x, 2)) + ", y=" + str( round(item.pose[0].pose.position.y, 2)) else: text += "\n" + "x=??, y=??" return text def _init_items_list(self): idata = [] self.items_map = {} # map from indexes (key) to item_id (value) self.items_map_rev = {} item_id = self.ph.get_first_item_id(self.block_id) while item_id[0] == self.block_id: idata.append(self.get_text_for_item(*item_id)) idx = len(idata) - 1 self.items_map[idx] = item_id[1] self.items_map_rev[item_id[1]] = idx item_id = self.ph.get_id_on_success(*item_id) # test for cycle (e.g. jump from the last item to the first one) if item_id[1] in self.items_map_rev: break self.items_list = ListItem(self.scene(), 0, 0, 0.2 - 2 * 0.005, idata, self.item_selected_cb, parent=self) for k, v in self.items_map.iteritems(): if self.ph.item_requires_learning(self.block_id, v): self._update_item(self.block_id, v) else: self.items_list.items[k].set_enabled(False) y = 50 self.items_list.setPos(self.sp, y) y += self.items_list._height() + self.sp if not self.readonly: self._place_childs_horizontally(y, self.sp, [ self.item_edit_btn, self.item_run_btn, self.item_on_failure_btn ]) y += self.item_finished_btn._height() + self.sp self._place_childs_horizontally(y, self.sp, [self.item_finished_btn]) y += self.item_finished_btn._height() + 3 * self.sp group_visible((self.item_finished_btn, self.item_run_btn, self.item_on_failure_btn, self.item_edit_btn), True) self.item_finished_btn.setEnabled(True) group_enable((self.item_run_btn, self.item_on_failure_btn, self.item_on_failure_btn), False) group_visible( (self.pr_pause_btn, self.pr_repeat_btn, self.pr_cancel_btn), False) else: self.items_list.setEnabled(False) self._place_childs_horizontally( y, self.sp, [self.pr_pause_btn, self.pr_repeat_btn, self.pr_cancel_btn]) y += self.pr_pause_btn._height() + 3 * self.sp pr = (self.pr_pause_btn, self.pr_repeat_btn, self.pr_cancel_btn) group_visible(pr, True) group_enable(pr, False) group_visible((self.item_finished_btn, self.item_run_btn, self.item_on_failure_btn, self.item_edit_btn), False) self.h = y self.update() def block_edit_btn_cb(self, btn): group_visible((self.block_finished_btn, self.block_edit_btn, self.block_on_failure_btn, self.blocks_list), False) self._init_items_list() def block_selected_cb(self): if self.blocks_list.selected_item_idx is not None: self.block_id = self.blocks_map[self.blocks_list.selected_item_idx] if self.ph.get_block_on_failure(self.block_id) != 0: self.block_on_failure_btn.set_enabled(True) else: self.block_on_failure_btn.set_enabled(False) self.block_edit_btn.set_enabled(True) if self.item_switched_cb is not None: self.item_switched_cb(self.block_id, None) self._update_learned() else: self.block_id = None self.item_id = None self.block_edit_btn.set_enabled(False) self.block_on_failure_btn.set_enabled(False) def _handle_item_btns(self): of = self.ph.get_id_on_failure(self.block_id, self.item_id) if of[0] == self.block_id and of[1] != 0: self.item_on_failure_btn.set_enabled(True) else: self.item_on_failure_btn.set_enabled(False) if not self.editing_item: if self.ph.item_requires_learning( self.block_id, self.item_id) and self.ph.item_learned( self.block_id, self.item_id): self.item_run_btn.set_enabled(True) else: self.item_run_btn.set_enabled(False) self.item_edit_btn.set_enabled( self.ph.item_requires_learning(self.block_id, self.item_id)) else: self.item_run_btn.set_enabled(False) def item_selected_cb(self): if self.items_list.selected_item_idx is not None: self.item_id = self.items_map[self.items_list.selected_item_idx] self._handle_item_btns() if self.item_switched_cb is not None: self.item_switched_cb(self.block_id, self.item_id) self._update_learned() else: self.item_id = None group_enable((self.item_run_btn, self.item_on_failure_btn, self.item_edit_btn), False) def block_on_failure_btn(self, btn): # TODO switch to on_failure item pass def block_finished_btn_cb(self, btn): if self.done_cb is not None: self.done_cb() def item_finished_btn_cb(self, btn): # go back to blocks view group_visible((self.block_finished_btn, self.block_edit_btn, self.block_on_failure_btn, self.blocks_list), True) group_visible((self.item_finished_btn, self.item_run_btn, self.item_on_failure_btn, self.item_edit_btn), False) self.block_selected_cb( ) # TODO extract method to set buttons to proper state self.blocks_list.setEnabled(True) self.block_finished_btn.setEnabled(True) self.scene().removeItem(self.items_list) self.items_list = None self.item_id = None if self.item_switched_cb is not None: self.item_switched_cb(self.block_id, self.item_id) def item_on_failure_btn_cb(self, btn): pass def item_run_btn_cb(self, btn): self.run_request = True self.set_enabled(False) self.learning_request_cb(LearningRequestGoal.EXECUTE_ITEM) def item_edit_btn_cb(self, btn): self.edit_request = True # call action / disable all, wait for result (callback), enable editing if not self.editing_item: self.learning_request_cb(LearningRequestGoal.GET_READY) else: self.learning_request_cb(LearningRequestGoal.DONE) self.set_enabled(False) def learning_request_result(self, success): self.set_enabled(True) # TODO no success, no editing if self.edit_request: self.edit_request = False if not self.editing_item: self.editing_item = True self.item_edit_btn.set_caption("Done") group_enable((self.item_finished_btn, self.items_list), False) else: self.editing_item = False self.item_edit_btn.set_caption("Edit") group_enable((self.item_finished_btn, self.items_list), True) self._update_learned() self._handle_item_btns() if self.item_switched_cb is not None: self.item_switched_cb(self.block_id, self.item_id, not self.editing_item) elif self.run_request: self.run_request = False def boundingRect(self): return QtCore.QRectF(0, 0, self.w, self.h) def set_place_pose(self, x, y, yaw): msg = self.get_current_item() msg.pose[0].pose.position.x = x msg.pose[0].pose.position.y = y msg.pose[0].pose.orientation = conversions.yaw2quaternion(yaw) self._update_item() def set_pose(self, ps): msg = self.get_current_item() msg.pose[0] = ps self._update_item() def set_object(self, obj): msg = self.get_current_item() msg.object = [obj] self._update_item() def set_polygon(self, pts): msg = self.get_current_item() del msg.polygon[0].polygon.points[:] for pt in pts: msg.polygon[0].polygon.points.append(Point32(pt[0], pt[1], 0)) self._update_item() def _update_block(self, block_id): idx = self.blocks_map_rev[block_id] if self.ph.block_learned(block_id): self.blocks_list.items[idx].set_background_color() else: self.blocks_list.items[idx].set_background_color(QtCore.Qt.red) def _update_item(self, block_id=None, item_id=None): if block_id is None and item_id is None: block_id = self.block_id item_id = self.item_id idx = self.items_map_rev[item_id] if self.ph.item_learned(block_id, item_id): self.items_list.items[idx].set_background_color() else: self.items_list.items[idx].set_background_color(QtCore.Qt.red) self.items_list.items[idx].set_caption( self.get_text_for_item(block_id, item_id)) self._update_block(block_id) def get_current_item(self): if (self.block_id is not None and self.item_id is not None): return self.ph.get_item_msg(self.block_id, self.item_id) return None def paint(self, painter, option, widget): if not self.scene(): return painter.setClipRect(option.exposedRect) painter.setRenderHint(QtGui.QPainter.Antialiasing) font = QtGui.QFont('Arial', 14) painter.setFont(font) painter.setPen(QtCore.Qt.white) # TODO measure text size / use label sp = self.m2pix(0.01) if self.block_id is not None: if not self.block_learned and not self.readonly: painter.setPen(QtCore.Qt.red) painter.drawText( sp, 2 * sp, translate("ProgramItem", "Block") + " ID: " + str(self.block_id)) else: if not self.program_learned and not self.readonly: painter.setPen(QtCore.Qt.red) painter.drawText( sp, 2 * sp, translate("ProgramItem", "Program") + " ID: " + str(self.ph.get_program_id())) pen = QtGui.QPen() pen.setStyle(QtCore.Qt.NoPen) painter.setPen(pen) painter.setBrush(QtCore.Qt.gray) painter.setOpacity(0.5) painter.drawRoundedRect(QtCore.QRect(0, 0, self.w, self.h), 5.0, 5.0)
def __init__(self, scene, x, y, program_helper, done_cb=None, item_switched_cb=None, learning_request_cb=None): self.w = 100 self.h = 100 self.done_cb = done_cb self.item_switched_cb = item_switched_cb self.learning_request_cb = learning_request_cb self.readonly = False super(ProgramItem, self).__init__(scene, x, y) self.w = self.m2pix(0.2) self.h = self.m2pix(0.25) self.sp = self.m2pix(0.005) self.ph = program_helper self.block_id = None self.item_id = None self.block_learned = False self.program_learned = False # block "view" self.block_finished_btn = ButtonItem(self.scene(), 0, 0, translate("ProgramItem", "Done"), self, self.block_finished_btn_cb) self.block_edit_btn = ButtonItem(self.scene(), 0, 0, translate("ProgramItem", "Edit"), self, self.block_edit_btn_cb) self.block_on_failure_btn = ButtonItem( self.scene(), 0, 0, translate("ProgramItem", "On fail"), self, self.block_on_failure_btn) bdata = [] self.blocks_map = {} # map from indexes (key) to block_id (value) self.blocks_map_rev = {} block_id = self.ph.get_first_block_id() while block_id != 0: bmsg = self.ph.get_block_msg(block_id) bdata.append("Block ID: " + str(block_id) + "\nName: " + bmsg.name) idx = len(bdata) - 1 self.blocks_map[idx] = block_id self.blocks_map_rev[block_id] = idx block_id = self.ph.get_block_on_success(block_id) # test for cycle if block_id in self.blocks_map_rev: break self.blocks_list = ListItem(self.scene(), 0, 0, 0.2 - 2 * 0.005, bdata, self.block_selected_cb, parent=self) for k, v in self.blocks_map.iteritems(): self._update_block(v) y = 50 self.blocks_list.setPos(self.sp, y) y += self.blocks_list._height() + self.sp self._place_childs_horizontally(y, self.sp, [ self.block_finished_btn, self.block_edit_btn, self.block_on_failure_btn ]) y += self.block_finished_btn._height() + self.sp group_enable((self.block_edit_btn, self.block_on_failure_btn), False) self.h = y self.update() # items "view" self.item_edit_btn = ButtonItem(self.scene(), 0, 0, translate("ProgramItem", "Edit"), self, self.item_edit_btn_cb) self.item_run_btn = ButtonItem(self.scene(), 0, 0, translate("ProgramItem", "Run"), self, self.item_run_btn_cb) self.item_on_failure_btn = ButtonItem( self.scene(), 0, 0, translate("ProgramItem", "On fail"), self, self.item_on_failure_btn_cb) self.item_finished_btn = ButtonItem( self.scene(), 0, 0, translate("ProgramItem", "Back to blocks"), self, self.item_finished_btn_cb) self.items_list = None group_visible((self.item_finished_btn, self.item_run_btn, self.item_on_failure_btn, self.item_edit_btn), False) # readonly (program running) "view" self.pr_pause_btn = ButtonItem(self.scene(), 0, 0, translate("ProgramItem", "Pause"), self, self.pr_pause_btn_cb) self.pr_repeat_btn = ButtonItem(self.scene(), 0, 0, translate("ProgramItem", "Repeat"), self, self.pr_repeat_btn_cb) self.pr_cancel_btn = ButtonItem(self.scene(), 0, 0, translate("ProgramItem", "Cancel"), self, self.pr_cancel_btn_cb) group_visible( (self.pr_pause_btn, self.pr_repeat_btn, self.pr_cancel_btn), False) self.fixed = False self.editing_item = False self.edit_request = False self.run_request = False self.setZValue(100)
class ProgramItem(Item): def __init__(self, scene, rpm, x, y, active_item_switched=None, program_state_changed=None): self.states = ['LEARNING', 'RUNNING', 'PAUSED', 'STOPPED'] self.state = 'LEARNING' self.w = 180 # TODO spocitat podle rpm self.h = 20 super(ProgramItem, self).__init__(scene, rpm, x, y) self.prog = None self.template = None self.items = [] self.active_item = None self.active_item_switched = active_item_switched self.program_state_changed = program_state_changed self.fixed = False self.setZValue(100) def set_running(self): self.state = 'RUNNING' def has_prog(self): return self.prog is None def set_active(self, it=None, inst_id=None): if it is None and inst_id is not None: it = self.get_item_by_id(inst_id) if it is None: return if self.active_item is not None: self.active_item.setPos(30, self.active_item.y()) self.active_item.active_item = False it.active_item = True self.active_item = it self.active_item.update() self.active_item.setPos(10, self.active_item.y()) def is_prog_learned(self): for it in self.items: if not it.item_learned(): return False return True def get_prog(self): # TODO deal with more blocks del self.prog.blocks[0].items[:] for it in self.items: self.prog.blocks[0].items.append(it.item) return self.prog def set_prog(self, prog, template): self.prog = prog self.template = template self.items = [] self.active_item = None cnt = 0 max_w = 0 # TODO Handle program groups - create ProgramGroupItem class and allow switching between groups. For now, let's assume that there will always be just one group for pitem in self.prog.blocks[0].items: if self.template: # to make sure that template is 'clear' pitem.object = "" del pitem.pick_polygon.polygon.points[:] pitem.place_pose.pose.position.x = 0 pitem.place_pose.pose.position.y = 0 pitem.place_pose.pose.position.z = 0 # TODO how to place items easily? using some layout?? self.items.append(ProgramItemItem(self.scene(), self.rpm, 0, 0, pitem, self, self.item_selected_cb)) if len(self.items) < 2: self.items[-1].setPos(30, 20) else: self.items[-1].setPos(30, 10 + self.items[-2].y() + self.items[-2].h) if self.items[-1].w > max_w: max_w = self.items[-1].w cnt += 1 # set first item as active if (self.active_item is None) and self.items[-1].item_req_learning(): self.set_active(self.items[-1]) # if pitem.type in self.items_req_learning: # if self.active_item is None: self.active_item = pitem self.btn = ButtonItem(self.scene(), self.rpm, 0, 0, translate("ProgramItem", "Start"), self, self.btn_clicked) self.btn.setPos(10, 5 + cnt * 50) self.btn.set_enabled(False) # TODO najit max. sirku itemu a tomu prizpusobit sirku programu self.h = 20 + cnt * 50 + 30 self.w = max_w + 40 self.update() def btn_clicked(self): if self.state == 'LEARNING': self.state = 'RUNNING' self.btn.set_caption(translate("ProgramItem", "Pause")) elif self.state == 'RUNNING': self.state = 'PAUSED' self.btn.set_caption(translate("ProgramItem", "Resume")) # TODO second button for STOP if self.program_state_changed is not None: self.program_state_changed(self.state) def item_selected_cb(self, it): if self.state == 'RUNNING': print "program running - ignoring item selection" return self.set_active(it) if self.active_item_switched is not None: self.active_item_switched() def update_size(self): self.active_item.update_size() max_w = 0 for it in self.items: if self.active_item.w + 40 > max_w: max_w = self.active_item.w + 40 self.w = max_w self.update() def program_updated(self): # TODO consides state if self.is_prog_learned(): print "enabling start button" self.btn.set_enabled(True) def set_object(self, obj): self.active_item.item.object = obj self.program_updated() self.update_size() def set_place_pose(self, x, y): self.active_item.item.place_pose.pose.position.x = x self.active_item.item.place_pose.pose.position.y = y self.active_item.item.place_pose.pose.orientation.w = 1.0 self.program_updated() self.update_size() def set_polygon(self, pts): del self.active_item.item.pick_polygon.polygon.points[:] for pt in pts: self.active_item.item.pick_polygon.polygon.points.append(Point32(pt[0], pt[1], 0)) self.program_updated() self.update_size() def boundingRect(self): return QtCore.QRectF(0, -30, self.w, self.h + 30) def get_item_by_id(self, id): for it in self.items: if it.item.id == id: return it return None def paint(self, painter, option, widget): if self.prog is None: return painter.setClipRect(option.exposedRect) painter.setRenderHint(QtGui.QPainter.Antialiasing) font = QtGui.QFont('Arial', 14) painter.setFont(font) painter.setPen(QtCore.Qt.white) painter.drawText(0, -10, translate("ProgramItem", "Program") + " ID=" + str(self.prog.id)) pen = QtGui.QPen() pen.setStyle(QtCore.Qt.NoPen) painter.setPen(pen) painter.setBrush(QtCore.Qt.gray) painter.setOpacity(0.5) # TODO projit itemy a zjistit skutecnou velikost (muze byt ruzna) painter.drawRect(0, 0, self.w, self.h)