Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/gtk_honeypot.py
blob: 645f5c22c7496fbed2436453d18028c7c3dfbf9f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
#!/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)