Skip to content

Commit

Permalink
gui: Introduces Panic() to handle crashes
Browse files Browse the repository at this point in the history
Fixes clearlinux#417

Also, removed unused variables in Gui struct:
- Removed "model" and "installReboot" variables from Gui struct as they
  are not being used.
- Updated log level from warning to errors wherever applicable.

Signed-off-by: Reagan Lopez <[email protected]>
  • Loading branch information
reaganlo committed Jul 3, 2019
1 parent 14c29ac commit 851dca7
Show file tree
Hide file tree
Showing 9 changed files with 132 additions and 40 deletions.
11 changes: 4 additions & 7 deletions gui/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,29 +61,26 @@ func CreateDialog(contentBox *gtk.Box, title string) (*gtk.Dialog, error) {
return widget, nil
}

// CreateDialogOneButton creates a gtk dialog with a single button
// CreateDialogOneButton creates a gtk dialog with one button
func CreateDialogOneButton(contentBox *gtk.Box, title, buttonLabel, buttonStyle string) (*gtk.Dialog, error) {
var err error
widget, err := CreateDialog(contentBox, title)
if err != nil {
return nil, err
}
widget.SetSkipTaskbarHint(false)
widget.SetResizable(false)

buttonExit, err := SetButton(buttonLabel, buttonStyle)
button, err := SetButton(buttonLabel, buttonStyle)
if err != nil {
return nil, err
}
buttonExit.SetMarginEnd(ButtonSpacing)
widget.AddActionWidget(buttonExit, gtk.RESPONSE_CANCEL)
button.SetMarginEnd(StartEndMargin)
widget.AddActionWidget(button, gtk.RESPONSE_OK)

return widget, nil
}

