示例#1
0
def getStorage(elid):
    """Return a tags.Storage object filled with the tags of the element with the given id."""
    result = db.query(
        "SELECT tag_id, value_id FROM {p}tags WHERE element_id = ?", elid)
    storage = tagsModule.Storage()
    for tagId, valueId in result:
        tag = tagsModule.get(tagId)
        storage.add(tag, value(tag, valueId))
    return storage
示例#2
0
 def setUp(self):
     super().setUp()
     self.f1 = self.level.collect(TestUrl('test://band 1 - song'))
     self.f2 = self.level.collect(TestUrl('test://band 2 - a song'))
     self.f3 = self.level.collect(TestUrl('test://band 3 - another song'))
     self.f4 = self.level.collect(TestUrl('test://band 4 - no song'))
     self.fs = [self.f1, self.f2, self.f3, self.f4]
     containerTags = tags.Storage({tags.TITLE: ['Weird album']})
     if self.real:
         # On real level createContainer does not work until we added the contents to the db
         self.level.addToDb(self.fs)
     self.c = self.level.createContainer(tags=containerTags, contents=[])
示例#3
0
 def setUp(self):
     super().setUp()
     self.subLevel = levels.Level('TEST', self.level)
     self.f1 = self.subLevel.collect(TestUrl('test://band 1 - song'))
     self.f2 = self.subLevel.collect(TestUrl('test://band 2 - a song'))
     self.f3 = self.subLevel.collect(
         TestUrl('test://band 3 - another song'))
     self.f4 = self.subLevel.collect(TestUrl('test://band 4 - no song'))
     self.fs = [self.f1, self.f2, self.f3, self.f4]
     self.containerTags = tags.Storage({tags.TITLE: ['Weird album']})
     self.contentList = elements.ContentList.fromPairs([(10, self.f1),
                                                        (12, self.f2)])
     self.c = self.subLevel.createContainer(tags=self.containerTags,
                                            contents=self.contentList)
示例#4
0
 def finish(self):
     elems = []
     for i, edit in enumerate(self.edits, start=1):
         url = urls.URL("audiocd://{0}.{1}{2}/{0}/{1}.flac".format(
                         self.discid, i, os.path.abspath(config.options.audiocd.rippath)))
         elem = self.level.collect(url)
         elTags = tags.Storage()
         elTags[tags.TITLE] = [edit.getValue()]
         elTags[tags.ALBUM] = [self.titleEdit.getValue()]
         elTags[tags.get('artist')] = [self.artistEdit.getValue()]
         elTags[tags.get('date')] = [self.dateEdit.getValue()]
         diff = tags.TagStorageDifference(None, elTags)
         self.level.changeTags({elem: diff})
         elems.append(elem)
     contTags = tags.Storage()
     contTags[tags.TITLE] = [self.titleEdit.getValue()]
     contTags[tags.ALBUM] = [self.titleEdit.getValue()]
     contTags[tags.get('date')] = [self.dateEdit.getValue()]
     contTags[tags.get('artist')] = [self.artistEdit.getValue()]
     cont = self.level.createContainer(contents=elems, type=ContainerType.Album,
                                       domain=domains.default(), tags=contTags)
     self.container = cont
     self.accept()
示例#5
0
    def readTags(self):
        """Load the tags from disk using pytaglib.

        Special tags (tracknumber, compilation, discnumber) are stored in the "specialTags" attribute.
        """
        self.tags = tags.Storage()
        self.specialTags = collections.OrderedDict()
        try:
            self._taglibFile = taglib.File(self.url.path)
        except OSError:
            if self.url.extension in config.options.main.audio_extensions:
                logging.warning(
                    __name__,
                    'TagLib failed to open "{}". Tags will be stored in database only'
                    .format(self.url.path))
            return
        self.length = self._taglibFile.length
        autoProcessingDone = False
        for key, values in self._taglibFile.tags.items():
            key = key.lower()
            if key in self.specialTagNames:
                self.specialTags[key] = values
            elif key in config.options.tags.auto_delete:
                autoProcessingDone = True
                continue
            elif key in autoReplaceTags:
                autoProcessingDone = True
                key = autoReplaceTags[key]
            elif tags.isValidTagName(key):
                tag = tags.get(key)
                validValues = []
                for string in values:
                    try:
                        validValues.append(tag.convertValue(string, crop=True))
                    except tags.TagValueError:
                        logging.error(
                            __name__,
                            "Invalid value for tag '{}' found: {}".format(
                                tag.name, string))
                if len(validValues) > 0:
                    self.tags.add(tag, *validValues)
            else:
                logging.error(
                    __name__,
                    "Invalid tag name '{}' found : {}".format(key, self.url))
        if autoProcessingDone:
            self.saveTags()
