Merged Rolf Schmidt's illysam branch
[hooke.git] / hooke / ui / gui / 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', 'plot', '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                 #path, name = os.path.split(element.getAttribute('path'))\r
95                 #path = path.split(os.sep)\r
96                 #filename = lib.libhooke.get_file_path(name, path)\r
97                 filename = element.getAttribute('path')\r
98             if element.hasAttribute('filename'):\r
99                 #path, name = os.path.split(element.getAttribute('filename'))\r
100                 #path = path.split(os.sep)\r
101                 #filename = lib.libhooke.get_file_path(name, path)\r
102                 filename = element.getAttribute('filename')\r
103             if os.path.isfile(filename):\r
104                 data_file = lib.file.File(filename)\r
105                 if element.hasAttribute('note'):\r
106                     data_file.note = element.getAttribute('note')\r
107                 self.files.append(data_file)\r
108         self.count = len(self.files)\r
109         if self.count > 0:\r
110             #populate generics\r
111             genericsDict = {}\r
112             generics_list = self.xml.getElementsByTagName('generics')\r
113             if generics_list:\r
114                 for attribute in generics_list[0].attributes.keys():\r
115                     genericsDict[attribute] = generics_list[0].getAttribute(attribute)\r
116             if genericsDict.has_key('pointer'):\r
117                 index = int(genericsDict['pointer'])\r
118                 if index >= 0 and index < self.count:\r
119                     self.index = index\r
120                 else:\r
121                     index = 0\r
122             self._saved = True\r
123 \r
124     def next(self):\r
125         self.index += 1\r
126         if self.index > self.count - 1:\r
127             self.index = 0\r
128 \r
129     def previous(self):\r
130         self.index -= 1\r
131         if self.index < 0:\r
132             self.index = self.count - 1\r
133 \r
134     def reset(self):\r
135         if self.count > 0:\r
136             self.index = 0\r
137         else:\r
138             self.index = -1\r
139 \r
140     def save(self, filename):\r
141         '''\r
142         Saves a playlist from a list of files.\r
143         A playlist is an XML document with the following syntax:\r
144         <playlist>\r
145         <element path="/my/file/path/"/ attribute="attribute">\r
146         <element path="...">\r
147         </playlist>\r
148         '''\r
149         try:\r
150             output_file = file(filename, 'w')\r
151         except IOError:\r
152             self.AppendToOutput('Cannot save playlist. Wrong path or filename')\r
153             return\r
154         #create the output playlist, a simple XML document\r
155         implementation = xml.dom.minidom.getDOMImplementation()\r
156         #create the document DOM object and the root element\r
157         self.xml = implementation.createDocument(None, 'playlist', None)\r
158         root = self.xml.documentElement\r
159 \r
160         #save generics variables\r
161         playlist_generics = self.xml.createElement('generics')\r
162         root.appendChild(playlist_generics)\r
163         self.generics_dict['pointer'] = self.index\r
164         for key in self.generics_dict.keys():\r
165         #for key in generics.keys():\r
166             self.xml.createAttribute(key)\r
167             playlist_generics.setAttribute(key, str(self.generics_dict[key]))\r
168 \r
169         #save files and their attributes\r
170         for item in self.files:\r
171             #playlist_element=newdoc.createElement("file")\r
172             playlist_element = self.xml.createElement('element')\r
173             root.appendChild(playlist_element)\r
174             for key in item.__dict__:\r
175                 if not (key in self.hidden_attributes):\r
176                     self.xml.createAttribute(key)\r
177                     playlist_element.setAttribute(key, str(item.__dict__[key]))\r
178         self._saved = False\r
179 \r
180         self.xml.writexml(output_file, indent='\n')\r
181         output_file.close()\r
182         self._saved = True\r