Esempio n. 1
0
	def dragMoveEvent(self, e):

		"""
		desc:
			Handles drag-move events to see if the item tree can handle
			incoming drops.

		arguments:
			e:
				desc:	A drag-move event.
				type:	QDragMoveEvent
		"""

		data = drag_and_drop.receive(e)
		if drag_and_drop.matches(data, [u'url-local']):
			e.accept()
			return
		if not drag_and_drop.matches(data, [u'item-new', u'item-existing']):
			e.accept()
			return
		target = self.itemAt(e.pos())
		if not self.droppable(target, data):
			e.ignore()
			return
		e.accept()
Esempio n. 2
0
    def drop_event_item_move(self, data, e):

        """
		desc:
			Handles drop events for item moves.

		arguments:
			data:
				desc:	A drop-data dictionary.
				type:	dict:
			e:
				desc:	A drop event.
				type:	QDropEvent
		"""

        if not drag_and_drop.matches(data, [u"item-existing"]):
            e.ignore()
            return
        target_treeitem = self.itemAt(e.pos())
        if not self.droppable(target_treeitem, data):
            debug.msg(u"Drop ignored: target not droppable")
            self.main_window.set_status(_(u"Drop cancelled: Target not droppable"))
            e.ignore()
            return
            # If the drop comes from this application, check for recursion etc.
        if data[u"application-id"] == self.main_window._id():
            target_item_name, target_item_ancestry = target_treeitem.ancestry()
            item_name = data[u"item-name"]
            item = self.experiment.items[item_name]
            if target_item_name in item.children():
                debug.msg(u"Drop ignored: recursion prevented")
                self.main_window.set_status(_(u"Drop cancelled: Recursion prevented"))
                e.ignore()
                return
            parent_item_name, index = self.parent_from_ancestry(data[u"ancestry"])
            if parent_item_name == None:
                debug.msg(u"Drop ignored: no parent")
                e.ignore()
                return
                # The logic below is a bit complicated, but works as follows:
                # - If we're in a move action, remove the dragged item from its parent,
                #   and set need_restore so that we know this happened.
                # - Try to drop the dragged item onto the target item
                # - If the drop action was unsuccesful, and if need_restore is set,
                #   re-add the dragged item to its former parent.
        need_restore = False
        if not QtCore.Qt.ControlModifier & e.keyboardModifiers() and data[u"application-id"] == self.main_window._id():
            if parent_item_name not in self.experiment.items:
                debug.msg(u"Don't know how to remove item from %s" % parent_item_name)
            else:
                self.locked = True
                need_restore = True
                self.experiment.items[parent_item_name].remove_child_item(item_name, index)
                self.locked = False
        if self.drop_event_item_new(data, e, target_treeitem=target_treeitem):
            return
        if need_restore:
            self.experiment.items[parent_item_name].insert_child_item(item_name, index)
            self.experiment.build_item_tree()
Esempio n. 3
0
    def dragMoveEvent(self, e):
        """
		desc:
			Handles drag-move events to see if the item tree can handle
			incoming drops.

		arguments:
			e:
				desc:	A drag-move event.
				type:	QDragMoveEvent
		"""

        data = drag_and_drop.receive(e)
        self.drop_indicator = None
        if drag_and_drop.matches(data, [u'url-local']):
            e.accept()
            self.end_drag()
            return
        if not drag_and_drop.matches(data,
                                     [u'item-snippet', u'item-existing']):
            e.accept()
            self.end_drag()
            return
        target = self.itemAt(e.pos())
        if not self.droppable(target, data):
            self.end_drag()
            e.ignore()
            return
        e.accept()
        # Update the drop indicator
        index = self.indexFromItem(target)
        rect = self.visualRect(index)
        if target.name == u'__unused__' or ( \
         target.item.name in self.experiment.items.used() and \
         isinstance(target.item, qtstructure_item) and \
         target.item.name != self.experiment.var.start and \
         target.parent() is not None):
            self.drop_indicator = rect
        else:
            self.drop_indicator = QtCore.QRect(rect.left(), rect.bottom(),
                                               rect.width(), 0)
        self.viewport().update()
Esempio n. 4
0
    def dragMoveEvent(self, e):

        """
		desc:
			Handles drag-move events to see if the item tree can handle
			incoming drops.

		arguments:
			e:
				desc:	A drag-move event.
				type:	QDragMoveEvent
		"""

        data = drag_and_drop.receive(e)
        self.drop_indicator = None
        if drag_and_drop.matches(data, [u"url-local"]):
            e.accept()
            self.end_drag()
            return
        if not drag_and_drop.matches(data, [u"item-snippet", u"item-existing"]):
            e.accept()
            self.end_drag()
            return
        target = self.itemAt(e.pos())
        if not self.droppable(target, data):
            self.end_drag()
            e.ignore()
            return
        e.accept()
        # Update the drop indicator
        index = self.indexFromItem(target)
        rect = self.visualRect(index)
        if target.name == u"__unused__" or (
            target.item.name in self.experiment.items.used()
            and isinstance(target.item, qtstructure_item)
            and target.item.name != self.experiment.var.start
            and target.parent() is not None
        ):
            self.drop_indicator = rect
        else:
            self.drop_indicator = QtCore.QRect(rect.left(), rect.bottom(), rect.width(), 0)
        self.viewport().update()
Esempio n. 5
0
	def dragMoveEvent(self, e):

		"""
		desc:
			Handles drag-move events to see if the item tree can handle
			incoming drops.

		arguments:
			e:
				desc:	A drag-move event.
				type:	QDragMoveEvent
		"""

		data = drag_and_drop.receive(e)
		self.drop_indicator = None
		if drag_and_drop.matches(data, [u'url-local']):
			e.accept()
			self.end_drag()
			return
		if not drag_and_drop.matches(data, [u'item-new', u'item-existing']):
			e.accept()
			self.end_drag()
			return
		target = self.itemAt(e.pos())
		if not self.droppable(target, data):
			self.end_drag()
			e.ignore()
			return
		e.accept()
		# Update the drop indicator
		index = self.indexFromItem(target)
		rect = self.visualRect(index)
		if target.name == u'__unused__' or (
			target.item.item_type in (u'loop', u'sequence') and \
			target.item.name != self.experiment.start and \
			target.parent() is not None):
			self.drop_indicator = rect
		else:
			self.drop_indicator = QtCore.QRect(rect.left(), rect.bottom(),
				rect.width(), 0)
		self.viewport().update()
Esempio n. 6
0
	def drop_event_item_move(self, data, e):

		"""
		desc:
			Handles drop events for item moves.

		arguments:
			data:
				desc:	A drop-data dictionary.
				type:	dict:
			e:
				desc:	A drop event.
				type:	QDropEvent
		"""

		if not drag_and_drop.matches(data, [u'item-existing']):
			e.ignore()
			return
		target_treeitem = self.itemAt(e.pos())
		if not self.droppable(target_treeitem, data):
			debug.msg(u'Drop ignored: target not droppable')
			self.main_window.set_status(
				_(u'Drop cancelled: Target not droppable'))
			e.ignore()
			return
		target_item_name, target_item_ancestry = target_treeitem.ancestry()
		item_name = data[u'item-name']
		item = self.experiment.items[item_name]
		if target_item_name in item.children():
			debug.msg(u'Drop ignored: recursion prevented')
			self.main_window.set_status(
				_(u'Drop cancelled: Recursion prevented'))
			e.ignore()
			return
		parent_item_name, index = self.parent_from_ancestry(data[u'ancestry'])
		if parent_item_name == None:
			debug.msg(u'Drop ignored: no parent')
			e.ignore()
			return
		if not QtCore.Qt.ControlModifier & e.keyboardModifiers():
			if parent_item_name not in self.experiment.items:
				debug.msg(u'Don\'t know how to remove item from %s' \
					% parent_item_name)
			else:
				self.locked = True
				self.experiment.items[parent_item_name].remove_child_item(
					item_name, index)
				self.locked = False
		self.drop_event_item_new(data, e, target_treeitem=target_treeitem)
