Commit 9e43d926 authored by Tristan Claverie's avatar Tristan Claverie

Merge branch '412_gui_various_improvements' into 'master'

412 gui various improvements

Waiting for !65 to be merged.

![Capture_d_écran_de_2016-04-22_23-28-13](/uploads/218670df9f3c89aff67ea92265d07488/Capture_d_écran_de_2016-04-22_23-28-13.png)

See merge request !66
parents 5e01804e 4c9fe6a3
Pipeline #897 failed with stages
......@@ -14,3 +14,7 @@ PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIG
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.`
const help = `Your configuration and authentication files are stored under your home directory, in a .dfss folder.
You may want to save this folder in a secure way in order to re-use your account on several computers.`
......@@ -10,5 +10,6 @@
<file>images/digital_signature_pen.png</file>
<file>signform/signform.ui</file>
<file>showcontract/showcontract.ui</file>
<file>welcome/welcome.ui</file>
</qresource>
</RCC>
......@@ -2,7 +2,7 @@ package authform
import (
"dfss/dfssc/user"
"dfss/gui/common"
"github.com/spf13/viper"
"github.com/visualfc/goqt/ui"
)
......@@ -17,7 +17,6 @@ func NewWidget(onAuth func()) *Widget {
form := loader.Load(file)
tokenField := ui.NewLineEditFromDriver(form.FindChild("tokenField"))
feedbackLabel := ui.NewLabelFromDriver(form.FindChild("feedbackLabel"))
authButton := ui.NewPushButtonFromDriver(form.FindChild("authButton"))
authButton.OnClicked(func() {
......@@ -28,7 +27,7 @@ func NewWidget(onAuth func()) *Widget {
)
form.SetDisabled(false)
if err != nil {
feedbackLabel.SetText(err.Error())
common.ShowMsgBox(err.Error(), true)
tokenField.SetFocus()
tokenField.SelectAll()
} else {
......
......@@ -93,33 +93,26 @@
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="authButton">
<property name="text">
<string>Authenticate</string>
</property>
<property name="autoDefault">
<bool>false</bool>
</property>
<property name="default">
<bool>true</bool>
</property>
<property name="flat">
<bool>false</bool>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="feedbackLabel">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="authButton">
<property name="text">
<string>Authenticate</string>
</property>
<property name="autoDefault">
<bool>false</bool>
</property>
<property name="default">
<bool>true</bool>
</property>
<property name="flat">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
......
package config
package common
// This file handles basic feedback messages.
import (
"errors"
"io/ioutil"
"dfss/auth"
"github.com/spf13/viper"
"github.com/visualfc/goqt/ui"
)
// ShowMsgBox pops a new Qt Msg Box containing the appropriate message regarding the critical flag.
func ShowMsgBox(content string, critical bool) {
m := ui.NewMessageBox()
m.SetText(content)
if critical {
m.SetWindowTitle("Error")
m.SetIcon(ui.QMessageBox_Critical)
} else {
m.SetWindowTitle("Information")
m.SetIcon(ui.QMessageBox_Information)
}
m.Exec()
}
// PasswordDialog checks the current private key for any passphrase.
// If the key is protected, it spawns an inputDialog window to ask the user's passphrase,
// and then calls the callback function with the result.
......
......@@ -14,8 +14,8 @@ import (
// Config is the structure that will be persisted in the configuration file
type Config struct {
Email string `json: email`
Platform string `json: platform`
Email string `json:"email"`
Platform string `json:"platform"`
}
// Load loads the configuration file into memory.
......
......@@ -4,8 +4,8 @@ import (
"strings"
"dfss/dfssc/sign"
"dfss/gui/common"
"dfss/gui/config"
"github.com/spf13/viper"
"github.com/visualfc/goqt/ui"
)
......@@ -26,7 +26,6 @@ func NewWidget() *Widget {
signersField := ui.NewPlainTextEditFromDriver(form.FindChild("signersField"))
fileButton := ui.NewPushButtonFromDriver(form.FindChild("fileButton"))
createButton := ui.NewPushButtonFromDriver(form.FindChild("createButton"))
feedbackLabel := ui.NewLabelFromDriver(form.FindChild("feedbackLabel"))
w := &Widget{
QWidget: form,
......@@ -43,11 +42,9 @@ func NewWidget() *Widget {
createButton.OnClicked(func() {
form.SetDisabled(true)
feedbackLabel.SetText("Please wait...")
config.PasswordDialog(func(err error, pwd string) {
common.PasswordDialog(func(err error, pwd string) {
if err != nil {
form.SetDisabled(false)
feedbackLabel.SetText("Aborted.")
return // wrong key or rejection, aborting
}
......@@ -59,9 +56,9 @@ func NewWidget() *Widget {
)
if err != nil {
feedbackLabel.SetText(err.Error())
common.ShowMsgBox(err.Error(), true)
} else {
feedbackLabel.SetText("Contract successfully sent to signers!")
common.ShowMsgBox("Contract successfully sent to signers!", false)
fileField.SetText("")
}
form.SetDisabled(false)
......
......@@ -108,27 +108,20 @@
<item row="2" column="1">
<widget class="QPlainTextEdit" name="commentField"/>
</item>
<item row="3" column="0">
<widget class="QPushButton" name="createButton">
<property name="text">
<string>Create contract</string>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="feedbackLabel">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="createButton">
<property name="text">
<string>Create contract</string>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
......
......@@ -3,6 +3,7 @@ package main
import (
"dfss"
"dfss/dfssp/contract"
"dfss/gui/common"
"dfss/gui/config"
"github.com/spf13/viper"
"github.com/visualfc/goqt/ui"
......@@ -33,13 +34,14 @@ func main() {
// Start first window
ui.Run(func() {
qw := ui.NewMainWindow()
w := &window{
QMainWindow: ui.NewMainWindow(),
QMainWindow: qw,
}
if viper.GetBool("authenticated") {
w.addActions()
w.showNewContractForm()
w.showWelcome()
} else if viper.GetBool("registered") {
w.showAuthForm()
} else {
......@@ -72,6 +74,11 @@ func (w *window) addActions() {
fetchAct := ui.NewActionWithTextParent("&Fetch", w)
fetchAct.OnTriggered(w.showFetchForm)
helpAct := ui.NewActionWithTextParent("&Help", w)
helpAct.OnTriggered(func() {
common.ShowMsgBox(help, false)
})
aboutAct := ui.NewActionWithTextParent("&About", w)
aboutAct.OnTriggered(func() {
ui.QMessageBoxAbout(w, "About DFSS Client", about)
......@@ -82,6 +89,9 @@ func (w *window) addActions() {
ui.QApplicationAboutQt()
})
userAct := ui.NewActionWithTextParent("Authenticated as "+viper.GetString("email")+" ("+viper.GetString("platform")+")", w)
userAct.SetDisabled(true)
fileMenu := w.MenuBar().AddMenuWithTitle("&File")
fileMenu.AddAction(newAct)
fileMenu.AddAction(openAct)
......@@ -89,9 +99,12 @@ func (w *window) addActions() {
fileMenu.AddAction(fetchAct)
helpMenu := w.MenuBar().AddMenuWithTitle("&Help")
helpMenu.AddAction(helpAct)
helpMenu.AddAction(aboutAct)
helpMenu.AddSeparator()
helpMenu.AddAction(aboutQtAct)
w.MenuBar().AddAction(userAct)
}
func (w *window) setScreen(wi widget) {
......
......@@ -3,15 +3,24 @@ package main
import (
"dfss/dfssc/sign"
"dfss/gui/authform"
"dfss/gui/config"
"dfss/gui/common"
"dfss/gui/contractform"
"dfss/gui/showcontract"
"dfss/gui/signform"
"dfss/gui/userform"
"dfss/gui/welcome"
"github.com/spf13/viper"
"github.com/visualfc/goqt/ui"
)
func (w *window) showWelcome() {
w.setScreen(welcome.NewWidget(
w.showNewContractForm,
func() { w.showShowContract("") },
w.showFetchForm,
))
}
func (w *window) showUserForm() {
w.setScreen(userform.NewWidget(func(pwd string) {
w.showAuthForm()
......@@ -41,17 +50,17 @@ func (w *window) showShowContract(filename string) {
w.contract = showcontract.Load(filename)
if w.contract == nil {
w.showMsgBox("Unable to load file", true)
common.ShowMsgBox("Unable to load file", true)
return
}
w.setScreen(showcontract.NewWidget(w.contract, w.showSignForm))
}
func (w *window) showSignForm() {
config.PasswordDialog(func(err error, pwd string) {
common.PasswordDialog(func(err error, pwd string) {
widget := signform.NewWidget(w.contract, pwd)
if widget == nil {
w.showMsgBox("Unable to start the signing procedure", true)
common.ShowMsgBox("Unable to start the signing procedure", true)
return
}
w.setScreen(widget)
......@@ -60,7 +69,7 @@ func (w *window) showSignForm() {
func (w *window) showFetchForm() {
w.current.Q().SetDisabled(true)
config.PasswordDialog(func(err error, pwd string) {
common.PasswordDialog(func(err error, pwd string) {
if err != nil {
w.current.Q().SetDisabled(false)
return
......@@ -78,11 +87,11 @@ func (w *window) showFetchForm() {
err := sign.FetchContract(pwd, uuid, path)
if err != nil {
w.showMsgBox(err.Error(), true)
common.ShowMsgBox(err.Error(), true)
return
}
w.showMsgBox("Contract stored as "+path, false)
w.showShowContract(path)
common.ShowMsgBox("Contract stored as "+path, false)
})
dialog.OnFinished(func(_ int32) {
......@@ -90,16 +99,3 @@ func (w *window) showFetchForm() {
})
})
}
func (w *window) showMsgBox(content string, critical bool) {
m := ui.NewMessageBoxWithParent(w)
m.SetText(content)
if critical {
m.SetWindowTitle("Error")
m.SetIcon(ui.QMessageBox_Critical)
} else {
m.SetWindowTitle("Information")
m.SetIcon(ui.QMessageBox_Information)
}
m.Exec()
}
......@@ -4,6 +4,7 @@ import (
"io/ioutil"
"dfss/dfssc/user"
"dfss/gui/common"
"dfss/gui/config"
"github.com/spf13/viper"
......@@ -23,8 +24,6 @@ func NewWidget(onRegistered func(pw string)) *Widget {
hostField := ui.NewLineEditFromDriver(form.FindChild("hostField"))
passwordField := ui.NewLineEditFromDriver(form.FindChild("passwordField"))
passwordField.SetEchoMode(ui.QLineEdit_Password)
feedbackLabel := ui.NewLabelFromDriver(form.FindChild("feedbackLabel"))
registerButton := ui.NewPushButtonFromDriver(form.FindChild("registerButton"))
home := viper.GetString("home_dir")
......@@ -33,7 +32,6 @@ func NewWidget(onRegistered func(pw string)) *Widget {
registerButton.OnClicked(func() {
form.SetDisabled(true)
feedbackLabel.SetText("Registration in progress...")
filter := "Root Certificates (*.pem);;Any (*.*)"
caFilename := ui.QFileDialogGetOpenFileNameWithParentCaptionDirFilterSelectedfilterOptions(form, "Select the CA file for the platform", home, filter, &filter, 0)
_ = copyCA(caFilename)
......@@ -44,7 +42,7 @@ func NewWidget(onRegistered func(pw string)) *Widget {
"", "", "", emailField.Text(), 2048,
)
if err != nil {
feedbackLabel.SetText(err.Error())
common.ShowMsgBox(err.Error(), true)
} else {
viper.Set("email", emailField.Text())
onRegistered(passwordField.Text())
......
......@@ -41,52 +41,35 @@
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>30</number>
</property>
<property name="sizeConstraint">
<enum>QLayout::SetDefaultConstraint</enum>
</property>
<property name="leftMargin">
<number>30</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>30</number>
</property>
<item>
<widget class="QLabel" name="welcomeLabel">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:20pt; font-weight:600;&quot;&gt;Welcome on DFSS Client!&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-size:14pt;&quot;&gt;Please tell us some information to start.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<widget class="QLabel" name="label">
<property name="minimumSize">
<size>
<width>0</width>
<height>20</height>
<height>100</height>
</size>
</property>
</spacer>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>100</height>
</size>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:20pt; font-weight:600;&quot;&gt;Welcome on DFSS Client!&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-size:14pt;&quot;&gt;Please tell us some information to start.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<property name="formAlignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="horizontalSpacing">
<number>30</number>
</property>
......@@ -153,30 +136,23 @@
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QPushButton" name="registerButton">
<property name="text">
<string>Register</string>
</property>
<property name="autoDefault">
<bool>false</bool>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="feedbackLabel">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="registerButton">
<property name="text">
<string>Register</string>
</property>
<property name="autoDefault">
<bool>false</bool>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
......
package welcome
import (
"github.com/visualfc/goqt/ui"
)
type Widget struct {
*ui.QWidget
}
func NewWidget(onNew, onOpen, onFetch func()) *Widget {
file := ui.NewFileWithName(":/welcome/welcome.ui")
loader := ui.NewUiLoader()
form := loader.Load(file)
(ui.NewPushButtonFromDriver(form.FindChild("createButton"))).OnClicked(onNew)
(ui.NewPushButtonFromDriver(form.FindChild("openButton"))).OnClicked(onOpen)
(ui.NewPushButtonFromDriver(form.FindChild("fetchButton"))).OnClicked(onFetch)
return &Widget{QWidget: form}
}
func (w *Widget) Q() *ui.QWidget {
return w.QWidget
}
func (w *Widget) Tick() {}
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Welcome</class>
<widget class="QWidget" name="Welcome">
<property name="enabled">
<bool>true</bool>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>776</width>
<height>353</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>650</width>
<height>350</height>
</size>
</property>
<property name="windowTitle">
<string>Calculator Builder</string>
</property>
<layout class="QGridLayout">
<property name="margin">
<number>9</number>
</property>
<property name="spacing">
<number>6</number>
</property>
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="authLabel">
<property name="minimumSize">
<size>
<width>0</width>
<height>100</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>100</height>
</size>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-size:20pt;&quot;&gt;Welcome&lt;/span&gt;&lt;/p&gt;&lt;p&gt;The DFSS client is ready.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<property name="formAlignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="horizontalSpacing">
<number>30</number>
</property>
<property name="verticalSpacing">
<number>10</number>
</property>
<property name="leftMargin">
<number>50</number>
</property>
<property name="rightMargin">
<number>50</number>
</property>
<item row="0" column="0">
<widget class="QPushButton" name="createButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>200</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>200</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Create a new contract</string>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QPushButton" name="openButton">
<property name="minimumSize">
<size>
<width>200</width>