PageRenderTime 44ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/tortoisehg/hgqt/bugreport.py

https://bitbucket.org/tinyfish/tortoisehg.winutf8
Python | 165 lines | 143 code | 13 blank | 9 comment | 3 complexity | 5093e2210366a6f621738390f7f9b515 MD5 | raw file
Possible License(s): GPL-2.0
  1. # bugreport.py - Report Python tracebacks to the user
  2. #
  3. # Copyright 2010 Steve Borho <steve@borho.org>
  4. #
  5. # This software may be used and distributed according to the terms of the
  6. # GNU General Public License version 2 or any later version.
  7. import os
  8. import sys
  9. from PyQt4.QtCore import *
  10. from PyQt4.QtGui import *
  11. from mercurial import extensions, ui
  12. from tortoisehg.util import hglib, version
  13. from tortoisehg.hgqt.i18n import _
  14. class BugReport(QDialog):
  15. def __init__(self, opts, parent=None):
  16. super(BugReport, self).__init__(parent)
  17. self.text = self.gettext(opts)
  18. layout = QVBoxLayout()
  19. tb = QTextBrowser()
  20. tb.setHtml('<pre>' + Qt.escape(self.text) + '</pre>')
  21. tb.setWordWrapMode(QTextOption.NoWrap)
  22. layout.addWidget(tb)
  23. # dialog buttons
  24. BB = QDialogButtonBox
  25. bb = QDialogButtonBox(BB.Ok|BB.Save)
  26. bb.accepted.connect(self.accept)
  27. bb.button(BB.Save).clicked.connect(self.save)
  28. bb.button(BB.Ok).setDefault(True)
  29. bb.addButton(_('Quit'), BB.DestructiveRole).clicked.connect(qApp.quit)
  30. layout.addWidget(bb)
  31. self.setLayout(layout)
  32. self.setWindowTitle(_('TortoiseHg Bug Report'))
  33. self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint)
  34. self.resize(650, 400)
  35. self._readsettings()
  36. def gettext(self, opts):
  37. text = '{{{\n#!python\n' # Wrap in Bitbucket wiki preformat markers
  38. text += _('** Please report this bug to'
  39. ' http://bitbucket.org/tortoisehg/thg/issues\n')
  40. text += '** Mercurial version (%s). TortoiseHg version (%s)\n' % (
  41. hglib.hgversion, version.version())
  42. text += '** Command: %s\n' % (hglib.tounicode(opts.get('cmd', 'N/A')))
  43. text += '** CWD: %s\n' % hglib.tounicode(os.getcwd())
  44. extlist = [x[0] for x in extensions.extensions()]
  45. text += '** Extensions loaded: %s\n' % ', '.join(extlist)
  46. text += '** Python version: %s\n' % sys.version.replace('\n', '')
  47. if os.name == 'nt':
  48. text += self.getarch()
  49. text += hglib.tounicode(opts.get('error', 'N/A'))
  50. text += '\n}}}'
  51. return text
  52. def getarch(self):
  53. text = '** Windows version: %s\n' % str(sys.getwindowsversion())
  54. arch = 'unknown (failed to import win32api)'
  55. try:
  56. import win32api
  57. arch = 'unknown'
  58. archval = win32api.GetNativeSystemInfo()[0]
  59. if archval == 9:
  60. arch = 'x64'
  61. elif archval == 0:
  62. arch = 'x86'
  63. except (ImportError, AttributeError):
  64. pass
  65. text += '** Processor architecture: %s\n' % arch
  66. return text
  67. def save(self):
  68. try:
  69. fd = QFileDialog(self)
  70. fname = fd.getSaveFileName(self,
  71. _('Save error report to'),
  72. os.path.join(os.getcwd(), 'bugreport.txt'),
  73. _('Text files (*.txt)'))
  74. if fname:
  75. open(fname, 'wb').write(self.text)
  76. except (EnvironmentError), e:
  77. QMessageBox.critical(self, _('Error writing file'), str(e))
  78. def accept(self):
  79. self._writesettings()
  80. super(BugReport, self).accept()
  81. def reject(self):
  82. self._writesettings()
  83. super(BugReport, self).reject()
  84. def _readsettings(self):
  85. s = QSettings()
  86. self.restoreGeometry(s.value('bugreport/geom').toByteArray())
  87. def _writesettings(self):
  88. s = QSettings()
  89. s.setValue('bugreport/geom', self.saveGeometry())
  90. class ExceptionMsgBox(QDialog):
  91. """Message box for recoverable exception"""
  92. def __init__(self, main, text, opts, parent=None):
  93. super(ExceptionMsgBox, self).__init__(parent)
  94. self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint)
  95. self.setWindowTitle(_('TortoiseHg Error'))
  96. self._opts = opts
  97. labelflags = Qt.TextSelectableByMouse | Qt.LinksAccessibleByMouse
  98. self.setLayout(QVBoxLayout())
  99. if '%(arg' in text:
  100. values = opts.get('values', [])
  101. msgopts = {}
  102. for i, val in enumerate(values):
  103. msgopts['arg' + str(i)] = Qt.escape(val)
  104. try:
  105. text = text % msgopts
  106. except Exception, e:
  107. print e, msgopts
  108. else:
  109. self._mainlabel = QLabel('<b>%s</b>' % Qt.escape(main),
  110. textInteractionFlags=labelflags)
  111. self.layout().addWidget(self._mainlabel)
  112. text = text + "<br><br>" + _('If you still have trouble, '
  113. '<a href="#bugreport">please file a bug report</a>.')
  114. self._textlabel = QLabel(text, wordWrap=True,
  115. textInteractionFlags=labelflags)
  116. self._textlabel.linkActivated.connect(self._openlink)
  117. self.layout().addWidget(self._textlabel)
  118. bb = QDialogButtonBox(QDialogButtonBox.Close, centerButtons=True)
  119. bb.rejected.connect(self.reject)
  120. self.layout().addWidget(bb)
  121. @pyqtSlot(QString)
  122. def _openlink(self, ref):
  123. ref = str(ref)
  124. if ref == '#bugreport':
  125. return BugReport(self._opts, self).exec_()
  126. if ref.startswith('#edit:'):
  127. from tortoisehg.hgqt import wctxactions
  128. fname, lineno = ref[6:].rsplit(':', 1)
  129. # A chicken-egg problem here, we need a ui to get your
  130. # editor in order to repair your ui config file.
  131. wctxactions.edit(self, ui.ui(), None, [fname], lineno, None)
  132. def run(ui, *pats, **opts):
  133. return BugReport(opts)
  134. if __name__ == "__main__":
  135. app = QApplication(sys.argv)
  136. form = BugReport({'cmd':'cmd', 'error':'error'})
  137. form.show()
  138. app.exec_()