-
Notifications
You must be signed in to change notification settings - Fork 0
/
shotwell-share.vala
125 lines (110 loc) · 3.82 KB
/
shotwell-share.vala
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
120
121
122
123
124
using GLib;
using Sqlite;
private struct Item {
string filename;
int rating;
int flags;
int is_primary_photo;
int event_id;
string event;
string transformations;
string title;
public string serialize () {
return "<item>"
+ "<filename>%s</filename>".printf (filename)
+ "<rating>%d</rating>".printf (rating)
+ "<flags>%d</flags>".printf (flags)
+ (is_primary_photo == 0 ? "" : "<primary>1</primary>")
+ "<event_id>%d</event_id>".printf (event_id)
+ (event == null ? "" : "<event><![CDATA[%s]]></event>".printf (event))
+ (transformations == null ? "" : "<transformations><![CDATA[%s]]></transformations>".printf (transformations))
+ (title == null ? "" : "<title><![CDATA[%s]]></title>".printf (title))
+ "</item>\n";
}
}
public class ShotwellXmlExporter {
private const string INDEX_FILE_NAME = "shotwell-export.xml";
string dbfile;
Database db;
Gee.Map<string, Gee.List<Item?>> folders = new Gee.HashMap<string, Gee.List<Item?>> ();
public ShotwellXmlExporter (string dbfile) {
this.dbfile = dbfile;
}
public static int main (string[] args) {
string dbfile = args[1];
var e = new ShotwellXmlExporter (dbfile);
e.export ();
return 0;
}
public void export () {
if (Database.open (dbfile, out db) != Sqlite.OK)
error ("Can't open DB file");
Statement stmt;
// eventtable: id, name, primary_source_id // (thumb0000001 or vide-000000a)
// phototable: id, filename, event_id, transformations, flags, rating, title
// videotable id, filename, event_id, rating, title, flags
string qry = "SELECT "
+ "P.id, P.filename, P.rating, P.flags, P.event_id, E.name, P.transformations, P.title, "
+ "E.primary_source_id "
+ "FROM PhotoTable P "
+ "JOIN EventTable E ON P.event_id=E.id";
if (db.prepare (qry, -1, out stmt, null) != Sqlite.OK) {
error ("SQL error: %s\n".printf (db.errmsg ()));
}
while (stmt.step () == Sqlite.ROW) {
int photo_id = stmt.column_int (0);
string filepath = stmt.column_text (1);
int l = filepath.last_index_of ("/");
assert (l < filepath.length);
string file_dir = filepath[0:l+1];
int rating = stmt.column_int (2);
int flags = stmt.column_int (3);
int event_id = stmt.column_int (4);
string event = stmt.column_text (5);
string transformations = stmt.column_text (6);
string title = stmt.column_text (7);
string primary_source_id = stmt.column_text (8);
int is_primary_photo = 0;
primary_source_id.scanf ("thumb%x", ref is_primary_photo);
is_primary_photo = (is_primary_photo == photo_id ? 1 : 0);
Item item = Item () {
filename = filepath[l+1:filepath.length],
rating = rating,
flags = flags,
event_id = event_id,
event = event,
transformations = transformations,
title = title,
is_primary_photo = is_primary_photo
};
Gee.List<Item?> folder = folders.get (file_dir);
if (folder == null) {
folder = new Gee.LinkedList<Item?> ();
folders.set (file_dir, folder);
}
folder.add (item);
}
// Generate some SID to match up events between xml files
// Would be even better if we could match up the originating DB
int micros = new DateTime.now_local ().get_microsecond ();
Random.set_seed (micros);
uint sid = Random.next_int ();
foreach (string path in folders.keys) {
try {
var file = File.new_for_path (path + INDEX_FILE_NAME);
var file_stream = file.replace (null, false, FileCreateFlags.NONE);
var stream = new DataOutputStream (file_stream);
stream.put_string ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
stream.put_string ("<shotwell-export sid=\"%u\">".printf (sid));
Gee.List<Item?> folder = folders.get(path);
foreach (Item? i in folder) {
assert (i != null);
stream.put_string (i.serialize ());
}
stream.put_string ("</shotwell-export>");
} catch (GLib.Error e) {
critical (e.message);
}
}
}
}