Esempio n. 7
0
    def drop_event_item_move(self, data, e):
        """
		desc:
			Handles drop events for item moves.

		arguments:
			data:
				desc:	A drop-data dictionary.
				type:	dict:
			e:
				desc:	A drop event.
				type:	QDropEvent
		"""

        if not drag_and_drop.matches(data, [u'item-existing']):
            e.ignore()
            return
        target_treeitem = self.itemAt(e.pos())
        if not self.droppable(target_treeitem, data):
            debug.msg(u'Drop ignored: target not droppable')
            self.main_window.set_status(
                _(u'Drop cancelled: Target not droppable'))
            e.ignore()
            return
        target_item_name, target_item_ancestry = target_treeitem.ancestry()
        item_name = data[u'item-name']
        if target_item_ancestry.startswith(u'%s:' % item_name) or \
         u'.%s:' % item_name  in target_item_ancestry:
            debug.msg(u'Drop ignored: recursion prevented')
            self.main_window.set_status(
                _(u'Drop cancelled: Recursion prevented'))
            e.ignore()
            return
        parent_item_name, index = self.parent_from_ancestry(data[u'ancestry'])
        if parent_item_name == None:
            debug.msg(u'Drop ignored: no parent')
            e.ignore()
            return
        if not QtCore.Qt.ControlModifier & e.keyboardModifiers():
            if parent_item_name not in self.experiment.items:
                debug.msg(u'Don\'t know how to remove item from %s' \
                 % parent_item_name)
            else:
                self.experiment.items[parent_item_name].remove_child_item(
                    item_name, index)
        self.drop_event_item_new(data, e)
Esempio n. 8
0
    def dragEnterEvent(self, e):
        """
		desc:
			Handles drag-enter events to see if the item tree can handle
			incoming drops.

		arguments:
			e:
				desc:	A drag-enter event.
				type:	QDragEnterEvent
		"""

        data = drag_and_drop.receive(e)
        if drag_and_drop.matches(
                data, [u'item-new', u'item-existing', u'url-local']):
            e.accept()
        else:
            e.ignore()
Esempio n. 9
0
    def dragEnterEvent(self, e):

        """
		desc:
			Handles drag-enter events to see if the item tree can handle
			incoming drops.

		arguments:
			e:
				desc:	A drag-enter event.
				type:	QDragEnterEvent
		"""

        data = drag_and_drop.receive(e)
        if drag_and_drop.matches(data, [u"item-new", u"item-existing", u"url-local"]):
            e.accept()
        else:
            e.ignore()
Esempio n. 10
0
    def dragEnterEvent(self, e):
        """
		desc:
			Handles drag-enter events to see if they are supported

		arguments:
			e:
				desc:	A drag-enter event.
				type:	QDragEnterEvent
		"""

        if not hasattr(self, u'supported_drop_types'):
            e.ignore()
            return
        data = drag_and_drop.receive(e)
        if drag_and_drop.matches(data, self.supported_drop_types):
            e.accept()
        else:
            e.ignore()
Esempio n. 11
0
    def dropEvent(self, e):
        """
		desc:
			Handles drop events and accepts them if supported.

		arguments:
			e:
				desc:	A drop event.
				type:	QDropEvent
		"""

        if not hasattr(self, u'supported_drop_types'):
            e.ignore()
            return
        data = drag_and_drop.receive(e)
        if drag_and_drop.matches(data, self.supported_drop_types):
            e.accept()
            self.accept_drop(data)
        else:
            e.ignore()
Esempio n. 12
0
	def dragEnterEvent(self, e):

		"""
		desc:
			Handles drag-enter events to see if they are supported

		arguments:
			e:
				desc:	A drag-enter event.
				type:	QDragEnterEvent
		"""

		if not hasattr(self, u'supported_drop_types'):
			e.ignore()
			return
		data = drag_and_drop.receive(e)
		if drag_and_drop.matches(data, self.supported_drop_types):
			e.accept()
		else:
			e.ignore()
Esempio n. 13
0
    def clipboard_data(self):
        """
		desc:
			Gets an item data dictionary from the clipboard.

		returns:
			desc:	A data dictionary or None if no valid data was found.
			type:	[dict, NoneType]
		"""

        import json
        from libqtopensesame.misc import drag_and_drop

        text = QtWidgets.QApplication.clipboard().text()
        try:
            data = json.loads(text)
        except:
            return None
        if drag_and_drop.matches(data, [u'item-snippet', u'item-existing']):
            return data
        return None
Esempio n. 14
0
	def dropEvent(self, e):

		"""
		desc:
			Handles drop events and accepts them if supported.

		arguments:
			e:
				desc:	A drop event.
				type:	QDropEvent
		"""

		if not hasattr(self, u'supported_drop_types'):
			e.ignore()
			return
		data = drag_and_drop.receive(e)
		if drag_and_drop.matches(data, self.supported_drop_types):
			e.accept()
			self.accept_drop(data)
		else:
			e.ignore()
Esempio n. 15
0
	def clipboard_data(self):

		"""
		desc:
			Gets an item data dictionary from the clipboard.

		returns:
			desc:	A data dictionary or None if no valid data was found.
			type:	[dict, NoneType]
		"""

		import json
		from libqtopensesame.misc import drag_and_drop

		text = unicode(QtGui.QApplication.clipboard().text())
		try:
			data = json.loads(text)
		except:
			return None
		if drag_and_drop.matches(data, [u'item-new']):
			return data
		return None
