使用golang来设计我们的Ubuntu Scope

159 篇文章 2 订阅
132 篇文章 0 订阅

我们知道golang越来越被很多的开发者来开发应用。go语言也可以用于开发Ubuntu Scope。在今天的教程中,我们将详细介绍如何使用go语言来开发我们的Scope。这对于很多的不太熟悉C/C++的开发者来说,无疑是一个福音。对我来说,这个语言也是比较新的。如果大家想学习golang的话,建议大家阅读“Go by Example”。


对于更多的关于Go Scope的开发,可以参阅文章“Go scopes development”。


IDE选择

由于一些原因,目前我们的Ubuntu SDK并没有支持go语言的Scope的开发。可喜的是,我们可以使用Command Line来完成我们的开发。俗话说,好镰不误砍柴功。一个好的工具无疑能帮我们更快更好地开发。我目前使用的编辑器是LiteIDE。这个是转为go语言而设计的IDE,非常简洁而使用,建议大家试用。




安装开发环境


我们首先必须安装 golang包及相关包:

$sudo apt-get install unity-scope-tool golang git bzr python3-scope-harness mercurial

为了能够为我们的手机生产我们需要的click包,我们必须在我们的armhf chroot安装我们所需要的包.我们首先在命令行中打入如下的命令进入到chroot的 maintainance模式下:

$ click chroot -aarmhf -fubuntu-sdk-15.04 maint  

然后按照如下的步骤安装所需要的包:

# apt-get install golang
# apt-get install golang-go-linux-arm
# apt-get install libaccounts-glib-dev:armhf
# apt-get install crossbuild-essential-armhf
# apt-get install libsignon-glib-dev:armhf

如果在安装上面的步骤apt-get install libaccounts-glib-dev:armhf出现如下的错误:

(click-ubuntu-sdk-15.04-armhf)root@liuxg:/home/liuxg# apt-get install libsignon-glib-dev:armhf -f
Reading package lists... Done
Building dependency tree       
Reading state information... Done
Some packages could not be installed. This may mean that you have
requested an impossible situation or if you are using the unstable
distribution that some required packages have not yet been created
or been moved out of Incoming.
The following information may help to resolve the situation:

The following packages have unmet dependencies:
 libsignon-glib-dev:armhf : Depends: libdbus-glib-1-dev:armhf but it is not going to be installed
                            Depends: libglib2.0-dev:armhf but it is not going to be installed
E: Unable to correct problems, you have held broken packages.
(click-ubuntu-sdk-15.04-armhf)root@liuxg:/home/liuxg# apt-get install libglib2.0-dev:armhf -f    
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following packages were automatically installed and are no longer required:
  gir1.2-freedesktop gir1.2-gdkpixbuf-2.0 gir1.2-rsvg-2.0 icu-devtools libbz2-dev
  libcairo-script-interpreter2 libcdt5 libcgraph6 libdjvulibre-dev libdjvulibre-text
  libdjvulibre21 libexif-dev libexpat1-dev libfftw3-double3 libfontconfig1-dev libfreetype6-dev
  libgraphviz-dev libgvc6 libgvpr2 libice-dev libicu-dev libilmbase-dev libilmbase6 libjasper-dev
  libjbig-dev libjpeg-dev libjpeg-turbo8-dev libjpeg8-dev liblcms2-dev liblqr-1-0 liblqr-1-0-dev
  liblzma-dev libmagick++-6-headers libmagick++-6.q16-5 libmagickcore-6-arch-config
  libmagickcore-6-headers libmagickcore-6.q16-2 libmagickcore-6.q16-2-extra
  libmagickwand-6-headers libmagickwand-6.q16-2 libopenexr-dev libopenexr6 libpathplan4
  libpcre3-dev libpcrecpp0 libpixman-1-dev libpng12-dev libpthread-stubs0-dev libsm-dev
  libtiff5-dev libtiffxx5 libwmf-dev libwmf0.2-7 libx11-dev libxau-dev libxcb-render0-dev
  libxcb-shm0-dev libxcb1-dev libxdmcp-dev libxdot4 libxext-dev libxml2-dev libxrender-dev
  libxt-dev libxt6 x11proto-render-dev zlib1g-dev
Use 'apt-get autoremove' to remove them.
The following extra packages will be installed:
  libpcre3-dev:armhf libpcrecpp0:armhf
