Keep move list selection synchronized.
[kaya.git] / lib / mainwindow.rb
blob25803ddb5f394549afa351211d8f99745648c967
1 require 'qtutils'
2 require 'board/board'
3 require 'board/pool'
4 require 'board/table'
5 require 'board/scene'
6 require 'history'
7 require 'controller'
9 require 'interaction/match'
11 require 'ics/protocol'
12 require 'ics/match_handler'
13 require 'ics/connection'
14 require 'console'
16 require 'filewriter'
18 class MainWindow < KDE::XmlGuiWindow
19   include ActionHandler
20   include FileWriter
21   
22   slots :load_game
24   def initialize(loader, game)
25     super nil
26     
27     @loader = loader
28     @default_game = game
29     
30     load_board(game)
31     
32     setup_actions
33     setupGUI
34   end
36 private
38   def setup_actions
39     std_action(:open_new) { new_game(Match.new(@default_game)) }
40     std_action(:open) { load_game }
41     std_action :quit, :slot => :close
42     std_action(:save) { save_game }
43     std_action(:saveAs) { save_game_as }
44     
45     regular_action :back, :icon => 'go-previous', 
46                           :text => KDE.i18n("&Back") do
47       @controller.back
48     end
49     regular_action :forward, :icon => 'go-next', 
50                              :text => KDE.i18n("&Forward") do
51       @controller.forward
52     end
53     regular_action :connect, :icon => 'network-connect',
54                              :text => KDE.i18n("&Connect to ICS") do
55       connect_to_ics
56     end
57     regular_action :disconnect, :icon => 'network-disconnect',
58                                 :text => KDE.i18n("&Disconnect from ICS") do
59       if @connection
60         @connection.close
61         @connection = nil
62       end
63     end
64     
65     regular_action :flip, :icon => 'object-rotate-left',
66                           :text => KDE.i18n("F&lip") do
67       @table.flip(! @table.flipped?)
68     end
69                   
70   end
71   
72   def load_board(game)
73     scene = Scene.new
74     @table = Table.new scene, @loader, self
75     @controller = Controller.new(@table)
77     movelist = @loader.get_matching(%w(movelist)).new(@controller)
78     movelist_dock = Qt::DockWidget.new(self)
79     movelist_dock.widget = movelist
80     movelist_dock.window_title = KDE.i18n("History")
81     movelist_dock.object_name = "movelist"
82     add_dock_widget(Qt::LeftDockWidgetArea, movelist_dock, Qt::Vertical)
83     movelist_dock.show
85     @console = Console.new(nil)
86     console_dock = Qt::DockWidget.new(self)                                                      
87     console_dock.widget = @console                                                             
88     console_dock.focus_proxy = @console                                                        
89     console_dock.window_title = KDE.i18n("Console")                                              
90     console_dock.object_name = "console"                                                         
91     add_dock_widget(Qt::BottomDockWidgetArea, console_dock, Qt::Horizontal)                      
92     console_dock.window_flags = console_dock.window_flags & ~Qt::WindowStaysOnTopHint            
93     console_dock.show                                                                            
95     new_game(Match.new(game))
96     
97     self.central_widget = @table
98   end
99   
100   def connect_to_ics
101     protocol = ICS::Protocol.new(:debug)
102     @connection = ICS::Connection.new('freechess.org', 23)
103     protocol.add_observer ICS::AuthModule.new(@connection, 'ujjajja', '')
104     protocol.add_observer ICS::StartupModule.new(@connection)
105     protocol.link_to @connection
107     protocol.observe :text do |text|
108       @console.append(text)
109     end
111     @console.observe :input do |text|
112       @connection.send_text text
113     end
115     handler = ICS::MatchHandler.new(@controller, protocol)
117     protocol.observe :creating_game do |data|
118       puts "CREATING GAME: #{data.inspect}"
119     end
121     @connection.start
122   end
123   
124   def new_game(match)
125     @controller.color = match.game.players.first
126     opponents = match.game.players[1..-1].map do |color|
127       DummyPlayer.new(color)
128     end
129     opponents.each do |p| 
130       @controller.add_controlled_player(p)
131     end
133     @controller.controlled.values.each do |p|
134       match.register(p)
135     end
136     @controller.controlled.values.each do |p|
137       match.start(p)
138     end
139     @controller.reset(match)
140   end
141   
142   def load_game
143     url = KDE::FileDialog.get_open_url(KDE::Url.new, '*.*', self,
144       KDE.i18n("Open game"))
145     unless url.is_empty
146       # find readers
147       ext = File.extname(url.path)[1..-1]
148       return unless ext
149       readers = Game.to_enum.find_all do |_, game|
150         game.respond_to?(:game_extensions) and
151         game.game_extensions.include?(ext)
152       end.map do |_, game|
153         [game, game.game_reader.new]
154       end
155       
156       if readers.empty?
157         warn "Unknown file extension #{ext}"
158         return
159       end
160       
161       tmp_file = ""
162       return unless KIO::NetAccess.download(url, tmp_file, self)
164       history = nil
165       game = nil
166       info = nil
167       
168       readers.each do |g, reader|
169         begin
170           data = File.open(tmp_file) do |f|
171             f.read
172           end
173           i = {}
174           history = reader.read(data, i)
175           game = g
176           info = i
177           break
178         rescue ParseException
179         end
180       end
181       
182       unless history
183         warn "Could not load file #{url.path}"
184       end
185       
186       # create game
187       match = Match.new(game)
188       @controller.color = match.game.players.first
189       opponents = match.game.players[1..-1].map do |color|
190         DummyPlayer.new(color)
191       end
192       opponents.each do |p| 
193         @controller.add_controlled_player(p)
194       end
196       @controller.controlled.values.each do |p|
197         match.register(p)
198       end
199       @controller.controlled.values.each do |p|
200         match.start(p)
201       end
202       match.history = history
203       match.add_info(info)
204       match.url = url
205       @controller.reset(match)
206     end
207   end
208   
209   def save_game_as
210     match = @controller.match
211     if match
212       pattern = match.game.game_extensions.map{|ext| "*.#{ext}"}.join(' ')
213       url = KDE::FileDialog.get_save_url(
214         KDE::Url.new, pattern, self, KDE.i18n("Save game"))
215       match.url = write_game(url)
216     end
217   end
218   
219   def save_game
220     match = @controller.match
221     if match
222       if match.url
223         write_game
224       else
225         save_game_as
226       end
227     end
228   end
229   
230   def write_game(url = nil)
231     match = @controller.match
232     if match
233       url ||= match.url
234       writer = match.game.game_writer.new
235       info = match.info
236       info[:players] = info[:players].inject({}) do |res, pl|
237         res[pl.color] = pl.name
238         res
239       end
240       result = writer.write(info, match.history)
241       write_file(url, result)
242     end
243   end
246 class DummyPlayer
247   include Observer
248   include Player
249   
250   attr_reader :color
251   attr_accessor :name
252   
253   def initialize(color)
254     @color = color
255   end