repobrowser: pass with_raw_output=True to git cat-file
[git-cola.git] / cola / controllers / repobrowser.py
blob9f828f7a00ed9d2e6f0911a01fe24efd226b6900
1 #!/usr/bin/env python
2 import os
3 from PyQt4.QtGui import QDialog
5 from cola import utils
6 from cola import qtutils
7 from cola import defaults
8 from cola.views import CommitView
9 from cola.qobserver import QObserver
11 def select_file_from_repo(model, parent):
12 model = model.clone()
13 view = CommitView(parent)
14 controller = RepoBrowserController(model, view,
15 title='Select File',
16 get_file=True)
17 view.show()
18 if view.exec_() == QDialog.Accepted:
19 return controller.filename
20 else:
21 return None
23 def browse_git_branch(model, parent, branch):
24 if not branch:
25 return
26 # Clone the model to allow opening multiple browsers
27 # with different sets of data
28 model = model.clone()
29 model.set_currentbranch(branch)
30 view = CommitView(parent)
31 controller = RepoBrowserController(model, view)
32 view.show()
33 return view.exec_() == QDialog.Accepted
35 class RepoBrowserController(QObserver):
36 def init(self, model, view, title='File Browser', get_file=False):
37 self.get_file = get_file
38 self.filename = None
39 view.setWindowTitle(title)
40 self.add_signals('itemSelectionChanged()', view.commit_list,)
41 self.add_actions(directory = self.action_directory_changed)
42 self.add_callbacks(commit_list = self.item_changed)
43 # Start at the root of the tree
44 model.set_directory('')
46 ######################################################################
47 # Actions
48 def action_directory_changed(self):
49 """This is called in response to a change in the the
50 model's directory."""
51 self.model.init_browser_data()
52 self.__display_items()
54 ######################################################################
55 # Qt callbacks
56 def item_changed(self,*rest):
57 """This is called when the current item changes in the
58 file/directory list(aka the commit_list)."""
59 current = self.view.commit_list.currentRow()
60 item = self.view.commit_list.item(current)
61 if item is None or not item.isSelected():
62 self.view.revision.setText('')
63 self.view.commit_text.setText('')
64 return
65 directories = self.model.get_directories()
66 directory_entries = self.model.get_directory_entries()
67 if current < len(directories):
68 # This is a directory...
69 self.filename = None
70 dirent = directories[current]
71 if dirent != '..':
72 # This is a real directory for which
73 # we have child entries
74 entries = directory_entries[dirent]
75 else:
76 # This is '..' which is a special case
77 # since it doesn't really exist
78 entries = []
79 self.view.commit_text.setText('\n'.join(entries))
80 self.view.revision.setText('')
81 else:
82 # This is a file entry. The current row is absolute,
83 # so get a relative index by subtracting the number
84 # of directory entries
85 idx = current - len(directories)
86 if idx >= len(self.model.get_subtree_sha1s()):
87 # This can happen when changing directories
88 self.filename = None
89 return
90 objtype, sha1, name = self.model.get_subtree_node(idx)
92 curdir = self.model.get_directory()
93 if curdir:
94 self.filename = os.path.join(curdir, name)
95 else:
96 self.filename = name
98 catguts = self.model.git.cat_file(objtype, sha1,
99 with_raw_output=True)
100 self.view.commit_text.setText(catguts)
102 self.view.revision.setText(sha1)
103 self.view.revision.selectAll()
105 # Copy the sha1 into the clipboard
106 qtutils.set_clipboard(sha1)
108 # automatically called by qobserver
109 def commit_list_doubleclick(self,*rest):
110 """This is called when an entry is double-clicked.
111 This callback changes the model's directory when
112 invoked on a directory item. When invoked on a file
113 it allows the file to be saved."""
115 current = self.view.commit_list.currentRow()
116 directories = self.model.get_directories()
118 # A file item was double-clicked.
119 # Create a save-as dialog and export the file,
120 # or if in get_file mode, grab the filename and finish the dialog.
121 if current >= len(directories):
122 idx = current - len(directories)
124 objtype, sha1, name = self.model.get_subtree_node(idx)
126 if self.get_file:
127 if self.model.get_directory():
128 curdir = self.model.get_directory()
129 self.filename = os.path.join(curdir, name)
130 else:
131 self.filename = name
132 self.view.accept()
133 return
135 nameguess = os.path.join(defaults.DIRECTORY, name)
137 filename = qtutils.save_dialog(self.view, 'Save', nameguess)
138 if not filename:
139 return
140 defaults.DIRECTORY = os.path.dirname(filename)
141 contents = self.model.git.cat_file(objtype, sha1,
142 with_raw_output=True)
143 utils.write(filename, contents)
144 return
146 dirent = directories[current]
147 curdir = self.model.get_directory()
149 # '..' is a special case--it doesn't really exist...
150 if dirent == '..':
151 newdir = os.path.dirname(os.path.dirname(curdir))
152 if newdir == '':
153 self.model.set_directory(newdir)
154 else:
155 self.model.set_directory(newdir + os.sep)
156 else:
157 self.model.set_directory(curdir + dirent)
159 ######################################################################
161 def __display_items(self):
162 """This method populates the commit_list(aka item list)
163 with the current directories and items. Directories are
164 always listed first."""
166 self.view.commit_text.setText('')
167 self.view.revision.setText('')
169 dir_icon = utils.get_icon('dir.png')
170 file_icon = utils.get_icon('generic.png')
171 creator = qtutils.create_listwidget_item
173 qtutils.set_items(self.view.commit_list,
174 map(lambda d: creator(d, dir_icon),
175 self.model.get_directories()))
177 qtutils.add_items(self.view.commit_list,
178 map(lambda s: creator(s, file_icon),
179 self.model.get_subtree_names()))