2 from __future__
import absolute_import
, division
, print_function
, unicode_literals
8 from qtpy
.QtCore
import Qt
10 from qtpy
import QtWidgets
14 from .. import resources
15 from .. import hotkeys
17 from .. import qtutils
18 from .. import version
22 def about_dialog(context
):
23 """Launches the Help -> About dialog"""
24 view
= AboutView(context
, qtutils
.active_window())
29 class ExpandingTabBar(QtWidgets
.QTabBar
):
30 """A TabBar with tabs that expand to fill the empty space
32 The setExpanding(True) method does not work in practice because
33 it respects the OS style. We override the style by implementing
34 tabSizeHint() so that we can specify the size explicitly.
38 def tabSizeHint(self
, tab_index
):
39 width
= self
.parent().width() // max(2, self
.count()) - 1
40 size
= super(ExpandingTabBar
, self
).tabSizeHint(tab_index
)
45 class ExpandingTabWidget(QtWidgets
.QTabWidget
):
46 def __init__(self
, parent
=None):
47 super(ExpandingTabWidget
, self
).__init
__(parent
)
48 self
.setTabBar(ExpandingTabBar(self
))
50 def resizeEvent(self
, event
):
51 """Forward resize events to the ExpandingTabBar"""
52 # Qt does not resize the tab bar when the dialog is resized
53 # so manually forward resize events to the tab bar.
54 width
= event
.size().width()
55 height
= self
.tabBar().height()
56 self
.tabBar().resize(width
, height
)
57 return super(ExpandingTabWidget
, self
).resizeEvent(event
)
60 class AboutView(QtWidgets
.QDialog
):
61 """Provides the git-cola 'About' dialog"""
63 def __init__(self
, context
, parent
=None):
64 QtWidgets
.QDialog
.__init
__(self
, parent
)
66 self
.context
= context
67 self
.setWindowTitle(N_('About git-cola'))
68 self
.setWindowModality(Qt
.WindowModal
)
71 logo_pixmap
= icons
.cola().pixmap(defs
.huge_icon
, defs
.large_icon
)
73 self
.logo_label
= QtWidgets
.QLabel()
74 self
.logo_label
.setPixmap(logo_pixmap
)
75 self
.logo_label
.setAlignment(Qt
.AlignCenter
)
77 self
.logo_text_label
= QtWidgets
.QLabel()
78 self
.logo_text_label
.setText('Git Cola')
79 self
.logo_text_label
.setAlignment(Qt
.AlignLeft | Qt
.AlignCenter
)
81 font
= self
.logo_text_label
.font()
82 font
.setPointSize(defs
.logo_text
)
83 self
.logo_text_label
.setFont(font
)
85 self
.text
= qtutils
.textbrowser(text
=copyright_text())
86 self
.version
= qtutils
.textbrowser(text
=version_text(context
))
87 self
.authors
= qtutils
.textbrowser(text
=authors_text())
88 self
.translators
= qtutils
.textbrowser(text
=translators_text())
90 self
.tabs
= ExpandingTabWidget()
91 self
.tabs
.addTab(self
.text
, N_('About'))
92 self
.tabs
.addTab(self
.version
, N_('Version'))
93 self
.tabs
.addTab(self
.authors
, N_('Authors'))
94 self
.tabs
.addTab(self
.translators
, N_('Translators'))
96 self
.close_button
= qtutils
.close_button()
97 self
.close_button
.setDefault(True)
99 self
.logo_layout
= qtutils
.hbox(
103 self
.logo_text_label
,
107 self
.button_layout
= qtutils
.hbox(
108 defs
.spacing
, defs
.margin
, qtutils
.STRETCH
, self
.close_button
111 self
.main_layout
= qtutils
.vbox(
118 self
.setLayout(self
.main_layout
)
120 qtutils
.connect_button(self
.close_button
, self
.accept
)
122 self
.resize(defs
.scale(600), defs
.scale(720))
125 def copyright_text():
127 Git Cola: The highly caffeinated Git GUI
129 Copyright (C) 2007-2020 David Aguilar and contributors
131 This program is free software: you can redistribute it and/or
132 modify it under the terms of the GNU General Public License
133 version 2 as published by the Free Software Foundation.
135 This program is distributed in the hope that it will
136 be useful, but WITHOUT ANY WARRANTY; without even the
137 implied warranty of MERCHANTABILITY or
138 FITNESS FOR A PARTICULAR PURPOSE.
140 See the GNU General Public License for more details.
142 You should have received a copy of the
143 GNU General Public License along with this program.
144 If not, see http://www.gnu.org/licenses/.
149 def version_text(context
):
150 git_version
= version
.git_version(context
)
151 cola_version
= version
.version()
152 build_version
= version
.build_version()
153 python_path
= sys
.executable
154 python_version
= sys
.version
155 qt_version
= qtpy
.QT_VERSION
156 qtpy_version
= qtpy
.__version
__
157 pyqt_api_name
= qtpy
.API_NAME
158 if qtpy
.PYQT5
or qtpy
.PYQT4
:
159 pyqt_api_version
= qtpy
.PYQT_VERSION
161 pyqt_api_version
= qtpy
.PYSIDE_VERSION
163 pyqt_api_version
= 'unknown'
165 platform_version
= platform
.platform()
167 # Only show the build version if _build_version.py exists
169 build_version
= '(%s)' % build_version
174 cola_version
=cola_version
,
175 build_version
=build_version
,
176 git_version
=git_version
,
177 platform_version
=platform_version
,
178 pyqt_api_name
=pyqt_api_name
,
179 pyqt_api_version
=pyqt_api_version
,
180 python_path
=python_path
,
181 python_version
=python_version
,
182 qt_version
=qt_version
,
183 qtpy_version
=qtpy_version
,
190 Git Cola version %(cola_version)s %(build_version)s
192 <li> %(platform_version)s
193 <li> Python (%(python_path)s) %(python_version)s
194 <li> Git %(git_version)s
195 <li> Qt %(qt_version)s
196 <li> QtPy %(qtpy_version)s
197 <li> %(pyqt_api_name)s %(pyqt_api_version)s
205 def link(url
, text
, palette
=None):
207 palette
= QtGui
.QPalette()
209 color
= palette
.color(QtGui
.QPalette
.Foreground
)
210 rgb
= 'rgb(%s, %s, %s)' % (color
.red(), color
.green(), color
.blue())
211 scope
= dict(rgb
=rgb
, text
=text
, url
=url
)
215 <a style="font-style: italic; text-decoration: none; color: %(rgb)s;"
224 def mailto(email
, text
, palette
):
225 return link('mailto:%s' % email
, text
, palette
) + '<br>'
228 def render_authors(authors
):
229 """Render a list of author details into richtext html"""
231 x
.setdefault('email', '')
237 <strong>%(name)s</strong><br>
238 <em>%(title)s</em><br>
244 for author
in authors
247 return ''.join(entries
)
250 def contributors_text(authors
, prelude
='', epilogue
=''):
251 author_text
= render_authors(authors
)
252 scope
= dict(author_text
=author_text
, epilogue
=epilogue
, prelude
=prelude
)
265 palette
= QtGui
.QPalette()
266 contact
= N_('Email contributor')
268 # The names listed here are listed in the same order as
269 # `git shortlog --summary --numbered --no-merges`
270 # Please submit a pull request if you would like to include your
271 # email address in the about screen.
272 # See the `generate-about` script in the "todo" branch.
273 # vim :read! ./Meta/generate-about
275 name
='David Aguilar',
276 title
=N_('Maintainer (since 2007) and developer'),
277 email
=mailto('davvid@gmail.com', contact
, palette
),
279 dict(name
='Daniel Harding', title
=N_('Developer')),
282 title
=N_('Developer'),
283 email
=mailto('Vdragon.Taiwan@gmail.com', contact
, palette
),
285 dict(name
='Efimov Vasily', title
=N_('Developer')),
286 dict(name
='Guillaume de Bure', title
=N_('Developer')),
287 dict(name
='Uri Okrent', title
=N_('Developer')),
288 dict(name
='Javier Rodriguez Cuevas', title
=N_('Developer')),
289 dict(name
='Alex Chernetz', title
=N_('Developer')),
290 dict(name
='xhl', title
=N_('Developer')),
291 dict(name
='Andreas Sommer', title
=N_('Developer')),
292 dict(name
='Thomas Kluyver', title
=N_('Developer')),
293 dict(name
='Minarto Margoliono', title
=N_('Developer')),
294 dict(name
='Ville Skyttä', title
=N_('Developer')),
295 dict(name
='Szymon Judasz', title
=N_('Developer')),
296 dict(name
='jm4R', title
=N_('Developer')),
297 dict(name
='Stanislaw Halik', title
=N_('Developer')),
298 dict(name
='Igor Galarraga', title
=N_('Developer')),
299 dict(name
='Virgil Dupras', title
=N_('Developer')),
300 dict(name
='wsdfhjxc', title
=N_('Developer')),
301 dict(name
='Barry Roberts', title
=N_('Developer')),
302 dict(name
='林博仁(Buo-ren Lin)', title
=N_('Developer')),
303 dict(name
='Guo Yunhe', title
=N_('Developer')),
304 dict(name
='cclauss', title
=N_('Developer')),
305 dict(name
='Stefan Naewe', title
=N_('Developer')),
306 dict(name
='Victor Nepveu', title
=N_('Developer')),
307 dict(name
='Pavel Rehak', title
=N_('Developer')),
308 dict(name
='Benedict Lee', title
=N_('Developer')),
309 dict(name
='Tim Brown', title
=N_('Developer')),
310 dict(name
='Steffen Prohaska', title
=N_('Developer')),
311 dict(name
='Filip Danilović', title
=N_('Developer')),
312 dict(name
='NotSqrt', title
=N_('Developer')),
313 dict(name
='Michael Geddes', title
=N_('Developer')),
314 dict(name
='Rustam Safin', title
=N_('Developer')),
315 dict(name
='Justin Lecher', title
=N_('Developer')),
316 dict(name
='Alex Gulyás', title
=N_('Developer')),
317 dict(name
='David Martínez Martí', title
=N_('Developer')),
318 dict(name
='Hualiang Xie', title
=N_('Developer')),
319 dict(name
='Kai Krakow', title
=N_('Developer')),
320 dict(name
='Karl Bielefeldt', title
=N_('Developer')),
321 dict(name
='Marco Costalba', title
=N_('Developer')),
322 dict(name
='Michael Homer', title
=N_('Developer')),
323 dict(name
='Sebastian Schuberth', title
=N_('Developer')),
324 dict(name
='Sven Claussner', title
=N_('Developer')),
325 dict(name
='Victor Gambier', title
=N_('Developer')),
326 dict(name
='bsomers', title
=N_('Developer')),
327 dict(name
='real', title
=N_('Developer')),
328 dict(name
='v.paritskiy', title
=N_('Developer')),
329 dict(name
='vanderkoort', title
=N_('Developer')),
330 dict(name
='wm4', title
=N_('Developer')),
331 dict(name
='Audrius Karabanovas', title
=N_('Developer')),
332 dict(name
='Matthew E. Levine', title
=N_('Developer')),
333 dict(name
='Matthias Mailänder', title
=N_('Developer')),
334 dict(name
='Md. Mahbub Alam', title
=N_('Developer')),
335 dict(name
='Jakub Szymański', title
=N_('Developer')),
336 dict(name
='ochristi', title
=N_('Developer')),
337 dict(name
='Miguel Boekhold', title
=N_('Developer')),
338 dict(name
='MiguelBoekhold', title
=N_('Developer')),
339 dict(name
='Mikhail Terekhov', title
=N_('Developer')),
340 dict(name
='Jake Biesinger', title
=N_('Developer')),
341 dict(name
='Iulian Udrea', title
=N_('Developer')),
342 dict(name
='Paul Hildebrandt', title
=N_('Developer')),
343 dict(name
='Paul Weingardt', title
=N_('Developer')),
344 dict(name
='Paulo Fidalgo', title
=N_('Developer')),
345 dict(name
='Ilya Tumaykin', title
=N_('Developer')),
346 dict(name
='Petr Gladkikh', title
=N_('Developer')),
347 dict(name
='Philip Stark', title
=N_('Developer')),
348 dict(name
='Radek Postołowicz', title
=N_('Developer')),
349 dict(name
='Rainer Müller', title
=N_('Developer')),
350 dict(name
='Ricardo J. Barberis', title
=N_('Developer')),
351 dict(name
='Rolando Espinoza', title
=N_('Developer')),
352 dict(name
='George Vasilakos', title
=N_('Developer')),
353 dict(name
="Samsul Ma'arif", title
=N_('Developer')),
354 dict(name
='Sebastian Brass', title
=N_('Developer')),
355 dict(name
='Arthur Coelho', title
=N_('Developer')),
356 dict(name
='Simon Peeters', title
=N_('Developer')),
357 dict(name
='Felipe Morales', title
=N_('Developer')),
358 dict(name
='David Zumbrunnen', title
=N_('Developer')),
359 dict(name
='David Schwörer', title
=N_('Developer')),
360 dict(name
='Stephen', title
=N_('Developer')),
361 dict(name
='Andrej', title
=N_('Developer')),
362 dict(name
='Daniel Pavel', title
=N_('Developer')),
363 dict(name
='Daniel King', title
=N_('Developer')),
364 dict(name
='Daniel Haskin', title
=N_('Developer')),
365 dict(name
='Clément Pit--Claudel', title
=N_('Developer')),
366 dict(name
='Vaibhav Sagar', title
=N_('Developer')),
367 dict(name
='Ved Vyas', title
=N_('Developer')),
368 dict(name
='Adrien be', title
=N_('Developer')),
369 dict(name
='Charles', title
=N_('Developer')),
370 dict(name
='Boris W', title
=N_('Developer')),
371 dict(name
='Ben Boeckel', title
=N_('Developer')),
372 dict(name
='Voicu Hodrea', title
=N_('Developer')),
373 dict(name
='Wesley Wong', title
=N_('Developer')),
374 dict(name
='Wolfgang Ocker', title
=N_('Developer')),
375 dict(name
='Zhang Han', title
=N_('Developer')),
376 dict(name
='beauxq', title
=N_('Developer')),
377 dict(name
='Jamie Pate', title
=N_('Developer')),
378 dict(name
='Jean-Francois Dagenais', title
=N_('Developer')),
379 dict(name
='Joachim Lusiardi', title
=N_('Developer')),
380 dict(name
='0xflotus', title
=N_('Developer')),
381 dict(name
='AJ Bagwell', title
=N_('Developer')),
382 dict(name
='Barrett Lowe', title
=N_('Developer')),
383 dict(name
='Karthik Manamcheri', title
=N_('Developer')),
384 dict(name
='Kelvie Wong', title
=N_('Developer')),
385 dict(name
='Kyle', title
=N_('Developer')),
386 dict(name
='Maciej Filipiak', title
=N_('Developer')),
387 dict(name
='Maicon D. Filippsen', title
=N_('Developer')),
388 dict(name
='Markus Heidelberg', title
=N_('Developer')),
390 bug_url
= 'https://github.com/git-cola/git-cola/issues'
391 bug_link
= link(bug_url
, bug_url
)
392 scope
= dict(bug_link
=bug_link
)
397 Please use %(bug_link)s to report issues.
404 return contributors_text(authors
, prelude
=prelude
)
407 def translators_text():
408 palette
= QtGui
.QPalette()
409 contact
= N_('Email contributor')
412 # See the `generate-about` script in the "todo" branch.
413 # vim :read! ./Meta/generate-about --translators
416 title
=N_('Traditional Chinese (Taiwan) translation'),
417 email
=mailto('Vdragon.Taiwan@gmail.com', contact
, palette
),
419 dict(name
='Pavel Rehak', title
=N_('Czech translation')),
420 dict(name
='Zhang Han', title
=N_('Simplified Chinese translation')),
421 dict(name
='Victorhck', title
=N_('Spanish translation')),
422 dict(name
='Vitor Lobo', title
=N_('Brazilian translation')),
423 dict(name
='Igor Kopach', title
=N_('Ukranian translation')),
424 dict(name
='Łukasz Wojniłowicz', title
=N_('Polish translation')),
425 dict(name
='Rafael Nascimento', title
=N_('Brazilian translation')),
426 dict(name
='Barış ÇELİK', title
=N_('Turkish translation')),
427 dict(name
='Minarto Margoliono', title
=N_('Indonesian translation')),
428 dict(name
='Sven Claussner', title
=N_('German translation')),
429 dict(name
='Shun Sakai', title
=N_('Japanese translation')),
430 dict(name
='Vaiz', title
=N_('Russian translation')),
431 dict(name
='adlgrbz', title
=N_('Turkish translation')),
432 dict(name
='fu7mu4', title
=N_('Japanese translation')),
433 dict(name
='Guo Yunhe', title
=N_('Simplified Chinese translation')),
434 dict(name
="Samsul Ma'arif", title
=N_('Indonesian translation')),
435 dict(name
='Gyuris Gellért', title
=N_('Hungarian translation')),
436 dict(name
='Joachim Lusiardi', title
=N_('German translation')),
437 dict(name
='Kai Krakow', title
=N_('German translation')),
438 dict(name
='Louis Rousseau', title
=N_('French translation')),
439 dict(name
='Mickael Albertus', title
=N_('French translation')),
441 name
='Peter Dave Hello',
442 title
=N_('Traditional Chinese (Taiwan) translation'),
444 dict(name
='Pilar Molina Lopez', title
=N_('Spanish translation')),
445 dict(name
='Rafael Reuber', title
=N_('Brazilian translation')),
446 dict(name
='Sabri Ünal', title
=N_('Turkish translation')),
447 dict(name
='Balázs Meskó', title
=N_('Translation')),
448 dict(name
='Zeioth', title
=N_('Spanish translation')),
449 dict(name
='balping', title
=N_('Hungarian translation')),
450 dict(name
='p-bo', title
=N_('Czech translation')),
452 name
='林博仁(Buo-ren Lin)',
453 title
=N_('Traditional Chinese (Taiwan) translation'),
457 bug_url
= 'https://github.com/git-cola/git-cola/issues'
458 bug_link
= link(bug_url
, bug_url
)
459 scope
= dict(bug_link
=bug_link
)
465 Git Cola has been translated into different languages thanks
466 to the help of the individuals listed below.
470 Translation is approximate. If you find a mistake,
471 please let us know by opening an issue on Github:
480 We invite you to participate in translation by adding or updating
481 a translation and opening a pull request.
490 return contributors_text(translators
, prelude
=prelude
)
493 def show_shortcuts():
494 hotkeys_html
= resources
.doc(N_('hotkeys.html'))
496 from qtpy
import QtWebEngineWidgets
# pylint: disable=all
497 except (ImportError, qtpy
.PythonQtError
):
498 # redhat disabled QtWebKit in their qt build but don't punish the users
499 webbrowser
.open_new_tab('file://' + hotkeys_html
)
502 html
= core
.read(hotkeys_html
)
504 parent
= qtutils
.active_window()
505 widget
= QtWidgets
.QDialog(parent
)
506 widget
.setWindowModality(Qt
.WindowModal
)
507 widget
.setWindowTitle(N_('Shortcuts'))
509 web
= QtWebEngineWidgets
.QWebEngineView()
512 layout
= qtutils
.hbox(defs
.no_margin
, defs
.spacing
, web
)
513 widget
.setLayout(layout
)
514 widget
.resize(800, min(parent
.height(), 600))
516 widget
, N_('Close'), widget
.accept
, hotkeys
.QUESTION
, *hotkeys
.ACCEPT