gnome-games r7323 - in trunk/gnome-sudoku: . help help/C help/C/figures src/lib



Author: thinkle
Date: Sat Feb  9 17:37:18 2008
New Revision: 7323
URL: http://svn.gnome.org/viewvc/gnome-games?rev=7323&view=rev

Log:
2008-02-09  Thomas Hinkle  <tmhinkle gmail com>

	* src/lib/saver.py (SudokuTracker.save_game): Display dialog
	warning user if unable to save. bug #486385
	(SudokuTracker.finish_jar): Display dialog warning user if unable
	to save. bug #486385
	(SudokuTracker.__init__): Display dialog warning user if unable to
	create directories for saved and finished files
	* src/lib/dialog_swallower.py (SwappableArea.run_dialog): Queue
	redraw when we switch back to main page. This fixes the annoying
	display bug that made numbers render badly when you started up
	gnome sudoku.
	* src/lib/main.py (UI.print_multiple_games): Fix bug #515411 -
	GamePrinter expected an instance of SudokuMaker, not SudokuTracker
	(UI.__init__): Add run_selector keyword arg to allow us to turn
	off selector dialog for testing purposes.
	* src/lib/gsudoku.py (SudokuGameDisplay.add_value): Clean up and
	comment function.
	(GridDancer): Speed up animation so people can appreciate all the
	awesomeness that is the victory dance.


2008-02-09  Thomas Hinkle  <tmhinkle gmail com>

	* C/gnome-sudoku.xml: Update manual for new version. This means
	updating description of saving/loading, mostly.
	* Makefile.am: Added resuming.png and starting.png figures.


Added:
   trunk/gnome-sudoku/help/C/figures/resuming.png   (contents, props changed)
   trunk/gnome-sudoku/help/C/figures/starting.png   (contents, props changed)
Modified:
   trunk/gnome-sudoku/ChangeLog
   trunk/gnome-sudoku/help/C/gnome-sudoku.xml
   trunk/gnome-sudoku/help/ChangeLog
   trunk/gnome-sudoku/help/Makefile.am
   trunk/gnome-sudoku/src/lib/dialog_swallower.py
   trunk/gnome-sudoku/src/lib/gsudoku.py
   trunk/gnome-sudoku/src/lib/main.py
   trunk/gnome-sudoku/src/lib/saver.py

Added: trunk/gnome-sudoku/help/C/figures/resuming.png
==============================================================================
Binary file. No diff available.

Added: trunk/gnome-sudoku/help/C/figures/starting.png
==============================================================================
Binary file. No diff available.

Modified: trunk/gnome-sudoku/help/C/gnome-sudoku.xml
==============================================================================
--- trunk/gnome-sudoku/help/C/gnome-sudoku.xml	(original)
+++ trunk/gnome-sudoku/help/C/gnome-sudoku.xml	Sat Feb  9 17:37:18 2008
@@ -2,9 +2,9 @@
 <!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" 
 "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"; [
   <!ENTITY legal SYSTEM "legal.xml">
-  <!ENTITY appversion "0.7">
-  <!ENTITY manrevision "2.0">
-  <!ENTITY date "October 2006">
+  <!ENTITY appversion "2.21.90">
+  <!ENTITY manrevision "3.0">
+  <!ENTITY date "February 2008">
   <!ENTITY app "<application>Sudoku</application>">
   <!-- Information about the entities
        The legal.xml file contains legal information, there is no need to edit the file. 
@@ -35,7 +35,7 @@
     </abstract>
 
     <copyright> 
-      <year>2006</year> 
+      <year>2008</year> 
       <holder>Thomas M. Hinkle</holder> 
     </copyright>
 <!-- translators: uncomment this:
@@ -219,17 +219,38 @@
     <title>When You Start &app;</title>
     <para>
 
-    When you start &app;, a puzzle will be
-    displayed. If it is your first time playing, you will begin with
-    an easy puzzle by default. If it is not your first time playing,
-    the game will open to the last puzzle you were working on by
-    default.
-
+    When you start &app; for the first time, you will see the puzzle
+    selector screen, where you can choose the difficulty of the puzzle
+    you want to play. If you've played before and have any unfinished
+    puzzles, you can select those puzzles from this screen as well.
+    </para>
+    <para>
+    In the puzzle selector screen, the difficulty of the puzzle is
+    displayed. The color surrounding the puzzle image corresponds to
+    the difficulty. A dark red puzzle is harder than a light red
+    puzzle, for example.
+    </para>
+    <para>
+    Double click on the puzzle of your choice to start playing.
     </para>
 
+<figure id="new-game-fig"> 
+	<title>Starting Sudoku</title> 
+	<screenshot> 
+	  <mediaobject> 
+	    <imageobject><imagedata
+		fileref="figures/starting.png" format="PNG"/> 
+	    </imageobject>
+	    <textobject> 
+	      <phrase>Starting up Sudoku: choose a difficulty level.</phrase> 
+	    </textobject>
+	  </mediaobject> 
+	</screenshot>
+      </figure>
+    
     <para>
     
-    To play different puzzle, click on
+    You can change puzzles at any time by pressing  
     <guibutton>New</guibutton>. This will bring you to the puzzle
     selection screen, where you can select whatever puzzle you like.
 
@@ -282,22 +303,26 @@
 	</screenshot>
       </figure>
     </note>
-    <sect2 id="myapp-saving">
+    </sect1>
+    <sect1 id="myapp-saving">
     <title>Saving and Resuming Games</title>
-    <para>When you close &app;, your current game is automatically saved; when you start, you will continue playing your game where you left off.</para>
+    <para>Sudokus are saved automatically every few minutes and whenever you change games or close the application.</para>
+        <figure id="open-game-fig"> 
+	<title>Resuming old games</title> 
+	<screenshot> 
+	  <mediaobject> 
+	    <imageobject><imagedata
+		fileref="figures/resuming.png" format="PNG"/> 
+	    </imageobject>
+	    <textobject> 
+	      <phrase>Resuming an old game from the puzzle selector screen.</phrase> 
+	    </textobject>
+	  </mediaobject> 
+	</screenshot>
+      </figure>
+    <para>Whenever you start &app; or click <guibutton>New</guibutton>, your saved games will be listed in the puzzle selection screen. You will see a miniature image of the saved puzzle, the date you last played it, and how long you have played it for. To open the puzzle, just double click on it.</para>
     <para>If you'd like to stop playing one game and begin another, just select <guibutton>New</guibutton> and begin your new game.</para>
-    <para>To resume an old game that you interrupted, select <menuchoice>
-    		<guisubmenu>Game</guisubmenu>
-    		<guimenuitem>Resume old game</guimenuitem>
-    		</menuchoice>. You can then select any game you've played before from a list.</para>
-    <para>To replay a game that you have already won, select <menuchoice>
-    		<guisubmenu>Tools</guisubmenu>
-    		<guimenuitem>High Scores</guimenuitem>
-    		</menuchoice>. Then select the game you would like to replay and click <guibutton>Replay Game</guibutton>.
-		</para>
-    </sect2>
-
-  </sect1>
+    </sect1>
 
 <!-- ================ Usage ================================ -->
 <!-- Use this section to describe how to use the application to perform the tasks for 
@@ -584,10 +609,6 @@
   
   </sect2>
 
-  <sect2>
-  <title>Negative High Scores</title>
-  <para>High scores are arguably an extraneous part of a sudoku game, but they seem like fun, so &app; includes them. The algorithm for high scores gives you points for speed and for puzzle difficulty and takes away points for using hints. The algorithm is designed to give reasonable-looking scores, but it sometimes produces negative scores, which can be upsetting for users.</para>
-  </sect2>
  </sect1>
 
 <!-- ============= About ================================== -->
@@ -599,10 +620,7 @@
   <sect1 id="myapp-about"> 
     <title>About &app;</title> 
     <para> &app; was written by Tom Hinkle
-      (<email>thomas_hinkle sf net</email>). To find more information about
-      &app;, please visit the 
-      <ulink url="http://gnome-sudoku.sf.net"; type="http">&app; Web
-	page</ulink>. </para>
+      (<email>tmhinkle gmail com</email>). &app is now part of GNOME games. </para>
     <para>
       To report a bug or make a suggestion regarding this application or
       this manual, see the Feedback section of the

Modified: trunk/gnome-sudoku/help/Makefile.am
==============================================================================
--- trunk/gnome-sudoku/help/Makefile.am	(original)
+++ trunk/gnome-sudoku/help/Makefile.am	Sat Feb  9 17:37:18 2008
@@ -12,6 +12,8 @@
 	figures/error_highlighting.png \
 	figures/highlighting.png \
 	figures/hints.png \
-	figures/Print_Sudokus.png
+	figures/Print_Sudokus.png \
+	figures/resuming.png \
+	figures/starting.png
 
 dist-hook: doc-dist-hook

Modified: trunk/gnome-sudoku/src/lib/dialog_swallower.py
==============================================================================
--- trunk/gnome-sudoku/src/lib/dialog_swallower.py	(original)
+++ trunk/gnome-sudoku/src/lib/dialog_swallower.py	Sat Feb  9 17:37:18 2008
@@ -1,4 +1,4 @@
-import gtk
+import gtk, gobject
 
 # Convenience library for a new kind of UI -- for e.g. this game, we
 # don't really want to have dialogs. Nonetheless, it's convenient to
@@ -50,6 +50,9 @@
             import traceback; traceback.print_exc()
             print 'forge on fearlessly...'
         self.set_current_page(self.main_page)
+        def redraw_page (*args):
+            self.get_nth_page(self.main_page).queue_draw()
+        gobject.timeout_add(100,redraw_page)
         self.running = None
         tmp_response = self.response
         self.response = None

Modified: trunk/gnome-sudoku/src/lib/gsudoku.py
==============================================================================
--- trunk/gnome-sudoku/src/lib/gsudoku.py	(original)
+++ trunk/gnome-sudoku/src/lib/gsudoku.py	Sat Feb  9 17:37:18 2008
@@ -1106,11 +1106,13 @@
 
         To specify NO trackers, use trackers=[-1]
         """
+        # Add the value to the UI to display
         self.__entries__[(x,y)].set_value(val)
         if self.doing_initial_setup:
             self.__entries__[(x,y)].set_read_only(True)
-        self.grid.add(x,y,val,True)
+        # Handle any trackers.
         if trackers:
+            # Explicitly specified tracker
             for tracker in trackers:
                 if tracker==-1: pass
                 self.__entries__[(x,y)].set_color(self.get_tracker_color(tracker))
@@ -1120,6 +1122,11 @@
                 if v:
                     self.__entries__[(x,y)].set_color(self.get_tracker_color(k))
                     self.trackers[k].append((x,y,val))
+        # Add value to our underlying sudoku grid -- this will raise
+        # an error if the value is out of bounds with the current
+        # rules. 
+        self.grid.add(x,y,val,True)
+        # Draw our entry
         self.__entries__[(x,y)].queue_draw()
 
     @simple_debug
@@ -1291,7 +1298,7 @@
         '#75507b', ]
                     ]
 
-    STEPS_PER_ANIMATION = 18
+    STEPS_PER_ANIMATION = 10
     
     def __init__ (self, grid):
         self.animations = [self.value_dance,
@@ -1308,7 +1315,7 @@
 
     def start_dancing (self):
         self.dancing = True
-        gobject.timeout_add(500,self.dance_grid)
+        gobject.timeout_add(350,self.dance_grid)
 
     def stop_dancing (self):
         self.dancing = False
@@ -1382,9 +1389,7 @@
     dancer = GridDancer(grid)
     dancer.start_dancing()
     def stop (*args): dancer.stop_dancing()
-    gobject.timeout_add(2000,stop)
-
-
+    gobject.timeout_add(15000,stop)
 
 if __name__ == '__main__':
     def test_sng ():
@@ -1409,6 +1414,38 @@
         w.show_all()
         gtk.main()
 
+    def reproduce_foobared_rendering ():
+        from sudoku import SudokuGrid, sample_open_sudoku
+        from dialog_swallower import SwappableArea
+        sgd = SudokuGameDisplay()
+        sgd.set_bg_color('black')
+        w = gtk.Window()
+        w.connect('delete-event', gtk.main_quit)
+        vb = gtk.VBox()
+        hb = gtk.HBox()
+        swallower = SwappableArea(hb)        
+        tb = gtk.Toolbar()
+        b = gtk.ToolButton(stock_id=gtk.STOCK_QUIT)
+        b.connect('clicked',lambda x: w.hide() or gtk.main_quit())
+        tb.add(b)
+        def run_swallowed_dialog (*args):
+            md = MessageDialog(title="Bar",label="Bar",sublabel="Baz "*12)
+            swallower.run_dialog(md)
+        b2 = gtk.ToolButton(label='Dialog')
+        b2.connect('clicked',run_swallowed_dialog)
+        tb.add(b2)
+        vb.pack_start(tb,fill=False,expand=False)
+        vb.pack_start(swallower,padding=12)
+        w.add(vb)
+        w.show_all()
+        #test_dance_grid(sgd)
+        from gtk_goodies.dialog_extras import MessageDialog
+        md = MessageDialog(title="Foo",label="Foo",sublabel="Bar "*12)
+        swallower.run_dialog(md)
+        hb.pack_start(sgd,padding=6)        
+        sgd.change_grid(SudokuGrid(sample_open_sudoku),9)
+        gtk.main()        
+
     def test_sudoku_game ():
         from sudoku import SudokuGrid, sample_open_sudoku
         sgd = SudokuGameDisplay(grid=SudokuGrid(sample_open_sudoku))
@@ -1432,7 +1469,8 @@
 
     #test_number_selector()
     #test_sng()
-    test_sudoku_game()
+    #test_sudoku_game()
+    reproduce_foobared_rendering()
 
         
             

Modified: trunk/gnome-sudoku/src/lib/main.py
==============================================================================
--- trunk/gnome-sudoku/src/lib/main.py	(original)
+++ trunk/gnome-sudoku/src/lib/main.py	Sat Feb  9 17:37:18 2008
@@ -163,7 +163,13 @@
                      }    
 
     @simple_debug
-    def __init__ (self):
+    def __init__ (self, run_selector=True):
+        """run_selector means that we start our regular game.
+
+        For testing purposes, it will be convenient to hand a
+        run_selector=False to this method to avoid running the dialog
+        and allow a tester to set up a game programmatically.
+        """
         gconf_wrapper.GConfWrapper.__init__(self,
                                             gconf_wrapper.GConf('gnome-sudoku')
                                             )
@@ -189,16 +195,18 @@
         # generate puzzles while our use is working...        
         self.show()
         #print 'Select game!'
-        if self.select_game():
-            # If this return True, the user closed...
-            #print 'select game returned True - exit'
-            self.quit = True
-        else:
-            self.quit = False
-            # Generate puzzles in background...
-            if self.gconf['generate_puzzles_in_background']:
-                gobject.timeout_add(1000,lambda *args: self.start_worker_thread() and True)
-                
+        if run_selector:
+            self.do_stop()
+            if self.select_game():
+                # If this return True, the user closed...
+                #print 'select game returned True - exit'                
+                self.quit = True
+            else:
+                self.quit = False
+                # Generate puzzles in background...
+                if self.gconf['generate_puzzles_in_background']:
+                    gobject.timeout_add(1000,lambda *args: self.start_worker_thread() and True)
+        
 
     @inactivate_new_game_etc
     def select_game (self):
@@ -876,7 +884,7 @@
 
     @simple_debug
     def print_multiple_games (self, *args):
-        gp=game_selector.GamePrinter(self.sudoku_tracker, self.gconf)
+        gp=game_selector.GamePrinter(self.sudoku_maker, self.gconf)
         gp.run_dialog()
 
     @simple_debug

Modified: trunk/gnome-sudoku/src/lib/saver.py
==============================================================================
--- trunk/gnome-sudoku/src/lib/saver.py	(original)
+++ trunk/gnome-sudoku/src/lib/saver.py	Sat Feb  9 17:37:18 2008
@@ -1,5 +1,7 @@
-import pickle, types, os, os.path, sudoku
+import pickle, types, os, os.path, sudoku, errno
 from defaults import *
+from gtk_goodies.dialog_extras import show_message
+from gettext import gettext as _
 
 SAVE_ATTRIBUTES = [('gsd.hints'),
                    ('gsd.impossible_hints'),
@@ -88,10 +90,30 @@
     def __init__ (self):
         self.save_path = os.path.expanduser('~/.sudoku/saved')
         self.finished_path = os.path.expanduser('~/.sudoku/finished')
-        if not os.path.exists(self.save_path):
-            os.makedirs(self.save_path)
-        if not os.path.exists(self.finished_path):
-            os.makedirs(self.finished_path)
+        self.create_dir_safely(self.save_path)
+        self.create_dir_safely(self.finished_path)
+
+    def create_dir_safely (self, path):
+        if not os.path.exists(path):
+            try:
+                os.makedirs(path)
+            except OSError, e:                
+                if e.errno == errno.ENOSPC:
+                    show_message(
+                        title=_('No Space'),
+                        label=_('No space left on disk'),
+                        message_type=gtk.MESSAGE_ERROR,
+                        sublabel=_('Sudoku is unable to created data folder %(path)s.')%locals() +\
+                                 _('There is no disk space left!')
+                        )
+                else:
+                    show_message(
+                        title='Error creating directory',
+                        label='Error creating directory',
+                        sublabel=_('Sudoku was unable to create data folder %(path)s.')%locals() +\
+                        _('Error %(errno)s: %(error)s')%{'errno':e.errno,
+                                                         'error':e.strerror}
+                        )
 
     def are_finished_games (self):
         if os.listdir(self.finished_path): return True
@@ -107,10 +129,23 @@
         game = self.game_from_ui(ui)
         jar = jar_game(ui)
         #jar['saved_at'] = time.time()
-        outfi = file(os.path.join(self.save_path,self.get_filename(jar['game'])),
-                     'w')
-        pickle.dump(jar,outfi)
-        outfi.close()
+        filename = os.path.join(self.save_path,self.get_filename(jar['game']))
+        try:
+            outfi = file(filename,'w')
+            pickle.dump(jar,outfi)
+            outfi.close()
+        except (OSError, IOError), e:
+            show_message(
+                title=_('Sudoku unable to save game.'),
+                label=_('Sudoku unable to save game.'),
+                message_type=gtk.MESSAGE_ERROR,
+                sublabel=(_('Unable to save file %(filename)s.')%locals()
+                          + '\n' +
+                          _('Error %(errno)s: %(error)s')%{
+                'errno':e.errno,
+                'error':e.strerror
+                })
+                )
 
     def finish_game (self, ui):
         game = self.game_from_ui(ui)
@@ -119,18 +154,42 @@
 
     def finish_jar (self, jar):
         self.remove_from_saved_games(jar) # 
-        outfi = file(os.path.join(self.finished_path,
-                                  self.get_filename(jar['game'])),
-                     'w'
-                     )
-        pickle.dump(jar,outfi)
-        outfi.close()
-        list_of_finished_games = os.path.join(
-            os.path.join(DATA_DIR,'puzzles'),'finished'
-            )
-        ofi = open(list_of_finished_games,'a')
-        ofi.write(jar['game'].split('\n')[0]+'\n')
-        ofi.close()
+        try:
+            filename = file(os.path.join(self.finished_path,
+                                      self.get_filename(jar['game'])),
+                         'w'
+                         )
+            pickle.dump(jar,filename)
+            outfi.close()
+        except (OSError, IOError), e:
+            show_message(
+                title=_('Sudoku unable to mark game as finished.'),
+                label=_('Sudoku unable to mark game as finished.'),
+                message_type=gtk.MESSAGE_ERROR,
+                sublabel=(_('Unable to save file %(filename)s.'%locals) + '\n' +
+                          _('Error %(errno)s: %(error)s')%{
+                'errno':e.errno,
+                'error':e.strerror
+                })
+                )
+        try:
+            filename = list_of_finished_games = os.path.join(
+                os.path.join(DATA_DIR,'puzzles'),'finished'
+                )
+            ofi = open(list_of_finished_games,'a')
+            ofi.write(jar['game'].split('\n')[0]+'\n')
+            ofi.close()
+        except (OSError, IOError), e:
+            show_message(
+                title=_('Sudoku unable to mark game as finished.'),
+                label=_('Sudoku unable to mark game as finished.'),
+                message_type=gtk.MESSAGE_ERROR,
+                sublabel=(_('Unable to save file %(filename)s.'%locals) + '\n' +
+                          _('Error %(errno)s: %(error)s')%{
+                'errno':e.errno,
+                'error':e.strerror
+                })
+                )
 
     def remove_from_saved_games (self, jar):
         previously_saved_game = os.path.join(



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]