Esempio n. 16
0
    def drop_event_item_existing(self, data, e=None, target_treeitem=None):
        """
		desc:
			Handles drop events for item moves.

		arguments:
			data:
				desc:	A drop-data dictionary.
				type:	dict:
			e:
				desc:	A drop event.
				type:	QDropEvent
		"""

        if not drag_and_drop.matches(data, [u'item-existing']):
            if e is not None:
                e.ignore()
            return
        # Only accept existing-item drops from this application
        if data[u'application-id'] != self.main_window._id():
            debug.msg(u'Drop ignored: from different instance')
            if e is not None:
                e.ignore()
            return
        if target_treeitem is None:
            target_treeitem = self.itemAt(e.pos())
        if not self.droppable(target_treeitem, data):
            debug.msg(u'Drop ignored: target not droppable')
            if e is not None:
                e.ignore()
            return
        # Don't drop on the same item that was the source (if any)
        if u'QTreeWidgetItem' in data and \
         data[u'QTreeWidgetItem'] == str(target_treeitem):
            debug.msg(u'Drop ignored: dropping on self')
            if e is not None:
                e.ignore()
            return
        item_name = data[u'item-name']
        # Check for recursion when dropping sequences and loops. The target item
        # may not have the dropped item in its ancestry. However, the target
        # item may occur multiple times in the experiment, so we need to check
        # that this constraint holds for all linked copies of the target item.
        if data.get(u'structure-item', False):
            for linked_target_treeitem in self.findItems(
                    target_treeitem.name,
                    QtCore.Qt.MatchFixedString | QtCore.Qt.MatchRecursive):
                target_item_name, target_item_ancestry = \
                 linked_target_treeitem.ancestry()
                if target_item_ancestry.startswith(u'%s:' % item_name) or \
                 u'.%s:' % item_name  in target_item_ancestry:
                    debug.msg(u'Drop ignored: recursion prevented')
                    if e is not None:
                        e.ignore()
                    return
        # Don't drop on undroppable parents
        parent_item_name, index = self.parent_from_ancestry(data[u'ancestry'])
        if parent_item_name is None:
            debug.msg(u'Drop ignored: no parent')
            if e is not None:
                e.ignore()
            return
        # The logic below is a bit complicated, but works as follows:
        # - If we're in a move action, remove the dragged item from its parent,
        #   and set need_restore so that we know this happened.
        # - Try to drop the dragged item onto the target item
        # - If the drop action was unsuccesful, and if need_restore is set,
        #   re-add the dragged item to its former parent.
        need_restore = False
        if data[u'move']:
            if parent_item_name not in self.experiment.items:
                debug.msg(u'Don\'t know how to remove item from %s' \
                 % parent_item_name)
            else:
                self.locked = True
                need_restore = True
                self.experiment.items[parent_item_name].remove_child_item(
                    item_name, index)
                self.locked = False
        if self.drop_event_item_new(data, e, target_treeitem=target_treeitem):
            return
        if need_restore:
            self.experiment.items[parent_item_name].insert_child_item(
                item_name, index)
            self.experiment.build_item_tree()
Esempio n. 17
0
	def drop_event_item_existing(self, data, e=None, target_treeitem=None):

		"""
		desc:
			Handles drop events for item moves.

		arguments:
			data:
				desc:	A drop-data dictionary.
				type:	dict:
			e:
				desc:	A drop event.
				type:	QDropEvent
		"""

		if not drag_and_drop.matches(data, [u'item-existing']):
			if e is not None:
				e.ignore()
			return
		# Only accept existing-item drops from this application
		if data[u'application-id'] != self.main_window._id():
			debug.msg(u'Drop ignored: from different instance')
			if e is not None:
				e.ignore()
			return
		if target_treeitem is None:
			target_treeitem = self.itemAt(e.pos())
		if not self.droppable(target_treeitem, data):
			debug.msg(u'Drop ignored: target not droppable')
			if e is not None:
				e.ignore()
			return
		# Don't drop on the same item that was the source (if any)
		if u'QTreeWidgetItem' in data and \
			data[u'QTreeWidgetItem'] == str(target_treeitem):
			debug.msg(u'Drop ignored: dropping on self')
			if e is not None:
				e.ignore()
			return
		item_name = data[u'item-name']
		# Check for recursion when dropping sequences and loops
		if data[u'item-type'] in [u'sequence', u'loop']:
			target_item_name, target_item_ancestry = target_treeitem.ancestry()
			if target_item_ancestry.startswith(u'%s:' % item_name) or \
				u'.%s:' % item_name  in target_item_ancestry:
				debug.msg(u'Drop ignored: recursion prevented')
				if e is not None:
					e.ignore()
				return
		# Don't drop on undroppable parents
		parent_item_name, index = self.parent_from_ancestry(data[u'ancestry'])
		if parent_item_name is None:
			debug.msg(u'Drop ignored: no parent')
			if e is not None:
				e.ignore()
			return
		# The logic below is a bit complicated, but works as follows:
		# - If we're in a move action, remove the dragged item from its parent,
		#   and set need_restore so that we know this happened.
		# - Try to drop the dragged item onto the target item
		# - If the drop action was unsuccesful, and if need_restore is set,
		#   re-add the dragged item to its former parent.
		need_restore = False
		if data[u'move']:
			if parent_item_name not in self.experiment.items:
				debug.msg(u'Don\'t know how to remove item from %s' \
					% parent_item_name)
			else:
				self.locked = True
				need_restore = True
				self.experiment.items[parent_item_name].remove_child_item(
					item_name, index)
				self.locked = False
		if self.drop_event_item_new(data, e, target_treeitem=target_treeitem):
			return
		if need_restore:
			self.experiment.items[parent_item_name].insert_child_item(
				item_name, index)
			self.experiment.build_item_tree()
	def droppable(self, data):

		return drag_and_drop.matches(data, [u'item-existing']) and \
			data[u'application-id'] == self.main_window._id()
Esempio n. 19
0
	def drop_event_item_new(self, data, e=None, target_treeitem=None):

		"""
		desc:
			Handles drop events for item creation.

		arguments:
			data:
				desc:	A drop-data dictionary.
				type:	dict:

		keywords:
			e:
				desc:	A drop event or None if a target treeitem is provided.
				type:	[QDropEvent, NoneType]
			target_treeitem:
				desc:	A target tree item or None in a drop event is specified.
				type:	[tree_base_item, NoneType]

		returns:
			desc:	True if the drop was successful, False otherwise.
			type:	bool
		"""

		self.main_window.set_busy(True)
		if not drag_and_drop.matches(data, [u'item-snippet', u'item-existing']):
			if e is not None:
				e.ignore()
			self.main_window.set_busy(False)
			return False
		if data[u'type'] == u'item-existing' and \
			data[u'item-name'] not in self.experiment.items:
			self.experiment.notify(_(u'Cannot create linked copy of "%s". Has '
				u'the item been permanently deleted?') % data[u'item-name'])
			if e is not None:
				e.ignore()
			self.main_window.set_busy(False)
			return False
		# Ignore drops on non-droppable tree items.
		if target_treeitem is None:
			target_treeitem = self.itemAt(e.pos())
		if not self.droppable(target_treeitem, data):
			if e is not None:
				e.ignore()
			self.main_window.set_busy(False)
			return False
		# Accept drops on the unused items bin and unused items (i.e. items
		# in the bin)
		if target_treeitem.name == u'__unused__' or \
			(target_treeitem.parent() is not None and \
			target_treeitem.parent().name == u'__unused__'):
			e.accept()
			self.structure_change.emit()
			self.main_window.set_busy(False)
			return True
		# Get the target item, check if it exists, and, if so, drop the source
		# item on it.
		target_item_name = target_treeitem.text(0)
		if target_item_name not in self.experiment.items:
			debug.msg(u'Don\'t know how to drop on %s' % target_item_name)
			if e is not None:
				e.ignore()
			self.structure_change.emit()
			self.main_window.set_busy(False)
			return False
		target_item = self.experiment.items[target_item_name]
		if data[u'type'] == u'item-existing':
			item, new_items = self.drop_get_item_existing(data)
		else:
			item, new_items = self.drop_get_item_snippet(data)

		inserted = False
		# If the item has no parent or if it is the experiment starting point,
		# we insert into it directly.
		if target_treeitem.parent() is None or \
			target_item.name == self.experiment.var.start:
			target_item.insert_child_item(item.name)
			inserted = True
		else:
			if target_item.item_type in (u'loop', u'sequence'):
				self.main_window.set_busy(False)
				# Choose appropriate option
				if target_item.item_type == u'loop':
					question = _('Set as item to run for %s') % target_item.name
					icon = u'os-loop'
				else:
					question = _('Insert into %s') % target_item.name
					icon = u'os-sequence'
				resp = popup_menu(self, [(0, question, icon),
					(1, _('Insert after %s' % target_item.name), 'list-add')
					]).show()
				# Confirmation
				if resp == 0 and target_item.item_type == u'loop' and \
					target_item.var.item in self.experiment.items:
					resp = popup_menu(self, [(0, _(u'I know, do it!'), icon)],
						title=_(u'This will replace %s' % (target_item.item))
						).show()
				# If the popup was cancelled
				if resp is None:
					if e is not None:
						e.accept()
					self.main_window.set_busy(False)
					for item in new_items:
						del self.experiment.items[item]
					return False
				# If the user chose to insert into the target item
				if resp == 0:
					target_item.insert_child_item(item.name)
					inserted = True
		# Otherwise, we find the parent of the target item, and insert the
		# new item at the correct position.
		if not inserted:
			while True:
				try:
					parent_treeitem = target_treeitem.parent()
				except:
					# A race condition can occur in which the tree_overview has
					# been rebuild, thus destroying target_treeitem. If this
					# happens, we re-take target_treeitem based on the mouse
					# coordinates.
					target_treeitem = self.itemAt(e.pos())
					parent_treeitem = target_treeitem.parent()
				if parent_treeitem is None:
					e.accept()
					del self.experiment.items[item.name]
					self.main_window.set_busy(False)
					return False
				parent_item_name = str(parent_treeitem.text(0))
				parent_item = self.experiment.items[parent_item_name]
				if isinstance(parent_item, sequence):
					break
				target_treeitem = parent_treeitem
			index = parent_treeitem.indexOfChild(target_treeitem)+1
			parent_item.insert_child_item(item.name, index=index)
		if e is not None:
			e.accept()
		self.structure_change.emit()
		if self.overview_mode:
			item.open_tab()
		self.main_window.set_busy(False)
		return True
