Esempio n. 1
0
    def removeElements(self, parent, rows):
        """Reimplements LevelTreeModel.removeElements so that elements that have been removed from
        the tree are also removed from editor level (unless they still appear in some EditorModel).
        """
        stack.beginMacro(self.tr("Remove elements"))
        
        # All elements from toCheck that are nowhere present in the editor will be removed.
        if isinstance(parent, Element):
            toCheck = [parent.contents[i] for i in rows]
        else: toCheck = [parent.contents[i].element.id for i in rows]
        super().removeElements(parent, rows)
        
        checked = set()
        elementsToRemove = []
        rootIds = [w.element.id for editorModel in EditorModel.instances for w in editorModel.root.contents]
        i = 0
        while i < len(toCheck):
            elid = toCheck[i]
            i += 1
            if elid in checked or elid not in self.level:
                continue
            element = self.level[elid]
            if not any(id in rootIds for id in self._getAncestorsInEditorLevel(element)):
                elementsToRemove.append(element)
                if element.isContainer():
                    toCheck.extend(element.contents) # check contents recursively
            checked.add(elid)
        
        if len(elementsToRemove) > 0:
            empty = elements.ContentList()
            contentsDict = {element: empty for element in elementsToRemove if element.isContainer()}
            self.level.changeContents(contentsDict)
            self.level.removeElements(elementsToRemove)

        stack.endMacro()
Esempio n. 2
0
    def doAction(self):
        model = self.parent().model()
        byParent = {}
        wrappers = self.parent().selection.wrappers()
        for wrapper in wrappers:
            if any(p in wrappers for p in wrapper.getParents()):
                continue
            parent = wrapper.parent
            if parent not in byParent:
                byParent[parent] = []
            byParent[parent].append(parent.contents.index(wrapper))
        for parent, indexes in byParent.items():
            byParent[parent] = sorted(set(indexes))

        stack.beginMacro('remove')
        from maestro.widgets import browser
        if isinstance(model, leveltreemodel.LevelTreeModel):
            for parent, indexes in byParent.items():
                model.removeElements(parent, indexes)
        elif isinstance(model, browser.model.BrowserModel):
            for parent, indexes in byParent.items():
                self.level().removeContentsAuto(parent.element, indexes=indexes)
        else:
            raise NotImplementedError()
        stack.endMacro()
Esempio n. 3
0
 def removeElements(self, parent, rows):
     """Undoably remove elements in *rows* under *parent* (a wrapper, an element or the root node).
     
     This convenience function either alters the RootNode, if parent is self.root, or updates
     the level.
     """
     stack.beginMacro(self.tr('remove elements'))
     if parent is self.root:
         stack.push(RemoveFromRootCommand(self, rows))
     else:
         element = parent if isinstance(parent, elements.Element) else parent.element
         self.level.removeContentsAuto(element, indexes=rows)
     stack.endMacro()
Esempio n. 4
0
 def removeElements(self, parent, rows):
     """Undoably remove elements in *rows* under *parent* (a wrapper, an element or the root node).
     
     This convenience function either alters the RootNode, if parent is self.root, or updates
     the level.
     """
     stack.beginMacro(self.tr('remove elements'))
     if parent is self.root:
         stack.push(RemoveFromRootCommand(self, rows))
     else:
         element = parent if isinstance(
             parent, elements.Element) else parent.element
         self.level.removeContentsAuto(element, indexes=rows)
     stack.endMacro()
Esempio n. 5
0
 def accept(self):
     stack.beginMacro(self.tr("Hide values"), transaction=True)
     from maestro.core import tagcommands
     for i in range(self.treeWidget.topLevelItemCount()):
         tagItem = self.treeWidget.topLevelItem(i)
         tag = tagItem.data(0, Qt.UserRole)
         vids = []
         if tagItem.checkState(0) != Qt.Unchecked:
             for j in range(tagItem.childCount()):
                 valueItem = tagItem.child(j)
                 if valueItem.checkState(0) == Qt.Checked:
                     vids.append(valueItem.data(0, Qt.UserRole))
         if len(vids) > 0:
             stack.push(tagcommands.HiddenAttributeCommand(tag, vids, True))
     stack.endMacro()
     self.close()
Esempio n. 6
0
 def accept(self):
     stack.beginMacro(self.tr("Hide values"), transaction=True)
     from maestro.core import tagcommands
     for i in range(self.treeWidget.topLevelItemCount()):
         tagItem = self.treeWidget.topLevelItem(i)
         tag = tagItem.data(0, Qt.UserRole)
         vids = []
         if tagItem.checkState(0) != Qt.Unchecked:
             for j in range(tagItem.childCount()):
                 valueItem = tagItem.child(j)
                 if valueItem.checkState(0) == Qt.Checked:
                     vids.append(valueItem.data(0, Qt.UserRole))
         if len(vids) > 0:
             stack.push(tagcommands.HiddenAttributeCommand(tag, vids, True))
     stack.endMacro()
     self.close()
Esempio n. 7
0
 def doAction(self):
     stack = self.level().stack
     stack.beginMacro(self.tr('flatten container(s)'))
     wrappers = self.parent().selection.wrappers()
     elements = [wrapper.element for wrapper in wrappers]
     positions = [wrapper.position for wrapper in wrappers]
     parent = wrappers[0].parent.element
     indices = sorted([parent.contents.positions.index(pos) for pos in positions], reverse=True)
     for i, index in enumerate(indices, start=1):
         element = self.level().collect(parent.contents.ids[index])
         pos = parent.contents.positions[index]
         children = list(element.getContents())
         self.level().removeContents(parent, [pos])
         self.level().removeContents(element, element.contents.positions)
         if element not in elements[:-i]:
             self.level().removeElements([element])
         self.level().insertContentsAuto(parent, index, children)
     stack.endMacro()