Suggested packages:
  libglib2.0-doc:armhf
The following packages will be REMOVED:
  libcairo2-dev libgdk-pixbuf2.0-dev libglib2.0-dev libmagick++-6.q16-dev libmagick++-dev
  libmagickcore-6.q16-dev libmagickwand-6.q16-dev librsvg2-dev libzbar-dev:armhf
The following NEW packages will be installed:
  libglib2.0-dev:armhf libpcre3-dev:armhf libpcrecpp0:armhf
0 upgraded, 3 newly installed, 9 to remove and 0 not upgraded.
Need to get 1598 kB of archives.
After this operation, 14.0 MB disk space will be freed.
Do you want to continue? [Y/n] y
Get:1 http://ports.ubuntu.com/ubuntu-ports/ vivid-updates/main libpcrecpp0 armhf 2:8.35-3.3ubuntu1.1 [13.4 kB]
Get:2 http://ports.ubuntu.com/ubuntu-ports/ vivid-updates/main libpcre3-dev armhf 2:8.35-3.3ubuntu1.1 [314 kB]
Get:3 http://ports.ubuntu.com/ubuntu-ports/ vivid-updates/main libglib2.0-dev armhf 2.44.1-1ubuntu1 [1270 kB]
Fetched 1598 kB in 3s (433 kB/s)                
(Reading database ... 59571 files and directories currently installed.)
Removing libzbar-dev (0.10+doc-10build1)

...

我们可以安装上面显示的那样加上"-f"选项来安装所需要的包.

# apt-get install libglib2.0-dev:armhf -f

为了说明问题的方便,大家可以先下载我的模版Scope: https://github.com/liu-xiao-guo/goscope

在自己的Terminal下键入上述的命令,你就可以在你所在的目录下发现一个叫做“goscope”的目录:

liuxg@liuxg:~/release/goscope$ ls -l
total 68
-rwxrwxr-x 1 liuxg liuxg 2886  7月  2 12:37 build-click-package.sh
-rwxrwxr-x 1 liuxg liuxg  752  7月  2 12:37 build.sh
-rwxrwxr-x 1 liuxg liuxg 1144  7月  2 12:37 clean.sh
-rw-rw-r-- 1 liuxg liuxg 9835  7月  2 12:37 goscope.go
-rw-rw-r-- 1 liuxg liuxg  329  7月  2 12:37 goscope.ini
-rw-rw-r-- 1 liuxg liuxg  102  7月  2 12:37 goscope-security.json
-rw-rw-r-- 1 liuxg liuxg 8403  7月  2 12:37 icon.jpg
-rw-rw-r-- 1 liuxg liuxg 4851  7月  2 12:37 logo.jpg
-rw-rw-r-- 1 liuxg liuxg  435  7月  2 12:37 manifest.json
-rwxrwxr-x 1 liuxg liuxg 1293  7月  2 12:37 run.sh
-rwxrwxr-x 1 liuxg liuxg 1666  7月  2 12:37 setup-chroot-go.sh
drwxrwxr-x 3 liuxg liuxg 4096  7月  2 12:37 src

从上面的显示中,我们可以看到除了我们期望的goscope.go文件外,我们多了几个脚本来帮我们完成我们的工作。我们可以按照如下的命令把下载后的script变为可以执行的脚本

$chmod +x *.sh


首先,我们来看一下我们的build.sh。

build.sh


#!/bin/bash

#
#  usage: ./build.sh 
#         it builds project and produces the armhf click package
#         ./build.sh -d
#		  it builds the project and deploy it to the phone	
#  A developer needs to change the armhf names in the following script according tuo your project	
#

export GOPATH=`pwd`
go get launchpad.net/go-unityscopes/v2
./setup-chroot-go.sh ubuntu-sdk-15.04 vivid 
./build-click-package.sh goscope liu-xiao-guo ubuntu-sdk-15.04 vivid