Esempio n. 20
0
    def drop_event_item_new(self, data, e=None, target_treeitem=None):

        """
		desc:
			Handles drop events for item creation.

		arguments:
			data:
				desc:	A drop-data dictionary.
				type:	dict:

		keywords:
			e:
				desc:	A drop event or None if a target treeitem is provided.
				type:	[QDropEvent, NoneType]
			target_treeitem:
				desc:	A target tree item or None in a drop event is specified.
				type:	[tree_base_item, NoneType]

		returns:
			desc:	True if the drop was successful, False otherwise.
			type:	bool
		"""

        self.main_window.set_busy(True)
        if not drag_and_drop.matches(data, [u"item-snippet", u"item-existing"]):
            if e is not None:
                e.ignore()
            self.main_window.set_busy(False)
            return False
        if data[u"type"] == u"item-existing" and data[u"item-name"] not in self.experiment.items:
            self.experiment.notify(
                _(u'Cannot create linked copy of "%s". Has ' u"the item been permanently deleted?") % data[u"item-name"]
            )
            if e is not None:
                e.ignore()
            self.main_window.set_busy(False)
            return False
            # Ignore drops on non-droppable tree items.
        if target_treeitem is None:
            target_treeitem = self.itemAt(e.pos())
        if not self.droppable(target_treeitem, data):
            if e is not None:
                e.ignore()
            self.main_window.set_busy(False)
            return False
            # Accept drops on the unused items bin and unused items (i.e. items
            # in the bin)
        if target_treeitem.name == u"__unused__" or (
            target_treeitem.parent() is not None and target_treeitem.parent().name == u"__unused__"
        ):
            e.accept()
            self.structure_change.emit()
            self.main_window.set_busy(False)
            return True
            # Get the target item, check if it exists, and, if so, drop the source
            # item on it.
        target_item_name = target_treeitem.text(0)
        if target_item_name not in self.experiment.items:
            debug.msg(u"Don't know how to drop on %s" % target_item_name)
            if e is not None:
                e.ignore()
            self.structure_change.emit()
            self.main_window.set_busy(False)
            return False
        target_item = self.experiment.items[target_item_name]
        if data[u"type"] == u"item-existing":
            item, new_items = self.drop_get_item_existing(data)
        else:
            # Creating an item may fail, and we therefore need to clean up when
            # this happens. But we don't catch the Exception itself, because it
            # will be handled with higher up, for example by the bug_report
            # extension.
            try:
                item = None
                item, new_items = self.drop_get_item_snippet(data)
            finally:
                if item is None:
                    if e is not None:
                        e.ignore()
                    self.structure_change.emit()
                    self.main_window.set_busy(False)
                    self.end_drag()
        inserted = False
        # If the item has no parent or if it is the experiment starting point,
        # we insert into it directly.
        if target_treeitem.parent() is None or target_item.name == self.experiment.var.start:
            target_item.insert_child_item(item.name)
            inserted = True
        else:
            if isinstance(target_item, qtstructure_item):
                self.main_window.set_busy(False)
                resp = popup_menu(
                    self,
                    [
                        (0, _("Insert into %s") % target_item.name, u"go-next"),
                        (1, _("Insert after %s") % target_item.name, u"go-down"),
                    ],
                ).show()
                # If the popup was cancelled
                if resp is None:
                    if e is not None:
                        e.accept()
                    self.main_window.set_busy(False)
                    for item in new_items:
                        del self.experiment.items[item]
                    return False
                    # If the user chose to insert into the target item
                if resp == 0:
                    target_item.insert_child_item(item.name)
                    inserted = True
                    # Otherwise, we find the parent of the target item, and insert the
                    # new item at the correct position.
        if not inserted:
            while True:
                try:
                    parent_treeitem = target_treeitem.parent()
                except:
                    # A race condition can occur in which the tree_overview has
                    # been rebuild, thus destroying target_treeitem. If this
                    # happens, we re-take target_treeitem based on the mouse
                    # coordinates.
                    target_treeitem = self.itemAt(e.pos())
                    parent_treeitem = target_treeitem.parent()
                if parent_treeitem is None:
                    e.accept()
                    del self.experiment.items[item.name]
                    self.main_window.set_busy(False)
                    return False
                parent_item_name = str(parent_treeitem.text(0))
                parent_item = self.experiment.items[parent_item_name]
                if isinstance(parent_item, sequence):
                    break
                target_treeitem = parent_treeitem
            index = parent_treeitem.indexOfChild(target_treeitem) + 1
            parent_item.insert_child_item(item.name, index=index)
        if e is not None:
            e.accept()
        self.structure_change.emit()
        if self.overview_mode:
            item.open_tab()
        self.main_window.set_busy(False)
        return True