Esempio n. 8
0
 def deleteElements(self, elements, fromDisk=False):
     elements = tuple(elements)
     stack.beginMacro("delete elements")
     # 1st step: isolate the elements (remove contents & parents)
     for element in elements:
         if element.isContainer() and len(element.contents) > 0:
             self.removeContents(element, element.contents.positions)
         if len(element.parents) > 0:
             for parentId in element.parents:
                 parent = self.collect(parentId)
                 self.removeContents(parent, parent.contents.positionsOf(id=element.id))
     self.removeFromDb([element for element in elements if element.isInDb()])
     stack.endMacro()
     if fromDisk:
         for element in elements:
             if element.isFile():
                 element.url.backendFile().delete()
         stack.clear()
Esempio n. 9
0
    def dropMimeData(self, mimeData, action, row, column, parentIndex):
        """Drop stuff into a leveltreemodel. Handles Maestro mime and text/uri-list.
        
        If URLs are dropped, they are loaded into the level. If there is an album guesser
        specified, it is run on the URLs before they are inserted.
        Elements dropped on the top layer are just inserted under the RootNode. Otherwise, the
        level is modified accordingly.
        """
        if action == Qt.IgnoreAction:
            return True

        # Compute drop position
        parent = self.data(parentIndex, Qt.EditRole)
        if parent.isFile():  # Drop onto a file => drop behind it
            row = parent.parent.index(parent) + 1
            parent = parent.parent
        elif row == -1:
            # no specific position: insert at the beginning or end
            if self.dndTarget is not None and self.dndTarget.isExpanded(
                    parentIndex):
                row = 0
            else:
                row = parent.getContentsCount()

        stack.beginMacro(self.tr("drop"))

        # Get elements to insert
        if mimeData.hasFormat(config.options.gui.mime):
            ids = [node.element.id for node in mimeData.wrappers()]
            elements = self.level.collect(ids)
        else:  # text/uri-list
            try:
                elements = self.prepareURLs(mimeData.urls(), parent)
            except CancelledByUser:
                stack.abortMacro()
                return False

        if len(elements) > 0:
            self.insertElements(parent, row, elements)
            self.rowsDropped.emit(self.getIndex(parent), row,
                                  row + len(elements) - 1)

        stack.endMacro()
        return len(elements) != 0
Esempio n. 10
0
    def dropMimeData(self, mimeData, action, row, column, parentIndex):
        """Drop stuff into a leveltreemodel. Handles Maestro mime and text/uri-list.
        
        If URLs are dropped, they are loaded into the level. If there is an album guesser
        specified, it is run on the URLs before they are inserted.
        Elements dropped on the top layer are just inserted under the RootNode. Otherwise, the
        level is modified accordingly.
        """
        if action == Qt.IgnoreAction:
            return True
        
        # Compute drop position
        parent = self.data(parentIndex, Qt.EditRole)
        if parent.isFile(): # Drop onto a file => drop behind it
            row = parent.parent.index(parent) + 1
            parent = parent.parent
        elif row == -1:
            # no specific position: insert at the beginning or end
            if self.dndTarget is not None and self.dndTarget.isExpanded(parentIndex):
                row = 0
            else: row = parent.getContentsCount()

        stack.beginMacro(self.tr("drop"))
        
        # Get elements to insert
        if mimeData.hasFormat(config.options.gui.mime):
            ids = [node.element.id for node in mimeData.wrappers()]
            elements = self.level.collect(ids)
        else:  # text/uri-list
            try:
                elements = self.prepareURLs(mimeData.urls(), parent)
            except CancelledByUser:
                stack.abortMacro()
                return False


        if len(elements) > 0:
            self.insertElements(parent, row, elements)
            self.rowsDropped.emit(self.getIndex(parent), row, row + len(elements) - 1)
            
        stack.endMacro()
        return len(elements) != 0
Esempio n. 11
0
 def deleteElements(self, elements, fromDisk=False):
     elements = tuple(elements)
     stack.beginMacro("delete elements")
     # 1st step: isolate the elements (remove contents & parents)
     for element in elements:
         if element.isContainer() and len(element.contents) > 0:
             self.removeContents(element, element.contents.positions)
         if len(element.parents) > 0:
             for parentId in element.parents:
                 parent = self.collect(parentId)
                 self.removeContents(
                     parent, parent.contents.positionsOf(id=element.id))
     self.removeFromDb(
         [element for element in elements if element.isInDb()])
     stack.endMacro()
     if fromDisk:
         for element in elements:
             if element.isFile():
                 element.url.backendFile().delete()
         stack.clear()
Esempio n. 12
0
 def clear(self):
     """Remove everything below the root node."""
     stack.beginMacro(self.tr('clear'))
     self.removeElements(self.root, range(len(self.root.contents)))
     stack.endMacro()
Esempio n. 13
0
 def clear(self):
     """Remove everything below the root node."""
     stack.beginMacro(self.tr('clear'))
     self.removeElements(self.root, range(len(self.root.contents)))
     stack.endMacro()