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