Commit 29ddd64d authored by Loïck Bonniot's avatar Loïck Bonniot

[d] Add GUI interface and log function

parent 252d84df
Pipeline #437 passed with stage
<RCC>
<qresource prefix="/">
<file>widget.ui</file>
</qresource>
</RCC>
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CalculatorForm</class>
<widget class="QWidget" name="CalculatorForm">
<property name="enabled">
<bool>true</bool>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>751</width>
<height>595</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</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="QGraphicsView" name="graphicsView">
<property name="minimumSize">
<size>
<width>700</width>
<height>300</height>
</size>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="topMargin">
<number>5</number>
</property>
<property name="bottomMargin">
<number>5</number>
</property>
<item>
<widget class="QPushButton" name="playButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Play</string>
</property>
<property name="default">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="replayButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Replay</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="quantumLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Quantum:</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="quantumField">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="suffix">
<string> us</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>1000000</number>
</property>
<property name="singleStep">
<number>100</number>
</property>
<property name="value">
<number>1000</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="speedLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Speed:</string>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="speedSlider">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TicksBothSides</enum>
</property>
<property name="tickInterval">
<number>5</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QTextEdit" name="logField">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>200</height>
</size>
</property>
<property name="font">
<font>
<family>Courier</family>
<pointsize>10</pointsize>
</font>
</property>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOn</enum>
</property>
<property name="undoRedoEnabled">
<bool>false</bool>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="acceptRichText">
<bool>false</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
package gui
import (
"dfss"
"github.com/visualfc/goqt/ui"
)
type Window struct {
*ui.QMainWindow
logField *ui.QTextEdit
}
func NewWindow() *Window {
file := ui.NewFileWithName(":/widget.ui")
loader := ui.NewUiLoader()
widget := loader.Load(file)
// Init main window
window := ui.NewMainWindow()
window.SetCentralWidget(widget)
window.SetWindowTitle("DFSS Demonstrator v" + dfss.Version)
w := &Window{
QMainWindow: window,
}
// Load dynamic elements from driver
w.logField = ui.NewTextEditFromDriver(widget.FindChild("logField"))
// Add actions
w.addActions()
w.StatusBar().ShowMessage("Ready")
return w
}
func (w *Window) Log(str string) {
w.logField.Append(str)
w.logField.EnsureCursorVisible()
}
func (w *Window) addActions() {
openAct := ui.NewActionWithTextParent("&Open", w)
openAct.SetShortcuts(ui.QKeySequence_Open)
openAct.SetStatusTip("Open a demonstration file")
saveAct := ui.NewActionWithTextParent("&Save", w)
saveAct.SetShortcuts(ui.QKeySequence_Save)
saveAct.SetStatusTip("Save a demonstration file")
w.MenuBar().AddAction(openAct)
w.MenuBar().AddAction(saveAct)
}
......@@ -9,6 +9,8 @@ import (
"dfss"
"dfss/dfssd/server"
"dfss/dfssd/gui"
"github.com/visualfc/goqt/ui"
)
var (
......@@ -49,10 +51,23 @@ func main() {
case "version":
fmt.Println("v"+dfss.Version, runtime.GOOS, runtime.GOARCH)
case "nogui":
err := server.Listen("0.0.0.0:" + strconv.Itoa(port))
lfn := func(str string) {
fmt.Println(str)
}
err := server.Listen("0.0.0.0:" + strconv.Itoa(port), lfn)
if err != nil {
os.Exit(1)
}
default:
ui.Run(func() {
window := gui.NewWindow()
go func() {
err := server.Listen("0.0.0.0:" + strconv.Itoa(port), window.Log)
if err != nil {
window.Log("!! " + err.Error())
}
}()
window.Show()
})
}
}
package server
import (
"log"
"net"
api "dfss/dfssd/api"
......@@ -21,17 +20,17 @@ func (s *Server) SendLog(ctx context.Context, in *api.Log) (*api.Ack, error) {
}
// Listen with gRPG service
func Listen(addrPort string) error {
func Listen(addrPort string, lfn func(string)) error {
// open tcp socket
lis, err := net.Listen("tcp", addrPort)
if err != nil {
grpclog.Fatalf("Failed to open tcp socket: %v", err)
return err
}
log.Printf("Server listening on %s", addrPort)
lfn("Server listening on " + addrPort)
// log display manager
go displayHandler()
go displayHandler(lfn)
// bootstrap gRPC service !
grpcServer := grpc.NewServer()
......
package server
import (
"log"
"fmt"
"sort"
"sync"
"time"
......@@ -23,7 +23,7 @@ func addMessage(msg *api.Log) {
}
// display logs that are more than since (ms) old
func display(since int64) {
func display(since int64, lfn func(string)) {
var out []*api.Log // sorted messages to display
var recycled []*api.Log // messages too recent to be displayed
......@@ -45,15 +45,15 @@ func display(since int64) {
sort.Sort(ByTimestamp(out))
for _, v := range out {
log.Printf("[%d] %s:: %s", v.Timestamp, v.Identifier, v.Log)
lfn(fmt.Sprintf("[%d] %s:: %s", v.Timestamp, v.Identifier, v.Log))
}
}
// refresh every second
func displayHandler() {
func displayHandler(lfn func(string)) {
ticker := time.NewTicker(time.Second)
for range ticker.C {
display(1000)
display(1000, lfn)
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment