#!/usr/bin/env python # # Copyright (C) 2010, Johannes Ponader # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA from mathparse_honeypot import mathparse_honeypot from xml_honeypot import xml_honeypot import gtk import gtk.glade import sys import random import time import logging import pango import pygtk ''' try: # should we use the treadsafe database module TS_Base?. # although it is very unlikelike that a user runs two instances on his account, # what would be the effect? from buzhug import Base # as long as buzhug is a subdirectory of Honeypot.activity, import should be trivial # do we want to install it anyway? would that be better for performance? except ImportError: from distutils.core import setup # this command, esp. sys_args = 'install', is not tested yet # perhaps run_setup('buzhug_setup', 'install') would be more clearly # btw, if we don't have the permission to install it into the standard location # ('/usr/', i guess), we have to sudo the install or have to use the home dir instead? # see http://docs.python.org/install/ # what about win users using the script as standalone? setup(name='buzhug', version='1.6', description='Buzhug, a pure-Python database', author='Pierre Quentel', author_email='pierre.quentel@gmail.com', url='http://buzhug.sourceforge.net/', packages = ['buzhug'], script_args = 'install') from buzhug import Base # if we don't have the permission to install it into the standard location # ('/usr/', i guess), we have to sudo the install or have to use the home dir instead? # see http://docs.python.org/install/ # what about win users using the script as standalone? ''' _logger = logging.getLogger('gtk_honeypot') # for logging outside sugar if __name__ == '__main__': LOG_FILENAME = 'logger.logfile' logging.basicConfig(filename=LOG_FILENAME,level=logging.DEBUG) _logger.setLevel(logging.DEBUG) # Pango is a library for rendering internationalized texts pygtk.require('2.0') # load xml parser from xml_honeypot.py # load mathparse parser from mathparse_honeypot.py # class guessfield(gtk_textfield): class gtk_honeypot: def __init__(self, runaslib=True): # Create DB, certainly, this goes into Journal afterwards, if it's not standalone # not yet implemented # path = '/home/olpc/Development/buzhug/' # db = Base(path) # Load glade xml self.xml = gtk.glade.XML("gtk_honeypot.glade") # get window self.window = self.xml.get_widget('window1') self.window.connect("delete_event", gtk.main_quit) # get window child self.window_child = self.window.get_child() _logger.debug("self.window_child: " + str(self.window_child)) # get the label_button self.label_question = self.xml.get_widget('label_question') self.label_question.connect('clicked', self.on_label_question) # with self.textfield_answer as tf: # funktioniert das? oder hat das seltame Nebeneffekte? # am ende von with wid das objekt schliesslich aufgeraeumt... # get the textfield self.textfield_answer = self.xml.get_widget('textfield_answer') # self.textfield_answer.connect('clicked', self.on_guessed) self.textfield_answer.connect('activate', self.on_textfield_answer_activate) # self.textfield_answer.connect('move-cursor', self.on_textfield_answer_move_cursor) self.textfield_answer.handler_id = [] # self.textfield.handler_id.append(self.textfield_answer.connect('insert-at-cursor', self.on_textfield_answer_insert_at_cursor)) self.textfield_answer.handler_id.append(self.textfield_answer.connect('move-cursor', self.kill_event, 'move-cursor')) self.textfield_answer.handler_id.append(self.textfield_answer.connect('delete-text', self.kill_event, 'delete-text')) self.textfield_answer.handler_id.append(self.textfield_answer.connect('insert-text', self.on_textfield_answer_insert_text)) # we need a get-focus or so event-handler, which sets the cursor right again in state STATE_WRONG self.textfield_answer.move_cursor_id = self.textfield_answer.handler_id[0] # block these handlers for now for i in range(0, len(self.textfield_answer.handler_id)): self.textfield_answer.handler_block(self.textfield_answer.handler_id[i]) # self.textfield_answer.connect('event', self.on_textfield_answer_event) # backspace, copy-clipboard, cut-clipboard, deleste-from-cursor, insert-at-cursor, move-cursor, paste-clipboard, # changed, delete-text, insert-text # gobject.stop_emission() # key-press-event # selection-clear-event, (selection-get-event), # drag-. # this is a dirty way to define the color, i suppose # we should use the current stylemap self.cursor_color_train = gtk.Entry().get_colormap().alloc_color("red") self.cursor_color_answer = gtk.Entry().get_colormap().alloc_color("black") self.textfield_answer.modify_cursor(self.cursor_color_answer, self.cursor_color_answer) # get the button self.button_guess = self.xml.get_widget('button_guess') self.button_guess.connect('clicked', self.on_button_guess) # self.button_guess.connect('activate', self.on_button_guess) # self.widget will be attached to the Activity # this can be any gtk widget except a window self.widget = self.window_child # Seed the random number generator random.seed(time.time()) # load one or more collections of questions and answers self.honeypot = xml_honeypot() self.honeypot.load_drops() # load the mathpars parser # note: there must be a parser regitration lateron, so that the script # can determine which parsers are successfully loaded self.mathparse = mathparse_honeypot() # we define four states: # 'fresh', 'open', 'wrong', 'right' self.STATE_FRESH = 0 self.STATE_OPEN = 1 self.STATE_WRONG = 2 # and safe the actual state in self.state self.state = self.STATE_FRESH if not runaslib: self.window.show_all() gtk.main() def on_textfield_answer_activate(self, *args): if self.state == self.STATE_FRESH: self.open_new_question() elif self.state == self.STATE_OPEN: self.check_answer() # we need no else, because we want to ignore RETURN in the state 'wrong' def on_textfield_answer_insert_text(self, *args): # insert-text(editable, new_text, text_length, position, data) if args[1] == self.drop[1][self.rewrite_position]: self.rewrite_position += 1 self.textfield_answer.handler_block(self.textfield_answer.move_cursor_id) self.textfield_answer.set_position(self.rewrite_position) self.textfield_answer.handler_unblock(self.textfield_answer.move_cursor_id) # we check if the user typed in the whole answer # kann ich die endposition eleganter auslesen? if self.textfield_answer.get_position() == len(self.drop[1]): self.label_question.set_label(self.drop[0] + "\nThat's it.\nClick here or hit RETURN for another question.") for i in range(0, len(self.textfield_answer.handler_id)): self.textfield_answer.handler_block(self.textfield_answer.handler_id[i]) self.state = self.STATE_FRESH self.textfield_answer.stop_emission('insert-text') def kill_event(self, *args): self.textfield_answer.stop_emission(args[len(args)-1]) def on_textfield_answer_event(self, *args): if args[1].type not in (3, 10, 11, 2): # GDK_MOTION_NOTIFY, GDK_ENTER_NOTIFY, GDK_LEAVE_NOTIFY, GDK_EXPOSE): print(args[1].type) def on_button_guess(self, *args): # self.textfield_answer.add_events() # self.textfield_answer.set_editable(False) # self.textfield_answer.select_region(0,1) pass def on_label_question(self, *args): self.open_new_question() def open_new_question(self): self.drop = random.choice(self.honeypot.content_handler.drops) _logger.debug('random choice: ' + str(self.drop)) # we now take always the mathparse parser - # choose the parser dynamically from xml-atribute lateron # self.label_question.set_label("I'll ask some other question, dude: " + self.drop[0]) self.drop = self.mathparse.parse(self.drop) self.label_question.set_label("Question:\n" + self.drop[0]) self.textfield_answer.grab_focus() self.textfield_answer.set_text('') self.state = self.STATE_OPEN def check_answer(self): if self.textfield_answer.get_text() == self.drop[1]: # correct answer self.label_question.set_label("Correct!\nClick here or hit RETURN for another question.") self.state = self.STATE_FRESH else: # wrong answer self.label_question.set_label(self.drop[0] + "\nYour answer:\n" + self.textfield_answer.get_text() + "\nThis answer is wrong :-(\nRetype the correct answer\nand hit RETURN for the next question.") # write correct answer self.textfield_answer.set_text(self.drop[1]) self.rewrite_position = 0 # activate special handlers for i in range(0, len(self.textfield_answer.handler_id)): self.textfield_answer.handler_unblock(self.textfield_answer.handler_id[i]) # self.textfield_answer.handler_unblock_by_func(self.on_textfield_answer_insert_text) self.textfield_answer.modify_cursor(self.cursor_color_train, self.cursor_color_train) self.state = self.STATE_WRONG if __name__ == '__main__': gtk_honeypot(False)