示例#6
0
 def asMaestroTags(self, mapping=None):
     """Convert the MBTagStorage to an maestro.tags.Storage object.
     
     *mapping* may be a dict mapping strings to Maestro tag types.
     """
     ret = tags.Storage()
     for key, values in self.items():
         if mapping and key in mapping:
             if mapping[key] is None:
                 continue
             else:
                 tag = mapping[key]
         else:
             tag = tags.get(key)
         ret[tag] = [tag.convertValue(str(v))
                     for v in values]  # converts AliasEntities to strings
     return ret
示例#7
0
    def runTest(self):
        if not self.real:
            self.assertEqual(self.level.elements,
                             {})  # this is important on undo
        self.f1 = self.level.collect(TestUrl('test://band 1 - song'))
        # due to the fixed url->id mapping, these id is the same on real and editor
        self.assertEqual(self.f1.id, 1)
        self.assertIn(self.f1.id, self.level)
        self.f2 = self.level.collect(TestUrl('test://band 2 - a song'))
        self.f3 = self.level.collect(TestUrl('test://band 3 - another song'))
        self.f4 = self.level.collect(TestUrl('test://band 4 - no song'))
        containerTags = tags.Storage({tags.TITLE: ['Weird album']})
        if self.real:  # On real level createContainer does not work until we added the contents to the db
            self.assertEqual(
                0,
                db.query("SELECT COUNT(*) FROM {}elements".format(
                    db.prefix)).getSingle())
            from maestro.core import reallevel
            self.assertEqual(reallevel._dbIds, set())
            self.level.addToDb([self.f1, self.f2, self.f3, self.f4])
            self.assertEqual(
                4,
                db.query("SELECT COUNT(*) FROM {}elements".format(
                    db.prefix)).getSingle())
            self.assertEqual(reallevel._dbIds, set([1, 2, 3, 4]))

        # note that this id will be different when this test is run for editor and real level
        predictedId = db._nextId
        self.assertNotIn(predictedId, self.level)
        self.assertEqual(self.f1.parents, [])
        self.c = self.level.createContainer(
            tags=containerTags, contents=[self.f1, self.f2, self.f3])
        self.assertEqual(self.c.id, predictedId)
        self.assertIn(predictedId, self.level)
        self.assertEqual(
            self.c.contents,
            elements.ContentList.fromList([self.f1.id, self.f2.id,
                                           self.f3.id]))
        self.assertEqual(self.f1.parents, [self.c.id])

        self.checkUndo()
        self.checkRedo()
