From abce15dd1a0e9f28b953179c4d9b6d27766685e8 Mon Sep 17 00:00:00 2001
From: Paolo Capriotti
Date: Mon, 16 Mar 2009 18:59:09 +0100
Subject: [PATCH] More work on the connection class.
---
.gitignore | 2 +
lib/console.rb | 45 +++++++++++++
lib/games/chess/chess.rb | 1 +
lib/ics/connection.rb | 168 ++++++++++++++++++++++++----------------------
lib/ics/driver.rb | 78 +++++++++++++++++++--
lib/ics/example/main.rb | 23 +++++++
lib/ics/example/window.rb | 28 ++++++++
lib/ics/protocol.rb | 7 +-
lib/ics/style12.rb | 3 +
lib/qtutils.rb | 18 ++++-
10 files changed, 280 insertions(+), 93 deletions(-)
create mode 100644 lib/console.rb
rewrite lib/ics/connection.rb (82%)
create mode 100644 lib/ics/example/main.rb
create mode 100644 lib/ics/example/window.rb
diff --git a/.gitignore b/.gitignore
index b25c15b..54e43cb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,3 @@
*~
+.#*
+\#*#
diff --git a/lib/console.rb b/lib/console.rb
new file mode 100644
index 0000000..27fcbf9
--- /dev/null
+++ b/lib/console.rb
@@ -0,0 +1,45 @@
+require 'qtutils'
+
+class Console < Qt::Widget
+ include Observable
+
+ def initialize(parent)
+ super
+
+ layout = Qt::VBoxLayout.new
+ @output = Qt::TextEdit.new(self)
+ @input = Qt::LineEdit.new(self)
+
+ layout.add_widget(@output)
+ layout.add_widget(@input)
+ setLayout layout
+
+ @output.read_only = true
+ f = @output.font
+ f.family = 'monospace'
+ @output.font = f
+ @output.current_font = f
+ @bold_font = f
+ @bold_font.bold = true
+
+ @input.on(:returnPressed) do
+ text = @input.text
+ with_font(@bold_font) do
+ @output.append text
+ end
+ @input.text = ''
+ fire :input => text
+ end
+ end
+
+ def with_font(font)
+ old = @output.current_font
+ @output.current_font = font
+ yield
+ @output.current_font = old
+ end
+
+ def append(text)
+ @output.append(text)
+ end
+end
diff --git a/lib/games/chess/chess.rb b/lib/games/chess/chess.rb
index a2d5827..a67474f 100644
--- a/lib/games/chess/chess.rb
+++ b/lib/games/chess/chess.rb
@@ -21,6 +21,7 @@ Game.add :chess, Game.new(
:piece => Piece,
:players => [:white, :black])
+
Game.add :chess5x5, Game.get(:chess).extend(
:size => Point.new(5, 5))
diff --git a/lib/ics/connection.rb b/lib/ics/connection.rb
dissimilarity index 82%
index 49234dc..b65fbf8 100644
--- a/lib/ics/connection.rb
+++ b/lib/ics/connection.rb
@@ -1,81 +1,87 @@
-require 'socket'
-
-module ICS
-
-#
-# A connection to an ICS server
-#
-class Connection
- attr_accessor :debug
-
- def initialize(host, port, protocol)
- @protocol = protocol
- @create_socket = lambda do
- puts "connecting to #{host}:#{port}"
- TCPSocket.new(host, port)
- end
-
- @state = :stopped
- @stop_flag = false
- @last_chunk = ''
- @ignore_pending = false
- @debug = false
- end
-
- def start
- @stop_flag = false
- @socket = @create_socket[]
-
- Thread.new do
- begin
- loop do
- break if @stop_flag
- data = @socket.recv(1024)
- break unless data
- read_chunk data
- end
-
- @state = :stopped
- rescue Exception => e
- puts "Connection thread died!!"
- puts e
- puts e.backtrace
- end
- end
- end
-
- def stop
- @stop_flag = true
- end
-
- def send(data)
- puts "> #{data}" if @debug
- @socket.print(data + "\n\r")
- end
-
- private
-
- def read_chunk(data)
- return if data.empty?
- chunks = data.split("\n\r", -1) # don't omit trailing empty fields
-
- i = if @ignore_pending
- 1
- else
- chunks[0] = @last_chunk + chunks[0]
- 0
- end
- chunks[i...-1].each do |c|
- line = c.chomp
- processed = @protocol.process line
- puts "< #{line}" if @debug
- end
- if not chunks.last.empty?
- @last_chunk = chunks.last
- processed = @protocol.process_partial chunks.last
- @last_chunk = '' if processed
- end
- end
-end
-
-end
+require 'qtutils'
+
+module ICS
+
+#
+# A connection to an ICS server
+#
+class Connection < Qt::Object
+ attr_accessor :debug
+
+ signals :hostFound, :established,
+ 'receivedLine(QString, int)',
+ 'receivedText(QString, int)'
+
+ def initialize(host, port)
+ super nil
+
+ @create_socket = lambda do
+ puts "connecting to #{host}:#{port}"
+ s = Qt::TcpSocket.new(self)
+ connect(s, SIGNAL(:hostFound), self, SIGNAL(:hostFound))
+ s.connect(s, SIGNAL(:connected), self, SIGNAL(:established))
+ s.on(:readyRead) { process_line }
+ s.connect_to_host(host, port)
+ s
+ end
+ end
+
+ def process_line
+ puts "processing line"
+ unless @socket
+ puts "no socket!"
+ return
+ end
+
+ while @socket.can_read_line
+ line = @socket.read_line.to_s
+ line = @buffer + line.gsub("\r", '')
+ emit receivedLine(line, @buffer.size)
+ @buffer = ''
+ end
+
+ if (size = @socket.bytes_available) > 0
+ data = @socket.read_all
+ offset = @buffer.size
+ @buffer += data.to_s.gsub("\r", '')
+ emit receivedText(@buffer, offset)
+ end
+
+ end
+
+ def start
+ @socket = @create_socket.call
+ @connected = true
+ @buffer = ''
+ end
+
+ def stop
+ end
+
+ def send_text(text)
+ puts "> #{text}" if @debug
+ unless @connected
+ @unsent_text += @text + "\n"
+ return
+ end
+
+ unless @socket
+ puts "no socket!"
+ return
+ end
+
+ process_line
+ os = Qt::TextStream(@socket)
+ os << text + "\n"
+ end
+
+ def on_received_line(&blk)
+ connect(self, SIGNAL('receivedLine(QString, int)'), &blk)
+ end
+
+ def on_received_text(&blk)
+ connect(self, SIGNAL('receivedText(QString, int)'), &blk)
+ end
+end
+
+end
diff --git a/lib/ics/driver.rb b/lib/ics/driver.rb
index cf20298..61dcc25 100644
--- a/lib/ics/driver.rb
+++ b/lib/ics/driver.rb
@@ -1,19 +1,85 @@
$:.unshift(File.join(File.dirname(__FILE__), '..'))
require 'qtutils'
+require 'board/table'
+require 'themes/loader'
+require 'games/chess/chess'
+require 'controller'
+require 'history'
require 'ics/connection'
require 'ics/protocol'
+require 'console'
protocol = ICS::Protocol.new
c = ICS::Connection.new('freechess.org', 5000, protocol)
protocol.add_observer ICS::AuthModule.new(c, 'guest', '')
protocol.add_observer ICS::StartupModule.new(c)
-protocol.observe :text do |line|
- puts line
+
+description = "KDE Board Game Suite"
+version = "1.5"
+about = KDE::AboutData.new("tagua", "Tagua", KDE.ki18n("Tagua"),
+ version, KDE.ki18n(description),KDE::AboutData::License_GPL,KDE.ki18n("(C) 2003 whoever the author is"))
+
+about.addAuthor(KDE.ki18n("author1"), KDE.ki18n("whatever they did"), "email@somedomain")
+about.addAuthor(KDE.ki18n("author2"), KDE.ki18n("they did something else"), "another@email.address")
+
+KDE::CmdLineArgs.init(ARGV, about)
+
+app = KDE::Application.new
+
+class Scene < Qt::GraphicsScene
+ def initialize
+ super
+ end
end
-# c.debug = true
-c.start
-while line = gets
- c.send line
+theme_loader = ThemeLoader.new
+theme = Struct.new(:pieces, :background).new
+theme.pieces = theme_loader.get('Celtic')
+theme.background = theme_loader.get('Default', Point.new(8, 8))
+
+chess = Chess::Game.new
+
+scene = Qt::GraphicsScene.new
+
+state = chess.new_state
+state.setup
+
+board = Board.new(scene, theme, chess, state)
+
+
+table = Table.new(scene, board)
+table.size = Qt::Size.new(500, 500)
+
+history = History.new(state)
+controller = Controller.new(board, history)
+
+table.show
+
+console = Console.new(nil)
+console.show
+
+protocol.observe :text do |text|
+ console.run_later { console.append(text) }
+end
+
+console.observe :input do |text|
+ c.send(text)
end
+board.observe :new_move do |data|
+ move = data[:move]
+ m = ('a'[0] + move.src.x).chr +
+ (8 - move.src.y).to_s +
+ ('a'[0] + move.dst.x).chr +
+ (8 - move.dst.y).to_s
+ puts m
+ c.send m
+end
+
+protocol.observe :style12 do |style12|
+ puts style12.inspect
+end
+
+c.start
+
+app.exec
diff --git a/lib/ics/example/main.rb b/lib/ics/example/main.rb
new file mode 100644
index 0000000..549e0e8
--- /dev/null
+++ b/lib/ics/example/main.rb
@@ -0,0 +1,23 @@
+require 'qtutils'
+require 'ics/connection'
+require 'ics/example/window'
+
+description = "Connection example"
+version = "0.1"
+about = KDE::AboutData.new("connection",
+ "Connection Example",
+ KDE.ki18n("Connection Example"),
+ version,
+ KDE.ki18n(description),
+ KDE::AboutData::License_GPL,
+ KDE.ki18n("(C) 2009 Paolo Capriotti"))
+
+KDE::CmdLineArgs.init(ARGV, about)
+
+app = KDE::Application.new
+
+w = Window.new
+w.show
+
+app.exec
+
diff --git a/lib/ics/example/window.rb b/lib/ics/example/window.rb
new file mode 100644
index 0000000..631af76
--- /dev/null
+++ b/lib/ics/example/window.rb
@@ -0,0 +1,28 @@
+class Window < Qt::Widget
+ def initialize(parent = nil)
+ super parent
+
+ quit = Qt::PushButton.new("Quit", self)
+ connect(quit, SIGNAL(:clicked),
+ self, SLOT(:close))
+
+ start_button = Qt::PushButton.new("Start", self)
+ start_button.on(:clicked) { start }
+
+ layout = Qt::VBoxLayout.new
+ layout.add_widget start_button
+ layout.add_widget quit
+ set_layout layout
+
+ @conn = ICS::Connection.new('freechess.org', 5000)
+ r = lambda do |text, off|
+ puts "received (#{off}): #{text}"
+ end
+ @conn.on_received_line(&r)
+ @conn.on_received_text(&r)
+ end
+
+ def start
+ @conn.start
+ end
+end
diff --git a/lib/ics/protocol.rb b/lib/ics/protocol.rb
index 1414af0..3d335c4 100644
--- a/lib/ics/protocol.rb
+++ b/lib/ics/protocol.rb
@@ -9,9 +9,9 @@ class Protocol
@@actions = []
@@partial_actions = []
GAME_TYPES = {
- :standard => :chess,
- :blitz => :chess,
- :lightning => :chess }
+ 'standard' => :chess,
+ 'blitz' => :chess,
+ 'lightning' => :chess }
def self.on(regex, type = :full, &blk)
# ugly hack to work around the missing
@@ -161,7 +161,6 @@ class StartupModule
def on_prompt
if not @startup
- puts "starting up!"
@connection.send("alias $ @");
@connection.send("iset startpos 1");
@connection.send("iset ms 1");
diff --git a/lib/ics/style12.rb b/lib/ics/style12.rb
index 78ac99c..6f3521e 100644
--- a/lib/ics/style12.rb
+++ b/lib/ics/style12.rb
@@ -1,4 +1,5 @@
require 'games/games'
+require 'ics/icsapi'
module ICS
@@ -63,11 +64,13 @@ class Style12
def self.from_match(match, games)
game_number = match[GAME_NUMBER].to_i
current_game = games[game_number]
+ puts "current_game = #{current_game.inspect}"
game = if current_game
current_game[:game]
else
Game.dummy
end
+ puts "game = #{game}"
icsapi = ICSApi.new(game)
state =
diff --git a/lib/qtutils.rb b/lib/qtutils.rb
index d7edaa0..6e279c5 100644
--- a/lib/qtutils.rb
+++ b/lib/qtutils.rb
@@ -106,9 +106,17 @@ class Qt::Pixmap
end
end
-class Qt::Object
+class Qt::Base
def on(sign, &blk)
- connect(SIGNAL(sign.to_s + '()', &blk))
+ connect(SIGNAL(sign.to_s + '()'), &blk)
+ end
+
+ def in(interval, &blk)
+ Qt::Timer.in(interval, self, &blk)
+ end
+
+ def run_later(&blk)
+ self.in(0, &blk)
end
end
@@ -125,4 +133,10 @@ class Qt::Timer
# that it is not garbage collected
timer
end
+
+ def self.in(interval, target = nil, &blk)
+ single_shot(interval,
+ Qt::BlockInvocation.new(target, blk, 'invoke()'),
+ SLOT('invoke()'))
+ end
end
--
2.11.4.GIT