示例#1
0
文件: tutorial.go 项目: hsk81/btcgui
// CreateTutorialDialog opens a tutorial dialog explaining usage for a
// first-time user.  If appWindow is non-nil, it will be used as the
// parent window of the dialog.  If nil, the tutorial dialog will open as
// a top-level window and a new application main window will be created
// and opened after the final tutorial message is shown.
func CreateTutorialDialog(appWindow *gtk.Window) (*gtk.Dialog, error) {
	d, err := gtk.DialogNew()
	if err != nil {
		return nil, err
	}
	d.SetTitle("btcgui First Start Tutorial")
	box, err := d.GetContentArea()
	if err != nil {
		return nil, err
	}
	grid, err := gtk.GridNew()
	if err != nil {
		return nil, err
	}
	grid.SetOrientation(gtk.ORIENTATION_VERTICAL)
	box.Add(grid)

	d.SetDefaultGeometry(500, 100)

	if appWindow != nil {
		d.SetTransientFor(appWindow)
		d.SetPosition(gtk.WIN_POS_CENTER_ON_PARENT)
	} else {
		d.Connect("destroy", func() {
			go StartMainApplication()
		})
		d.SetPosition(gtk.WIN_POS_CENTER)
	}

	// Add a notebook and tab for each dialog message.
	nb, err := gtk.NotebookNew()
	if err != nil {
		return nil, err
	}

	// Because the labels added below will wrap and their final minimum
	// heights and widths will be absurdly large, first give a size request
	// and show the notebook (allocating space for the requested size).
	// This will make text wrapping labels size nicely inside the notebook.
	nb.SetSizeRequest(500, 100)
	nb.Show()

	// Create messages and append each in a notebook page.
	for _, msg := range dialogMessages {
		lbl, err := gtk.LabelNew("")
		if err != nil {
			return nil, err
		}
		lbl.SetMarkup(msg)
		lbl.SetLineWrap(true)
		lbl.Show()
		lbl.SetAlignment(0, 0)
		nb.AppendPage(lbl, nil)
	}
	nb.SetShowTabs(false)
	grid.Add(nb)

	prevPage, err := d.AddButton("_Previous", gtk.RESPONSE_NONE)
	if err != nil {
		return nil, err
	}
	prevPage.SetSensitive(false)
	nextPage, err := d.AddButton("_Next", gtk.RESPONSE_NONE)
	if err != nil {
		return nil, err
	}
	prevPage.Connect("clicked", func() {
		nb.PrevPage()
		pagen := nb.GetCurrentPage()
		if pagen == 0 {
			prevPage.SetSensitive(false)
		}
		nextPage.SetSensitive(true)
	})
	nextPage.Connect("clicked", func() {
		nb.NextPage()
		pagen := nb.GetCurrentPage()
		if pagen == len(dialogMessages)-1 {
			nextPage.SetSensitive(false)
		}
		prevPage.SetSensitive(true)
	})
	_, err = d.AddButton("_Close", gtk.RESPONSE_CLOSE)
	if err != nil {
		return nil, err
	}
	d.Connect("response", func(_ *glib.Object, rt gtk.ResponseType) {
		if rt == gtk.RESPONSE_CLOSE {
			// Using w.Close() would be nice but it needs GTK 3.10.
			d.Hide()
			d.Destroy()
		}
	})

	return d, nil
}
示例#2
0
func createNewWalletDialog() (*gtk.Dialog, error) {
	dialog, err := gtk.DialogNew()
	if err != nil {
		return nil, err
	}
	dialog.SetTitle("New wallet")

	dialog.AddButton("_OK", gtk.RESPONSE_OK)

	dialog.SetDefaultGeometry(500, 100)

	grid, err := gtk.GridNew()
	if err != nil {
		return nil, err
	}
	grid.SetHExpand(true)
	grid.SetVExpand(true)

	b, err := dialog.GetContentArea()
	if err != nil {
		return nil, err
	}
	b.Add(grid)

	// Because the label will wrap and the final minimum heights
	// and widths will be absurdly large, first give a size request and
	// show the grid (allocating space for the requested size).  This will
	// make text wrapping labels size nicely inside the grid.
	grid.SetSizeRequest(500, 100)
	grid.Show()

	l, err := gtk.LabelNew("")
	if err != nil {
		return nil, err
	}
	l.SetLineWrap(true)
	l.SetMarkup(newWalletMessage)
	l.SetAlignment(0, 0)
	grid.Attach(l, 0, 0, 2, 1)

	b.SetHExpand(true)
	b.SetVExpand(true)

	l, err = gtk.LabelNew("Enter passphrase:")
	if err != nil {
		return nil, err
	}
	l.SetAlignment(1.0, 0.5)
	grid.Attach(l, 0, 1, 1, 1)

	passphrase, err := gtk.EntryNew()
	if err != nil {
		return nil, err
	}
	passphrase.SetVisibility(false)
	passphrase.SetHExpand(true)
	passphrase.Connect("activate", func() {
		dialog.Emit("response", gtk.RESPONSE_OK, nil)
	})
	grid.Attach(passphrase, 1, 1, 1, 1)

	l, err = gtk.LabelNew("Confirm passphrase:")
	if err != nil {
		return nil, err
	}
	l.SetAlignment(1.0, 0.5)
	grid.Attach(l, 0, 2, 1, 1)

	repeated, err := gtk.EntryNew()
	if err != nil {
		return nil, err
	}
	repeated.SetVisibility(false)
	repeated.SetVAlign(gtk.ALIGN_START)
	repeated.Connect("activate", func() {
		dialog.Emit("response", gtk.RESPONSE_OK, nil)
	})
	grid.Attach(repeated, 1, 2, 1, 1)

	showEntryText, err := gtk.CheckButtonNewWithLabel("Show passphrase")
	if err != nil {
		return nil, err
	}
	showEntryText.Connect("toggled", func() {
		active := showEntryText.GetActive()
		passphrase.SetVisibility(active)
		repeated.SetVisibility(active)
	})
	grid.Attach(showEntryText, 1, 3, 2, 1)

	dialog.SetTransientFor(mainWindow)
	dialog.SetPosition(gtk.WIN_POS_CENTER_ON_PARENT)
	dialog.ShowAll()

	dialog.Connect("response", func(_ *glib.Object, rt gtk.ResponseType) {
		switch rt {
		case gtk.RESPONSE_OK:
			pStr, err := passphrase.GetText()
			if err != nil {
				log.Print(err)
				return
			}
			rStr, err := repeated.GetText()
			if err != nil {
				log.Print(err)
				return
			}
			if len(pStr) == 0 {
				mDialog := gtk.MessageDialogNew(dialog, 0,
					gtk.MESSAGE_ERROR, gtk.BUTTONS_OK,
					"A passphrase must be entered to create a wallet.")
				mDialog.SetTitle("Wallet creation failed")
				mDialog.Run()
				mDialog.Destroy()
				return
			}
			if pStr == rStr {
				go func() {
					triggers.newWallet <- &NewWalletParams{
						passphrase: pStr,
					}

					if err := <-triggerReplies.walletCreationErr; err != nil {
						glib.IdleAdd(func() {
							mDialog := gtk.MessageDialogNew(dialog, 0,
								gtk.MESSAGE_ERROR, gtk.BUTTONS_OK,
								err.Error())
							mDialog.SetTitle("Wallet creation failed")
							mDialog.Run()
							mDialog.Destroy()
						})
					} else {
						glib.IdleAdd(func() {
							dialog.Destroy()
						})
					}
				}()
			} else {
				msg := "The supplied passphrases do not match."
				mDialog := gtk.MessageDialogNew(dialog, 0,
					gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, msg)
				mDialog.SetTitle("Wallet creation failed")
				mDialog.Run()
				mDialog.Destroy()
			}
		case gtk.RESPONSE_CANCEL:
			dialog.Destroy()
		}
	})

	dialog.Connect("delete-event", func() {
		mDialog := gtk.MessageDialogNew(mainWindow, 0,
			gtk.MESSAGE_INFO, gtk.BUTTONS_OK,
			"btcgui cannot be used without a wallet and will now close.")
		mDialog.Show()
		mDialog.Run()
		mDialog.Destroy()
		gtk.MainQuit()
	})

	return dialog, nil
}
示例#3
0
func createTxFeeDialog() (*gtk.Dialog, error) {
	dialog, err := gtk.DialogNew()
	if err != nil {
		return nil, err
	}
	dialog.SetTitle("Set Transaction Fee")

	dialog.AddButton("_OK", gtk.RESPONSE_OK)
	dialog.AddButton("_Cancel", gtk.RESPONSE_CANCEL)

	grid, err := gtk.GridNew()
	if err != nil {
		return nil, err
	}
	grid.SetHExpand(true)
	grid.SetVExpand(true)
	grid.SetOrientation(gtk.ORIENTATION_VERTICAL)
	b, err := dialog.GetContentArea()
	if err != nil {
		return nil, err
	}
	b.Add(grid)
	b.SetHExpand(true)
	b.SetVExpand(true)

	l, err := gtk.LabelNew(txFeeMessage)
	if err != nil {
		return nil, err
	}
	l.SetHExpand(true)
	l.SetVExpand(true)
	l.SetHAlign(gtk.ALIGN_START)
	grid.Add(l)

	spinb, err := gtk.SpinButtonNewWithRange(0, 21000000, 0.00000001)
	if err != nil {
		return nil, err
	}
	grid.Add(spinb)

	dialog.SetTransientFor(mainWindow)
	dialog.SetPosition(gtk.WIN_POS_CENTER_ON_PARENT)
	dialog.ShowAll()

	dialog.Connect("response", func(_ *glib.Object, rt gtk.ResponseType) {
		switch rt {
		case gtk.RESPONSE_OK:
			fee := spinb.GetValue()
			go func() {
				triggers.setTxFee <- fee

				if err := <-triggerReplies.setTxFeeErr; err != nil {
					d := errorDialog("Error setting transaction fee:",
						err.Error())
					d.Run()
					d.Destroy()
				} else {
					glib.IdleAdd(func() {
						dialog.Destroy()
					})
				}
			}()

		case gtk.RESPONSE_CANCEL:
			dialog.Destroy()
		}
	})

	return dialog, nil
}
示例#4
0
func createEncryptionDialog() (*gtk.Dialog, error) {
	dialog, err := gtk.DialogNew()
	if err != nil {
		return nil, err
	}
	dialog.SetTitle("Encrypt wallet")

	dialog.AddButton("_OK", gtk.RESPONSE_OK)
	dialog.AddButton("_Cancel", gtk.RESPONSE_CANCEL)

	grid, err := gtk.GridNew()
	if err != nil {
		return nil, err
	}
	grid.SetHExpand(true)
	grid.SetVExpand(true)
	b, err := dialog.GetContentArea()
	if err != nil {
		return nil, err
	}
	b.Add(grid)
	b.SetHExpand(true)
	b.SetVExpand(true)

	l, err := gtk.LabelNew("")
	if err != nil {
		return nil, err
	}
	l.SetMarkup(encryptMessage)
	l.SetHExpand(true)
	l.SetVExpand(true)
	l.SetHAlign(gtk.ALIGN_START)
	grid.Attach(l, 0, 0, 2, 1)

	l, err = gtk.LabelNew("New passphrase")
	if err != nil {
		return nil, err
	}
	grid.Attach(l, 0, 1, 1, 1)

	passphrase, err := gtk.EntryNew()
	if err != nil {
		return nil, err
	}
	passphrase.SetVisibility(false)
	passphrase.SetHExpand(true)
	passphrase.Connect("activate", func() {
		dialog.Emit("response", gtk.RESPONSE_OK, nil)
	})
	grid.Attach(passphrase, 1, 1, 1, 1)

	l, err = gtk.LabelNew("Repeat new passphrase")
	if err != nil {
		return nil, err
	}
	l.SetVExpand(true)
	l.SetVAlign(gtk.ALIGN_START)
	grid.Attach(l, 0, 2, 1, 1)

	repeated, err := gtk.EntryNew()
	if err != nil {
		return nil, err
	}
	repeated.SetVisibility(false)
	repeated.SetVExpand(true)
	repeated.SetVAlign(gtk.ALIGN_START)
	repeated.Connect("activate", func() {
		dialog.Emit("response", gtk.RESPONSE_OK, nil)
	})
	grid.Attach(repeated, 1, 2, 1, 1)

	dialog.SetTransientFor(mainWindow)
	dialog.SetPosition(gtk.WIN_POS_CENTER_ON_PARENT)
	dialog.ShowAll()

	dialog.Connect("response", func(_ *glib.Object, rt gtk.ResponseType) {
		switch rt {
		case gtk.RESPONSE_OK:
			pStr, err := passphrase.GetText()
			if err != nil {
				log.Print(err)
				return
			}
			rStr, err := repeated.GetText()
			if err != nil {
				log.Print(err)
				return
			}
			if pStr == rStr {
				// use the passphrase, encrypt wallet...
				dialog.Destroy()
			} else {
				msg := "The supplied passphrases do not match."
				mDialog := gtk.MessageDialogNew(dialog, 0,
					gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, msg)
				mDialog.SetTitle("Wallet encryption failed")
				mDialog.Run()
				mDialog.Destroy()
			}
		case gtk.RESPONSE_CANCEL:
			dialog.Destroy()
		}
	})

	return dialog, nil
}
示例#5
0
// createUnlockDialog creates a dialog to enter a passphrase and unlock
// an encrypted wallet.  If an OK response is received, the passphrase will
// be used to attempt a wallet unlock.
//
// If success is non-nil, the caller may pass in a channel to receive a
// notification for whether the unlock was successful.  If the dialog is
// closed without sending a request to btcwallet and the channel is
// non-nil, the channel is closed.
func createUnlockDialog(reason *UnlockText,
	success chan bool) (*gtk.Dialog, error) {

	dialog, err := gtk.DialogNew()
	if err != nil {
		return nil, err
	}
	dialog.SetTitle(reason.Title)

	dialog.AddButton("_OK", gtk.RESPONSE_OK)
	dialog.AddButton("_Cancel", gtk.RESPONSE_CANCEL)

	grid, err := gtk.GridNew()
	if err != nil {
		return nil, err
	}
	grid.SetHExpand(true)
	grid.SetVExpand(true)
	b, err := dialog.GetContentArea()
	if err != nil {
		return nil, err
	}
	b.Add(grid)
	b.SetHExpand(true)
	b.SetVExpand(true)

	lbl, err := gtk.LabelNew(reason.Message)
	if err != nil {
		return nil, err
	}
	grid.Attach(lbl, 0, 0, 2, 1)

	lbl, err = gtk.LabelNew("Passphrase")
	if err != nil {
		return nil, err
	}
	grid.Attach(lbl, 0, 1, 1, 1)

	passphrase, err := gtk.EntryNew()
	if err != nil {
		return nil, err
	}
	passphrase.SetVisibility(false)
	passphrase.SetHExpand(true)
	passphrase.SetVExpand(true)
	passphrase.Connect("activate", func() {
		dialog.Emit("response", gtk.RESPONSE_OK, nil)
	})
	grid.Attach(passphrase, 1, 1, 1, 1)

	lbl, err = gtk.LabelNew("Timeout (s)")
	if err != nil {
		return nil, err
	}
	grid.Attach(lbl, 0, 2, 1, 1)

	timeout, err := gtk.SpinButtonNewWithRange(0, float64(1<<64-1), 1)
	if err != nil {
		return nil, err
	}
	timeout.SetValue(60)
	timeout.Connect("activate", func() {
		dialog.Emit("response", gtk.RESPONSE_OK, nil)
	})
	grid.Attach(timeout, 1, 2, 1, 1)

	dialog.SetTransientFor(mainWindow)
	dialog.SetPosition(gtk.WIN_POS_CENTER_ON_PARENT)
	dialog.ShowAll()

	dialog.Connect("response", func(_ *glib.Object, rt gtk.ResponseType) {
		switch rt {
		case gtk.RESPONSE_OK:
			pStr, err := passphrase.GetText()
			if err != nil {
				log.Print(err)
				return
			}

			timeoutSecs := timeout.GetValueAsInt()

			go func() {
				triggers.unlockWallet <- &UnlockParams{
					pStr,
					int64(timeoutSecs),
				}

				if ok := <-triggerReplies.unlockSuccessful; ok {
					if success != nil {
						success <- true
					}
					glib.IdleAdd(func() {
						dialog.Destroy()
					})
				} else {
					if success != nil {
						success <- false
					}
					glib.IdleAdd(func() {
						mDialog := gtk.MessageDialogNew(dialog, 0,
							gtk.MESSAGE_ERROR, gtk.BUTTONS_OK,
							"Wallet decryption failed.")
						mDialog.SetTitle("Wallet decryption failed")
						mDialog.Run()
						mDialog.Destroy()
					})
				}
			}()

		case gtk.RESPONSE_CANCEL:
			if success != nil {
				close(success)
			}
			dialog.Destroy()
		}
	})

	return dialog, nil
}