Esempio n. 21
0
    def drop_event_item_existing(self, data, e=None, target_treeitem=None):

        """
		desc:
			Handles drop events for item moves.

		arguments:
			data:
				desc:	A drop-data dictionary.
				type:	dict:
			e:
				desc:	A drop event.
				type:	QDropEvent
		"""

        if not drag_and_drop.matches(data, [u"item-existing"]):
            if e is not None:
                e.ignore()
            return
            # Only accept existing-item drops from this application
        if data[u"application-id"] != self.main_window._id():
            debug.msg(u"Drop ignored: from different instance")
            if e is not None:
                e.ignore()
            return
        if target_treeitem is None:
            target_treeitem = self.itemAt(e.pos())
        if not self.droppable(target_treeitem, data):
            debug.msg(u"Drop ignored: target not droppable")
            if e is not None:
                e.ignore()
            return
            # Don't drop on the same item that was the source (if any)
        if u"QTreeWidgetItem" in data and data[u"QTreeWidgetItem"] == str(target_treeitem):
            debug.msg(u"Drop ignored: dropping on self")
            if e is not None:
                e.ignore()
            return
        item_name = data[u"item-name"]
        # Check for recursion when dropping sequences and loops. The target item
        # may not have the dropped item in its ancestry. However, the target
        # item may occur multiple times in the experiment, so we need to check
        # that this constraint holds for all linked copies of the target item.
        if data.get(u"structure-item", False):
            for linked_target_treeitem in self.findItems(
                target_treeitem.name, QtCore.Qt.MatchFixedString | QtCore.Qt.MatchRecursive
            ):
                target_item_name, target_item_ancestry = linked_target_treeitem.ancestry()
                if target_item_ancestry.startswith(u"%s:" % item_name) or u".%s:" % item_name in target_item_ancestry:
                    debug.msg(u"Drop ignored: recursion prevented")
                    if e is not None:
                        e.ignore()
                    return
                    # Don't drop on undroppable parents
        parent_item_name, index = self.parent_from_ancestry(data[u"ancestry"])
        if parent_item_name is None:
            debug.msg(u"Drop ignored: no parent")
            if e is not None:
                e.ignore()
            return
            # The logic below is a bit complicated, but works as follows:
            # - If we're in a move action, remove the dragged item from its parent,
            #   and set need_restore so that we know this happened.
            # - Try to drop the dragged item onto the target item
            # - If the drop action was unsuccesful, and if need_restore is set,
            #   re-add the dragged item to its former parent.
        need_restore = False
        if data[u"move"]:
            if parent_item_name not in self.experiment.items:
                debug.msg(u"Don't know how to remove item from %s" % parent_item_name)
            else:
                self.locked = True
                need_restore = True
                self.experiment.items[parent_item_name].remove_child_item(item_name, index)
                self.locked = False
        if self.drop_event_item_new(data, e, target_treeitem=target_treeitem):
            return
        if need_restore:
            self.experiment.items[parent_item_name].insert_child_item(item_name, index)
            self.experiment.build_item_tree()
Esempio n. 22
0
	def droppable(self, data):

		return drag_and_drop.matches(data, [u'item-existing'])
Esempio n. 23
0
    def drop_event_item_new(self, data, e=None, target_treeitem=None):

        """
		desc:
			Handles drop events for item creation.

		arguments:
			data:
				desc:	A drop-data dictionary.
				type:	dict:

		keywords:
			e:
				desc:	A drop event or None if a target treeitem is provided.
				type:	[QDropEvent, NoneType]
			target_treeitem:
				desc:	A target tree item or None in a drop event is specified.
				type:	[tree_base_item, NoneType]

		returns:
			desc:	True if the drop was successful, False otherwise.
			type:	bool
		"""

        self.main_window.set_busy(True)
        if not drag_and_drop.matches(data, [u"item-existing", u"item-new"]):
            if e != None:
                e.ignore()
            self.main_window.set_busy(False)
            return False
            # Ignore drops on non-droppable tree items.
        if target_treeitem == None:
            target_treeitem = self.itemAt(e.pos())
        if not self.droppable(target_treeitem, data):
            if e != None:
                e.ignore()
            self.main_window.set_busy(False)
            return False
            # Accept drops on the unused items bin and unused items (i.e. items
            # in the bin)
        if target_treeitem.name == u"__unused__" or (
            target_treeitem.parent() is not None and target_treeitem.parent().name == u"__unused__"
        ):
            e.accept()
            self.structure_change.emit()
            self.main_window.set_busy(False)
            return True
            # Get the target item, check if it exists, and, if so, drop the source
            # item on it.
        target_item_name = unicode(target_treeitem.text(0))
        if target_item_name not in self.experiment.items:
            debug.msg(u"Don't know how to drop on %s" % target_item_name)
            if e != None:
                e.ignore()
            self.structure_change.emit()
            self.main_window.set_busy(False)
            return False
        target_item = self.experiment.items[target_item_name]
        # Get the item to be inserted. If the drop type is item-new, we need
        # to create a new item, otherwise we get an existin item. Also, if
        # the drop doesn't originate from this application, we create a new
        # item.
        if data[u"type"] == u"item-new" or data[u"application-id"] != self.main_window._id():
            try:
                item = self.experiment.items.new(data[u"item-type"], data[u"item-name"], data[u"script"])
            except Exception as ex:
                if not isinstance(e, osexception):
                    ex = osexception(msg=u"Plug-in error", exception=ex)
                self.notify(u"Failed to load plug-in %s (see debug window for stack trace)" % data[u"item-type"])
                self.main_window.print_debug_window(ex)
                e.accept()
                self.main_window.set_busy(False)
                return False
            self.extension_manager.fire(u"new_item", name=data[u"item-name"], _type=data[u"item-type"])
        else:
            item = self.experiment.items[data[u"item-name"]]

        inserted = False
        # If the item has no parent or if it is the experiment starting point,
        # we insert into it directly.
        if target_treeitem.parent() == None or target_item.name == self.experiment.start:
            target_item.insert_child_item(item.name)
            inserted = True
        else:
            if target_item.item_type in (u"loop", u"sequence"):
                self.main_window.set_busy(False)
                # Choose appropriate option
                if target_item.item_type == u"loop":
                    question = _("Set as item to run for %s") % target_item.name
                    icon = u"os-loop"
                else:
                    question = _("Insert into %s") % target_item.name
                    icon = u"os-sequence"
                resp = popup_menu(
                    self, [(0, question, icon), (1, _("Insert after %s" % target_item.name), "list-add")]
                ).show()
                # Confirmation
                if resp == 0 and target_item.item_type == u"loop" and target_item.item in self.experiment.items:
                    resp = popup_menu(
                        self, [(0, _(u"I know, do it!"), icon)], title=_(u"This will replace %s" % (target_item.item))
                    ).show()
                    # If the popup was cancelled
                if resp == None:
                    e.accept()
                    # Delete the item if it was new or didn't originate from
                    # this application.
                    if data[u"type"] == u"item-new" or data[u"application-id"] != self.main_window._id():
                        del self.experiment.items[item.name]
                    self.main_window.set_busy(False)
                    return False
                    # If the user chose to insert into the target item
                if resp == 0:
                    target_item.insert_child_item(item.name)
                    inserted = True
                    # Otherwise, we find the parent of the target item, and insert the
                    # new item at the correct position.
        if not inserted:
            while True:
                try:
                    parent_treeitem = target_treeitem.parent()
                except:
                    # A race condition can occur in which the tree_overview has
                    # been rebuild, thus destroying target_treeitem. If this
                    # happens, we re-take target_treeitem based on the mouse
                    # coordinates.
                    target_treeitem = self.itemAt(e.pos())
                    parent_treeitem = target_treeitem.parent()
                if parent_treeitem == None:
                    e.accept()
                    del self.experiment.items[item.name]
                    self.main_window.set_busy(False)
                    return False
                parent_item_name = unicode(parent_treeitem.text(0))
                parent_item = self.experiment.items[parent_item_name]
                if isinstance(parent_item, sequence):
                    break
                target_treeitem = parent_treeitem
            index = parent_treeitem.indexOfChild(target_treeitem) + 1
            parent_item.insert_child_item(item.name, index=index)
        if e != None:
            e.accept()
        self.structure_change.emit()
        if self.overview_mode:
            item.open_tab()
        self.main_window.set_busy(False)
        return True
