mirror of
https://github.com/clearlinux/clr-installer.git
synced 2026-09-02 03:31:38 +00:00
798 lines
23 KiB
Go
798 lines
23 KiB
Go
// Copyright © 2019 Intel Corporation
|
|
//
|
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
|
|
package gui
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"github.com/gotk3/gotk3/gtk"
|
|
|
|
"github.com/clearlinux/clr-installer/args"
|
|
"github.com/clearlinux/clr-installer/gui/common"
|
|
"github.com/clearlinux/clr-installer/gui/pages"
|
|
"github.com/clearlinux/clr-installer/log"
|
|
"github.com/clearlinux/clr-installer/model"
|
|
"github.com/clearlinux/clr-installer/storage"
|
|
"github.com/clearlinux/clr-installer/syscheck"
|
|
"github.com/clearlinux/clr-installer/utils"
|
|
)
|
|
|
|
const (
|
|
// WindowWidth specifies the default width of the window
|
|
WindowWidth int = 950
|
|
|
|
// WindowHeight specifies the default height of the window
|
|
WindowHeight int = 600
|
|
)
|
|
|
|
// PageConstructor is a typedef of the constructors for our pages
|
|
type PageConstructor func(controller pages.Controller, model *model.SystemInstall) (pages.Page, error)
|
|
|
|
// Window provides management of the underlying GtkWindow and
|
|
// associated windows to provide a level of OOP abstraction.
|
|
type Window struct {
|
|
handle *gtk.Window // Abstract the underlying GtkWindow
|
|
mainLayout *gtk.Box // Content layout (horizontal)
|
|
banner *Banner // Banner
|
|
contentLayout *gtk.Box // Content Layout
|
|
rootStack *gtk.Stack // Root-level stack
|
|
|
|
model *model.SystemInstall // model
|
|
options args.Args // installer args
|
|
rootDir string // root directory
|
|
|
|
// Menu
|
|
menu struct {
|
|
switcher *Switcher // Allow switching between main menu
|
|
stack *gtk.Stack // Menu switching
|
|
screens map[bool]*ContentView // Mapping to content views
|
|
welcomePage pages.Page // Pointer to the welcome page
|
|
currentPage pages.Page // Pointer to the currently open page
|
|
installPage pages.Page // Pointer to the installer page
|
|
}
|
|
|
|
// Buttons
|
|
buttons struct {
|
|
stack *gtk.Stack // Storage for buttons
|
|
boxWelcome *gtk.Box // Storage for welcome buttons
|
|
boxPrimary *gtk.Box // Storage for primary buttons
|
|
boxSecondary *gtk.Box // Storage for secondary buttons
|
|
|
|
// Welcome buttons
|
|
next *gtk.Button // Launch primary view
|
|
exit *gtk.Button // Exit installer
|
|
|
|
// Primary buttons
|
|
install *gtk.Button // Install Clear Linux
|
|
quit *gtk.Button // Exit installer
|
|
back *gtk.Button // Back to welcome page
|
|
|
|
// Secondary buttons
|
|
confirm *gtk.Button // Confirm changes
|
|
cancel *gtk.Button // Cancel changes
|
|
}
|
|
|
|
didInit bool // Whether initialized the view animation
|
|
pages map[int]gtk.IWidget // Mapping to each root page
|
|
scanInfo pages.ScanInfo // Information related to scanning the media
|
|
}
|
|
|
|
// CreateHeaderBar creates invisible header bar
|
|
func (window *Window) CreateHeaderBar() error {
|
|
box, err := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 0)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
st, err := box.GetStyleContext()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
window.handle.SetTitlebar(box)
|
|
st.RemoveClass("titlebar")
|
|
st.RemoveClass("headerbar")
|
|
st.RemoveClass("header")
|
|
st.AddClass("invisible-titlebar")
|
|
|
|
return nil
|
|
}
|
|
|
|
// NewWindow creates a new instance of the welcome page
|
|
func NewWindow(model *model.SystemInstall, rootDir string, options args.Args) (*Window, error) {
|
|
var err error
|
|
|
|
// Create basic window
|
|
window := &Window{
|
|
didInit: false,
|
|
pages: make(map[int]gtk.IWidget),
|
|
model: model,
|
|
rootDir: rootDir,
|
|
options: options,
|
|
}
|
|
|
|
// Default Icon the application
|
|
gtk.WindowSetDefaultIconName("system-software-install")
|
|
|
|
// Construct main window
|
|
window.handle, err = gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
window.handle.SetPosition(gtk.WIN_POS_CENTER)
|
|
window.handle.SetDefaultSize(WindowWidth, WindowHeight)
|
|
window.handle.SetResizable(false)
|
|
|
|
// Create invisible header bar
|
|
if err = window.CreateHeaderBar(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Set up the content layout within main layout
|
|
window.mainLayout, err = gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 0)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
window.handle.Add(window.mainLayout)
|
|
|
|
// Set locale
|
|
utils.SetLocale(model.Language.Code)
|
|
|
|
// Create welcome page
|
|
window, err = window.createWelcomePage()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
window.scanInfo.Channel = make(chan bool)
|
|
go func() {
|
|
log.Debug("Scanning media")
|
|
window.scanInfo.Media, err = storage.RescanBlockDevices(window.model.TargetMedias)
|
|
if err != nil {
|
|
log.Warning("Error scanning media %s", err.Error())
|
|
}
|
|
window.scanInfo.Channel <- true
|
|
}()
|
|
|
|
return window, nil
|
|
}
|
|
|
|
// createWelcomePage creates the welcome page
|
|
func (window *Window) createWelcomePage() (*Window, error) {
|
|
var err error
|
|
// Create banner and add to main layout
|
|
if window.banner, err = NewBanner(); err != nil {
|
|
return nil, err
|
|
}
|
|
window.mainLayout.PackStart(window.banner.GetRootWidget(), false, false, 0)
|
|
|
|
// Set up content layout and add to main layout
|
|
window.contentLayout, err = gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 0)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
window.mainLayout.PackStart(window.contentLayout, true, true, 0)
|
|
|
|
// Set up the root stack and add to content layout
|
|
window.rootStack, err = gtk.StackNew()
|
|
window.rootStack.SetTransitionType(gtk.STACK_TRANSITION_TYPE_CROSSFADE)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
window.contentLayout.PackStart(window.rootStack, true, true, 0)
|
|
|
|
// Set up the menu stack and add to root stack
|
|
window.menu.stack, err = gtk.StackNew()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
window.menu.stack.SetTransitionType(gtk.STACK_TRANSITION_TYPE_SLIDE_LEFT_RIGHT)
|
|
window.rootStack.AddTitled(window.menu.stack, "menu", "Menu")
|
|
|
|
// Create the welcome page
|
|
pageCreators := []PageConstructor{
|
|
pages.NewLanguagePage,
|
|
}
|
|
|
|
for _, f := range pageCreators {
|
|
page, err := f(window, window.model)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if err = window.AddPage(page); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
// TODO: Remove this temporary code after development phase
|
|
_, err = window.handle.Connect("destroy", func() {
|
|
gtk.MainQuit()
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Create footer area now
|
|
if err = window.CreateFooter(window.contentLayout); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
window.handle.ShowAll()
|
|
window.ActivatePage(window.menu.welcomePage)
|
|
|
|
return window, nil
|
|
}
|
|
|
|
// createMenuPages creates the menu pages
|
|
func (window *Window) createMenuPages() (*Window, error) {
|
|
var err error
|
|
window.banner.labelText.SetMarkup(GetWelcomeMessage())
|
|
window.menu.screens = make(map[bool]*ContentView)
|
|
|
|
// Set up the stack switcher
|
|
window.menu.switcher, err = NewSwitcher(nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
window.menu.switcher.SetStack(window.menu.stack)
|
|
|
|
if err = window.InitScreens(); err != nil {
|
|
return nil, err
|
|
}
|
|
window.contentLayout.Remove(window.rootStack)
|
|
window.contentLayout.PackStart(window.menu.switcher.GetRootWidget(), false, false, 0)
|
|
window.contentLayout.PackStart(window.rootStack, true, true, 0)
|
|
|
|
// Create footer area
|
|
if err = window.UpdateFooter(window.contentLayout); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Our pages
|
|
pageCreators := []PageConstructor{
|
|
// required
|
|
pages.NewTimezonePage,
|
|
pages.NewKeyboardPage,
|
|
pages.NewDiskConfigPage,
|
|
pages.NewUserAddPage,
|
|
pages.NewTelemetryPage,
|
|
|
|
// advanced
|
|
pages.NewBundlePage,
|
|
pages.NewHostnamePage,
|
|
|
|
// always last
|
|
pages.NewInstallPage,
|
|
}
|
|
|
|
// Create all pages
|
|
for _, f := range pageCreators {
|
|
page, err := f(window, window.model)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if err = window.AddPage(page); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
// Show the whole window now
|
|
window.handle.ShowAll()
|
|
|
|
// Show the menu view
|
|
window.ShowMenuView()
|
|
|
|
return window, nil
|
|
}
|
|
|
|
// ShowMenuView displays the menu view
|
|
func (window *Window) ShowMenuView() {
|
|
done := window.menu.screens[ContentViewRequired].IsDone()
|
|
window.buttons.install.SetSensitive(done)
|
|
|
|
window.banner.Show()
|
|
window.menu.switcher.Show()
|
|
|
|
window.rootStack.SetVisibleChildName("menu")
|
|
window.menu.stack.SetVisibleChildName("required")
|
|
window.buttons.stack.SetVisibleChildName("primary")
|
|
}
|
|
|
|
// InitScreens initializes the switcher screens
|
|
func (window *Window) InitScreens() error {
|
|
var err error
|
|
|
|
// Set up required screen
|
|
if window.menu.screens[true], err = NewContentView(window); err != nil {
|
|
return err
|
|
}
|
|
window.menu.stack.AddNamed(window.menu.screens[ContentViewRequired].GetRootWidget(), "required")
|
|
|
|
// Set up non required screen
|
|
if window.menu.screens[false], err = NewContentView(window); err != nil {
|
|
return err
|
|
}
|
|
window.menu.stack.AddNamed(window.menu.screens[ContentViewAdvanced].GetRootWidget(), "advanced")
|
|
|
|
return nil
|
|
}
|
|
|
|
// AddPage adds the page to the relevant switcher screen
|
|
func (window *Window) AddPage(page pages.Page) error {
|
|
var (
|
|
err error
|
|
id int
|
|
)
|
|
|
|
id = page.GetID()
|
|
|
|
if id == pages.PageIDWelcome {
|
|
window.menu.welcomePage = page
|
|
} else if id == pages.PageIDInstall {
|
|
window.menu.installPage = page
|
|
} else { // Add to the required or advanced (optional) screen
|
|
err := window.menu.screens[page.IsRequired()].AddPage(page)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
// Create a header page wrap for the page
|
|
header, err := PageHeaderNew(page)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
root := header.GetRootWidget()
|
|
|
|
// Make available via root stack
|
|
window.pages[id] = root
|
|
window.rootStack.AddNamed(root, "page:"+string(id))
|
|
|
|
return nil
|
|
}
|
|
|
|
// createNavButton creates specialised navigation button
|
|
func createNavButton(label, style string) (*gtk.Button, error) {
|
|
button, err := gtk.ButtonNewWithLabel(label)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
sc, err := button.GetStyleContext()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
// Not able to set size using CSS
|
|
button.SetSizeRequest(100, 36)
|
|
sc.AddClass(style)
|
|
|
|
return button, nil
|
|
}
|
|
|
|
// CreateFooter creates the navigation footer area
|
|
func (window *Window) CreateFooter(store *gtk.Box) error {
|
|
var err error
|
|
|
|
// Create stack for buttons
|
|
if window.buttons.stack, err = gtk.StackNew(); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Set alignment up
|
|
window.buttons.stack.SetMarginTop(4)
|
|
window.buttons.stack.SetMarginBottom(6)
|
|
window.buttons.stack.SetMarginEnd(18)
|
|
window.buttons.stack.SetHAlign(gtk.ALIGN_FILL)
|
|
window.buttons.stack.SetTransitionType(gtk.STACK_TRANSITION_TYPE_CROSSFADE)
|
|
store.PackEnd(window.buttons.stack, false, false, 0)
|
|
|
|
// Create box for welcome page buttons
|
|
if window.buttons.boxWelcome, err = gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 0); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Install button
|
|
if window.buttons.next, err = createNavButton(utils.Locale.Get("NEXT"), "button-confirm"); err != nil {
|
|
return err
|
|
}
|
|
if _, err = window.buttons.next.Connect("clicked", func() { window.launchMenuView() }); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Exit button
|
|
if window.buttons.exit, err = createNavButton(utils.Locale.Get("EXIT"), "button-cancel"); err != nil {
|
|
return err
|
|
}
|
|
if _, err = window.buttons.exit.Connect("clicked", func() { gtk.MainQuit() }); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Pack the buttons
|
|
window.buttons.boxWelcome.PackEnd(window.buttons.next, false, false, 4)
|
|
window.buttons.boxWelcome.PackEnd(window.buttons.exit, false, false, 4)
|
|
|
|
// Add the boxes
|
|
window.buttons.stack.AddNamed(window.buttons.boxWelcome, "welcome")
|
|
|
|
return nil
|
|
}
|
|
|
|
// UpdateFooter updates the navigation footer area
|
|
func (window *Window) UpdateFooter(store *gtk.Box) error {
|
|
var err error
|
|
|
|
// Install button
|
|
if window.buttons.install, err = createNavButton(utils.Locale.Get("INSTALL"), "button-confirm"); err != nil {
|
|
return err
|
|
}
|
|
if _, err = window.buttons.install.Connect("clicked", func() { window.confirmInstall() }); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Exit button
|
|
if window.buttons.quit, err = createNavButton(utils.Locale.Get("EXIT"), "button-cancel"); err != nil {
|
|
return err
|
|
}
|
|
if _, err = window.buttons.quit.Connect("clicked", func() { gtk.MainQuit() }); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Back button
|
|
if window.buttons.back, err = createNavButton(utils.Locale.Get("CHANGE LANGUAGE"), "button-cancel"); err != nil {
|
|
return err
|
|
}
|
|
if _, err = window.buttons.back.Connect("clicked", func() { window.launchWelcomeView() }); err != nil {
|
|
return err
|
|
}
|
|
|
|
width, _ := window.handle.GetSize() // get current size
|
|
marginEnd := width * 35 / 100
|
|
window.buttons.back.SetMarginEnd(marginEnd) // TODO: MarginStart would be ideal but does not work
|
|
|
|
// Confirm button
|
|
if window.buttons.confirm, err = createNavButton(utils.Locale.Get("CONFIRM"), "button-confirm"); err != nil {
|
|
return err
|
|
}
|
|
if _, err = window.buttons.confirm.Connect("clicked", func() { window.pageClosed(true) }); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Cancel button
|
|
if window.buttons.cancel, err = createNavButton(utils.Locale.Get("CANCEL"), "button-cancel"); err != nil {
|
|
return err
|
|
}
|
|
if _, err = window.buttons.cancel.Connect("clicked", func() { window.pageClosed(false) }); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Create box for primary buttons
|
|
if window.buttons.boxPrimary, err = gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 0); err != nil {
|
|
return err
|
|
}
|
|
window.buttons.boxPrimary.PackEnd(window.buttons.install, false, false, 4)
|
|
window.buttons.boxPrimary.PackEnd(window.buttons.quit, false, false, 4)
|
|
window.buttons.boxPrimary.PackEnd(window.buttons.back, false, false, 4)
|
|
|
|
// Create box for secondary buttons
|
|
if window.buttons.boxSecondary, err = gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 0); err != nil {
|
|
return err
|
|
}
|
|
window.buttons.boxSecondary.PackEnd(window.buttons.confirm, false, false, 4)
|
|
window.buttons.boxSecondary.PackEnd(window.buttons.cancel, false, false, 4)
|
|
|
|
// Add the boxes
|
|
window.buttons.stack.AddNamed(window.buttons.boxPrimary, "primary")
|
|
window.buttons.stack.AddNamed(window.buttons.boxSecondary, "secondary")
|
|
|
|
return nil
|
|
}
|
|
|
|
// pageClosed handles closure of a page.
|
|
func (window *Window) pageClosed(applied bool) {
|
|
// If applied, tell page to stash in model
|
|
// otherwise, reset from existing model
|
|
if applied {
|
|
window.menu.currentPage.StoreChanges()
|
|
} else {
|
|
window.menu.currentPage.ResetChanges()
|
|
}
|
|
|
|
// Let installation continue if possible
|
|
done := window.menu.screens[ContentViewRequired].IsDone()
|
|
window.buttons.install.SetSensitive(done)
|
|
|
|
// Reset the SummaryWidget for responsible controller
|
|
window.menu.screens[window.menu.currentPage.IsRequired()].UpdateView(window.menu.currentPage)
|
|
|
|
// Reset currentPage
|
|
window.menu.currentPage = nil
|
|
|
|
// Switch UI back to primary view
|
|
window.rootStack.SetVisibleChildName("menu")
|
|
window.banner.Show()
|
|
window.menu.switcher.Show()
|
|
window.buttons.stack.SetVisibleChildName("primary")
|
|
}
|
|
|
|
// ActivatePage displays the page
|
|
func (window *Window) ActivatePage(page pages.Page) {
|
|
window.menu.currentPage = page
|
|
id := page.GetID()
|
|
|
|
if id == pages.PageIDWelcome { // Welcome Page
|
|
window.banner.Show()
|
|
window.buttons.stack.SetVisibleChildName("welcome")
|
|
} else if id == pages.PageIDInstall { // Install Page
|
|
window.menu.switcher.Hide()
|
|
window.banner.Show()
|
|
window.banner.labelText.SetMarkup(GetThankYouMessage())
|
|
window.buttons.stack.SetVisibleChildName("primary")
|
|
window.buttons.install.Hide()
|
|
window.buttons.back.Hide()
|
|
sc, err := window.buttons.quit.GetStyleContext()
|
|
sc.RemoveClass("button-cancel")
|
|
if err != nil {
|
|
log.Warning("Error getting style context: ", err) // Just log trivial error
|
|
} else {
|
|
sc.AddClass("button-confirm")
|
|
}
|
|
window.SetButtonState(pages.ButtonQuit, false)
|
|
} else {
|
|
window.menu.switcher.Hide()
|
|
window.banner.Hide()
|
|
window.buttons.stack.SetVisibleChildName("secondary")
|
|
window.SetButtonState(pages.ButtonConfirm, false)
|
|
}
|
|
|
|
// Allow page to take control now
|
|
page.ResetChanges()
|
|
|
|
// Set the root stack to show the new page
|
|
window.rootStack.SetVisibleChild(window.pages[id])
|
|
}
|
|
|
|
// SetButtonState is called by the pages to enable/disable certain buttons.
|
|
func (window *Window) SetButtonState(flags pages.Button, enabled bool) {
|
|
if window.menu.currentPage.GetID() != pages.PageIDWelcome {
|
|
if flags&pages.ButtonCancel == pages.ButtonCancel {
|
|
window.buttons.cancel.SetSensitive(enabled)
|
|
}
|
|
if flags&pages.ButtonConfirm == pages.ButtonConfirm {
|
|
window.buttons.confirm.SetSensitive(enabled)
|
|
}
|
|
if flags&pages.ButtonQuit == pages.ButtonQuit {
|
|
window.buttons.quit.SetSensitive(enabled)
|
|
}
|
|
if flags&pages.ButtonBack == pages.ButtonBack {
|
|
window.buttons.back.SetSensitive(enabled)
|
|
}
|
|
} else {
|
|
if flags&pages.ButtonNext == pages.ButtonNext {
|
|
window.buttons.next.SetSensitive(enabled)
|
|
}
|
|
if flags&pages.ButtonExit == pages.ButtonExit {
|
|
window.buttons.exit.SetSensitive(enabled)
|
|
}
|
|
}
|
|
}
|
|
|
|
// SetButtonVisible is called by the pages to view/hide certain buttons.
|
|
func (window *Window) SetButtonVisible(flags pages.Button, visible bool) {
|
|
if window.menu.currentPage.GetID() != pages.PageIDWelcome {
|
|
if flags&pages.ButtonCancel == pages.ButtonCancel {
|
|
window.buttons.cancel.SetVisible(visible)
|
|
}
|
|
if flags&pages.ButtonConfirm == pages.ButtonConfirm {
|
|
window.buttons.confirm.SetVisible(visible)
|
|
}
|
|
if flags&pages.ButtonQuit == pages.ButtonQuit {
|
|
window.buttons.quit.SetVisible(visible)
|
|
}
|
|
if flags&pages.ButtonBack == pages.ButtonBack {
|
|
window.buttons.back.SetVisible(visible)
|
|
}
|
|
} else {
|
|
if flags&pages.ButtonNext == pages.ButtonNext {
|
|
window.buttons.next.SetVisible(visible)
|
|
}
|
|
if flags&pages.ButtonExit == pages.ButtonExit {
|
|
window.buttons.exit.SetVisible(visible)
|
|
}
|
|
}
|
|
}
|
|
|
|
// launchWelcomeView launches the welcome view
|
|
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
|
|
}
|
|
}
|
|
|
|
// launchMenuView launches the menu view
|
|
func (window *Window) launchMenuView() {
|
|
window.menu.currentPage.StoreChanges()
|
|
|
|
// If syscheck fails, launch a dialog box and force the user to exit
|
|
if retErr := syscheck.RunSystemCheck(true); retErr != nil {
|
|
contentBox, err := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 10)
|
|
contentBox.SetHAlign(gtk.ALIGN_FILL)
|
|
contentBox.SetMarginBottom(common.TopBottomMargin)
|
|
if err != nil {
|
|
log.Warning("Error creating box")
|
|
return
|
|
}
|
|
|
|
st, err := contentBox.GetStyleContext()
|
|
if err != nil {
|
|
log.Warning("Error getting style context")
|
|
return
|
|
}
|
|
|
|
// Style the dialog
|
|
st.AddClass("dialog-warning")
|
|
|
|
icon, err := gtk.ImageNewFromIconName("dialog-error-symbolic", gtk.ICON_SIZE_DIALOG)
|
|
if err != nil {
|
|
log.Warning("gtk.ImageNewFromIconName failed for icon dialog-error-symbolic")
|
|
return
|
|
}
|
|
|
|
icon.SetMarginEnd(12)
|
|
icon.SetHAlign(gtk.ALIGN_START)
|
|
icon.SetVAlign(gtk.ALIGN_START)
|
|
contentBox.PackStart(icon, false, true, 0)
|
|
|
|
label, err := gtk.LabelNew(utils.Locale.Get("System failed to pass pre-install checks.") + "\n\n" + retErr.Error())
|
|
if err != nil {
|
|
log.Warning("Error creating label")
|
|
return
|
|
}
|
|
label.SetUseMarkup(true)
|
|
label.SetHAlign(gtk.ALIGN_END)
|
|
contentBox.PackStart(label, false, true, 0)
|
|
|
|
dialog, err := common.CreateDialogOneButton(contentBox, utils.Locale.Get("System Check Failed"), utils.Locale.Get("EXIT"), "button-cancel")
|
|
if err != nil {
|
|
log.Warning("Error creating dialog")
|
|
return
|
|
}
|
|
|
|
_, err = dialog.Connect("response", func() { gtk.MainQuit() })
|
|
if err != nil {
|
|
log.Warning("Error connecting to dialog")
|
|
}
|
|
dialog.ShowAll()
|
|
dialog.Run()
|
|
} else {
|
|
if _, err := window.createMenuPages(); err != nil {
|
|
log.ErrorError(err) // TODO: Handle error
|
|
}
|
|
}
|
|
}
|
|
|
|
// confirmInstall prompts the user for confirmation before installing
|
|
func (window *Window) confirmInstall() {
|
|
var text, primaryText, secondaryText string
|
|
var err error
|
|
|
|
if window.model.InstallSelected.EraseDisk {
|
|
primaryText = utils.Locale.Get(storage.DestructiveWarning)
|
|
} else if window.model.InstallSelected.DataLoss {
|
|
primaryText = utils.Locale.Get(storage.DataLossWarning)
|
|
} else if window.model.InstallSelected.WholeDisk {
|
|
primaryText = utils.Locale.Get(storage.SafeWholeWarning)
|
|
} else {
|
|
primaryText = utils.Locale.Get(storage.SafePartialWarning)
|
|
}
|
|
|
|
// Build the string with the media being modified
|
|
targets := []string{}
|
|
if len(window.model.TargetMedias) == 0 {
|
|
targets = append(targets, utils.Locale.Get("None"))
|
|
} else {
|
|
for _, media := range window.model.TargetMedias {
|
|
targets = append(targets, media.GetDeviceFile())
|
|
}
|
|
}
|
|
secondaryText = utils.Locale.Get("Target Media") + ": " + strings.Join(targets, ", ")
|
|
|
|
title := utils.Locale.Get(storage.ConfirmInstallation)
|
|
text = primaryText + "\n" + "<small>" + secondaryText + "</small>"
|
|
|
|
contentBox, err := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 0)
|
|
contentBox.SetHAlign(gtk.ALIGN_FILL)
|
|
contentBox.SetMarginBottom(common.TopBottomMargin)
|
|
if err != nil {
|
|
log.Warning("Error creating box")
|
|
return
|
|
}
|
|
|
|
label, err := gtk.LabelNew(text)
|
|
if err != nil {
|
|
log.Warning("Error creating label")
|
|
return
|
|
}
|
|
label.SetUseMarkup(true)
|
|
label.SetHAlign(gtk.ALIGN_START)
|
|
contentBox.PackStart(label, false, true, 0)
|
|
|
|
dialog, err := common.CreateDialogOkCancel(contentBox, title, utils.Locale.Get("CONFIRM"), utils.Locale.Get("CANCEL"))
|
|
if err != nil {
|
|
log.Warning("Error creating dialog")
|
|
return
|
|
}
|
|
_, err = dialog.Connect("response", window.dialogResponse)
|
|
if err != nil {
|
|
log.Warning("Error connecting to dialog")
|
|
}
|
|
dialog.ShowAll()
|
|
dialog.Run()
|
|
}
|
|
|
|
// dialogResponse handles the response from the dialog message
|
|
func (window *Window) dialogResponse(msgDialog *gtk.Dialog, responseType gtk.ResponseType) {
|
|
if responseType == gtk.RESPONSE_OK {
|
|
window.ActivatePage(window.menu.installPage)
|
|
}
|
|
msgDialog.Destroy()
|
|
}
|
|
|
|
// GetOptions returns the options given to the window
|
|
func (window *Window) GetOptions() args.Args {
|
|
return window.options
|
|
}
|
|
|
|
// GetRootDir returns the root dir
|
|
func (window *Window) GetRootDir() string {
|
|
return window.rootDir
|
|
}
|
|
|
|
// GetScanChannel is the getter for ScanInfo Channel
|
|
func (window *Window) GetScanChannel() chan bool {
|
|
return window.scanInfo.Channel
|
|
}
|
|
|
|
// GetScanDone is the getter for ScanInfo Done
|
|
func (window *Window) GetScanDone() bool {
|
|
return window.scanInfo.Done
|
|
}
|
|
|
|
// SetScanDone is the setter for ScanInfo Done
|
|
func (window *Window) SetScanDone(done bool) {
|
|
window.scanInfo.Done = done
|
|
}
|
|
|
|
// GetScanMedia is the getter for ScanInfo Media
|
|
func (window *Window) GetScanMedia() []*storage.BlockDevice {
|
|
return window.scanInfo.Media
|
|
}
|
|
|
|
// SetScanMedia is the setter for ScanInfo Media
|
|
func (window *Window) SetScanMedia(scannedMedia []*storage.BlockDevice) {
|
|
window.scanInfo.Media = scannedMedia
|
|
}
|
|
|
|
// 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>"
|
|
if model.Version != model.DemoVersion {
|
|
text += "\n\n<small>" + utils.Locale.Get("VERSION %s", model.Version) + "</small>"
|
|
}
|
|
|
|
return text
|
|
}
|
|
|
|
// GetThankYouMessage gets the thank you message
|
|
func GetThankYouMessage() string {
|
|
text := "<span font-size='xx-large'>" + utils.Locale.Get("Thank you for choosing Clear Linux* OS") + "</span>"
|
|
if model.Version != model.DemoVersion {
|
|
text += "\n\n<small>" + utils.Locale.Get("VERSION %s", model.Version) + "</small>"
|
|
}
|
|
|
|
return text
|
|
}
|