Source code for apptools.logger.agent.quality_agent_view

# (C) Copyright 2005-2022 Enthought, Inc., Austin, TX
# All rights reserved.
#
# This software is provided without warranty under the terms of the BSD
# license included in LICENSE.txt and may be redistributed only under
# the conditions described in the aforementioned license. The license
# is also available online at http://www.enthought.com/licenses/BSD.txt
#
# Thanks for using Enthought open source!

# Standard library imports.
import logging

# Enthought library imports.
from pyface.api import Dialog
from traits.api import Any, Str, Tuple


# Setup a logger for this module.
logger = logging.getLogger(__name__)


priority_levels = ["Low", "Medium", "High", "Critical"]


[docs]class QualityAgentView(Dialog): size = Tuple((700, 900)) title = Str("Quality Agent") # The associated LoggerService. service = Any() msg = Str("") subject = Str("Untitled Error Report") to_address = Str() cc_address = Str("") from_address = Str() smtp_server = Str() priority = Str(priority_levels[2]) comments = Str("None") include_userdata = Any ########################################################################### # Protected 'Dialog' interface. ########################################################################### # fixme: Ideally, this should be passed in; this topic ID belongs to the # Enlib help project/plug-in. help_id = "enlib|HID_Quality_Agent_Dlg" def _create_dialog_area(self, parent): """ Creates the main content of the dialog. """ import wx parent.SetSizeHints(minW=300, minH=575) # Add the main panel sizer = wx.BoxSizer(wx.VERTICAL) panel = wx.Panel(parent, -1) panel.SetSizer(sizer) panel.SetAutoLayout(True) # Add a descriptive label at the top ... label = wx.StaticText(panel, -1, "Send a comment or bug report ...") sizer.Add(label, 0, wx.ALL, border=5) # Add the stack trace view ... error_panel = self._create_error_panel(panel) sizer.Add( error_panel, 1, wx.ALL | wx.EXPAND | wx.CLIP_CHILDREN, border=5 ) # Update the layout: sizer.Fit(panel) # Add the error report view ... report_panel = self._create_report_panel(panel) sizer.Add( report_panel, 2, wx.ALL | wx.EXPAND | wx.CLIP_CHILDREN, border=5 ) # Update the layout: sizer.Fit(panel) return panel def _create_buttons(self, parent): """ Creates the buttons. """ import wx sizer = wx.BoxSizer(wx.HORIZONTAL) # 'Send' button. send = wx.Button(parent, wx.ID_OK, "Send") wx.EVT_BUTTON(parent, wx.ID_OK, self._on_send) sizer.Add(send) send.SetDefault() # 'Cancel' button. cancel = wx.Button(parent, wx.ID_CANCEL, "Cancel") wx.EVT_BUTTON(parent, wx.ID_CANCEL, self._wx_on_cancel) sizer.Add(cancel, 0, wx.LEFT, 10) # 'Help' button. if len(self.help_id) > 0: help = wx.Button(parent, wx.ID_HELP, "Help") wx.EVT_BUTTON(parent, wx.ID_HELP, self._wx_on_help) sizer.Add(help, 0, wx.LEFT, 10) return sizer ### Utility methods ####################################################### def _create_error_panel(self, parent): import wx box = wx.StaticBox(parent, -1, "Message:") sizer = wx.StaticBoxSizer(box, wx.VERTICAL) # Print the stack trace label2 = wx.StaticText( parent, -1, "The following information will be included in the report:", ) sizer.Add( label2, 0, wx.LEFT | wx.TOP | wx.BOTTOM | wx.CLIP_CHILDREN, border=5, ) details = wx.TextCtrl( parent, -1, self.msg, size=(-1, 75), style=wx.TE_MULTILINE | wx.TE_READONLY | wx.HSCROLL | wx.VSCROLL | wx.TE_RICH2 | wx.CLIP_CHILDREN, ) details.SetSizeHints(minW=-1, minH=75) # Set the font to not be proportional font = wx.Font(12, wx.MODERN, wx.NORMAL, wx.NORMAL) details.SetStyle(0, len(self.msg), wx.TextAttr(font=font)) sizer.Add(details, 1, wx.EXPAND | wx.ALL | wx.CLIP_CHILDREN, 5) return sizer def _create_report_panel(self, parent): import wx box = wx.StaticBox(parent, -1, "Report Information:") sizer = wx.StaticBoxSizer(box, wx.VERTICAL) # Add email info ... sizer.Add(self._create_email_info(parent), 0, wx.ALL | wx.EXPAND, 5) # Add priority combo: sizer.Add(self._create_priority_combo(parent), 0, wx.ALL | wx.RIGHT, 5) # Extra comments from the user: label3 = wx.StaticText(parent, -1, "Additional Comments:") sizer.Add( label3, 0, wx.LEFT | wx.TOP | wx.BOTTOM | wx.CLIP_CHILDREN, 5 ) comments_field = wx.TextCtrl( parent, -1, self.comments, size=(-1, 75), style=wx.TE_MULTILINE | wx.TE_RICH2 | wx.CLIP_CHILDREN, ) comments_field.SetSizeHints(minW=-1, minH=75) font = wx.Font(12, wx.MODERN, wx.NORMAL, wx.NORMAL) comments_field.SetStyle(0, len(self.comments), wx.TextAttr(font=font)) sizer.Add(comments_field, 1, wx.ALL | wx.EXPAND | wx.CLIP_CHILDREN, 5) wx.EVT_TEXT(parent, comments_field.GetId(), self._on_comments) # Include the project combobox? if len(self.service.mail_files) > 0: sizer.Add(self._create_project_upload(parent), 0, wx.ALL, border=5) return sizer def _create_email_info(self, parent): import wx # Layout setup .. sizer = wx.FlexGridSizer(5, 2, 10, 10) sizer.AddGrowableCol(1) title_label = wx.StaticText(parent, -1, "Subject:") sizer.Add(title_label, 0, wx.ALL | wx.ALIGN_RIGHT) title_field = wx.TextCtrl(parent, -1, self.subject, wx.Point(-1, -1)) sizer.Add( title_field, 1, wx.EXPAND | wx.ALL | wx.ALIGN_RIGHT | wx.CLIP_CHILDREN, ) wx.EVT_TEXT(parent, title_field.GetId(), self._on_subject) to_label = wx.StaticText(parent, -1, "To:") sizer.Add(to_label, 0, wx.ALL | wx.ALIGN_RIGHT) to_field = wx.TextCtrl(parent, -1, self.to_address) sizer.Add( to_field, 1, wx.EXPAND | wx.ALL | wx.ALIGN_RIGHT | wx.CLIP_CHILDREN ) wx.EVT_TEXT(parent, to_field.GetId(), self._on_to) cc_label = wx.StaticText(parent, -1, "Cc:") sizer.Add(cc_label, 0, wx.ALL | wx.ALIGN_RIGHT) cc_field = wx.TextCtrl(parent, -1, "") sizer.Add( cc_field, 1, wx.EXPAND | wx.ALL | wx.ALIGN_RIGHT | wx.CLIP_CHILDREN ) wx.EVT_TEXT(parent, cc_field.GetId(), self._on_cc) from_label = wx.StaticText(parent, -1, "From:") sizer.Add(from_label, 0, wx.ALL | wx.ALIGN_RIGHT) from_field = wx.TextCtrl(parent, -1, self.from_address) sizer.Add( from_field, 1, wx.EXPAND | wx.ALL | wx.ALIGN_RIGHT | wx.CLIP_CHILDREN, ) wx.EVT_TEXT(parent, from_field.GetId(), self._on_from) smtp_label = wx.StaticText(parent, -1, "SMTP Server:") sizer.Add(smtp_label, 0, wx.ALL | wx.ALIGN_RIGHT) smtp_server_field = wx.TextCtrl(parent, -1, self.smtp_server) sizer.Add( smtp_server_field, 1, wx.EXPAND | wx.ALL | wx.ALIGN_RIGHT | wx.CLIP_CHILDREN, ) wx.EVT_TEXT(parent, smtp_server_field.GetId(), self._on_smtp_server) return sizer def _create_priority_combo(self, parent): import wx sizer = wx.BoxSizer(wx.HORIZONTAL) label = wx.StaticText(parent, -1, "How critical is this issue?") sizer.Add(label, 0, wx.ALL, border=0) cb = wx.ComboBox( parent, -1, self.priority, wx.Point(90, 50), wx.Size(95, -1), priority_levels, wx.CB_READONLY, ) sizer.Add(cb, 1, wx.EXPAND | wx.LEFT | wx.CLIP_CHILDREN, border=10) wx.EVT_COMBOBOX(parent, cb.GetId(), self._on_priority) return sizer def _create_project_upload(self, parent): import wx id = wx.NewId() cb = wx.CheckBox( parent, id, "Include Workspace Files (will increase email size) ", wx.Point(65, 80), wx.Size(-1, 20), wx.NO_BORDER, ) wx.EVT_CHECKBOX(parent, id, self._on_project) return cb ## UI Listeners ########################################################### def _on_subject(self, event): self.subject = event.GetEventObject().GetValue() def _on_to(self, event): self.to_address = event.GetEventObject().GetValue() def _on_cc(self, event): self.cc_address = event.GetEventObject().GetValue() def _on_from(self, event): self.from_address = event.GetEventObject().GetValue() def _on_smtp_server(self, event): self.smtp_server = event.GetEventObject().GetValue() def _on_priority(self, event): self.priority = event.GetEventObject().GetStringSelection() def _on_comments(self, event): self.comments = event.GetEventObject().GetValue() def _on_project(self, event): self.include_userdata = event.Checked() cb = event.GetEventObject() if event.Checked(): cb.SetLabel( "Include Workspace Files (approx. %.2f MBytes)" % self._compute_project_size() ) else: cb.SetLabel("Include Workspace Files (will increase email size)") def _on_send(self, event): # Disable the Send button while we go through the possibly # time-consuming email-sending process. button = event.GetEventObject() button.Enable(0) fromaddr, toaddrs, ccaddrs = self._create_email_addresses() message = self._create_email(fromaddr, toaddrs, ccaddrs) self.service.send_bug_report( self.smtp_server, fromaddr, toaddrs, ccaddrs, message ) # save the user's preferences self.service.preferences.smtp_server = self.smtp_server self.service.preferences.to_address = self.to_address self.service.preferences.from_address = self.from_address # finally we close the dialog self._wx_on_ok(event) ## Private ################################################################ def _create_email_addresses(self): # utility function map addresses from ui into the standard format # FIXME: We should use standard To: header parsing instead of this ad # hoc whitespace-only approach. fromaddr = self.from_address if "" == fromaddr.strip(): fromaddr = "anonymous" toaddrs = self.to_address.split() ccaddrs = self.cc_address.split() return fromaddr, toaddrs, ccaddrs def _compute_project_size(self): # determine size of email in MBytes fromaddr, toaddrs, ccaddrs = self._create_email_addresses() message = self._create_email(fromaddr, toaddrs, ccaddrs) return len(message.as_string()) / (2.0 ** 20) def _create_email(self, fromaddr, toaddrs, ccaddrs): return self.service.create_email_message( fromaddr, toaddrs, ccaddrs, self.subject, self.priority, self.include_userdata, self.msg, self.comments, ) def _to_address_default(self): return self.service.preferences.to_address def _from_address_default(self): return self.service.preferences.from_address def _smtp_server_default(self): return self.service.preferences.smtp_server