Esempio n. 24
0
	def drop_event_item_new(self, data, e=None, target_treeitem=None):

		"""
		desc:
			Handles drop events for item creation.

		arguments:
			data:
				desc:	A drop-data dictionary.
				type:	dict:

		keywords:
			e:
				desc:	A drop event or None if a target treeitem is provided.
				type:	[QDropEvent, NoneType]
			target_treeitem:
				desc:	A target tree item or None in a drop event is specified.
				type:	[tree_base_item, NoneType]
		"""

		self.main_window.set_busy(True)
		if not drag_and_drop.matches(data, [u'item-existing', u'item-new']):
			if e != None:
				e.ignore()
			self.main_window.set_busy(False)
			return
		# Ignore drops on non-droppable tree items.
		if target_treeitem == None:
			target_treeitem = self.itemAt(e.pos())
		if not self.droppable(target_treeitem, data):
			if e != None:
				e.ignore()
			self.main_window.set_busy(False)
			return
		# Get the target item, check if it exists, and, if so, drop the source
		# item on it.
		target_item_name = unicode(target_treeitem.text(0))
		if target_item_name not in self.experiment.items:
			debug.msg(u'Don\'t know how to drop on %s' % target_item_name)
			if e != None:
				e.ignore()
			self.structure_change.emit()
			self.main_window.set_busy(False)
			return
		target_item = self.experiment.items[target_item_name]
		# Get the item to be inserted. If the drop type is item-new, we need
		# to create a new item, otherwise we get an existin item. Also, if
		# the drop doesn't originate from this application, we create a new
		# item.
		if data[u'type'] == u'item-new' \
			or data[u'application-id'] != self.main_window._id():
			try:
				item = self.experiment.items.new(data[u'item-type'],
					data[u'item-name'], data[u'script'])
			except Exception as ex:
				if not isinstance(e, osexception):
					ex = osexception(msg=u'Plug-in error', exception=ex)
				self.notify(
					u'Failed to load plug-in %s (see debug window for stack trace)' \
					% data[u'item-type'])
				self.main_window.print_debug_window(ex)
				e.accept()
				self.main_window.set_busy(False)
				return
			self.extension_manager.fire(u'new_item',
				name=data[u'item-name'], _type=data[u'item-type'])
		else:
			item = self.experiment.items[data[u'item-name']]

		inserted = False
		# If the item has no parent or if it is the experiment starting point,
		# we insert into it directly.
		if target_treeitem.parent() == None or \
			target_item.name == self.experiment.start:
			target_item.insert_child_item(item.name)
			inserted = True
		else:
			if target_item.item_type in (u'loop', u'sequence'):
				self.main_window.set_busy(False)
				# Choose appropriate option
				if target_item.item_type == u'loop':
					question = _('Set as item to run for %s') % target_item.name
					icon = u'os-loop'
				else:
					question = _('Insert into %s') % target_item.name
					icon = u'os-sequence'
				resp = popup_menu(self, [(0, question, icon),
					(1, _('Insert after %s' % target_item.name), 'list-add')
					]).show()
				# If the popup was cancelled
				if resp == None:
					e.accept()
					del self.experiment.items[item.name]
					self.main_window.set_busy(False)
					return
				# If the user chose to insert into the target item
				if resp == 0:
					target_item.insert_child_item(item.name)
					inserted = True
		# Otherwise, we find the parent of the target item, and insert the
		# new item at the correct position.
		if not inserted:
			while True:
				try:
					parent_treeitem = target_treeitem.parent()
				except:
					# A race condition can occur in which the tree_overview has
					# been rebuild, thus destroying target_treeitem. If this
					# happens, we re-take target_treeitem based on the mouse
					# coordinates.
					target_treeitem = self.itemAt(e.pos())
					parent_treeitem = target_treeitem.parent()
				if parent_treeitem == None:
					e.accept()
					del self.experiment.items[item.name]
					self.main_window.set_busy(False)
					return
				parent_item_name = unicode(parent_treeitem.text(0))
				parent_item = self.experiment.items[parent_item_name]
				if isinstance(parent_item, sequence):
					break
				target_treeitem = parent_treeitem
			index = parent_treeitem.indexOfChild(target_treeitem)+1
			parent_item.insert_child_item(item.name, index=index)
		if e != None:
			e.accept()
		self.structure_change.emit()
		if self.overview_mode:
			item.open_tab()
		self.main_window.set_busy(False)
	def droppable(self, data):

		return drag_and_drop.matches(data, [u'item-existing']) and \
			data[u'application-id'] == self.main_window._id()