// CreateDialogOkCancel creates a gtk dialog with Ok and Cancel buttons
func CreateDialogOkCancel(contentBox *gtk.Box, title, ok, cancel string) (*gtk.Dialog, error) {
//parentWindow := GetWinHandle()
var err error
widget, err := CreateDialog(contentBox, title)
if err != nil {
Expand Down
15 changes: 6 additions & 9 deletions gui/gui.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,7 @@ const (
// Gui is the main gui data struct and holds data about the higher level data for this
// front end, it also implements the Frontend interface
type Gui struct {
window *Window
model *model.SystemInstall
installReboot bool
window *Window // TODO: Technically there need NOT be a separate Window struct. Its contents can be in this Gui struct.
}

// New creates a new Gui frontend instance
Expand All @@ -50,12 +48,10 @@ func (gui *Gui) MustRun(args *args.Args) bool {

// Run is part of the Frontend interface implementation and is the gui frontend main entry point
func (gui *Gui) Run(md *model.SystemInstall, rootDir string, options args.Args) (bool, error) {
gui.model = md
gui.installReboot = false

// When using the Interactive Installer we always want to copy network
// configurations to the target system
gui.model.CopyNetwork = options.CopyNetwork
md.CopyNetwork = options.CopyNetwork

// Use dark theming if available to differentiate from other apps
st, err := gtk.SettingsGetDefault()
Expand Down Expand Up @@ -87,17 +83,18 @@ func (gui *Gui) Run(md *model.SystemInstall, rootDir string, options args.Args)
gtk.AddProviderForScreen(screen, sc, gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)

// Construct window
win, err := NewWindow(md, rootDir, options)
gui.window, err = NewWindow(md, rootDir, options)
if err != nil {
// NOTE: Error popup dialog i.e Panic() should not be called for crashes during initial window creation
// as gtk.Main() is not running at this point. Such errors are only logged.
return false, err
}
gui.window = win

// Configure the Gnome proxy function
SetupGnomeProxy()

// Main loop
gtk.Main()

return gui.installReboot, nil
return false, nil
}
1 change: 1 addition & 0 deletions gui/pages/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ type Controller interface {
SetScanDone(bool)
GetScanMedia() []*storage.BlockDevice
SetScanMedia([]*storage.BlockDevice)
Panic(err error)
}

// ScanInfo holds the information related to scanning the media
Expand Down
61 changes: 54 additions & 7 deletions gui/window.go
Original file line number Diff line number Diff line change
Expand Up @@ -656,7 +656,7 @@ func (window *Window) launchWelcomeView() {
window.mainLayout.Remove(window.contentLayout)
window.mainLayout.Remove(window.banner.GetRootWidget())
if _, err := window.createWelcomePage(); err != nil {
log.ErrorError(err) // TODO: Handle error
window.Panic(err)
}
}

Expand All @@ -666,7 +666,7 @@ func (window *Window) launchPreCheckView() {
window.menu.currentPage.StoreChanges()

if _, err := window.createPreCheckPage(); err != nil {
log.ErrorError(err) // TODO: Handle error
window.Panic(err)
}
}

Expand All @@ -676,7 +676,7 @@ func (window *Window) launchMenuView() {
window.menu.currentPage.StoreChanges()

if _, err := window.createMenuPages(); err != nil {
log.ErrorError(err) // TODO: Handle error
window.Panic(err)
}
}

Expand Down Expand Up @@ -713,13 +713,13 @@ func (window *Window) confirmInstall() {
contentBox.SetHAlign(gtk.ALIGN_FILL)
contentBox.SetMarginBottom(common.TopBottomMargin)
if err != nil {
log.Warning("Error creating box")
log.Error("Error creating box", err)
return
}

label, err := gtk.LabelNew(text)
if err != nil {
log.Warning("Error creating label")
log.Error("Error creating label", err)
return
}
label.SetUseMarkup(true)
Expand All @@ -728,12 +728,13 @@ func (window *Window) confirmInstall() {

dialog, err := common.CreateDialogOkCancel(contentBox, title, utils.Locale.Get("CONFIRM"), utils.Locale.Get("CANCEL"))
if err != nil {
log.Warning("Error creating dialog")
log.Error("Error creating dialog", err)
return
}
_, err = dialog.Connect("response", window.dialogResponse)
if err != nil {
log.Warning("Error connecting to dialog")
log.Error("Error connecting to dialog", err)
return
}
dialog.ShowAll()
dialog.Run()
Expand Down Expand Up @@ -782,6 +783,16 @@ func (window *Window) SetScanMedia(scannedMedia []*storage.BlockDevice) {
window.scanInfo.Media = scannedMedia
}

// Panic handles the gui crashes
func (window *Window) Panic(err error) {
log.Debug("Panic")
if errLog := window.model.Telemetry.LogRecord("guipanic", 3, err.Error()); errLog != nil {
log.Error("Failed to log Telemetry fail record: %s", "guipanic")
}
log.RequestCrashInfo()
displayErrorDialog(err)
}

// GetWelcomeMessage gets the welcome message
func GetWelcomeMessage() string {
text := "<span font-size='xx-large'>" + utils.Locale.Get("Welcome to Clear Linux* OS Desktop Installation") + "</span>"
Expand All @@ -801,3 +812,39 @@ func GetThankYouMessage() string {

return text
}

func displayErrorDialog(err error) {
contentBox, err := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 0)
contentBox.SetHAlign(gtk.ALIGN_FILL)
if err != nil {
log.Error("Error creating box", err)
return
}

label, err := gtk.LabelNew(log.GetCrashInfoMsg())
if err != nil {
log.Error("Error creating label", err)
return
}
label.SetHAlign(gtk.ALIGN_CENTER)
label.SetMarginBottom(common.TopBottomMargin)
label.SetSelectable(true)
contentBox.PackStart(label, true, true, 0)

title := utils.Locale.Get("Something went wrong...")
dialog, err := common.CreateDialogOneButton(contentBox, title, utils.Locale.Get("OK"), "button-confirm")
if err != nil {
log.Error("Error creating dialog", err)
return
}
_, err = dialog.Connect("response", func() {
dialog.Destroy()
gtk.MainQuit() // Exit Installer
})
if err != nil {
log.Error("Error connecting to dialog", err)
return
}
dialog.ShowAll()
dialog.Run()
}
16 changes: 16 additions & 0 deletions locale/en_US/LC_MESSAGES/clr-installer.po
Original file line number Diff line number Diff line change
Expand Up @@ -604,3 +604,19 @@ msgstr "System not compatible."

msgid "Prerequisites passed."
msgstr "Prerequisites passed."

msgid "Something went wrong..."
msgstr "Something went wrong..."

#, c-format
msgid "Please report this crash using %s"
msgstr "Please report this crash using %s"

msgid "Include the following as attachments to enable diagnosis:"
msgstr "Include the following as attachments to enable diagnosis:"

msgid "You may need to remove any personal data of concern from the attachments."
msgstr "You may need to remove any personal data of concern from the attachments."

msgid "The Installer will now exit."
msgstr "The Installer will now exit."
16 changes: 16 additions & 0 deletions locale/es_MX/LC_MESSAGES/clr-installer.po
Original file line number Diff line number Diff line change
Expand Up @@ -604,3 +604,19 @@ msgstr "Sistema no compatible."

msgid "Prerequisites passed."
msgstr "Requisitos previos aprobados."

msgid "Something went wrong..."
msgstr "Hemos detectado un problema desconocido."

#, c-format
msgid "Please report this crash using %s"
msgstr "Por favor, informe de este accidente usando %s"

msgid "Include the following as attachments to enable diagnosis:"
msgstr "Incluya lo siguiente como datos adjuntos para habilitar el diagnóstico:"

msgid "You may need to remove any personal data of concern from the attachments."
msgstr "Es posible que deba eliminar cualquier dato personal de preocupación de los archivos adjuntos."

msgid "The Installer will now exit."
msgstr "El instalador se cerrará ahora."
16 changes: 16 additions & 0 deletions locale/zh_CN/LC_MESSAGES/clr-installer.po
Original file line number Diff line number Diff line change
Expand Up @@ -604,3 +604,19 @@ msgstr "Sistema no compatible."

msgid "Prerequisites passed."
msgstr "先决条件已过。"

msgid "Something went wrong..."
msgstr "出问题了..."

#, c-format
msgid "Please report this crash using %s"
msgstr "请使用 %s 报告此崩溃"

msgid "Include the following as attachments to enable diagnosis:"
msgstr "包括以下附件作为附件,以便启用诊断:"

msgid "You may need to remove any personal data of concern from the attachments."
msgstr "您可能需要从附件中删除任何值得关注的个人数据。"

msgid "The Installer will now exit."
msgstr "安装程序现在将退出。"
32 changes: 15 additions & 17 deletions log/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (

"github.com/clearlinux/clr-installer/conf"
"github.com/clearlinux/clr-installer/errors"
"github.com/clearlinux/clr-installer/utils"
)

const (
Expand Down Expand Up @@ -86,26 +87,23 @@ func SetOutputFilename(logFile string) (*os.File, error) {
return filehandle, nil
}

// GetCrashInfoMsg returns the crash info message.
func GetCrashInfoMsg() string {
msg := utils.Locale.Get("Please report this crash using %s", "GitHub Issues:")
msg += "\n" + "https://github.com/clearlinux/clr-installer/issues"
msg += "\n\n" + utils.Locale.Get("Include the following as attachments to enable diagnosis:")
msg += "\n" + preConfName
msg += "\n" + logFileName
msg += "\n\n" + utils.Locale.Get("You may need to remove any personal data of concern from the attachments.")
msg += "\n" + utils.Locale.Get("The Installer will now exit.")

return msg
}

// RequestCrashInfo prints information for the user on how to properly report the
// crash of the installer and how to gather more information
func RequestCrashInfo() {
fmt.Println("Please report this crash using GitHub Issues:")
fmt.Println("\thttps://github.com/clearlinux/clr-installer/issues")

fmt.Println("")

fmt.Println("Include the following as attachments to enable diagnosis:")
fmt.Printf("\t%s\n", preConfName)
fmt.Printf("\t%s\n", logFileName)

fmt.Println("")

fmt.Println("If the problem persists, enabling additional logging will be helpful in")
fmt.Println("diagnosing the issue. At the OS Boot screen, hit 'e' to edit the kernel")
fmt.Println("command line. Add the following to the end of the line:")
fmt.Println("\tclri.loglevel=4")

fmt.Println("")
fmt.Println(GetCrashInfoMsg())
}

// GetLogFileName ... returns the filename of the current log
Expand Down
4 changes: 4 additions & 0 deletions log/log_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ import (
"github.com/clearlinux/clr-installer/utils"
)

func init() {
utils.SetLocale("en_US.UTF-8")
}

func setLog(t *testing.T) *os.File {
var handle *os.File

Expand Down

0 comments on commit 851dca7

Please sign in to comment.