1 # Copyright (c) 2009 Paolo Capriotti <p.capriotti@gmail.com>
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 2 of the License, or
6 # (at your option) any later version.
13 require 'interaction/history'
15 require 'dummy_player'
17 require 'interaction/match'
23 require 'engine_prefs'
28 class MainWindow < KDE::XmlGuiWindow
34 def initialize(loader, game)
38 @theme_loader = @loader.get_matching(:theme_loader).new
44 new_game(Match.new(game), :new_tab => false)
49 controller.match.close
55 @view.current.controller
62 std_action(:open_new) { create_game }
63 std_action(:open) { load_game }
64 std_action :quit, :slot => :close
65 std_action(:save) { save_game }
66 std_action(:saveAs) { save_game_as }
68 @actions[:back] = regular_action :back, :icon => 'go-previous',
69 :text => KDE.i18n("B&ack") do
72 @actions[:forward] = regular_action :forward, :icon => 'go-next',
73 :text => KDE.i18n("&Forward") do
77 regular_action :flip, :icon => 'object-rotate-left',
78 :text => KDE.i18n("F&lip") do
79 table = @view.current.table
80 table.flip(!table.flipped?)
83 regular_action :configure_engines,
85 :text => KDE.i18n("Configure &Engines...") do
86 dialog = EnginePrefs.new(@engine_loader, self)
90 regular_action :configure_themes,
91 :icon => 'games-config-theme',
92 :text => KDE.i18n("Configure &Themes...") do
93 dialog = ThemePrefs.new(@loader, @theme_loader, self)
97 @actions[:undo] = std_action(:undo) do
101 @actions[:redo] = std_action(:redo) do
106 def load_action_providers
107 @loader.get_all_matching(:action_provider).each do |provider_klass|
108 provider = provider_klass.new
109 ActionProviderClient.new(self, provider)
113 def create_view(opts = { })
115 table = Table.new(scene, @loader, @theme_loader, @view)
116 contr = Controller.new(table, @field)
117 movelist = @loader.get_matching(:movelist).new(contr)
118 v = View.new(table, contr, movelist)
123 @field = AnimationField.new(20)
126 movelist_stack = Qt::StackedWidget.new(self)
127 movelist_dock = Qt::DockWidget.new(self)
128 movelist_dock.widget = movelist_stack
129 movelist_dock.window_title = KDE.i18n("History")
130 movelist_dock.object_name = "movelist"
131 add_dock_widget(Qt::LeftDockWidgetArea, movelist_dock, Qt::Vertical)
133 action_collection.add_action('toggle_history',
134 movelist_dock.toggle_view_action)
136 @view = MultiView.new(self, movelist_stack)
137 create_view(:name => game.class.plugin_name)
139 @engine_loader = @loader.get_matching(:engine_loader).new
140 @engine_loader.reload
142 @console = Console.new(nil)
143 console_dock = Qt::DockWidget.new(self)
144 console_dock.widget = @console
145 console_dock.focus_proxy = @console
146 console_dock.window_title = KDE.i18n("Console")
147 console_dock.object_name = "console"
148 add_dock_widget(Qt::BottomDockWidgetArea, console_dock, Qt::Horizontal)
149 console_dock.window_flags = console_dock.window_flags & ~Qt::WindowStaysOnTopHint
151 action_collection.add_action('toggle_console',
152 console_dock.toggle_view_action)
154 self.central_widget = @view
157 def new_game(match, opts = { })
158 setup_single_player(match)
159 controller.reset(match)
162 def setup_single_player(match)
163 controller.color = match.game.players.first
164 controller.premove = false
165 opponents = match.game.players[1..-1].map do |color|
166 DummyPlayer.new(color)
168 opponents.each do |p|
169 controller.add_controlled_player(p)
172 controller.controlled.values.each do |p|
175 controller.controlled.values.each do |p|
180 def create_game(opts = { })
181 current_game = if controller.match
182 controller.match.game
184 diag = NewGame.new(self, @engine_loader, current_game)
185 diag.observe(:ok) do |data|
187 match = Match.new(game, :editable => data[:engines].empty?)
189 create_view(:activate => true,
190 :name => game.class.plugin_name)
192 @view.set_tab_text(@view.index, game.class.plugin_name)
197 match.observe(:started) do
201 # set up engine players
202 players = game.players
203 data[:engines].each do |player, engine|
204 e = engine.new(player, match)
208 # set up human players
209 if data[:humans].empty?
212 contr.color = data[:humans].first
213 contr.premove = data[:humans].size == 1
214 match.register(contr)
216 data[:humans][1..-1].each do |player|
217 p = DummyPlayer.new(player)
218 contr.add_controlled_player(p)
222 contr.controlled.values.each {|p| match.start(p) }
228 url = KDE::FileDialog.get_open_url(KDE::Url.new, '*.*', self,
229 KDE.i18n("Open game"))
232 ext = File.extname(url.path)[1..-1]
234 readers = Game.to_enum.find_all do |_, game|
235 game.respond_to?(:game_extensions) and
236 game.game_extensions.include?(ext)
238 [game, game.game_reader]
242 warn "Unknown file extension #{ext}"
247 return unless KIO::NetAccess.download(url, tmp_file, self)
253 readers.each do |g, reader|
255 data = File.open(tmp_file) do |f|
259 history = reader.read(data, i)
263 rescue ParseException
268 warn "Could not load file #{url.path}"
273 match = Match.new(game)
274 create_view(:activate => true,
275 :name => game.class.plugin_name)
276 setup_single_player(match)
277 match.history = history
280 controller.reset(match)
285 match = controller.match
287 pattern = if match.game.respond_to?(:game_extensions)
288 match.game.game_extensions.map{|ext| "*.#{ext}"}.join(' ')
292 url = KDE::FileDialog.get_save_url(
293 KDE::Url.new, pattern, self, KDE.i18n("Save game"))
294 match.url = write_game(url)
299 match = controller.match
309 def write_game(url = nil)
310 match = controller.match
313 writer = match.game.game_writer
315 info[:players] = info[:players].inject({}) do |res, pl|
316 res[pl.color] = pl.name
319 result = writer.write(info, match.history)
320 write_file(url, result)
324 def update_game_actions(match)
325 unplug_action_list('game_actions')
326 actions = if match.game.respond_to?(:actions)
327 match.game.actions(self, action_collection, controller.policy)
331 plug_action_list('game_actions', actions)