2 """This controller handles the repository file browser."""
6 from PyQt4
.QtGui
import QDialog
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
):
16 view
= CommitView(parent
)
17 controller
= RepoBrowserController(model
, view
,
21 if view
.exec_() == QDialog
.Accepted
:
22 return controller
.filename
26 def browse_git_branch(model
, parent
, branch
):
29 # Clone the model to allow opening multiple browsers
30 # with different sets of data
32 model
.set_currentbranch(branch
)
33 view
= CommitView(parent
)
34 controller
= RepoBrowserController(model
, view
)
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
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 ######################################################################
51 def action_directory_changed(self
):
52 """This is called in response to a change in the the
54 self
.model
.init_browser_data()
55 self
.__display
_items
()
57 ######################################################################
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('')
68 directories
= self
.model
.get_directories()
69 directory_entries
= self
.model
.get_directory_entries()
70 if current
< len(directories
):
71 # This is a directory...
73 dirent
= directories
[current
]
75 # This is a real directory for which
76 # we have child entries
77 entries
= directory_entries
[dirent
]
79 # This is '..' which is a special case
80 # since it doesn't really exist
82 self
.view
.commit_text
.setText('\n'.join(entries
))
83 self
.view
.revision
.setText('')
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
93 objtype
, sha1
, name
= self
.model
.get_subtree_node(idx
)
95 curdir
= self
.model
.get_directory()
97 self
.filename
= os
.path
.join(curdir
, 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
)
130 if self
.model
.get_directory():
131 curdir
= self
.model
.get_directory()
132 self
.filename
= os
.path
.join(curdir
, name
)
138 nameguess
= os
.path
.join(defaults
.DIRECTORY
, name
)
140 filename
= qtutils
.save_dialog(self
.view
, 'Save', nameguess
)
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
)
149 dirent
= directories
[current
]
150 curdir
= self
.model
.get_directory()
152 # '..' is a special case--it doesn't really exist...
154 newdir
= os
.path
.dirname(os
.path
.dirname(curdir
))
156 self
.model
.set_directory(newdir
)
158 self
.model
.set_directory(newdir
+ os
.sep
)
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()))