summaryrefslogtreecommitdiff
path: root/scripts/tellico2lesana
blob: 7b4df165fd5d595670655917120b7db0de294e99 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#!/usr/bin/env python3

from xml.etree import ElementTree
import zipfile

import lesana

import guacamole


NS = {'tellico': 'http://periapsis.org/tellico/'}

# https://docs.kde.org/trunk5/en/extragear-office/tellico/field-type-values.html
F_TYPE_MAP = {
    '0': 'string',      # not in the specs, but seen in the wild
    '1': 'string',
    '2': 'text',
    '3': 'string',
    '4': 'bool',
    '6': 'integer',
    '7': 'url',
    '8': 'list',       # single column table
    '10': 'file',
    '12': 'timestamp',  # date
    '14': 'integer',    # rating

    }


class T2L(guacamole.Command):
    """
    Manage collections
    """

    def register_arguments(self, parser):
        parser.add_argument(
            '-c', '--collection',
            help='Name of the new lesana collection',
            default=None,
            )
        parser.add_argument(
            'file',
            help='Tellico file to convert to lesana.',
            )

    def read_field_data(self, xfield):
        if xfield.iter().__next__():
            data = []
            for child in xfield:
                data.append(self.read_field_data(child))
        else:
            data = xfield.text
        return data


    def invoked(self, ctx):
        with zipfile.ZipFile(ctx.args.file, 'r') as zp:
            tree = ElementTree.parse(zp.open('tellico.xml'))
        # open collection
        xml_collection = tree.getroot().find('tellico:collection', NS)

        # get collection settings
        title = xml_collection.attrib['title']
        xml_fields = xml_collection.find('tellico:fields', NS)
        fields = []
        for xf in xml_fields:
            f_type = F_TYPE_MAP.get(xf.attrib['format'])
            # TODO: support fields with the multiple values flag
            # (they should probably become lists)
            try:
                flags = int(xf.attrib['flags'])
            except ValueError:
                flags = 0
            if flags % 2 == 1:
                l_type = f_type
                f_type = 'list'
            else:
                l_type = None
            field = {
                'name': xf.attrib['name'],
                'type': f_type,
                'help': xf.attrib['title'],
                }
            if l_type:
                field['list'] = l_type
            fields.append(field)
        # Create a collection with the settings we have loaded
        directory = ctx.args.collection or ctx.args.file.replace(
            '.tc',
            '.lesana'
            )
        self.collection = lesana.collection.Collection.init(
            directory=directory,
            git_enabled=False,
            settings={
                'name': title,
                'fields': fields,
                }
            )

        # import data
        for xe in xml_collection.findall('tellico:entry', NS):
            data = {
                'uid': xe.attrib['id']
                }
            for xfield in xe.getchildren():
                field_name = xfield.tag.replace(
                    '{'+NS['tellico']+'}',
                    '')
                data[field_name] = self.read_field_data(xfield)
            new_entry = lesana.collection.Entry(self.collection, data=data)
            self.collection.save_entries([new_entry])
        self.collection.update_cache()




if __name__ == '__main__':
    T2L().main()