Commit ae7eeac3 authored by Loïck Bonniot's avatar Loïck Bonniot

Merge branch '204_demo_gui_kernel' into 'master'

204 demo gui kernel

![Capture_d_écran_de_2016-04-05_15-59-48](/uploads/ee8eb206d0931bc5d01c55d014761654/Capture_d_écran_de_2016-04-05_15-59-48.png)

See merge request !46
parents edd6dce5 b6f61d7c
Pipeline #439 passed with stages
......@@ -22,7 +22,7 @@ Unit tests:
script:
- "ln -s $(pwd) $GOPATH/src/dfss"
- "./build/deps.sh"
- "cd $GOPATH/src/dfss && rm -rf gui && go install ./..."
- "cd $GOPATH/src/dfss && make install"
- "go test -coverprofile auth.part -v dfss/auth"
- "go test -coverprofile mgdb.part -v dfss/mgdb"
- "go test -coverprofile mails.part -v dfss/mails"
......@@ -32,7 +32,6 @@ Unit tests:
- "go test -coverprofile dfssp_contract.part -v dfss/dfssp/contract"
- "go test -coverprofile dfssp_templates.part -v dfss/dfssp/templates"
- "go test -coverprofile dfssp_common.part -v dfss/dfssp/common"
- "go test -coverprofile dfssd.part -v dfss/dfssd"
- "go test -coverprofile dfssc_common.part -v dfss/dfssc/common"
- "go test -coverprofile dfssc_security.part -v dfss/dfssc/security"
- "go test -coverprofile dfssc_user.part -v dfss/dfssc/user"
......@@ -53,7 +52,7 @@ Integration tests:
script:
- "ln -s -f $(pwd) $GOPATH/src/dfss"
- "./build/deps.sh"
- "cd $GOPATH/src/dfss && rm -rf gui && go install ./..."
- "cd $GOPATH/src/dfss && make install"
- "go test -v dfss/tests"
Code lint:
......@@ -68,9 +67,9 @@ Code lint:
- "ln -s $(pwd) $GOPATH/src/dfss"
- "go get github.com/alecthomas/gometalinter"
- "./build/deps.sh"
- "cd $GOPATH/src/dfss && rm -rf gui && go install ./..."
- "cd $GOPATH/src/dfss && make install_all"
- "gometalinter --install"
- "gometalinter -t --deadline=600s -j1 --skip=api --skip=fixtures --disable=aligncheck ./..."
- "gometalinter -t --deadline=600s -j1 --skip=api --skip=fixtures --skip=gui --skip=dfssd --disable=aligncheck ./..."
Deploy:
stage: deploy
......
......@@ -7,18 +7,20 @@ endif
.PHONY:
install: nocache
go install .
go install ./dfssc
go install ./dfssd
go install ./dfssp
go install ./dfsst
release: clean build_all package
clean:
rm -rf release
# install_all installs everything, including libraries. It's mandatory for linter, but should be improved in the future.
install_all: install
git stash
rm -rf gui
rm -rf dfssd/gui
rm -f dfssd/main.go
go install ./...
git reset --hard
# GUI Build (Docker required)
release: clean build_all package
# prepare_gui builds a new container from the goqt image, adding DFSS dependencies for faster builds.
# call it once or after dependency addition.
......@@ -35,11 +37,24 @@ gui: nocache
docker run --rm -v ${PWD}:/go/src/dfss -w /go/src/dfss/gui dfss:builder \
go build -ldflags "-r ." -o ../bin/gui
# Release internals
# dfssd builds the demonstrator into a docker container, outputing the result in bin/ directory
dfssd: nocache
docker run --rm -v ${PWD}:/go/src/dfss -w /go/src/dfss/dfssd/gui dfss:builder \
../../bin/goqt_rcc -go gui -o application.qrc.go application.qrc
docker run --rm -v ${PWD}:/go/src/dfss -w /go/src/dfss/dfssd dfss:builder \
go build -ldflags "-r ." -o ../bin/dfssd
protobuf:
cd .. && \
protoc --go_out=plugins=grpc:. dfss/dfssc/api/client.proto && \
protoc --go_out=plugins=grpc:. dfss/dfssd/api/demonstrator.proto && \
protoc --go_out=plugins=grpc:. dfss/dfssp/api/platform.proto && \
protoc --go_out=plugins=grpc:. dfss/dfsst/api/resolution.proto
# Release internals
build_all:
go get github.com/mitchellh/gox
gox -os "linux darwin windows" -parallel 1 -output "release/dfss_${VERSION}_{{.OS}}_{{.Arch}}/{{.Dir}}" dfss/dfssc dfss/dfssd dfss/dfssp dfss/dfsst
gox -os "linux darwin windows" -parallel 1 -output "release/dfss_${VERSION}_{{.OS}}_{{.Arch}}/{{.Dir}}" dfss/dfssc dfss/dfssp dfss/dfsst
package:
echo "$(VERSION) $(REVISION)" > build/embed/VERSION
......@@ -50,11 +65,7 @@ deploy:
mkdir -p /deploy/$(VERSION)
cp release/*.tar.gz /deploy/$(VERSION)/
protobuf:
cd .. && \
protoc --go_out=plugins=grpc:. dfss/dfssc/api/client.proto && \
protoc --go_out=plugins=grpc:. dfss/dfssd/api/demonstrator.proto && \
protoc --go_out=plugins=grpc:. dfss/dfssp/api/platform.proto && \
protoc --go_out=plugins=grpc:. dfss/dfsst/api/resolution.proto
clean:
rm -rf release
nocache:
package main
import (
dapi "dfss/dfssd/api"
"testing"
)
// Test for a client-server dialing
//
// Cannot add output statement because output includes timestamp
func TestServerAndClient(t *testing.T) {
// Start a server
go func() {
err := listen("localhost:3000")
if err != nil {
t.Error("Unable to start server")
}
}()
// Start a client
go func() {
defer dapi.DClose()
// this one fails silently, so you can't really test it
dapi.DLog("This is a log message from a client")
}()
// Start another client
go func() {
defer dapi.DClose()
// this one fails silently, so you can't really test it
dapi.DLog("This is a log message from another client")
}()
}
<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)
}
package main
import (
"dfss"
"flag"
"fmt"
"os"
"runtime"
"strconv"
"dfss"
"dfss/dfssd/server"
"dfss/dfssd/gui"
"github.com/visualfc/goqt/ui"
)
var (
verbose bool
port int
)
func init() {
flag.BoolVar(&verbose, "v", false, "Print verbose messages")
flag.IntVar(&port, "p", 3000, "Network port used")
flag.Usage = func() {
fmt.Println("DFSS demonstrator v" + dfss.Version)
......@@ -26,7 +31,8 @@ func init() {
fmt.Println("\nThe commands are:")
fmt.Println(" help print this help")
fmt.Println(" version print dfss client version")
fmt.Println(" start start demonstrator server")
fmt.Println(" nogui start demonstrator server without GUI")
fmt.Println(" gui start demonstrator server with GUI")
fmt.Println("\nFlags:")
flag.PrintDefaults()
......@@ -40,14 +46,28 @@ func main() {
command := flag.Arg(0)
switch command {
case "help":
flag.Usage()
case "version":
fmt.Println("v"+dfss.Version, runtime.GOOS, runtime.GOARCH)
case "start":
err := listen("localhost:3000")
case "nogui":
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:
flag.Usage()
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 main
package server
import (
"golang.org/x/net/context"
"google.golang.org/grpc"
"google.golang.org/grpc/grpclog"
"log"
"net"
api "dfss/dfssd/api"
"golang.org/x/net/context"
"google.golang.org/grpc"
"google.golang.org/grpc/grpclog"
)
type server struct{}
type Server struct{}
// Sendlog Handler
//
// Handle incoming log messages
func (s *server) SendLog(ctx context.Context, in *api.Log) (*api.Ack, error) {
func (s *Server) SendLog(ctx context.Context, in *api.Log) (*api.Ack, error) {
addMessage(in)
return &api.Ack{}, nil
}
// 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()
api.RegisterDemonstratorServer(grpcServer, &server{})
api.RegisterDemonstratorServer(grpcServer, &Server{})
err = grpcServer.Serve(lis)
return err
......
package main
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