Esempio n. 26
0
	def drop_event_item_new(self, data, e=None, target_treeitem=None):

		"""
		desc:
			Handles drop events for item creation.

		arguments:
			data:
				desc:	A drop-data dictionary.
				type:	dict:

		keywords:
			e:
				desc:	A drop event or None if a target treeitem is provided.
				type:	[QDropEvent, NoneType]
			target_treeitem:
				desc:	A target tree item or None in a drop event is specified.
				type:	[tree_base_item, NoneType]

		returns:
			desc:	True if the drop was successful, False otherwise.
			type:	bool
		"""

		self.main_window.set_busy(True)
		if not drag_and_drop.matches(data, [u'item-snippet', u'item-existing']):
			if e is not None:
				e.ignore()
			self.main_window.set_busy(False)
			return False
		# Ignore drops on non-droppable tree items.
		if target_treeitem is None:
			target_treeitem = self.itemAt(e.pos())
		if not self.droppable(target_treeitem, data):
			if e is not None:
				e.ignore()
			self.main_window.set_busy(False)
			return False
		# Accept drops on the unused items bin and unused items (i.e. items
		# in the bin)
		if target_treeitem.name == u'__unused__' or \
			(target_treeitem.parent() is not None and \
			target_treeitem.parent().name == u'__unused__'):
			e.accept()
			self.structure_change.emit()
			self.main_window.set_busy(False)
			return True
		# Get the target item, check if it exists, and, if so, drop the source
		# item on it.
		target_item_name = target_treeitem.text(0)
		if target_item_name not in self.experiment.items:
			debug.msg(u'Don\'t know how to drop on %s' % target_item_name)
			if e is not None:
				e.ignore()
			self.structure_change.emit()
			self.main_window.set_busy(False)
			return False
		target_item = self.experiment.items[target_item_name]
		if data[u'type'] == u'item-existing':
			item, new_items = self.drop_get_item_existing(data)
		else:
			item, new_items = self.drop_get_item_snippet(data)

		inserted = False
		# If the item has no parent or if it is the experiment starting point,
		# we insert into it directly.
		if target_treeitem.parent() is None or \
			target_item.name == self.experiment.var.start:
			target_item.insert_child_item(item.name)
			inserted = True
		else:
			if target_item.item_type in (u'loop', u'sequence'):
				self.main_window.set_busy(False)
				# Choose appropriate option
				if target_item.item_type == u'loop':
					question = _('Set as item to run for %s') % target_item.name
					icon = u'os-loop'
				else:
					question = _('Insert into %s') % target_item.name
					icon = u'os-sequence'
				resp = popup_menu(self, [(0, question, icon),
					(1, _('Insert after %s' % target_item.name), 'list-add')
					]).show()
				# Confirmation
				if resp == 0 and target_item.item_type == u'loop' and \
					target_item.var.item in self.experiment.items:
					resp = popup_menu(self, [(0, _(u'I know, do it!'), icon)],
						title=_(u'This will replace %s' % (target_item.item))
						).show()
				# If the popup was cancelled
				if resp is None:
					if e is not None:
						e.accept()
					self.main_window.set_busy(False)
					for item in new_items:
						del self.experiment.items[item]
					return False
				# If the user chose to insert into the target item
				if resp == 0:
					target_item.insert_child_item(item.name)
					inserted = True
		# Otherwise, we find the parent of the target item, and insert the
		# new item at the correct position.
		if not inserted:
			while True:
				try:
					parent_treeitem = target_treeitem.parent()
				except:
					# A race condition can occur in which the tree_overview has
					# been rebuild, thus destroying target_treeitem. If this
					# happens, we re-take target_treeitem based on the mouse
					# coordinates.
					target_treeitem = self.itemAt(e.pos())
					parent_treeitem = target_treeitem.parent()
				if parent_treeitem is None:
					e.accept()
					del self.experiment.items[item.name]
					self.main_window.set_busy(False)
					return False
				parent_item_name = str(parent_treeitem.text(0))
				parent_item = self.experiment.items[parent_item_name]
				if isinstance(parent_item, sequence):
					break
				target_treeitem = parent_treeitem
			index = parent_treeitem.indexOfChild(target_treeitem)+1
			parent_item.insert_child_item(item.name, index=index)
		if e is not None:
			e.accept()
		self.structure_change.emit()
		if self.overview_mode:
			item.open_tab()
		self.main_window.set_busy(False)
		return True
Esempio n. 27
0
	def drop_event_item_move(self, data, e):

		"""
		desc:
			Handles drop events for item moves.

		arguments:
			data:
				desc:	A drop-data dictionary.
				type:	dict:
			e:
				desc:	A drop event.
				type:	QDropEvent
		"""

		if not drag_and_drop.matches(data, [u'item-existing']):
			e.ignore()
			return
		target_treeitem = self.itemAt(e.pos())
		if not self.droppable(target_treeitem, data):
			debug.msg(u'Drop ignored: target not droppable')
			self.main_window.set_status(
				_(u'Drop cancelled: Target not droppable'))
			e.ignore()
			return
		# If the drop comes from this application, check for recursion etc.
		if data[u'application-id'] == self.main_window._id():
			target_item_name, target_item_ancestry = target_treeitem.ancestry()
			item_name = data[u'item-name']
			item = self.experiment.items[item_name]
			if target_item_name in item.children():
				debug.msg(u'Drop ignored: recursion prevented')
				self.main_window.set_status(
					_(u'Drop cancelled: Recursion prevented'))
				e.ignore()
				return
			parent_item_name, index = self.parent_from_ancestry(
				data[u'ancestry'])
			if parent_item_name == None:
				debug.msg(u'Drop ignored: no parent')
				e.ignore()
				return
		# The logic below is a bit complicated, but works as follows:
		# - If we're in a move action, remove the dragged item from its parent,
		#   and set need_restore so that we know this happened.
		# - Try to drop the dragged item onto the target item
		# - If the drop action was unsuccesful, and if need_restore is set,
		#   re-add the dragged item to its former parent.
		need_restore = False
		if not QtCore.Qt.ControlModifier & e.keyboardModifiers() and \
			data[u'application-id'] == self.main_window._id():
			if parent_item_name not in self.experiment.items:
				debug.msg(u'Don\'t know how to remove item from %s' \
					% parent_item_name)
			else:
				self.locked = True
				need_restore = True
				self.experiment.items[parent_item_name].remove_child_item(
					item_name, index)
				self.locked = False
		if self.drop_event_item_new(data, e, target_treeitem=target_treeitem):
			return
		if need_restore:
			self.experiment.items[parent_item_name].insert_child_item(
				item_name, index)
			self.experiment.build_item_tree()
    def droppable(self, data):

        return drag_and_drop.matches(data, [u'item-existing'])