示例#8
0
    def performMerge(self):
        """The actual merge operation."""
        self.level.stack.beginMacro(self.tr("Merge elements"),
                                    transaction=self.level is levels.real)
        containerTitle = self.titleEdit.text().strip()
        domain = self.domainBox.currentDomain()
        containerType = self.parentTypeBox.currentType()

        # Container tags & flags
        if self.commonTagsBox.isChecked():
            containerTags = tags.findCommonTags(self.elements)
            containerFlags = list(
                set.intersection(*(set(el.flags) for el in self.elements)))
        else:
            containerTags = tags.Storage()
            containerFlags = []

        if len(containerTitle) > 0:
            containerTags[tags.TITLE] = [containerTitle]
            if containerType == ContainerType.Album and tags.ALBUM not in containerTags:
                containerTags[tags.ALBUM] = [containerTitle]

        # Before creating anything, change tags of children (might raise filesystem errors)
        removePrefixes = hasattr(
            self, 'removePrefixBox') and self.removePrefixBox.isChecked()
        removeNumbers = hasattr(
            self, 'removeNumbersBox') and self.removeNumbersBox.isChecked()

        tagChanges = {}
        prefix = self.removeEdit.text() if removePrefixes else ''
        for element in self.elements:
            additions = removals = replacements = None
            if (removePrefixes
                    or removeNumbers) and tags.TITLE in element.tags:
                removals, replacements = [], []
                for value in element.tags[tags.TITLE]:
                    if removePrefixes and value.startswith(prefix):
                        newValue = value[len(prefix):]
                    else:
                        newValue = value
                    if removeNumbers:
                        number = utils.strings.numberFromPrefix(newValue)[1]
                        if len(number) > 0:
                            newValue = newValue[len(number):]
                    if len(newValue) == 0:
                        removals.append((tags.TITLE, value))
                    elif value != newValue:
                        replacements.append((tags.TITLE, value, newValue))
            if containerType == ContainerType.Album and tags.ALBUM not in element.tags:
                additions = [(tags.ALBUM, containerTitle)]
            tagChanges[element] = tags.TagDifference(additions=additions,
                                                     removals=removals,
                                                     replacements=replacements)

        if len(tagChanges) > 0:
            try:
                self.level.changeTags(tagChanges)
            except urls.TagWriteError as e:
                e.displayMessage()
                self.level.stack.abortMacro()
                self.reject()
                return

        if hasattr(self, 'changeTypeBox') and self.changeTypeBox.isChecked():
            newType = self.childrenTypeBox.currentType()
            self.level.setTypes({
                elem: newType
                for elem in self.elements
                if elem.isContainer and elem.type != newType
            })

        contents = elements.ContentList.fromPairs(
            enumerate(self.elements, start=1))
        container = self.level.createContainer(domain=domain,
                                               tags=containerTags,
                                               flags=containerFlags,
                                               contents=contents,
                                               type=containerType)

        if isinstance(self.parentNode, nodes.Wrapper):
            parent = self.parentNode.element
            insertPosition = self.wrappers[0].position
            insertIndex = parent.contents.positions.index(insertPosition)
            if self.positionCheckBox.isChecked():
                self.level.removeContentsAuto(
                    parent, [wrapper.position for wrapper in self.wrappers])
                self.level.insertContentsAuto(parent, insertIndex, [container])
            else:
                self.level.removeContents(
                    parent, [wrapper.position for wrapper in self.wrappers])
                self.level.insertContents(parent,
                                          [(insertPosition, container)])
        else:
            from ..models import leveltreemodel
            if isinstance(self.model, leveltreemodel.LevelTreeModel):
                rows = [
                    self.parentNode.contents.index(wrapper)
                    for wrapper in self.wrappers
                ]
                insertIndex = rows[0]
                for i in range(len(rows)):
                    if rows[i] >= insertIndex:
                        rows[i] += 1
                # Insert first, otherwise EditorTreeModel might remove elements from the level.
                self.model.insertElements(self.parentNode, insertIndex,
                                          [container])
                self.model.removeElements(self.parentNode, rows)
            # else: Nothing to do: Merge has been performed in the level and the model does not allow a merge

        self.level.stack.endMacro()

        if containerType != self.DefaultType:
            config.storage.gui.merge_dialog_container_type = containerType
        else:
            config.storage.gui.merge_dialog_container_type = None

        self.accept()
示例#9
0
 def readTags(self):
     self.tags = tags.Storage()
     artist, title = self.url.parsedUrl.path[1:].split(
         ' - ')  # skip leading /
     self.tags.add(tags.TITLE, title)
     self.tags.add(tags.get('artist'), artist)
示例#10
0
 def readTags(self):
     self.tags, self.length = tags.Storage(), 0