if [ $# -eq 1 ]
then
	if [ $1 = "-d" ] 
	then
		echo "Start to deploy to the phone ..."
		adb push ./goscope.liu-xiao-guo/goscope.liu-xiao-guo_1.0.0_armhf.click /tmp
		adb shell "sudo -iu phablet pkcon --allow-untrusted install-local /tmp/goscope.liu-xiao-guo_1.0.0_armhf.click"
		exit 0
	fi
fi

从这个脚本中,我们可以看到当脚本执行的时候,它执行:

go get launchpad.net/go-unityscopes/v2

这个语句的作用是从上面的地址处下载最新的“ go-unityscope”版本2。当你们下载完我的模版后,其实里面已经有一个叫做“ src”的目录。里面已经包含了所有的所需要的文件。

当我们加入“ -d”选项后,这个script将会自动帮我们把脚本部署到手机中去。 记得根据自己的scope名字不同,需要修改部署部分的click包的文件名及目录名字

setup-chroot-go.sh


#!/bin/bash

# Function that executes a given command and compares its return command with a given one.
# In case the expected and the actual return codes are different it exits
# the script.
# Parameters:
#               $1: Command to be executed (string)
#               $2: Expected return code (number), Can be not defined.
function executeCommand()
{
    # gets the command
    CMD=$1
    # sets the return code expected
    # if it's not definedset it to 0
    OK_CODE=$2
    if [ -n $2 ]
    then
        OK_CODE=0
    fi
    # executes the command
    ${CMD}

    # checks if the command was executed successfully
    RET_CODE=$?
    if [ $RET_CODE -ne $OK_CODE ]
    then
        echo "ERROR executing command: \"$CMD\""
        echo "Exiting..."
        exit 1
    fi
}


# ******************************************************************************
# *                                   MAIN                                     *
# ******************************************************************************

if [ $# -ne 2 ]
then
    echo "usage: $0 FRAMEWORK_CHROOT SERIES_CHROOT"
    exit 1
fi

CHROOT=$1
SERIES=$2

sudo click chroot -aarmhf -f$CHROOT -s $SERIES create
sudo click chroot -aarmhf -f$CHROOT -s $SERIES maint apt-get install golang-go golang-go-linux-arm golang-go-dbus-dev golang-go-xdg-dev golang-gocheck-dev golang-gosqlite-dev golang-uuid-dev libgcrypt20-dev:armhf libglib2.0-dev:armhf libwhoopsie-dev:armhf libdbus-1-dev:armhf libnih-dbus-dev:armhf libsqlite3-dev:armhf crossbuild-essential-armhf

echo "Executing go get launchpad.net/go-unityscopes/v2 ...."
GOPATH=`pwd` go get launchpad.net/go-unityscopes/v2
echo "Done."



这个脚本是为了帮我们下载我们所需要的chroots,这样可以进行交叉编译armhf架构从而部署到我们的手机上。如果大家已经安装好自己的Ubuntu SDK,并且已经安装好所需要的armhf chroot,这个script将不会下载任何的东西。

build-click-package.sh


#/bin/bash

# Function that executes a given command and compares its return command with a given one.
# In case the expected and the actual return codes are different it exits
# the script.
# Parameters:
#               $1: Command to be executed (string)
#               $2: Expected return code (number), may be undefined.
function executeCommand()
{
    # gets the command
    CMD=$1
    # sets the return code expected
    # if it's not definedset it to 0
    OK_CODE=$2
    if [ -n $2 ]
    then
        OK_CODE=0
    fi
    # executes the command
    eval ${CMD}

    # checks if the command was executed successfully
    RET_CODE=$?
    if [ $RET_CODE -ne $OK_CODE ]
    then
	echo ""
        echo "ERROR executing command: \"$CMD\""
        echo "Exiting..."
        exit 1
    fi
}

# ******************************************************************************
# *                                   MAIN                                     *
# ******************************************************************************

if [ $# -ne 4 ]
then
    echo "usage: $0 SCOPE_NAME DEVELOPER_NAME FRAMEWORK_CHROOT SERIES_CHROOT"
    exit 1
fi

SCOPE_NAME=$1
DEVELOPER_NAME=$2
CHROOT=$3
SERIES=$4

CURRENT_DIR=`pwd`

FILE_NAME="${SCOPE_NAME}.${DEVELOPER_NAME}"
MANIFEST_NAME="${SCOPE_NAME}.${DEVELOPER_NAME}"

echo -n "Removing ${FILE_NAME} directory... "
executeCommand "rm -rf ./${FILE_NAME}"
echo "Done"

echo -n "Creating clean ${FILE_NAME} directory... "
executeCommand "mkdir -p ${FILE_NAME}/${FILE_NAME}"
echo "Done"

echo -n "Copying scope ini file... "
executeCommand "cp $SCOPE_NAME.ini ${FILE_NAME}/${FILE_NAME}/${FILE_NAME}_${SCOPE_NAME}.ini"
echo "Done"

echo -n "Copying the logo file ... "
executeCommand "cp logo.jpg ${FILE_NAME}/${FILE_NAME}/logo.jpg"
echo "Done"

echo -n "Copying the icon file ... "
executeCommand "cp icon.jpg ${FILE_NAME}/${FILE_NAME}/icon.jpg"
echo "Done"

echo -n "Setting scope name in ini file..."
executeCommand 'sed -i "s/%SCOPE_NAME%/${FILE_NAME}/g" ${FILE_NAME}/${FILE_NAME}/${FILE_NAME}_${SCOPE_NAME}.ini'
echo "Done"

echo -n "Copying scope json files... "
executeCommand "cp *.json ${FILE_NAME}/"
echo "Done"

echo -n "Setting scope name in manifest file..."
executeCommand 'sed -i "s/%SCOPE_NAME%/${MANIFEST_NAME}/g" ${FILE_NAME}/manifest.json'
echo "Done"

echo -n "Cross compiling ${FILE_NAME}..."
executeCommand "click chroot -aarmhf -f$CHROOT -s $SERIES run CGO_ENABLED=1 GOARCH=arm GOARM=7 PKG_CONFIG_LIBDIR=/usr/lib/arm-linux-gnueabihf/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfig GOPATH=/usr/share/gocode/:$GOPATH CC=arm-linux-gnueabihf-gcc CXX=arm-linux-gnueabihf-g++ go build -ldflags '-extld=arm-linux-gnueabihf-g++' -o ${FILE_NAME}/${FILE_NAME}/${FILE_NAME}"
echo "Done"

executeCommand "cd ./${FILE_NAME}"

echo -n "Building click package ... "
executeCommand "click build ./"
echo "Done"

executeCommand "cd .."

我们可以通过这个脚本来交叉编译我们的goscope armhf click包。使用时,就像上面的 build.sh中展示的那样:

$./build-click-package.sh goscope liu-xiao-guo ubuntu-sdk-15.04 vivid

这里,我们把项目的Scope名,开发者的名字,framework 及Ubuntud的系列号传入即可。


run.sh


#!/bin/bash

#
# This is the script to build and run the scope on desktop environment. 
# A developer needs to change the following variable according to your projectt
# 		SCOPE_NAME=goscope
# 		DEVELOPER_NAME=liu-xiao-guo
#
#

function executeCommand()
{
    # gets the command
    CMD=$1
    # sets the return code expected
    # if it's not definedset it to 0
    OK_CODE=$2
    if [ -n $2 ]
    then
        OK_CODE=0
    fi
    # executes the command
    eval ${CMD}

    # checks if the command was executed successfully
    RET_CODE=$?
    if [ $RET_CODE -ne $OK_CODE ]
    then
	echo ""
        echo "ERROR executing command: \"$CMD\""
        echo "Exiting..."
        exit 1
    fi
}

export GOPATH=`pwd`

SCOPE_NAME=goscope
DEVELOPER_NAME=liu-xiao-guo

FILE_NAME="${SCOPE_NAME}.${DEVELOPER_NAME}"

echo -n "Removing ${FILE_NAME} directory... "
executeCommand "rm -rf ./${FILE_NAME}"
echo "Done"

echo -n "Copying scope ini file... "
executeCommand "cp $SCOPE_NAME.ini ${FILE_NAME}_${SCOPE_NAME}.ini"
echo "Done"

echo -n "Setting scope name in ini file..."
executeCommand 'sed -i "s/%SCOPE_NAME%/${FILE_NAME}/g" ${FILE_NAME}_${SCOPE_NAME}.ini'
echo "Done"

echo -n "Building the scope"
executeCommand "go build -o ${FILE_NAME}"

unity-scope-tool ${FILE_NAME}_${SCOPE_NAME}.ini


这个脚本是为了把我们的Scope在Desktop的环境中进行编译,并使用unity-scope-tool来启动我们的Scope:





clean.sh


#!/bin/bash

#
# This file cleans all of the intermediate files produced during the compilation. For each project
# a developer needs to customize the variables
#     SCOPE_NAME
# 	  DEVELOPER_NAME
#
#

function executeCommand()
{
    # gets the command
    CMD=$1
    # sets the return code expected
    # if it's not definedset it to 0
    OK_CODE=$2
    if [ -n $2 ]
    then
        OK_CODE=0
    fi
    # executes the command
    eval ${CMD}

    # checks if the command was executed successfully
    RET_CODE=$?
    if [ $RET_CODE -ne $OK_CODE ]
    then
	echo ""
        echo "ERROR executing command: \"$CMD\""
        echo "Exiting..."
        exit 1
    fi
}

SCOPE_NAME=goscope
DEVELOPER_NAME=liu-xiao-guo

FILE_NAME="${SCOPE_NAME}.${DEVELOPER_NAME}"

echo -n "Removing ${FILE_NAME} directory... "
executeCommand "rm -rf ./${FILE_NAME}"
echo "Done"

echo -n "Removing ${FILE_NAME}_${SCOPE_NAME}.ini ..."
executeCommand "rm -f ${FILE_NAME}_${SCOPE_NAME}.ini"
echo "Done"

echo -n "Removing ${FILE_NAME} ..."
executeCommand "rm -f ${FILE_NAME}"
echo "Done"

echo -n "Removing pkg directory ..."
executeCommand "rm -rf pkg"
echo "Done"


这个脚本是为了我们能够删除我们在编译过程中所产生任何的中间文件。

goscope.go


package main

import (
	"launchpad.net/go-unityscopes/v2"
	"log"
	"encoding/json"
	"net/url"
	"net/http"
)


const searchCategoryYellow = `{
    "schema-version" : 1,
    "template" : {
        "category-layout" : "vertical-journal",
        "card-layout": "horizontal",
        "card-size": "small",
        "collapsed-rows": 0
     },
    "components" : {
        "title" : "title",
        "subtitle":"subtitle",
        "summary":"summary",
        "art":{
        	"field": "art",
       		"aspect-ratio": 1
        }
    }
}`

const searchCategoryTemplate = `{
    "schema-version" : 1,  
    "template" : {  
        "category-layout" : "carousel",  
        "card-size": "large",  
        "overlay" : true  
    },  
    "components" : {  
        "title" : "title",  
        "art" : {  
            "field": "art",  
            "aspect-ratio": 1.6,  
            "fill-mode": "fit"  
        }  
    }  
}`

// SCOPE ***********************************************************************

var scope_interface scopes.Scope

type MyScope struct {
	BaseURI string
	Key     string
	URI		string
	Dir     string	
	base *scopes.ScopeBase
}

type WathereResponse struct {
	WeatherList []Weather `json:"results"`
	Date string `json:"date"`
}

type Weather struct {
	CurrentCity string `json:"currentCity"`
	Pm25 string `json:"pm25"`
	IndexList []Index `json:"index"`
	Weather_datalist []Weather_data `json:"weather_data"`
}

type Index struct {
	Title string `json:"title"`
	Zs string `json:"zs"`
	Tipt string `json:"tipt"`
	Des string `json:"des"`
}

type Weather_data struct {
	Date string `json:"date"`
	DayPictureUrl string `json:"dayPictureUrl"`
	NightPictureUrl string `json:"nightPictureUrl"`
	Weather string `json:"weather"`
	Wind string `json:"wind"`
	Temperature string `json:"temperature"`
}

func (s *MyScope) buildUrl(url2 string, params map[string]string) string {
	query := make(url.Values)
	for key, value := range params {
		query.Set(key, value)
	}
	log.Println(url2 + query.Encode())
	return url2 + query.Encode()
}

// This is used to get results from a webservice
func (s *MyScope) get(url string, params map[string]string, result interface{}) error {
	resp, err := http.Get(s.buildUrl(url, params))
	if err != nil {
		return err
	}
	defer resp.Body.Close()
	decoder := json.NewDecoder(resp.Body)
	return decoder.Decode(result)
}

func (s *MyScope) Search(q *scopes.CannedQuery, metadata *scopes.SearchMetadata, reply *scopes.SearchReply, cancelled <-chan bool) error {
	root_department := s.CreateDepartments(q, metadata, reply)
	reply.RegisterDepartments(root_department)

	query := q.QueryString()
	log.Println(query)	
	
	// Try to get the city name
	loc := metadata.Location()
	city := loc.City;
	log.Println("city: ", city)
	
	if query == "" {
		if q.DepartmentID() == "" {
			query = city
		} else {
			query = q.DepartmentID()
		}			
	} 
	
	log.Println("query: ", query)
	
	var response WathereResponse
	
	if err := s.get(s.BaseURI, map[string]string{"location": query, "ak": s.Key, "output": "json"}, &response); err != nil {
		return err
	} else {
		log.Println("there is no error!")
	}
	
	// log.Println(response)
	date := response.Date;
	log.Println("date: ", date)
	
	var cat *scopes.Category;
	
	if len(q.QueryString()) == 0 && q.DepartmentID() == "" {
		cat = reply.RegisterCategory("weather", query, "", searchCategoryTemplate)
	} else {
		cat = reply.RegisterCategory("weather", "", "", searchCategoryTemplate)
	}
		
	
	for _, data := range response.WeatherList {
		result := scopes.NewCategorisedResult(cat)
		result.SetURI(s.URI)

//		log.Println("Current city:", data.CurrentCity)
//		log.Println("PM25: ", data.Pm25)
		
		var yellocalendar string = ""
		for _, index := range data.IndexList {
//			log.Println("title: ", index.Title)
//			log.Println("zs: ", index.Zs)
//			log.Println("tipt: ", index.Tipt)
//			log.Println("Des: ", index.Des)
			
			yellocalendar += index.Title + " "
			yellocalendar += index.Zs + " "
			yellocalendar += index.Tipt + " "
			yellocalendar += index.Des
		}
		
		for i, weather := range data.Weather_datalist {
//			log.Println("date: ", weather.Date)
//			log.Println("dayPictureUrl: ", weather.DayPictureUrl)
//			log.Println("nightPictureUrl: ", weather.NightPictureUrl)
//			log.Println("weather: ",weather.Weather)
//			log.Println("wind: ", weather.Wind)
//			log.Println("temperature: ", weather.Temperature)
			
			result.SetTitle(weather.Date)
			result.SetArt(weather.DayPictureUrl)
			result.Set("wind", weather.Wind)
			result.Set("weather", weather.Weather)
			result.Set("temperature", weather.Temperature)
			
			if err := reply.Push(result); err != nil {
				return err
			}
			
			result.SetArt(weather.NightPictureUrl)
			if err := reply.Push(result); err != nil {
				return err
			}			
			
			// Push the yellow calender now
			if i == 0  {
				cat1 := reply.RegisterCategory("weather1", "今天天气", "", searchCategoryYellow)
				result1 := scopes.NewCategorisedResult(cat1)								
				
				result1.SetURI(s.URI)
				result1.SetTitle(date)
				result1.SetArt(weather.DayPictureUrl)
				result1.Set("subtitle", weather.Weather + " " + weather.Wind + " " +  weather.Temperature + "  PMI: " +  data.Pm25)
				result1.Set("summary", yellocalendar)
				
				if err := reply.Push(result1); err != nil {
					return err
				}					
			}		
		}		
	}
	
	return nil
}

func (s *MyScope) Preview(result *scopes.Result, metadata *scopes.ActionMetadata, reply *scopes.PreviewReply, cancelled <-chan bool) error {
	layout1col := scopes.NewColumnLayout(1)
	layout2col := scopes.NewColumnLayout(2)
	layout3col := scopes.NewColumnLayout(3)

	// Single cyolumn layout
	layout1col.AddColumn("header", "image",  "wind", "weather", "temperature", "summary", "actions")

	// Two column layout
	layout2col.AddColumn("header")
	layout2col.AddColumn("image", "wind", "weather", "temperature", "summary", "actions")

	// Three cokumn layout
	layout3col.AddColumn("header")
	layout3col.AddColumn("image", "wind", "weather", "temperature","summary", "actions")
	layout3col.AddColumn()

	// Register the layouts we just created
	reply.RegisterLayout(layout1col, layout2col, layout3col)

	header := scopes.NewPreviewWidget("header", "header")

	// It has title and a subtitle properties
	header.AddAttributeMapping("title", "title")
	header.AddAttributeMapping("subtitle", "subtitle")

	// Define the image section
	image := scopes.NewPreviewWidget("image", "image")
	// It has a single source property, mapped to the result's art property
	image.AddAttributeMapping("source", "art")

	// Define the summary section
	description := scopes.NewPreviewWidget("summary", "text")
	description.AddAttributeMapping("text", "summary")

	wind := scopes.NewPreviewWidget("wind", "text")
	wind.AddAttributeMapping("text", "wind")

	weather := scopes.NewPreviewWidget("weather", "text")
	weather.AddAttributeMapping("text", "weather")

	temperature := scopes.NewPreviewWidget("temperature", "text")
	temperature.AddAttributeMapping("text", "temperature")

	// build variant map.
	var uri string

	if err := result.Get("uri", &uri); err != nil {
		log.Println(err)
	}

	tuple1 := make(map[string]interface{})
	tuple1["id"] = "open"
	tuple1["label"] = "Open"
	tuple1["uri"] = uri

	actions := scopes.NewPreviewWidget("actions", "actions")
	actions.AddAttributeValue("actions", []interface{}{tuple1})

	var summary string
	if err := result.Get("summary", &summary); err != nil {
		log.Println(err)
	}

	if len(summary) > 0 {
		reply.PushWidgets(header, image, description, actions)
	} else {
		reply.PushWidgets(header, image, wind, weather, temperature, actions)
	}

	return nil
}

func (s *MyScope) SetScopeBase(base *scopes.ScopeBase) {
	s.base = base
}


func (s *MyScope) GetSubdepartments1(query *scopes.CannedQuery,
	metadata *scopes.SearchMetadata,
	reply *scopes.SearchReply) *scopes.Department {
	active_dep, err := scopes.NewDepartment("wuhan", query, "湖北")
	
	if err == nil {
//		active_dep.SetAlternateLabel("Rock Music Alt")
		department, _ := scopes.NewDepartment("武汉", query, "武汉")
		active_dep.AddSubdepartment(department)

		department2, _ := scopes.NewDepartment("宜昌", query, "宜昌")
		active_dep.AddSubdepartment(department2)
				
		department3, _ := scopes.NewDepartment("随州", query, "随州")
		active_dep.AddSubdepartment(department3)
	}

	return active_dep
}

func (s *MyScope) GetSubdepartments2(query *scopes.CannedQuery,
	metadata *scopes.SearchMetadata,
	reply *scopes.SearchReply) *scopes.Department {
	active_dep, err := scopes.NewDepartment("changsha", query, "湖南")
	
	if err == nil {
		department, _ := scopes.NewDepartment("长沙", query, "长沙")
		active_dep.AddSubdepartment(department)

		department2, _ := scopes.NewDepartment("株洲", query, "株洲")
		active_dep.AddSubdepartment(department2)
	}

	return active_dep
}

func (s *MyScope) CreateDepartments(query *scopes.CannedQuery,
	metadata *scopes.SearchMetadata,
	reply *scopes.SearchReply) *scopes.Department {
		
	department, _ := scopes.NewDepartment("", query, "选择地点")

	dept1 := s.GetSubdepartments1(query, metadata, reply)
	if dept1 != nil {
		department.AddSubdepartment(dept1)
	}

	dept2 := s.GetSubdepartments2(query, metadata, reply)
	if dept2 != nil {
		department.AddSubdepartment(dept2)
	}

	return department
}

// MAIN ************************************************************************

func main() {
	scope := &MyScope {
		BaseURI: "http://api.map.baidu.com/telematics/v3/weather?",
		Key:     "DdzwVcsGMoYpeg5xQlAFrXQt",
		URI: 	 "http://www.weather.com.cn/html/weather/101010100.shtml",
		Dir:     "",
	}
	
	scope_interface = scope
	
	if err := scopes.Run(scope); err != nil {
		log.Fatalln(err)
	}
}

这是我们的goscope的go语言程序设计。在这个goscope里,我们使用了百度的天气API来显示天气的数据。整个scope的设计其实和C++的Scope设计比较相似,但是显得更加简洁明了。

我们可以通过如下的命令来把我们的Scope打包并部署到我们的手机上:

$./build.sh -d

如果我们只想得到armhf的click包,我们可以不需要“ -d”参数。在手机上的运行情况:



    


如何运行Scope


我们可以在Terminal中:

[plain]  view plain copy
  1. $chmod +x *.sh  
通过上述命令来使得.sh文件变为可以执行的文件

[plain]  view plain copy
  1. $./run.sh  
通过上面的脚本执行,在Desktop上运行我们的Scope
[plain]  view plain copy
  1. $./build.sh -d  

通过我们上面的脚本执行,可以编译goscope,并部署到手机中去

[plain]  view plain copy
  1. $./clean.sh  
通过上面的脚本执行,清除所有的编译的中间文件
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值