Esempio n. 29
0
	def drop_event_item_new(self, data, e=None, target_treeitem=None):

		"""
		desc:
			Handles drop events for item creation.

		arguments:
			data:
				desc:	A drop-data dictionary.
				type:	dict:

		keywords:
			e:
				desc:	A drop event or None if a target treeitem is provided.
				type:	[QDropEvent, NoneType]
			target_treeitem:
				desc:	A target tree item or None in a drop event is specified.
				type:	[tree_base_item, NoneType]

		returns:
			desc:	True if the drop was successful, False otherwise.
			type:	bool
		"""

		self.main_window.set_busy(True)
		if not drag_and_drop.matches(data, [u'item-existing', u'item-new']):
			if e != None:
				e.ignore()
			self.main_window.set_busy(False)
			return False
		# Ignore drops on non-droppable tree items.
		if target_treeitem == None:
			target_treeitem = self.itemAt(e.pos())
		if not self.droppable(target_treeitem, data):
			if e != None:
				e.ignore()
			self.main_window.set_busy(False)
			return False
		# Accept drops on the unused items bin and unused items (i.e. items
		# in the bin)
		if target_treeitem.name == u'__unused__' or \
			(target_treeitem.parent() is not None and \
			target_treeitem.parent().name == u'__unused__'):			
			e.accept()
			self.structure_change.emit()
			self.main_window.set_busy(False)
			return True
		# Get the target item, check if it exists, and, if so, drop the source
		# item on it.
		target_item_name = unicode(target_treeitem.text(0))
		if target_item_name not in self.experiment.items:
			debug.msg(u'Don\'t know how to drop on %s' % target_item_name)
			if e != None:
				e.ignore()
			self.structure_change.emit()
			self.main_window.set_busy(False)
			return False
		target_item = self.experiment.items[target_item_name]
		# Get the item to be inserted. If the drop type is item-new, we need
		# to create a new item, otherwise we get an existin item. Also, if
		# the drop doesn't originate from this application, we create a new
		# item.
		if data[u'type'] == u'item-new' \
			or data[u'application-id'] != self.main_window._id():
			try:
				item = self.experiment.items.new(data[u'item-type'],
					data[u'item-name'], data[u'script'])
			except Exception as ex:
				if not isinstance(e, osexception):
					ex = osexception(msg=u'Plug-in error', exception=ex)
				self.notify(
					u'Failed to load plug-in %s (see debug window for stack trace)' \
					% data[u'item-type'])
				self.main_window.print_debug_window(ex)
				e.accept()
				self.main_window.set_busy(False)
				return False
			self.extension_manager.fire(u'new_item',
				name=data[u'item-name'], _type=data[u'item-type'])
		else:
			item = self.experiment.items[data[u'item-name']]

		inserted = False
		# If the item has no parent or if it is the experiment starting point,
		# we insert into it directly.
		if target_treeitem.parent() == None or \
			target_item.name == self.experiment.start:
			target_item.insert_child_item(item.name)
			inserted = True
		else:
			if target_item.item_type in (u'loop', u'sequence'):
				self.main_window.set_busy(False)
				# Choose appropriate option
				if target_item.item_type == u'loop':
					question = _('Set as item to run for %s') % target_item.name
					icon = u'os-loop'
				else:
					question = _('Insert into %s') % target_item.name
					icon = u'os-sequence'
				resp = popup_menu(self, [(0, question, icon),
					(1, _('Insert after %s' % target_item.name), 'list-add')
					]).show()
				# Confirmation
				if resp == 0 and target_item.item_type == u'loop' and \
					target_item.item in self.experiment.items:
					resp = popup_menu(self, [(0, _(u'I know, do it!'), icon)],
						title=_(u'This will replace %s' % (target_item.item))
						).show()
				# If the popup was cancelled
				if resp == None:
					e.accept()
					# Delete the item if it was new or didn't originate from
					# this application.
					if data[u'type'] == u'item-new' \
						or data[u'application-id'] != self.main_window._id():
						del self.experiment.items[item.name]
					self.main_window.set_busy(False)
					return False
				# If the user chose to insert into the target item
				if resp == 0:
					target_item.insert_child_item(item.name)
					inserted = True
		# Otherwise, we find the parent of the target item, and insert the
		# new item at the correct position.
		if not inserted:
			while True:
				try:
					parent_treeitem = target_treeitem.parent()
				except:
					# A race condition can occur in which the tree_overview has
					# been rebuild, thus destroying target_treeitem. If this
					# happens, we re-take target_treeitem based on the mouse
					# coordinates.
					target_treeitem = self.itemAt(e.pos())
					parent_treeitem = target_treeitem.parent()
				if parent_treeitem == None:
					e.accept()
					del self.experiment.items[item.name]
					self.main_window.set_busy(False)
					return False
				parent_item_name = unicode(parent_treeitem.text(0))
				parent_item = self.experiment.items[parent_item_name]
				if isinstance(parent_item, sequence):
					break
				target_treeitem = parent_treeitem
			index = parent_treeitem.indexOfChild(target_treeitem)+1
			parent_item.insert_child_item(item.name, index=index)
		if e != None:
			e.accept()
		self.structure_change.emit()
		if self.overview_mode:
			item.open_tab()
		self.main_window.set_busy(False)
		return True
Esempio n. 30
0
    def drop_event_item_new(self, data, e=None, target_treeitem=None):
        """
		desc:
			Handles drop events for item creation.

		arguments:
			data:
				desc:	A drop-data dictionary.
				type:	dict:

		keywords:
			e:
				desc:	A drop event or None if a target treeitem is provided.
				type:	[QDropEvent, NoneType]
			target_treeitem:
				desc:	A target tree item or None in a drop event is specified.
				type:	[tree_base_item, NoneType]

		returns:
			desc:	True if the drop was successful, False otherwise.
			type:	bool
		"""

        self.main_window.set_busy(True)
        if not drag_and_drop.matches(data,
                                     [u'item-snippet', u'item-existing']):
            if e is not None:
                e.ignore()
            self.main_window.set_busy(False)
            return False
        if data[u'type'] == u'item-existing' and \
         data[u'item-name'] not in self.experiment.items:
            self.experiment.notify(
                _(u'Cannot create linked copy of "%s". Has '
                  u'the item been permanently deleted?') % data[u'item-name'])
            if e is not None:
                e.ignore()
            self.main_window.set_busy(False)
            return False
        # Ignore drops on non-droppable tree items.
        if target_treeitem is None:
            target_treeitem = self.itemAt(e.pos())
        if not self.droppable(target_treeitem, data):
            if e is not None:
                e.ignore()
            self.main_window.set_busy(False)
            return False
        # Accept drops on the unused items bin and unused items (i.e. items
        # in the bin)
        if target_treeitem.name == u'__unused__' or \
         (target_treeitem.parent() is not None and \
         target_treeitem.parent().name == u'__unused__'):
            e.accept()
            self.structure_change.emit()
            self.main_window.set_busy(False)
            return True
        # Get the target item, check if it exists, and, if so, drop the source
        # item on it.
        target_item_name = target_treeitem.text(0)
        if target_item_name not in self.experiment.items:
            debug.msg(u'Don\'t know how to drop on %s' % target_item_name)
            if e is not None:
                e.ignore()
            self.structure_change.emit()
            self.main_window.set_busy(False)
            return False
        target_item = self.experiment.items[target_item_name]
        if data[u'type'] == u'item-existing':
            item, new_items = self.drop_get_item_existing(data)
        else:
            # Creating an item may fail, and we therefore need to clean up when
            # this happens. But we don't catch the Exception itself, because it
            # will be handled with higher up, for example by the bug_report
            # extension.
            try:
                item = None
                item, new_items = self.drop_get_item_snippet(data)
            finally:
                if item is None:
                    if e is not None:
                        e.ignore()
                    self.structure_change.emit()
                    self.main_window.set_busy(False)
                    self.end_drag()
        inserted = False
        # If the item has no parent or if it is the experiment starting point,
        # we insert into it directly.
        if target_treeitem.parent() is None or \
         target_item.name == self.experiment.var.start:
            target_item.insert_child_item(item.name)
            inserted = True
        else:
            if isinstance(target_item, qtstructure_item):
                self.main_window.set_busy(False)
                resp = popup_menu(self, [
                    (0, _('Insert into %s') % target_item.name, u'go-next'),
                    (1, _('Insert after %s') % target_item.name, u'go-down')
                ]).show()
                # If the popup was cancelled
                if resp is None:
                    if e is not None:
                        e.accept()
                    self.main_window.set_busy(False)
                    for item in new_items:
                        del self.experiment.items[item]
                    return False
                # If the user chose to insert into the target item
                if resp == 0:
                    target_item.insert_child_item(item.name)
                    inserted = True
        # Otherwise, we find the parent of the target item, and insert the
        # new item at the correct position.
        if not inserted:
            while True:
                try:
                    parent_treeitem = target_treeitem.parent()
                except:
                    # A race condition can occur in which the tree_overview has
                    # been rebuild, thus destroying target_treeitem. If this
                    # happens, we re-take target_treeitem based on the mouse
                    # coordinates.
                    target_treeitem = self.itemAt(e.pos())
                    parent_treeitem = target_treeitem.parent()
                if parent_treeitem is None:
                    e.accept()
                    del self.experiment.items[item.name]
                    self.main_window.set_busy(False)
                    return False
                parent_item_name = str(parent_treeitem.text(0))
                parent_item = self.experiment.items[parent_item_name]
                if isinstance(parent_item, sequence):
                    break
                target_treeitem = parent_treeitem
            index = parent_treeitem.indexOfChild(target_treeitem) + 1
            parent_item.insert_child_item(item.name, index=index)
        if e is not None:
            e.accept()
        self.structure_change.emit()
        if self.overview_mode:
            item.open_tab()
        self.main_window.set_busy(False)
        return True