git-cola v4.0.0
[git-cola.git] / cola / widgets / startup.py
blob7c5d29103f94a66ab5ab0f1a8417ca242217d166
1 """The startup dialog is presented when no repositories can be found at startup"""
2 from __future__ import absolute_import, division, print_function, unicode_literals
4 from qtpy.QtCore import Qt
5 from qtpy import QtCore
6 from qtpy import QtGui
7 from qtpy import QtWidgets
9 from ..i18n import N_
10 from .. import core
11 from .. import display
12 from .. import guicmds
13 from .. import hotkeys
14 from .. import icons
15 from .. import qtutils
16 from .. import version
17 from . import clone
18 from . import defs
19 from . import standard
22 class StartupDialog(standard.Dialog):
23 """Provides a GUI to Open or Clone a git repository."""
25 def __init__(self, context, parent=None):
26 standard.Dialog.__init__(self, parent)
27 self.context = context
28 self.setWindowTitle(N_('git-cola'))
30 # Top-most large icon
31 logo_pixmap = icons.cola().pixmap(defs.huge_icon, defs.huge_icon)
33 self.logo_label = QtWidgets.QLabel()
34 self.logo_label.setPixmap(logo_pixmap)
35 self.logo_label.setAlignment(Qt.AlignCenter)
37 self.logo_text_label = qtutils.label(text=version.cola_version())
38 self.logo_text_label.setAlignment(Qt.AlignCenter)
40 self.repodir = None
41 if context.runtask:
42 self.runtask = context.runtask
43 else:
44 self.runtask = context.runtask = qtutils.RunTask(parent=self)
46 self.new_button = qtutils.create_button(text=N_('New...'), icon=icons.new())
47 self.open_button = qtutils.create_button(
48 text=N_('Open...'), icon=icons.folder()
50 self.clone_button = qtutils.create_button(
51 text=N_('Clone...'), icon=icons.cola()
53 self.close_button = qtutils.close_button()
55 self.bookmarks_model = bookmarks_model = QtGui.QStandardItemModel()
56 self.items = items = []
58 item = QtGui.QStandardItem(N_('Open...'))
59 item.setEditable(False)
60 item.setIcon(icons.open_directory())
61 bookmarks_model.appendRow(item)
63 # The tab bar allows choosing between Folder and List mode
64 self.tab_bar = QtWidgets.QTabBar()
65 self.tab_bar.setMovable(False)
66 self.tab_bar.addTab(icons.directory(), N_('Folder'))
67 self.tab_bar.addTab(icons.three_bars(), N_('List'))
69 # Bookmarks/"Favorites" and Recent are lists of {name,path: str}
70 settings = context.settings
71 bookmarks = settings.bookmarks
72 recent = settings.recent
73 all_repos = bookmarks + recent
75 directory_icon = icons.directory()
76 user_role = Qt.UserRole
77 normalize = display.normalize_path
78 paths = set([normalize(repo['path']) for repo in all_repos])
79 short_paths = display.shorten_paths(paths)
80 self.short_paths = short_paths
82 added = set()
83 for repo in all_repos:
84 path = normalize(repo['path'])
85 if path in added:
86 continue
87 added.add(path)
89 item = QtGui.QStandardItem(path)
90 item.setEditable(False)
91 item.setData(path, user_role)
92 item.setIcon(directory_icon)
93 item.setToolTip(path)
94 item.setText(self.short_paths.get(path, path))
95 bookmarks_model.appendRow(item)
96 items.append(item)
98 selection_mode = QtWidgets.QAbstractItemView.SingleSelection
99 self.bookmarks = bookmarks = QtWidgets.QListView()
100 bookmarks.setSelectionMode(selection_mode)
101 bookmarks.setModel(bookmarks_model)
102 bookmarks.setViewMode(QtWidgets.QListView.IconMode)
103 bookmarks.setResizeMode(QtWidgets.QListView.Adjust)
104 bookmarks.setGridSize(make_size(defs.large_icon))
105 bookmarks.setIconSize(make_size(defs.medium_icon))
106 bookmarks.setDragEnabled(False)
107 bookmarks.setWordWrap(True)
109 self.tab_layout = qtutils.vbox(
110 defs.no_margin, defs.no_spacing, self.tab_bar, self.bookmarks
113 self.logo_layout = qtutils.vbox(
114 defs.no_margin,
115 defs.spacing,
116 self.logo_label,
117 self.logo_text_label,
118 defs.button_spacing,
119 qtutils.STRETCH,
122 self.button_layout = qtutils.hbox(
123 defs.no_margin,
124 defs.spacing,
125 self.open_button,
126 self.clone_button,
127 self.new_button,
128 qtutils.STRETCH,
129 self.close_button,
132 self.main_layout = qtutils.grid(defs.margin, defs.spacing)
133 self.main_layout.addItem(self.logo_layout, 1, 1)
134 self.main_layout.addItem(self.tab_layout, 1, 2)
135 self.main_layout.addItem(self.button_layout, 2, 1, columnSpan=2)
136 self.setLayout(self.main_layout)
138 qtutils.connect_button(self.open_button, self.open_repo)
139 qtutils.connect_button(self.clone_button, self.clone_repo)
140 qtutils.connect_button(self.new_button, self.new_repo)
141 qtutils.connect_button(self.close_button, self.reject)
142 # Open the selected repository when "enter" is pressed.
143 self.action_open_repo = qtutils.add_action(
144 self, N_('Open'), self.open_selected_bookmark, *hotkeys.ACCEPT
147 # pylint: disable=no-member
148 self.tab_bar.currentChanged.connect(self.tab_changed)
149 self.bookmarks.activated.connect(self.open_bookmark)
151 self.init_state(settings, self.resize_widget)
152 self.setFocusProxy(self.bookmarks)
153 self.bookmarks.setFocus()
155 # Update the list mode
156 list_mode = context.cfg.get('cola.startupmode', default='folder')
157 self.list_mode = list_mode
158 if list_mode == 'list':
159 self.tab_bar.setCurrentIndex(1)
161 def tab_changed(self, idx):
162 bookmarks = self.bookmarks
163 if idx == 0:
164 bookmarks.setViewMode(QtWidgets.QListView.IconMode)
165 bookmarks.setIconSize(make_size(defs.medium_icon))
166 bookmarks.setGridSize(make_size(defs.large_icon))
167 list_mode = 'folder'
168 for item in self.items:
169 path = item.data(Qt.UserRole)
170 item.setText(self.short_paths.get(path, path))
171 else:
172 bookmarks.setViewMode(QtWidgets.QListView.ListMode)
173 bookmarks.setIconSize(make_size(defs.default_icon))
174 bookmarks.setGridSize(QtCore.QSize())
175 list_mode = 'list'
176 for item in self.items:
177 path = item.data(Qt.UserRole)
178 item.setText(path)
180 if list_mode != self.list_mode:
181 self.list_mode = list_mode
182 self.context.cfg.set_user('cola.startupmode', list_mode)
184 def resize_widget(self):
185 screen = QtWidgets.QApplication.instance().desktop()
186 self.setGeometry(
187 screen.width() // 4,
188 screen.height() // 4,
189 screen.width() // 2,
190 screen.height() // 2,
193 def find_git_repo(self):
195 Return a path to a git repository
197 This is the entry point for external callers.
198 This method finds a git repository by allowing the
199 user to browse to one on the filesystem or by creating
200 a new one with git-clone.
203 self.show()
204 self.raise_()
205 if self.exec_() == QtWidgets.QDialog.Accepted:
206 return self.repodir
207 return None
209 def open_repo(self):
210 self.repodir = self.get_selected_bookmark()
211 if not self.repodir:
212 self.repodir = qtutils.opendir_dialog(
213 N_('Open Git Repository...'), core.getcwd()
215 if self.repodir:
216 self.accept()
218 def clone_repo(self):
219 context = self.context
220 progress = standard.progress('', '', self)
221 clone.clone_repo(context, True, progress, self.clone_repo_done, False)
223 def clone_repo_done(self, task):
224 if task.cmd and task.cmd.status == 0:
225 self.repodir = task.destdir
226 self.accept()
227 else:
228 clone.task_finished(task)
230 def new_repo(self):
231 context = self.context
232 repodir = guicmds.new_repo(context)
233 if repodir:
234 self.repodir = repodir
235 self.accept()
237 def open_selected_bookmark(self):
238 selected = self.bookmarks.selectedIndexes()
239 if selected:
240 self.open_bookmark(selected[0])
242 def open_bookmark(self, index):
243 if index.row() == 0:
244 self.open_repo()
245 else:
246 self.repodir = self.bookmarks_model.data(index, Qt.UserRole)
247 if not self.repodir:
248 return
249 if not core.exists(self.repodir):
250 self.handle_broken_repo(index)
251 return
252 self.accept()
254 def handle_broken_repo(self, index):
255 settings = self.context.settings
256 all_repos = settings.bookmarks + settings.recent
257 repodir = self.bookmarks_model.data(index, Qt.UserRole)
259 repo = next(repo for repo in all_repos if repo['path'] == repodir)
260 title = N_('Repository Not Found')
261 text = N_('%s could not be opened. Remove from bookmarks?') % repo['path']
262 logo = icons.from_style(QtWidgets.QStyle.SP_MessageBoxWarning)
263 if standard.question(title, text, N_('Remove'), logo=logo):
264 self.context.settings.remove_bookmark(repo['path'], repo['name'])
265 self.context.settings.remove_recent(repo['path'])
266 self.context.settings.save()
268 item = self.bookmarks_model.item(index.row())
269 self.items.remove(item)
270 self.bookmarks_model.removeRow(index.row())
272 def get_selected_bookmark(self):
273 selected = self.bookmarks.selectedIndexes()
274 if selected and selected[0].row() != 0:
275 return self.bookmarks_model.data(selected[0], Qt.UserRole)
276 return None
279 def make_size(size):
280 """Construct a QSize from a single value"""
281 return QtCore.QSize(size, size)