Added illysam branch
[hooke.git] / lib / playlist.py
1 #!/usr/bin/env python\r
2 \r
3 '''\r
4 playlist.py\r
5 \r
6 Playlist class for Hooke.\r
7 \r
8 Copyright 2010 by Dr. Rolf Schmidt (Concordia University, Canada)\r
9 \r
10 This program is released under the GNU General Public License version 2.\r
11 '''\r
12 \r
13 import os.path\r
14 import xml.dom.minidom\r
15 \r
16 import lib.libhooke\r
17 import lib.file\r
18 \r
19 class Playlist(object):\r
20 \r
21     def __init__(self, filename=None):\r
22         self._saved = False\r
23         self.count = 0\r
24         self.figure = None\r
25         self.files = []\r
26         self.generics_dict = {}\r
27         self.hidden_attributes = ['curve', 'data', 'driver', 'fits', 'name', 'plots']\r
28         self.index = -1\r
29         self.name = None\r
30         self.path = None\r
31         self.plot_panel = None\r
32         self.plot_tab = None\r
33         if filename is None:\r
34             self.filename = None\r
35         else:\r
36             self.load(filename)\r
37 \r
38     def add_file(self, filename):\r
39         if os.path.isfile(filename):\r
40             file_to_add = lib.file.File(filename)\r
41             self.files.append(file_to_add)\r
42             self._saved = False\r
43         self.count = len(self.files)\r
44 \r
45     def delete_file(self, name):\r
46         for index, item in enumerate(self.files):\r
47             if item.name == name:\r
48                 del self.files[index]\r
49                 self.index = index\r
50         self.count = len(self.files)\r
51         if self.index > self.count - 1:\r
52             self.index = 0\r
53 \r
54     def filter_curves(self, curves_to_keep=[]):\r
55         playlist = Playlist()\r
56         for curve_index in curves_to_keep:\r
57             playlist.files.append(self.files[curve_index])\r
58         playlist.count = len(playlist.files)\r
59         playlist.index = 0\r
60         return playlist\r
61 \r
62     def get_active_file(self):\r
63         return self.files[self.index]\r
64 \r
65     #def get_active_plot(self):\r
66         ##TODO: is this the only active (or default?) plot?\r
67         #return self.files[self.index].plots[0]\r
68 \r
69     def get_status_string(self):\r
70         if self.count > 0:\r
71             activeFileStr = ''.join([' (%s/%s)' %(self.index + 1, self.count)])\r
72             return ''.join([self.name, activeFileStr])\r
73         else:\r
74             return ''.join(['The file ', self.name, ' does not contain any valid force curve data.\n'])\r
75 \r
76     def load(self, filename):\r
77         '''\r
78         loads a playlist file\r
79         '''\r
80         self.filename = filename\r
81         self.path, self.name = os.path.split(filename)\r
82         playlist_file = lib.libhooke.delete_empty_lines_from_xmlfile(filename)\r
83         self.xml = xml.dom.minidom.parseString(playlist_file)\r
84         #TODO: rename 'element' to 'curve' or something in hkp file\r
85         #TODO: rename 'path' to 'filename'\r
86         #TODO: switch from attributes to nodes, it's cleaner XML in my eyes\r
87 \r
88         element_list = self.xml.getElementsByTagName('element')\r
89         #populate playlist with files\r
90         for index, element in enumerate(element_list):\r
91             #rebuild a data structure from the xml attributes\r
92             #the next two lines are here for backwards compatibility, newer playlist files use 'filename' instead of 'path'\r
93             if element.hasAttribute('path'):\r
94                 filename = lib.libhooke.get_file_path(element.getAttribute('path'))\r
95             if element.hasAttribute('filename'):\r
96                 filename = lib.libhooke.get_file_path(element.getAttribute('filename'))\r
97             if os.path.isfile(filename):\r
98                 data_file = lib.file.File(filename)\r
99                 self.files.append(data_file)\r
100         self.count = len(self.files)\r
101         if self.count > 0:\r
102             #populate generics\r
103             genericsDict = {}\r
104             generics_list = self.xml.getElementsByTagName('generics')\r
105             if generics_list:\r
106                 for attribute in generics_list[0].attributes.keys():\r
107                     genericsDict[attribute] = generics_list[0].getAttribute(attribute)\r
108             if genericsDict.has_key('pointer'):\r
109                 index = int(genericsDict['pointer'])\r
110                 if index >= 0 and index < self.count:\r
111                     self.index = index\r
112                 else:\r
113                     index = 0\r
114             self._saved = True\r
115 \r
116     def next(self):\r
117         self.index += 1\r
118         if self.index > self.count - 1:\r
119             self.index = 0\r
120 \r
121     def previous(self):\r
122         self.index -= 1\r
123         if self.index < 0:\r
124             self.index = self.count - 1\r
125 \r
126     def reset(self):\r
127         if self.count > 0:\r
128             self.index = 0\r
129         else:\r
130             self.index = -1\r
131 \r
132     def save(self, filename):\r
133         '''\r
134         Saves a playlist from a list of files.\r
135         A playlist is an XML document with the following syntax:\r
136         <playlist>\r
137         <element path="/my/file/path/"/ attribute="attribute">\r
138         <element path="...">\r
139         </playlist>\r
140         '''\r
141         try:\r
142             output_file = file(filename, 'w')\r
143         except IOError:\r
144             self.AppendToOutput('Cannot save playlist. Wrong path or filename')\r
145             return\r
146         #create the output playlist, a simple XML document\r
147         implementation = xml.dom.minidom.getDOMImplementation()\r
148         #create the document DOM object and the root element\r
149         self.xml = implementation.createDocument(None, 'playlist', None)\r
150         root = self.xml.documentElement\r
151 \r
152         #save generics variables\r
153         playlist_generics = self.xml.createElement('generics')\r
154         root.appendChild(playlist_generics)\r
155         self.generics_dict['pointer'] = self.index\r
156         for key in self.generics_dict.keys():\r
157         #for key in generics.keys():\r
158             self.xml.createAttribute(key)\r
159             playlist_generics.setAttribute(key, str(self.generics_dict[key]))\r
160 \r
161         #save files and their attributes\r
162         for item in self.files:\r
163             #playlist_element=newdoc.createElement("file")\r
164             playlist_element = self.xml.createElement('element')\r
165             root.appendChild(playlist_element)\r
166             for key in item.__dict__:\r
167                 if not (key in self.hidden_attributes):\r
168                     self.xml.createAttribute(key)\r
169                     playlist_element.setAttribute(key, str(item.__dict__[key]))\r
170         self._saved = False\r
171 \r
172         self.xml.writexml(output_file, indent='\n')\r
173         output_file.close()\r
174         self._saved = True\r