From f41a84c82bc1f040ef7a2d7847ef54727cad47a5 Mon Sep 17 00:00:00 2001 From: Shubhojyoti Date: Fri, 30 Oct 2015 18:04:53 +0530 Subject: [PATCH 01/34] Basic barebones interface from kivy catalog --- gui/kivycatalog.kv | 128 ++++++++++++++++++++++++++++++ gui/main.py | 191 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 319 insertions(+) create mode 100644 gui/kivycatalog.kv create mode 100755 gui/main.py diff --git a/gui/kivycatalog.kv b/gui/kivycatalog.kv new file mode 100644 index 0000000..1d22e8e --- /dev/null +++ b/gui/kivycatalog.kv @@ -0,0 +1,128 @@ +#:kivy 1.4 +#:import MatlabLexer pygments.lexers.MatlabLexer + +[ContainerToggle@ToggleButton]: + group: "container_toggle" + text: ctx.text + on_press: root.parent.parent.parent.show_kv(*args) + state: ctx.state if hasattr(ctx, "state") else "normal" + +: + canvas.before: + Color: + rgb: 0, 0, 0 + Rectangle: + pos: self.pos + size: self.size + +: + language_box: language_box + screen_manager: screen_manager + auto_reload: chkbx.active + info_label: info_lbl + orientation: 'vertical' + BoxLayout: + padding: '2sp' + canvas: + Color: + rgba: 1, 1, 1, .6 + Rectangle: + size: self.size + pos: self.pos + size_hint: 1, None + height: '45sp' + Spinner: + size_hint: None, 1 + width: '108sp' + text: 'Welcome' + values: [screen.name for screen in screen_manager.screens] + on_text: root.show_kv(*args) + Widget: + BoxLayout: + size_hint: None, 1 + width: '150sp' + Label: + text: "Auto Reload" + CheckBox: + id: chkbx + active: True + size_hint_x: 1 + Button: + size_hint: None, 1 + width: '108sp' + text: 'Render Now' + on_release: root.change_kv(*args) + BoxLayout: + id: reactive_layout + orientation: 'vertical' if self.width < self.height else 'horizontal' + + Splitter: + id: editor_pane + max_size: (reactive_layout.height if self.vertical else reactive_layout.width) - self.strip_size + min_size: sp(30) + self.strip_size + vertical: 1 if reactive_layout.width < reactive_layout.height else 0 + sizable_from: 'bottom' if self.vertical else 'right' + size_hint: (1, None) if self.vertical else (None, 1) + size: 400, 400 + on_vertical: + mid_size = self.max_size/2 + if args[1]: self.height = mid_size + if not args[1]: self.width = mid_size + ScrollView: + id: kr_scroll + KivyRenderTextInput: + catalog: root + id: language_box + auto_indent: True + #lexer: MatlabLexer() + size_hint: 1, None + height: max(kr_scroll.height, self.minimum_height) + font_name: "data/fonts/DroidSansMono.ttf" + valign: "top" + text: "This box will display the kivy language for whatever has been selected" + on_text: root.schedule_reload() + on_cursor: root.schedule_reload() + ScreenManager: + id: screen_manager + Screen: + name: "Welcome" + PlaygroundContainer: + Screen: + name: "ex1" + PlaygroundContainer: + Screen: + name: "ex2" + FloatLayoutContainer + Screen: + name: "ex3" + BoxLayoutContainer: + Screen: + name: "ex4" + AnchorLayoutContainer: + Screen: + name: "ex5" + GridLayoutContainer: + Screen: + name: "ex6" + StackLayoutContainer: + Screen: + name: "ex7" + ButtonContainer: + Screen: + name: "ex8" + LabelContainer: + + FloatLayout: + size_hint: 1, None + height: 0 + TextInput: + id:info_lbl + readonly: True + font_size: '14sp' + background_color: (0, 0, 0, 1) + foreground_color: (1, 1, 1, 1) + opacity:0 + size_hint: 1, None + text_size: self.size + height: '150pt' + top: 0 diff --git a/gui/main.py b/gui/main.py new file mode 100755 index 0000000..97dc4ad --- /dev/null +++ b/gui/main.py @@ -0,0 +1,191 @@ +#!/usr/bin/kivy +''' +Kivy Catalog +============ + +The Kivy Catalog viewer showcases widgets available in Kivy +and allows interactive editing of kivy language code to get immediate +feedback. You should see a two panel screen with a menu spinner button +(starting with 'Welcome') and other controls across the top.The left pane +contains kivy (.kv) code, and the right side is that code rendered. You can +edit the left pane, though changes will be lost when you use the menu +spinner button. The catalog will show you dozens of .kv examples controlling +different widgets and layouts. + +The catalog's interface is set in the file kivycatalog.kv, while the +interfaces for each menu option are set in containers_kvs directory. To +add a new .kv file to the Kivy Catalog, add a .kv file into the container_kvs +directory and reference that file in the ScreenManager section of +kivycatalog.kv. + +Known bugs include some issue with the drop +''' +import kivy +kivy.require('1.4.2') +import os +import sys +from kivy.app import App +from kivy.factory import Factory +from kivy.lang import Builder, Parser, ParserException +from kivy.properties import ObjectProperty +from kivy.config import Config +from kivy.compat import PY2 + +from kivy.uix.boxlayout import BoxLayout +from kivy.uix.codeinput import CodeInput +from kivy.animation import Animation +from kivy.clock import Clock + +CATALOG_ROOT = os.path.dirname(__file__) + +#Config.set('graphics', 'width', '1024') +#Config.set('graphics', 'height', '768') + +'''List of classes that need to be instantiated in the factory from .kv files. +''' +CONTAINER_KVS = os.path.join(CATALOG_ROOT, 'container_kvs') +CONTAINER_CLASSES = [c[:-3] for c in os.listdir(CONTAINER_KVS) + if c.endswith('.kv')] + + +class Container(BoxLayout): + '''A container is essentially a class that loads its root from a known + .kv file. + + The name of the .kv file is taken from the Container's class. + We can't just use kv rules because the class may be edited + in the interface and reloaded by the user. + See :meth: change_kv where this happens. + ''' + + def __init__(self, **kwargs): + super(Container, self).__init__(**kwargs) + self.previous_text = open(self.kv_file).read() + parser = Parser(content=self.previous_text) + widget = Factory.get(parser.root.name)() + Builder._apply_rule(widget, parser.root, parser.root) + self.add_widget(widget) + + @property + def kv_file(self): + '''Get the name of the kv file, a lowercase version of the class + name. + ''' + return os.path.join(CONTAINER_KVS, self.__class__.__name__ + '.kv') + + +for class_name in CONTAINER_CLASSES: + globals()[class_name] = type(class_name, (Container,), {}) + + +class KivyRenderTextInput(CodeInput): + def keyboard_on_key_down(self, window, keycode, text, modifiers): + is_osx = sys.platform == 'darwin' + # Keycodes on OSX: + ctrl, cmd = 64, 1024 + key, key_str = keycode + + if text and not key in (list(self.interesting_keys.keys()) + [27]): + # This allows *either* ctrl *or* cmd, but not both. + if modifiers == ['ctrl'] or (is_osx and modifiers == ['meta']): + if key == ord('s'): + self.catalog.change_kv(True) + return + + return super(KivyRenderTextInput, self).keyboard_on_key_down( + window, keycode, text, modifiers) + + +class Catalog(BoxLayout): + '''Catalog of widgets. This is the root widget of the app. It contains + a tabbed pain of widgets that can be displayed and a textbox where .kv + language files for widgets being demoed can be edited. + + The entire interface for the Catalog is defined in kivycatalog.kv, + although individual containers are defined in the container_kvs + directory. + + To add a container to the catalog, + first create the .kv file in container_kvs + The name of the file (sans .kv) will be the name of the widget available + inside the kivycatalog.kv + Finally modify kivycatalog.kv to add an AccordionItem + to hold the new widget. + Follow the examples in kivycatalog.kv to ensure the item + has an appropriate id and the class has been referenced. + + You do not need to edit any python code, just .kv language files! + ''' + language_box = ObjectProperty() + screen_manager = ObjectProperty() + + def __init__(self, **kwargs): + self._previously_parsed_text = '' + super(Catalog, self).__init__(**kwargs) + self.show_kv(None, 'Welcome') + self.carousel = None + + def show_kv(self, instance, value): + '''Called when an a item is selected, we need to show the .kv language + file associated with the newly revealed container.''' + + self.screen_manager.current = value + + child = self.screen_manager.current_screen.children[0] + with open(child.kv_file, 'rb') as file: + self.language_box.text = file.read().decode('utf8') + Clock.unschedule(self.change_kv) + self.change_kv() + # reset undo/redo history + self.language_box.reset_undo() + + def schedule_reload(self): + if self.auto_reload: + txt = self.language_box.text + child = self.screen_manager.current_screen.children[0] + if txt == child.previous_text: + return + child.previous_text = txt + Clock.unschedule(self.change_kv) + Clock.schedule_once(self.change_kv, 2) + + def change_kv(self, *largs): + '''Called when the update button is clicked. Needs to update the + interface for the currently active kv widget, if there is one based + on the kv file the user entered. If there is an error in their kv + syntax, show a nice popup.''' + + txt = self.language_box.text + kv_container = self.screen_manager.current_screen.children[0] + try: + parser = Parser(content=txt) + kv_container.clear_widgets() + widget = Factory.get(parser.root.name)() + Builder._apply_rule(widget, parser.root, parser.root) + kv_container.add_widget(widget) + except (SyntaxError, ParserException) as e: + self.show_error(e) + except Exception as e: + self.show_error(e) + + def show_error(self, e): + self.info_label.text = str(e) + self.anim = Animation(top=190.0, opacity=1, d=2, t='in_back') +\ + Animation(top=190.0, d=3) +\ + Animation(top=0, opacity=0, d=2) + self.anim.start(self.info_label) + + +class KivyCatalogApp(App): + '''The kivy App that runs the main root. All we do is build a catalog + widget into the root.''' + + def build(self): + return Catalog() + + def on_pause(self): + return True + + +if __name__ == "__main__": + KivyCatalogApp().run() From 0a902845cfb550d845aa6e59d89d26591c4b0583 Mon Sep 17 00:00:00 2001 From: Shubhojyoti Date: Fri, 30 Oct 2015 22:57:31 +0530 Subject: [PATCH 02/34] Raw barebones created from scratch --- gui/interface.py | 58 ++++++++++++++ gui/kivycatalog.kv | 128 ------------------------------ gui/main.py | 191 --------------------------------------------- 3 files changed, 58 insertions(+), 319 deletions(-) create mode 100644 gui/interface.py delete mode 100644 gui/kivycatalog.kv delete mode 100755 gui/main.py diff --git a/gui/interface.py b/gui/interface.py new file mode 100644 index 0000000..8f67bf7 --- /dev/null +++ b/gui/interface.py @@ -0,0 +1,58 @@ +from kivy.app import App +from kivy.uix.boxlayout import BoxLayout +from kivy.uix.button import Button +from kivy.uix.label import Label +from kivy.uix.textinput import TextInput + + +class LoginScreen(BoxLayout): + + def __init__(self, **kwargs): + super(LoginScreen, self).__init__(**kwargs) + self.orientation='vertical' + self.add_widget(self.titlebar()) + self.add_widget(self.maineditor()) + self.add_widget(self.filebar()) + + def titlebar(self): + layout=BoxLayout() + layout.orientation='horizontal' + #submit = Button(text='Submit') + #submit.bind(on_press=self.submission) + #layout.add_widget(submit) + layout.add_widget(Label(text='Excercise1')) + layout.add_widget(Label(text='Title')) + layout.add_widget(Label(text='Submit')) + + return layout + + + def submission(self,sub): + print('The button <%s> is being pressed' % instance.text) + + def maineditor(self): + layout=BoxLayout() + layout.orientation='horizontal' + layout.add_widget(Label(text='Code Editor')) + layout.add_widget(Label(text='Instructions')) + return layout + + def filebar(self): + layout=BoxLayout() + layout.orientation='horizontal' + layout.add_widget(Label(text='File1')) + layout.add_widget(Label(text='File2')) + layout.add_widget(Label(text='File3')) + return layout + + +class MainApp(App): + + def build(self): + return LoginScreen() + def on_pause(self): + return True + + +if __name__ == '__main__': + MainApp().run() \ No newline at end of file diff --git a/gui/kivycatalog.kv b/gui/kivycatalog.kv deleted file mode 100644 index 1d22e8e..0000000 --- a/gui/kivycatalog.kv +++ /dev/null @@ -1,128 +0,0 @@ -#:kivy 1.4 -#:import MatlabLexer pygments.lexers.MatlabLexer - -[ContainerToggle@ToggleButton]: - group: "container_toggle" - text: ctx.text - on_press: root.parent.parent.parent.show_kv(*args) - state: ctx.state if hasattr(ctx, "state") else "normal" - -: - canvas.before: - Color: - rgb: 0, 0, 0 - Rectangle: - pos: self.pos - size: self.size - -: - language_box: language_box - screen_manager: screen_manager - auto_reload: chkbx.active - info_label: info_lbl - orientation: 'vertical' - BoxLayout: - padding: '2sp' - canvas: - Color: - rgba: 1, 1, 1, .6 - Rectangle: - size: self.size - pos: self.pos - size_hint: 1, None - height: '45sp' - Spinner: - size_hint: None, 1 - width: '108sp' - text: 'Welcome' - values: [screen.name for screen in screen_manager.screens] - on_text: root.show_kv(*args) - Widget: - BoxLayout: - size_hint: None, 1 - width: '150sp' - Label: - text: "Auto Reload" - CheckBox: - id: chkbx - active: True - size_hint_x: 1 - Button: - size_hint: None, 1 - width: '108sp' - text: 'Render Now' - on_release: root.change_kv(*args) - BoxLayout: - id: reactive_layout - orientation: 'vertical' if self.width < self.height else 'horizontal' - - Splitter: - id: editor_pane - max_size: (reactive_layout.height if self.vertical else reactive_layout.width) - self.strip_size - min_size: sp(30) + self.strip_size - vertical: 1 if reactive_layout.width < reactive_layout.height else 0 - sizable_from: 'bottom' if self.vertical else 'right' - size_hint: (1, None) if self.vertical else (None, 1) - size: 400, 400 - on_vertical: - mid_size = self.max_size/2 - if args[1]: self.height = mid_size - if not args[1]: self.width = mid_size - ScrollView: - id: kr_scroll - KivyRenderTextInput: - catalog: root - id: language_box - auto_indent: True - #lexer: MatlabLexer() - size_hint: 1, None - height: max(kr_scroll.height, self.minimum_height) - font_name: "data/fonts/DroidSansMono.ttf" - valign: "top" - text: "This box will display the kivy language for whatever has been selected" - on_text: root.schedule_reload() - on_cursor: root.schedule_reload() - ScreenManager: - id: screen_manager - Screen: - name: "Welcome" - PlaygroundContainer: - Screen: - name: "ex1" - PlaygroundContainer: - Screen: - name: "ex2" - FloatLayoutContainer - Screen: - name: "ex3" - BoxLayoutContainer: - Screen: - name: "ex4" - AnchorLayoutContainer: - Screen: - name: "ex5" - GridLayoutContainer: - Screen: - name: "ex6" - StackLayoutContainer: - Screen: - name: "ex7" - ButtonContainer: - Screen: - name: "ex8" - LabelContainer: - - FloatLayout: - size_hint: 1, None - height: 0 - TextInput: - id:info_lbl - readonly: True - font_size: '14sp' - background_color: (0, 0, 0, 1) - foreground_color: (1, 1, 1, 1) - opacity:0 - size_hint: 1, None - text_size: self.size - height: '150pt' - top: 0 diff --git a/gui/main.py b/gui/main.py deleted file mode 100755 index 97dc4ad..0000000 --- a/gui/main.py +++ /dev/null @@ -1,191 +0,0 @@ -#!/usr/bin/kivy -''' -Kivy Catalog -============ - -The Kivy Catalog viewer showcases widgets available in Kivy -and allows interactive editing of kivy language code to get immediate -feedback. You should see a two panel screen with a menu spinner button -(starting with 'Welcome') and other controls across the top.The left pane -contains kivy (.kv) code, and the right side is that code rendered. You can -edit the left pane, though changes will be lost when you use the menu -spinner button. The catalog will show you dozens of .kv examples controlling -different widgets and layouts. - -The catalog's interface is set in the file kivycatalog.kv, while the -interfaces for each menu option are set in containers_kvs directory. To -add a new .kv file to the Kivy Catalog, add a .kv file into the container_kvs -directory and reference that file in the ScreenManager section of -kivycatalog.kv. - -Known bugs include some issue with the drop -''' -import kivy -kivy.require('1.4.2') -import os -import sys -from kivy.app import App -from kivy.factory import Factory -from kivy.lang import Builder, Parser, ParserException -from kivy.properties import ObjectProperty -from kivy.config import Config -from kivy.compat import PY2 - -from kivy.uix.boxlayout import BoxLayout -from kivy.uix.codeinput import CodeInput -from kivy.animation import Animation -from kivy.clock import Clock - -CATALOG_ROOT = os.path.dirname(__file__) - -#Config.set('graphics', 'width', '1024') -#Config.set('graphics', 'height', '768') - -'''List of classes that need to be instantiated in the factory from .kv files. -''' -CONTAINER_KVS = os.path.join(CATALOG_ROOT, 'container_kvs') -CONTAINER_CLASSES = [c[:-3] for c in os.listdir(CONTAINER_KVS) - if c.endswith('.kv')] - - -class Container(BoxLayout): - '''A container is essentially a class that loads its root from a known - .kv file. - - The name of the .kv file is taken from the Container's class. - We can't just use kv rules because the class may be edited - in the interface and reloaded by the user. - See :meth: change_kv where this happens. - ''' - - def __init__(self, **kwargs): - super(Container, self).__init__(**kwargs) - self.previous_text = open(self.kv_file).read() - parser = Parser(content=self.previous_text) - widget = Factory.get(parser.root.name)() - Builder._apply_rule(widget, parser.root, parser.root) - self.add_widget(widget) - - @property - def kv_file(self): - '''Get the name of the kv file, a lowercase version of the class - name. - ''' - return os.path.join(CONTAINER_KVS, self.__class__.__name__ + '.kv') - - -for class_name in CONTAINER_CLASSES: - globals()[class_name] = type(class_name, (Container,), {}) - - -class KivyRenderTextInput(CodeInput): - def keyboard_on_key_down(self, window, keycode, text, modifiers): - is_osx = sys.platform == 'darwin' - # Keycodes on OSX: - ctrl, cmd = 64, 1024 - key, key_str = keycode - - if text and not key in (list(self.interesting_keys.keys()) + [27]): - # This allows *either* ctrl *or* cmd, but not both. - if modifiers == ['ctrl'] or (is_osx and modifiers == ['meta']): - if key == ord('s'): - self.catalog.change_kv(True) - return - - return super(KivyRenderTextInput, self).keyboard_on_key_down( - window, keycode, text, modifiers) - - -class Catalog(BoxLayout): - '''Catalog of widgets. This is the root widget of the app. It contains - a tabbed pain of widgets that can be displayed and a textbox where .kv - language files for widgets being demoed can be edited. - - The entire interface for the Catalog is defined in kivycatalog.kv, - although individual containers are defined in the container_kvs - directory. - - To add a container to the catalog, - first create the .kv file in container_kvs - The name of the file (sans .kv) will be the name of the widget available - inside the kivycatalog.kv - Finally modify kivycatalog.kv to add an AccordionItem - to hold the new widget. - Follow the examples in kivycatalog.kv to ensure the item - has an appropriate id and the class has been referenced. - - You do not need to edit any python code, just .kv language files! - ''' - language_box = ObjectProperty() - screen_manager = ObjectProperty() - - def __init__(self, **kwargs): - self._previously_parsed_text = '' - super(Catalog, self).__init__(**kwargs) - self.show_kv(None, 'Welcome') - self.carousel = None - - def show_kv(self, instance, value): - '''Called when an a item is selected, we need to show the .kv language - file associated with the newly revealed container.''' - - self.screen_manager.current = value - - child = self.screen_manager.current_screen.children[0] - with open(child.kv_file, 'rb') as file: - self.language_box.text = file.read().decode('utf8') - Clock.unschedule(self.change_kv) - self.change_kv() - # reset undo/redo history - self.language_box.reset_undo() - - def schedule_reload(self): - if self.auto_reload: - txt = self.language_box.text - child = self.screen_manager.current_screen.children[0] - if txt == child.previous_text: - return - child.previous_text = txt - Clock.unschedule(self.change_kv) - Clock.schedule_once(self.change_kv, 2) - - def change_kv(self, *largs): - '''Called when the update button is clicked. Needs to update the - interface for the currently active kv widget, if there is one based - on the kv file the user entered. If there is an error in their kv - syntax, show a nice popup.''' - - txt = self.language_box.text - kv_container = self.screen_manager.current_screen.children[0] - try: - parser = Parser(content=txt) - kv_container.clear_widgets() - widget = Factory.get(parser.root.name)() - Builder._apply_rule(widget, parser.root, parser.root) - kv_container.add_widget(widget) - except (SyntaxError, ParserException) as e: - self.show_error(e) - except Exception as e: - self.show_error(e) - - def show_error(self, e): - self.info_label.text = str(e) - self.anim = Animation(top=190.0, opacity=1, d=2, t='in_back') +\ - Animation(top=190.0, d=3) +\ - Animation(top=0, opacity=0, d=2) - self.anim.start(self.info_label) - - -class KivyCatalogApp(App): - '''The kivy App that runs the main root. All we do is build a catalog - widget into the root.''' - - def build(self): - return Catalog() - - def on_pause(self): - return True - - -if __name__ == "__main__": - KivyCatalogApp().run() From 5f6462ddd780ad1be74c1c474a8ae27f9bd589e4 Mon Sep 17 00:00:00 2001 From: Shubhojyoti Date: Fri, 30 Oct 2015 22:58:37 +0530 Subject: [PATCH 03/34] changed class name --- gui/interface.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gui/interface.py b/gui/interface.py index 8f67bf7..522a5b8 100644 --- a/gui/interface.py +++ b/gui/interface.py @@ -5,10 +5,10 @@ from kivy.uix.textinput import TextInput -class LoginScreen(BoxLayout): +class MainScreen(BoxLayout): def __init__(self, **kwargs): - super(LoginScreen, self).__init__(**kwargs) + super(MainScreen, self).__init__(**kwargs) self.orientation='vertical' self.add_widget(self.titlebar()) self.add_widget(self.maineditor()) @@ -49,7 +49,7 @@ def filebar(self): class MainApp(App): def build(self): - return LoginScreen() + return MainScreen() def on_pause(self): return True From 0e01d2af1cdea0ace54e34f41e8ed8a57923ff32 Mon Sep 17 00:00:00 2001 From: Shubhojyoti Date: Sat, 31 Oct 2015 18:04:39 +0530 Subject: [PATCH 04/34] added filebar elements --- gui/interface.py | 42 ++++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/gui/interface.py b/gui/interface.py index 522a5b8..1f794b8 100644 --- a/gui/interface.py +++ b/gui/interface.py @@ -1,3 +1,4 @@ +import os from kivy.app import App from kivy.uix.boxlayout import BoxLayout from kivy.uix.button import Button @@ -5,6 +6,21 @@ from kivy.uix.textinput import TextInput + +class generate_elements(): + def __init__(self, **args): + pass + + def files(self,excercise): + path = '../'+excercise + filelist = [c[:-3] for c in os.listdir(path) if c.endswith('.py')] + # files=[] + # for ex in filelist: + # files.append(open(path+'/'+ex)) + return filelist + def manual(self, excercise): + pass + class MainScreen(BoxLayout): def __init__(self, **kwargs): @@ -15,20 +31,20 @@ def __init__(self, **kwargs): self.add_widget(self.filebar()) def titlebar(self): - layout=BoxLayout() + layout=BoxLayout(spacing=10) layout.orientation='horizontal' - #submit = Button(text='Submit') - #submit.bind(on_press=self.submission) - #layout.add_widget(submit) - layout.add_widget(Label(text='Excercise1')) + submit = Button(text='Submit',size=(.5,.1)) + submit.bind(on_press=self.submission) + layout.add_widget(Label(text='Excercise1',size=(100,100))) layout.add_widget(Label(text='Title')) - layout.add_widget(Label(text='Submit')) + layout.add_widget(submit) return layout - def submission(self,sub): + def submission(self,instance): print('The button <%s> is being pressed' % instance.text) + def maineditor(self): layout=BoxLayout() @@ -37,19 +53,21 @@ def maineditor(self): layout.add_widget(Label(text='Instructions')) return layout - def filebar(self): + def filebar(self,excercise='ex1'): layout=BoxLayout() layout.orientation='horizontal' - layout.add_widget(Label(text='File1')) - layout.add_widget(Label(text='File2')) - layout.add_widget(Label(text='File3')) + element=generate_elements() + files = element.files(excercise) + for f in files: + layout.add_widget(Label(text=f)) + return layout class MainApp(App): def build(self): - return MainScreen() + return MainScreen() def on_pause(self): return True From ca4bc03707a3a4aa88dabea0544a0b680503ea89 Mon Sep 17 00:00:00 2001 From: Shubhojyoti Date: Sun, 1 Nov 2015 10:07:24 +0530 Subject: [PATCH 05/34] Code editor and manual added --- gui/interface.py | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/gui/interface.py b/gui/interface.py index 1f794b8..a7927e3 100644 --- a/gui/interface.py +++ b/gui/interface.py @@ -1,8 +1,11 @@ import os +import pypandoc from kivy.app import App from kivy.uix.boxlayout import BoxLayout from kivy.uix.button import Button +from kivy.uix.codeinput import CodeInput from kivy.uix.label import Label +from kivy.uix.rst import RstDocument from kivy.uix.textinput import TextInput @@ -19,13 +22,22 @@ def files(self,excercise): # files.append(open(path+'/'+ex)) return filelist def manual(self, excercise): - pass + path = 'res/'+excercise+'/manual.md' + return pypandoc.convert(path,'rst') + + def readFile(self,excercise,filename): + path = '../'+excercise+'/'+filename + f=open(path,'rw') + return f class MainScreen(BoxLayout): def __init__(self, **kwargs): super(MainScreen, self).__init__(**kwargs) self.orientation='vertical' + self.current_ex = 'ex1' + self.current_file = 'warmUpExercise.py' + self.element=generate_elements() self.add_widget(self.titlebar()) self.add_widget(self.maineditor()) self.add_widget(self.filebar()) @@ -49,15 +61,16 @@ def submission(self,instance): def maineditor(self): layout=BoxLayout() layout.orientation='horizontal' - layout.add_widget(Label(text='Code Editor')) - layout.add_widget(Label(text='Instructions')) + man = self.element.manual(self.current_ex) + code = self.element.readFile(self.current_ex,self.current_file) + layout.add_widget(CodeInput(text=code.read())) + layout.add_widget(RstDocument(text=man)) return layout def filebar(self,excercise='ex1'): layout=BoxLayout() layout.orientation='horizontal' - element=generate_elements() - files = element.files(excercise) + files = self.element.files(excercise) for f in files: layout.add_widget(Label(text=f)) From b0945b794aa7ffd406ca394246e3f95d3bfcd738 Mon Sep 17 00:00:00 2001 From: Shubhojyoti Date: Sun, 1 Nov 2015 11:24:37 +0530 Subject: [PATCH 06/34] Added filelist support for exercises --- gui/interface.py | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/gui/interface.py b/gui/interface.py index a7927e3..e0fe793 100644 --- a/gui/interface.py +++ b/gui/interface.py @@ -15,12 +15,15 @@ def __init__(self, **args): pass def files(self,excercise): - path = '../'+excercise - filelist = [c[:-3] for c in os.listdir(path) if c.endswith('.py')] - # files=[] - # for ex in filelist: - # files.append(open(path+'/'+ex)) - return filelist + path = 'res/'+excercise+'/filelist.txt' + #filelist = [c[:-3] for c in os.listdir(path) if c.endswith('.py')] + filehandler = open(path) + filelist=[] + while True: + try: + filelist.append(filehandler.next()) + except Exception, e: + return filelist def manual(self, excercise): path = 'res/'+excercise+'/manual.md' return pypandoc.convert(path,'rst') @@ -45,10 +48,10 @@ def __init__(self, **kwargs): def titlebar(self): layout=BoxLayout(spacing=10) layout.orientation='horizontal' - submit = Button(text='Submit',size=(.5,.1)) + submit = Button(text='Submit') submit.bind(on_press=self.submission) - layout.add_widget(Label(text='Excercise1',size=(100,100))) - layout.add_widget(Label(text='Title')) + layout.add_widget(Label(text='Run Exercise')) + layout.add_widget(Label(text=self.current_ex)) layout.add_widget(submit) return layout @@ -62,15 +65,17 @@ def maineditor(self): layout=BoxLayout() layout.orientation='horizontal' man = self.element.manual(self.current_ex) - code = self.element.readFile(self.current_ex,self.current_file) - layout.add_widget(CodeInput(text=code.read())) + codeFile = self.element.readFile(self.current_ex,self.current_file) + code = CodeInput(text=codeFile.read()) + + layout.add_widget(code) layout.add_widget(RstDocument(text=man)) return layout - def filebar(self,excercise='ex1'): + def filebar(self): layout=BoxLayout() layout.orientation='horizontal' - files = self.element.files(excercise) + files = self.element.files(self.current_ex) for f in files: layout.add_widget(Label(text=f)) From 2225fff1a00a6bba920ef20f1443a654509d1f43 Mon Sep 17 00:00:00 2001 From: Shubhojyoti Date: Sun, 1 Nov 2015 11:30:20 +0530 Subject: [PATCH 07/34] Run button added --- gui/interface.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/gui/interface.py b/gui/interface.py index e0fe793..4ad8efe 100644 --- a/gui/interface.py +++ b/gui/interface.py @@ -49,14 +49,18 @@ def titlebar(self): layout=BoxLayout(spacing=10) layout.orientation='horizontal' submit = Button(text='Submit') + run = Button(text='Run') + run.bind(on_press=self.run) submit.bind(on_press=self.submission) - layout.add_widget(Label(text='Run Exercise')) + layout.add_widget(run) layout.add_widget(Label(text=self.current_ex)) layout.add_widget(submit) return layout + def run(self,instance): + print('The button <%s> is being pressed' % instance.text) def submission(self,instance): print('The button <%s> is being pressed' % instance.text) From d600765215e63135e9912acae1c1182940e80b85 Mon Sep 17 00:00:00 2001 From: Shubhojyoti Date: Sun, 1 Nov 2015 14:15:16 +0530 Subject: [PATCH 08/34] filebar buttons added --- gui/interface.py | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/gui/interface.py b/gui/interface.py index 4ad8efe..4a2130f 100644 --- a/gui/interface.py +++ b/gui/interface.py @@ -7,7 +7,7 @@ from kivy.uix.label import Label from kivy.uix.rst import RstDocument from kivy.uix.textinput import TextInput - +from kivy.metrics import dp class generate_elements(): @@ -48,12 +48,13 @@ def __init__(self, **kwargs): def titlebar(self): layout=BoxLayout(spacing=10) layout.orientation='horizontal' - submit = Button(text='Submit') - run = Button(text='Run') + submit = Button(text='Submit',size_hint=(0.4,1)) + run = Button(text='Run',size_hint=(0.4,1)) run.bind(on_press=self.run) submit.bind(on_press=self.submission) + title = Label(text=self.current_ex,size_hint=(1,1),font_size='35sp') layout.add_widget(run) - layout.add_widget(Label(text=self.current_ex)) + layout.add_widget(title) layout.add_widget(submit) return layout @@ -67,24 +68,37 @@ def submission(self,instance): def maineditor(self): layout=BoxLayout() - layout.orientation='horizontal' + layout.orientation='horizontal' man = self.element.manual(self.current_ex) codeFile = self.element.readFile(self.current_ex,self.current_file) code = CodeInput(text=codeFile.read()) - layout.add_widget(code) layout.add_widget(RstDocument(text=man)) return layout + + + def update_man(): + pass def filebar(self): layout=BoxLayout() layout.orientation='horizontal' files = self.element.files(self.current_ex) for f in files: - layout.add_widget(Label(text=f)) + button = Button(text=f) + button.bind(on_press=self.update_code) + layout.add_widget(button) return layout + #Use bind to see how it works + def update_code(self,instance): + if instance.text.endswith('\n'): + instance.text=instance.text[:-1] + self.current_file = instance.text + self.add_widget(self.maineditor()) + print 'Current file changed to: ', self.current_file + class MainApp(App): From 665b1a61e0c2838d775576f94b0d4f2f63199df9 Mon Sep 17 00:00:00 2001 From: Shubhojyoti Date: Sun, 1 Nov 2015 14:52:09 +0530 Subject: [PATCH 09/34] Spinner added --- gui/interface.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/gui/interface.py b/gui/interface.py index 4a2130f..989f090 100644 --- a/gui/interface.py +++ b/gui/interface.py @@ -7,7 +7,8 @@ from kivy.uix.label import Label from kivy.uix.rst import RstDocument from kivy.uix.textinput import TextInput -from kivy.metrics import dp +#from kivy.metrics import dp +from kivy.uix.spinner import Spinner class generate_elements(): @@ -68,7 +69,8 @@ def submission(self,instance): def maineditor(self): layout=BoxLayout() - layout.orientation='horizontal' + layout.orientation='horizontal' + #self.bind(self.current_ex=self.update_code) man = self.element.manual(self.current_ex) codeFile = self.element.readFile(self.current_ex,self.current_file) code = CodeInput(text=codeFile.read()) @@ -95,7 +97,7 @@ def filebar(self): def update_code(self,instance): if instance.text.endswith('\n'): instance.text=instance.text[:-1] - self.current_file = instance.text + self.current_file = instance.text self.add_widget(self.maineditor()) print 'Current file changed to: ', self.current_file From 533d0a44c956f510e6e0c52f5a4cbfe7bb7305f8 Mon Sep 17 00:00:00 2001 From: Shubhojyoti Date: Sun, 1 Nov 2015 15:38:08 +0530 Subject: [PATCH 10/34] code editor fixed --- gui/interface.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/gui/interface.py b/gui/interface.py index 989f090..ef08c2c 100644 --- a/gui/interface.py +++ b/gui/interface.py @@ -42,10 +42,13 @@ def __init__(self, **kwargs): self.current_ex = 'ex1' self.current_file = 'warmUpExercise.py' self.element=generate_elements() - self.add_widget(self.titlebar()) - self.add_widget(self.maineditor()) - self.add_widget(self.filebar()) + self.draw_screen() + def draw_screen(self): + self.add_widget(self.titlebar()) + self.add_widget(self.maineditor()) + self.add_widget(self.filebar()) + def titlebar(self): layout=BoxLayout(spacing=10) layout.orientation='horizontal' @@ -98,7 +101,8 @@ def update_code(self,instance): if instance.text.endswith('\n'): instance.text=instance.text[:-1] self.current_file = instance.text - self.add_widget(self.maineditor()) + self.clear_widgets() + self.draw_screen() print 'Current file changed to: ', self.current_file From 39ae7e97f94e69bed2b132005aeec653e1b3a0a9 Mon Sep 17 00:00:00 2001 From: Shubhojyoti Date: Sun, 1 Nov 2015 16:06:39 +0530 Subject: [PATCH 11/34] Splitter added --- gui/interface.py | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/gui/interface.py b/gui/interface.py index ef08c2c..04a4a7b 100644 --- a/gui/interface.py +++ b/gui/interface.py @@ -9,6 +9,7 @@ from kivy.uix.textinput import TextInput #from kivy.metrics import dp from kivy.uix.spinner import Spinner +from kivy.uix.splitter import Splitter class generate_elements(): @@ -52,11 +53,15 @@ def draw_screen(self): def titlebar(self): layout=BoxLayout(spacing=10) layout.orientation='horizontal' + submit = Button(text='Submit',size_hint=(0.4,1)) + submit.bind(on_press=self.submission) + run = Button(text='Run',size_hint=(0.4,1)) run.bind(on_press=self.run) - submit.bind(on_press=self.submission) + title = Label(text=self.current_ex,size_hint=(1,1),font_size='35sp') + layout.add_widget(run) layout.add_widget(title) layout.add_widget(submit) @@ -72,12 +77,24 @@ def submission(self,instance): def maineditor(self): layout=BoxLayout() - layout.orientation='horizontal' - #self.bind(self.current_ex=self.update_code) + #reactive layout not working + + if self.width < self.height: + layout.orientation='vertical' + else: + layout.orientation='horizontal' + #self.bind(self.current_ex=self.update_currentFile) man = self.element.manual(self.current_ex) codeFile = self.element.readFile(self.current_ex,self.current_file) code = CodeInput(text=codeFile.read()) - layout.add_widget(code) + splitter = Splitter() + if layout.orientation == 'vertical': + splitter.sizable_from='bottom' + else: + splitter.sizable_from='right' + splitter.add_widget(code) + layout.add_widget(splitter) + layout.add_widget(RstDocument(text=man)) return layout @@ -91,13 +108,13 @@ def filebar(self): files = self.element.files(self.current_ex) for f in files: button = Button(text=f) - button.bind(on_press=self.update_code) + button.bind(on_press=self.update_currentFile) layout.add_widget(button) return layout #Use bind to see how it works - def update_code(self,instance): + def update_currentFile(self,instance): if instance.text.endswith('\n'): instance.text=instance.text[:-1] self.current_file = instance.text From 9496a6aa05a590b425ee546f17bb6ccebd776192 Mon Sep 17 00:00:00 2001 From: Shubhojyoti Date: Sun, 1 Nov 2015 16:48:41 +0530 Subject: [PATCH 12/34] fixed layout heights --- gui/interface.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gui/interface.py b/gui/interface.py index 04a4a7b..f870773 100644 --- a/gui/interface.py +++ b/gui/interface.py @@ -51,7 +51,7 @@ def draw_screen(self): self.add_widget(self.filebar()) def titlebar(self): - layout=BoxLayout(spacing=10) + layout=BoxLayout(padding='2sp',size_hint=(1,None),height='65sp') layout.orientation='horizontal' submit = Button(text='Submit',size_hint=(0.4,1)) @@ -103,7 +103,7 @@ def maineditor(self): def update_man(): pass def filebar(self): - layout=BoxLayout() + layout=BoxLayout(padding='2sp',size_hint=(1,None),height='100sp') layout.orientation='horizontal' files = self.element.files(self.current_ex) for f in files: From 6e7aef9a21ab715ed2db4faebeb0377c884d83df Mon Sep 17 00:00:00 2001 From: Shubhojyoti Date: Sun, 1 Nov 2015 16:51:18 +0530 Subject: [PATCH 13/34] Resources added to repo --- gui/res/ex1/filelist.txt | 3 +++ gui/res/ex1/manual.md | 29 +++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 gui/res/ex1/filelist.txt create mode 100644 gui/res/ex1/manual.md diff --git a/gui/res/ex1/filelist.txt b/gui/res/ex1/filelist.txt new file mode 100644 index 0000000..f0834b7 --- /dev/null +++ b/gui/res/ex1/filelist.txt @@ -0,0 +1,3 @@ +warmUpExercise.py +plotData.py +normalEqn.py \ No newline at end of file diff --git a/gui/res/ex1/manual.md b/gui/res/ex1/manual.md new file mode 100644 index 0000000..0517a54 --- /dev/null +++ b/gui/res/ex1/manual.md @@ -0,0 +1,29 @@ +#Exercise 1: Linear Regression +>Coursera Assignment 1 of linear regression + + +I have always been fascinated by people - their impromptu, unconditioned actions governed by preconceived perceptions rising from base emotions and past experiences; the innumerous masks that they put on to hide a trivial truth; their insatiable hunger for causes that mean nothing to them. +This had made me curious if it was possible to understand all the underlying foundations for a person's actions tracing it back to the baser emotions or experiences and whether it was possible to influnce people with crafted experiences which could lead to a possible action in an unforseeable future. + + +In my quest for understanding people, I quickly concluded that there was no singular governing cause that drives all mankind. Each person is unique in his own way and there can be no generalization in human behaviour. But, there does exist a general structure in which people construct their behaviour and build upon it. So, to see people for what they really are it is important to understand the thought process of people rather than the thoughts itself. + +To understand these thought processes, I devised carefully crafted situations and tactfully let myself and my peers get involved in my game without their knowledge while I silently noted down each person's reactions and how they interacted and gained profound knowledge about their most innate proclivities. In due course, I was so consumed in this game that I lost all connection to myself. To truly understand what everyone is going through, I had to involve myself in this game and yet remain unattached to my own emotions so as to remain in full control of my senses. Slowly and steadily, I had detached myself from all worldly emotions. Finally, there came a moment when I realized. +>Blocking emotions is like wearing an armour. I will be safe from the bullets but I will never feel the breeze. + +There was a wave of understanding that hit me like thunder and I realized I haven't learned anything. When people were reacting to a situation that I created, they were influenced by my thoughts indirectly and as a result all of their actions henceforth was a product of my thought pattern. The true variability and randomness in every person's thought pattern was lost and there was no way to predict their unique thought process as the process had become rigged. +To truly understand someone's thought person, I can't influence them but I need to be influenced by them. Only then can I dwelve into the various unique thought processes in order to gain deep knowledge about them. + +Thereby, I set upon a new milestone in my quest where I needed to collect as many minds as I can until I can accurately understand the nature of human thought. I needed to relate to people in the most basest form possible and build up upon them. Sadly, I do not have a very active social life or sibblings whom I can experiment. Naturally, I chose facebook and other social media my means of finding people who can open up to me and I to them so that I can relate to them in the deepest way. + +It was no mere coincidence that I found my way amongst female company a lot as girls tend to get very emotional and are looking for someone to open up to and I was a guy looking for people to open up to me. In due course, I became very good at it and I did learn a get deal, no doubt. But this post is not about my findings but rather my psyche and how I dealt with whatever I found. + +No sooner than later, I became acquainted with so many different types of psychologies and thought processes that I could relate to new people by fitting them to a psychology from my existing reservoir. Added to this my observational skills and I could tell lot about a person with just one glance. Progressively and with subsequent encounters I could not just tell about a person but I could replicate their entire thought process in my brain. With time, I got so good at it that this replication was nearly flawless and it was like harbouring a new mind in my old brain. I was like mirroring the person who was closest to me. I was so drawn into it that this had become my habbit and I could do this subconsciously until it finally reached to a point when I could no longer control it but rather it controlled me. + +>The painful realization hit me that I had no mind of my own. Like a snake changes skins and moves on to survive, I change personalitites to keep moving. I have become a sum of everyone around me while I lost myself from within me. + +The reaction of people to my uniqueness was something I couldn't fathom. Though, every person immediately related to me when they saw similarities to themselves yet they became very self-aware when the similarities became more vivid and as I became more like a reflection of themselves. It was very disturbing for most of them to see a version of themselves with all the perfection and imperfection that they have but within a different body. People with even a slightly low self esteem could not reconcile to the reality of the reflection that they were seeing in front of them. Finally, in order to save them from themselves, I had to distance myself from them and it was my time to move on. I could have no friends no people with whom I can share my life. + +>Was loneliness the price for wisdom? + +I am filled with fear of the unknown. I don't know what I have become. Am I good or evil? In my search, have I let myself become something I do not want to face? Can I recover? \ No newline at end of file From c3043ae48256fb65ccb72bf5a33cf24c21339bd2 Mon Sep 17 00:00:00 2001 From: Shubhojyoti Date: Sun, 1 Nov 2015 17:20:29 +0530 Subject: [PATCH 14/34] dropdown menu added --- gui/interface.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/gui/interface.py b/gui/interface.py index f870773..b39c0c2 100644 --- a/gui/interface.py +++ b/gui/interface.py @@ -16,6 +16,8 @@ class generate_elements(): def __init__(self, **args): pass + + def files(self,excercise): path = 'res/'+excercise+'/filelist.txt' #filelist = [c[:-3] for c in os.listdir(path) if c.endswith('.py')] @@ -60,10 +62,13 @@ def titlebar(self): run = Button(text='Run',size_hint=(0.4,1)) run.bind(on_press=self.run) - title = Label(text=self.current_ex,size_hint=(1,1),font_size='35sp') + ex_dropdown = Spinner(text='Welcome',size_hint=(1,1)) + ex_dropdown.values = os.listdir('./res/') + + #title = Label(text=self.current_ex,size_hint=(1,1),font_size='35sp') layout.add_widget(run) - layout.add_widget(title) + layout.add_widget(ex_dropdown) layout.add_widget(submit) return layout From 3f165870efbc2e206bc54a1f25ace55c015209ef Mon Sep 17 00:00:00 2001 From: Shubhojyoti Date: Sun, 1 Nov 2015 20:11:13 +0530 Subject: [PATCH 15/34] completed dropdown menu --- gui/interface.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/gui/interface.py b/gui/interface.py index b39c0c2..0f96eac 100644 --- a/gui/interface.py +++ b/gui/interface.py @@ -64,6 +64,7 @@ def titlebar(self): ex_dropdown = Spinner(text='Welcome',size_hint=(1,1)) ex_dropdown.values = os.listdir('./res/') + ex_dropdown.bind(text=self.updateExercise) #title = Label(text=self.current_ex,size_hint=(1,1),font_size='35sp') @@ -74,6 +75,20 @@ def titlebar(self): return layout + def updateExercise(self,spinner,text): + self.current_ex=text + spinner.text=text + current_file = self.element.files(self.current_ex)[0] + if current_file.endswith('\n'): + current_file=current_file[:-1] + self.current_file= current_file + self.clear_widgets() + self.draw_screen() + print('The spinner', spinner, 'have text', text) + print 'Current file changed to: ', self.current_ex + + + def run(self,instance): print('The button <%s> is being pressed' % instance.text) def submission(self,instance): @@ -105,8 +120,7 @@ def maineditor(self): - def update_man(): - pass + def filebar(self): layout=BoxLayout(padding='2sp',size_hint=(1,None),height='100sp') layout.orientation='horizontal' From 0b47594d599a9881c3702f50b2c40cd91c0535f3 Mon Sep 17 00:00:00 2001 From: Shubhojyoti Date: Sun, 1 Nov 2015 20:25:31 +0530 Subject: [PATCH 16/34] changed name of app to coursera --- gui/interface.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/gui/interface.py b/gui/interface.py index 0f96eac..47a9b3d 100644 --- a/gui/interface.py +++ b/gui/interface.py @@ -62,7 +62,7 @@ def titlebar(self): run = Button(text='Run',size_hint=(0.4,1)) run.bind(on_press=self.run) - ex_dropdown = Spinner(text='Welcome',size_hint=(1,1)) + ex_dropdown = Spinner(text='Select Exercise',size_hint=(1,1)) ex_dropdown.values = os.listdir('./res/') ex_dropdown.bind(text=self.updateExercise) @@ -77,7 +77,6 @@ def titlebar(self): def updateExercise(self,spinner,text): self.current_ex=text - spinner.text=text current_file = self.element.files(self.current_ex)[0] if current_file.endswith('\n'): current_file=current_file[:-1] @@ -142,7 +141,7 @@ def update_currentFile(self,instance): print 'Current file changed to: ', self.current_file -class MainApp(App): +class CourseraApp(App): def build(self): return MainScreen() @@ -151,4 +150,4 @@ def on_pause(self): if __name__ == '__main__': - MainApp().run() \ No newline at end of file + CourseraApp().run() \ No newline at end of file From c74dcc53582756518fbbb95cbdc29f9806ab29e1 Mon Sep 17 00:00:00 2001 From: Shubhojyoti Date: Sun, 1 Nov 2015 20:44:59 +0530 Subject: [PATCH 17/34] popup added --- gui/interface.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/gui/interface.py b/gui/interface.py index 47a9b3d..ee8c09d 100644 --- a/gui/interface.py +++ b/gui/interface.py @@ -10,6 +10,7 @@ #from kivy.metrics import dp from kivy.uix.spinner import Spinner from kivy.uix.splitter import Splitter +from kivy.uix.popup import Popup class generate_elements(): @@ -56,8 +57,11 @@ def titlebar(self): layout=BoxLayout(padding='2sp',size_hint=(1,None),height='65sp') layout.orientation='horizontal' + submit_popup = Popup(title='Enter credentials',content=Label(text='Hello world'), + size_hint=(0.5, 0.5)) + submit = Button(text='Submit',size_hint=(0.4,1)) - submit.bind(on_press=self.submission) + submit.bind(on_press=submit_popup.open) run = Button(text='Run',size_hint=(0.4,1)) run.bind(on_press=self.run) From 089574da7bf7bba15225232daa875a263e817e6b Mon Sep 17 00:00:00 2001 From: Shubhojyoti Date: Sun, 1 Nov 2015 23:20:03 +0530 Subject: [PATCH 18/34] submission popup added --- gui/interface.py | 71 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 58 insertions(+), 13 deletions(-) diff --git a/gui/interface.py b/gui/interface.py index ee8c09d..7c59acb 100644 --- a/gui/interface.py +++ b/gui/interface.py @@ -2,12 +2,12 @@ import pypandoc from kivy.app import App from kivy.uix.boxlayout import BoxLayout +from kivy.uix.gridlayout import GridLayout from kivy.uix.button import Button from kivy.uix.codeinput import CodeInput from kivy.uix.label import Label from kivy.uix.rst import RstDocument from kivy.uix.textinput import TextInput -#from kivy.metrics import dp from kivy.uix.spinner import Spinner from kivy.uix.splitter import Splitter from kivy.uix.popup import Popup @@ -18,10 +18,20 @@ def __init__(self, **args): pass - + def read_token(self,instance): + path = '../'+instance.current_ex+'/token.txt' + try: + credentials = open(path) + instance.email = credentials.readline()[:-1] + instance.token = credentials.readline()[:-1] + return True + except Exception, e: + return False + + + def files(self,excercise): path = 'res/'+excercise+'/filelist.txt' - #filelist = [c[:-3] for c in os.listdir(path) if c.endswith('.py')] filehandler = open(path) filelist=[] while True: @@ -46,6 +56,11 @@ def __init__(self, **kwargs): self.current_ex = 'ex1' self.current_file = 'warmUpExercise.py' self.element=generate_elements() + #popup = Popup(title='CourseraApp', content=Label(text='Hello World'),size_hint=(0.6, 0.35)) + #popup.open() + #sleep(10) + #popup.dismiss() + self.draw_screen() def draw_screen(self): @@ -57,11 +72,15 @@ def titlebar(self): layout=BoxLayout(padding='2sp',size_hint=(1,None),height='65sp') layout.orientation='horizontal' - submit_popup = Popup(title='Enter credentials',content=Label(text='Hello world'), - size_hint=(0.5, 0.5)) - - submit = Button(text='Submit',size_hint=(0.4,1)) - submit.bind(on_press=submit_popup.open) + #credentials = self.accept_credentials() + self.submit_popup = Popup(title='Enter credentials',content=self.accept_credentials(),size_hint=(0.6, 0.35)) + #credentials.children[1].bind(on_press=self.submit_popup.dismiss) + + submit = Button(text='Submit',size_hint=(0.4,1)) + if self.element.read_token(self): + submit.bind(on_press=self.submit_assignment) + else: + submit.bind(on_press=self.submit_popup.open) run = Button(text='Run',size_hint=(0.4,1)) run.bind(on_press=self.run) @@ -70,8 +89,6 @@ def titlebar(self): ex_dropdown.values = os.listdir('./res/') ex_dropdown.bind(text=self.updateExercise) - #title = Label(text=self.current_ex,size_hint=(1,1),font_size='35sp') - layout.add_widget(run) layout.add_widget(ex_dropdown) layout.add_widget(submit) @@ -79,6 +96,35 @@ def titlebar(self): return layout + def accept_credentials(self): + main_layout= BoxLayout(padding='2sp') + main_layout.orientation='vertical' + layout=GridLayout(padding='2sp',size_hint=(1,None)) + layout.cols=2 + layout.add_widget(Label(text='Email id:')) + email = TextInput(multiline=False) + email.bind(on_text_validate=self.update_email) + layout.add_widget(email) + token = TextInput(multiline=False) + token.bind(on_text_validate=self.update_token) + layout.add_widget(Label(text='Submission Token:')) + layout.add_widget(token) + main_layout.add_widget(layout) + submit = Button(text='Submit') + submit.bind(on_press=self.submit_assignment) + main_layout.add_widget(submit) + return main_layout + + def update_email(self,instance): + self.email=instance.text + def update_token(self,instance): + self.token=instance.text + + def submit_assignment(self,instance): + print 'Email',self.email + print 'Token', self.token + self.submit_popup.dismiss() + def updateExercise(self,spinner,text): self.current_ex=text current_file = self.element.files(self.current_ex)[0] @@ -87,7 +133,6 @@ def updateExercise(self,spinner,text): self.current_file= current_file self.clear_widgets() self.draw_screen() - print('The spinner', spinner, 'have text', text) print 'Current file changed to: ', self.current_ex @@ -153,5 +198,5 @@ def on_pause(self): return True -if __name__ == '__main__': - CourseraApp().run() \ No newline at end of file +if __name__ == '__main__': + CourseraApp().run() \ No newline at end of file From 2cb9f8ae97593c3e38117aeb0ae133e8c8d80968 Mon Sep 17 00:00:00 2001 From: Shubhojyoti Date: Mon, 2 Nov 2015 11:47:33 +0530 Subject: [PATCH 19/34] autosave feature tried, bug prone --- gui/interface.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/gui/interface.py b/gui/interface.py index 7c59acb..b00c7d4 100644 --- a/gui/interface.py +++ b/gui/interface.py @@ -11,6 +11,8 @@ from kivy.uix.spinner import Spinner from kivy.uix.splitter import Splitter from kivy.uix.popup import Popup +from kivy.clock import Clock +from functools import partial class generate_elements(): @@ -133,14 +135,12 @@ def updateExercise(self,spinner,text): self.current_file= current_file self.clear_widgets() self.draw_screen() - print 'Current file changed to: ', self.current_ex + print 'Current Exercise changed to: ', self.current_ex def run(self,instance): print('The button <%s> is being pressed' % instance.text) - def submission(self,instance): - print('The button <%s> is being pressed' % instance.text) def maineditor(self): @@ -155,6 +155,7 @@ def maineditor(self): man = self.element.manual(self.current_ex) codeFile = self.element.readFile(self.current_ex,self.current_file) code = CodeInput(text=codeFile.read()) + code.bind(focus =self.schedule_reload) splitter = Splitter() if layout.orientation == 'vertical': splitter.sizable_from='bottom' @@ -166,8 +167,18 @@ def maineditor(self): layout.add_widget(RstDocument(text=man)) return layout - - + def updateAssignment(self,assignment,*largs): + filehandler = self.element.readFile(self.current_ex,self.current_file) + filehandler.write(assignment.text) + + def schedule_reload(self,instance,value): + if value: + #Schedule Update + Clock.schedule_interval(partial(self.updateAssignment,instance),5) + else: + Clock.unschedule(partial(self.updateAssignment,instance)) + self.updateAssignment(instance) + #Update now def filebar(self): layout=BoxLayout(padding='2sp',size_hint=(1,None),height='100sp') From 35b36f11c072bb34b880f3e4b86027e9b32b0f8a Mon Sep 17 00:00:00 2001 From: Shubhojyoti Date: Tue, 3 Nov 2015 00:23:25 +0530 Subject: [PATCH 20/34] autosaves only updates --- gui/interface.py | 69 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 20 deletions(-) diff --git a/gui/interface.py b/gui/interface.py index b00c7d4..5ad599e 100644 --- a/gui/interface.py +++ b/gui/interface.py @@ -13,6 +13,7 @@ from kivy.uix.popup import Popup from kivy.clock import Clock from functools import partial +from kivy.animation import Animation class generate_elements(): @@ -45,11 +46,16 @@ def manual(self, excercise): path = 'res/'+excercise+'/manual.md' return pypandoc.convert(path,'rst') - def readFile(self,excercise,filename): + def writeFile(self,excercise,filename): path = '../'+excercise+'/'+filename - f=open(path,'rw') + f=open(path,'w') return f + def readFile(self,excercise,filename): + path = '../'+excercise+'/'+filename + f=open(path,'r') + return f.read() + class MainScreen(BoxLayout): def __init__(self, **kwargs): @@ -65,6 +71,7 @@ def __init__(self, **kwargs): self.draw_screen() + def draw_screen(self): self.add_widget(self.titlebar()) self.add_widget(self.maineditor()) @@ -80,7 +87,7 @@ def titlebar(self): submit = Button(text='Submit',size_hint=(0.4,1)) if self.element.read_token(self): - submit.bind(on_press=self.submit_assignment) + submit.bind(on_press=partial(self.submit_assignment)) else: submit.bind(on_press=self.submit_popup.open) @@ -105,27 +112,28 @@ def accept_credentials(self): layout.cols=2 layout.add_widget(Label(text='Email id:')) email = TextInput(multiline=False) - email.bind(on_text_validate=self.update_email) layout.add_widget(email) token = TextInput(multiline=False) - token.bind(on_text_validate=self.update_token) layout.add_widget(Label(text='Submission Token:')) layout.add_widget(token) main_layout.add_widget(layout) submit = Button(text='Submit') - submit.bind(on_press=self.submit_assignment) + submit.bind(on_press=partial(self.submit_assignment,email,token)) main_layout.add_widget(submit) return main_layout - def update_email(self,instance): - self.email=instance.text - def update_token(self,instance): - self.token=instance.text - - def submit_assignment(self,instance): - print 'Email',self.email - print 'Token', self.token + def submit_assignment(self,*largs): + if len(largs)>1: + email = largs[0].text + token = largs[1].text + else: + email=self.email + token=self.token + + print 'Email',email + print 'Token', token self.submit_popup.dismiss() + #TODO:submission call def updateExercise(self,spinner,text): self.current_ex=text @@ -140,6 +148,7 @@ def updateExercise(self,spinner,text): def run(self,instance): + #TODO: Display output in popup print('The button <%s> is being pressed' % instance.text) @@ -154,7 +163,7 @@ def maineditor(self): #self.bind(self.current_ex=self.update_currentFile) man = self.element.manual(self.current_ex) codeFile = self.element.readFile(self.current_ex,self.current_file) - code = CodeInput(text=codeFile.read()) + code = CodeInput(text=codeFile) code.bind(focus =self.schedule_reload) splitter = Splitter() if layout.orientation == 'vertical': @@ -168,17 +177,27 @@ def maineditor(self): return layout def updateAssignment(self,assignment,*largs): - filehandler = self.element.readFile(self.current_ex,self.current_file) - filehandler.write(assignment.text) + try: + if not self.element.readFile(self.current_ex,self.current_file)==assignment.text: + filehandler = self.element.writeFile(self.current_ex,self.current_file) + filehandler.write(assignment.text) + #print 'INFO: Autosaved' + except Exception, e: + raise e + #self.show_error(e) + def schedule_reload(self,instance,value): + self.callback = partial(self.updateAssignment,instance) if value: #Schedule Update - Clock.schedule_interval(partial(self.updateAssignment,instance),5) + Clock.schedule_interval(self.callback,5) else: - Clock.unschedule(partial(self.updateAssignment,instance)) + #TODO:Unsceduling not working properly. Autosave feature cannot be turned off automatically + Clock.unschedule(self.callback) self.updateAssignment(instance) #Update now + def filebar(self): layout=BoxLayout(padding='2sp',size_hint=(1,None),height='100sp') @@ -200,6 +219,16 @@ def update_currentFile(self,instance): self.draw_screen() print 'Current file changed to: ', self.current_file + def show_error(self, e): + print 'Error',str(e) + info_label = Label(text=str(e)) + #self.anim = Animation(top=190.0, opacity=1, d=2) +\ + # Animation(top=190.0, d=3) +\ + # Animation(top=0, opacity=0, d=2) + anim = Animation(x=10,y=10) + anim.start(info_label) + + class CourseraApp(App): @@ -210,4 +239,4 @@ def on_pause(self): if __name__ == '__main__': - CourseraApp().run() \ No newline at end of file + CourseraApp().run() From 60b4f6a05ba2bcecca2dbda4b9284f159a795cc1 Mon Sep 17 00:00:00 2001 From: Shubhojyoti Date: Tue, 3 Nov 2015 08:53:25 +0530 Subject: [PATCH 21/34] autosave unscheduling bug fixed --- gui/interface.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/gui/interface.py b/gui/interface.py index 5ad599e..a91356b 100644 --- a/gui/interface.py +++ b/gui/interface.py @@ -53,6 +53,7 @@ def writeFile(self,excercise,filename): def readFile(self,excercise,filename): path = '../'+excercise+'/'+filename + #print 'Opening ',path f=open(path,'r') return f.read() @@ -177,25 +178,26 @@ def maineditor(self): return layout def updateAssignment(self,assignment,*largs): + print 'callback called' try: if not self.element.readFile(self.current_ex,self.current_file)==assignment.text: filehandler = self.element.writeFile(self.current_ex,self.current_file) filehandler.write(assignment.text) - #print 'INFO: Autosaved' + print 'INFO: Autosaved file' except Exception, e: raise e #self.show_error(e) def schedule_reload(self,instance,value): - self.callback = partial(self.updateAssignment,instance) if value: #Schedule Update + self.callback = partial(self.updateAssignment,instance) Clock.schedule_interval(self.callback,5) else: - #TODO:Unsceduling not working properly. Autosave feature cannot be turned off automatically + #When clicking on another file, both focus=False and button bound callbacks are executed simultaneously Clock.unschedule(self.callback) - self.updateAssignment(instance) + #self.updateAssignment(instance) #Update now From b9804a65b326ba94578ddce95f0c742576b83524 Mon Sep 17 00:00:00 2001 From: Shubhojyoti Date: Tue, 3 Nov 2015 12:05:23 +0530 Subject: [PATCH 22/34] console animation added --- gui/interface.py | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/gui/interface.py b/gui/interface.py index a91356b..1be06fe 100644 --- a/gui/interface.py +++ b/gui/interface.py @@ -3,6 +3,7 @@ from kivy.app import App from kivy.uix.boxlayout import BoxLayout from kivy.uix.gridlayout import GridLayout +from kivy.uix.floatlayout import FloatLayout from kivy.uix.button import Button from kivy.uix.codeinput import CodeInput from kivy.uix.label import Label @@ -77,6 +78,7 @@ def draw_screen(self): self.add_widget(self.titlebar()) self.add_widget(self.maineditor()) self.add_widget(self.filebar()) + self.add_widget(self.console()) def titlebar(self): layout=BoxLayout(padding='2sp',size_hint=(1,None),height='65sp') @@ -106,6 +108,17 @@ def titlebar(self): return layout + def console(self): + layout = FloatLayout(size_hint=(1,None),height=100) + self.info_label = TextInput(size_hint=(1,None),readonly=True,background_color=(0,0,0,1),foreground_color=(1,1,1,1),opacity=0) + self.info_label.text_size = self.size + self.info_label.text = 'console' + self.info_label.height = '150pt' + self.info_label.top = 0 + layout.add_widget(self.info_label) + return layout + + def accept_credentials(self): main_layout= BoxLayout(padding='2sp') main_layout.orientation='vertical' @@ -150,12 +163,13 @@ def updateExercise(self,spinner,text): def run(self,instance): #TODO: Display output in popup + self.show_error('Cannot be run') print('The button <%s> is being pressed' % instance.text) def maineditor(self): layout=BoxLayout() - #reactive layout not working + #TODO:reactive layout not working if self.width < self.height: layout.orientation='vertical' @@ -177,7 +191,7 @@ def maineditor(self): layout.add_widget(RstDocument(text=man)) return layout - def updateAssignment(self,assignment,*largs): + def saveAssignment(self,assignment,*largs): print 'callback called' try: if not self.element.readFile(self.current_ex,self.current_file)==assignment.text: @@ -192,12 +206,12 @@ def updateAssignment(self,assignment,*largs): def schedule_reload(self,instance,value): if value: #Schedule Update - self.callback = partial(self.updateAssignment,instance) + self.callback = partial(self.saveAssignment,instance) Clock.schedule_interval(self.callback,5) else: #When clicking on another file, both focus=False and button bound callbacks are executed simultaneously Clock.unschedule(self.callback) - #self.updateAssignment(instance) + #self.saveAssignment(instance) #Update now @@ -222,13 +236,11 @@ def update_currentFile(self,instance): print 'Current file changed to: ', self.current_file def show_error(self, e): - print 'Error',str(e) - info_label = Label(text=str(e)) - #self.anim = Animation(top=190.0, opacity=1, d=2) +\ - # Animation(top=190.0, d=3) +\ - # Animation(top=0, opacity=0, d=2) - anim = Animation(x=10,y=10) - anim.start(info_label) + self.info_label.text = str(e) + anim = Animation(top=190.0, opacity=1, d=2) +\ + Animation(top=190.0, d=3) +\ + Animation(top=0, opacity=0, d=2) + anim.start(self.info_label) From 8052c4a621d446fc4de93a3ed6bf6738feead3e0 Mon Sep 17 00:00:00 2001 From: Shubhojyoti Date: Tue, 3 Nov 2015 13:50:50 +0530 Subject: [PATCH 23/34] submit button made reactive --- gui/interface.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gui/interface.py b/gui/interface.py index 1be06fe..8eec19d 100644 --- a/gui/interface.py +++ b/gui/interface.py @@ -122,7 +122,7 @@ def console(self): def accept_credentials(self): main_layout= BoxLayout(padding='2sp') main_layout.orientation='vertical' - layout=GridLayout(padding='2sp',size_hint=(1,None)) + layout=GridLayout(padding='2sp') layout.cols=2 layout.add_widget(Label(text='Email id:')) email = TextInput(multiline=False) @@ -131,7 +131,7 @@ def accept_credentials(self): layout.add_widget(Label(text='Submission Token:')) layout.add_widget(token) main_layout.add_widget(layout) - submit = Button(text='Submit') + submit = Button(text='Submit',size_hint=(1,0.4)) submit.bind(on_press=partial(self.submit_assignment,email,token)) main_layout.add_widget(submit) return main_layout @@ -209,7 +209,7 @@ def schedule_reload(self,instance,value): self.callback = partial(self.saveAssignment,instance) Clock.schedule_interval(self.callback,5) else: - #When clicking on another file, both focus=False and button bound callbacks are executed simultaneously + #When clicking on another file, both focus=False and filebar button callbacks are executed simultaneously leading to deadlock Clock.unschedule(self.callback) #self.saveAssignment(instance) #Update now From 6c103c2ba7bf0aa6560609344743482ab585577f Mon Sep 17 00:00:00 2001 From: Shubhojyoti Date: Tue, 3 Nov 2015 16:57:44 +0530 Subject: [PATCH 24/34] linked with submission --- gui/interface.py | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/gui/interface.py b/gui/interface.py index 8eec19d..327d1a2 100644 --- a/gui/interface.py +++ b/gui/interface.py @@ -15,6 +15,7 @@ from kivy.clock import Clock from functools import partial from kivy.animation import Animation +from Submission import Submission class generate_elements(): @@ -26,8 +27,8 @@ def read_token(self,instance): path = '../'+instance.current_ex+'/token.txt' try: credentials = open(path) - instance.email = credentials.readline()[:-1] - instance.token = credentials.readline()[:-1] + instance.email = credentials.readline().split() + instance.token = credentials.readline().split() return True except Exception, e: return False @@ -53,6 +54,8 @@ def writeFile(self,excercise,filename): return f def readFile(self,excercise,filename): + print excercise + print filename path = '../'+excercise+'/'+filename #print 'Opening ',path f=open(path,'r') @@ -65,6 +68,7 @@ def __init__(self, **kwargs): self.orientation='vertical' self.current_ex = 'ex1' self.current_file = 'warmUpExercise.py' + self.submit_ob = Submission() self.element=generate_elements() #popup = Popup(title='CourseraApp', content=Label(text='Hello World'),size_hint=(0.6, 0.35)) #popup.open() @@ -138,22 +142,22 @@ def accept_credentials(self): def submit_assignment(self,*largs): if len(largs)>1: - email = largs[0].text - token = largs[1].text + self.submit_ob.__login = largs[0].text + self.submit_ob.__password = largs[1].text else: - email=self.email - token=self.token + self.submit_ob.__login=self.email + self.submit_ob.__password=self.token - print 'Email',email - print 'Token', token + print 'Email',self.submit_ob.__login + print 'Token', self.submit_ob.__password self.submit_popup.dismiss() #TODO:submission call + def updateExercise(self,spinner,text): self.current_ex=text current_file = self.element.files(self.current_ex)[0] - if current_file.endswith('\n'): - current_file=current_file[:-1] + current_file=current_file.split() self.current_file= current_file self.clear_widgets() self.draw_screen() @@ -228,8 +232,7 @@ def filebar(self): #Use bind to see how it works def update_currentFile(self,instance): - if instance.text.endswith('\n'): - instance.text=instance.text[:-1] + instance.text=instance.text.split() self.current_file = instance.text self.clear_widgets() self.draw_screen() From b9da5aaa43d9a5493e1775d898f119ba13ba7ad1 Mon Sep 17 00:00:00 2001 From: Shubhojyoti Date: Tue, 3 Nov 2015 17:02:15 +0530 Subject: [PATCH 25/34] Fixed most bugs and stable --- gui/interface.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gui/interface.py b/gui/interface.py index 327d1a2..b277a68 100644 --- a/gui/interface.py +++ b/gui/interface.py @@ -54,8 +54,6 @@ def writeFile(self,excercise,filename): return f def readFile(self,excercise,filename): - print excercise - print filename path = '../'+excercise+'/'+filename #print 'Opening ',path f=open(path,'r') @@ -157,7 +155,8 @@ def submit_assignment(self,*largs): def updateExercise(self,spinner,text): self.current_ex=text current_file = self.element.files(self.current_ex)[0] - current_file=current_file.split() + if current_file.endswith('\n'): + current_file=current_file[:-1] self.current_file= current_file self.clear_widgets() self.draw_screen() @@ -232,7 +231,8 @@ def filebar(self): #Use bind to see how it works def update_currentFile(self,instance): - instance.text=instance.text.split() + if instance.text.endswith('\n'): + instance.text=instance.text[:-1] self.current_file = instance.text self.clear_widgets() self.draw_screen() From 2438990800b9aed9722f15877e601ada82189780 Mon Sep 17 00:00:00 2001 From: Shubhojyoti Date: Tue, 3 Nov 2015 17:05:52 +0530 Subject: [PATCH 26/34] fixed all bugs --- gui/interface.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/gui/interface.py b/gui/interface.py index b277a68..33ae2d5 100644 --- a/gui/interface.py +++ b/gui/interface.py @@ -27,8 +27,8 @@ def read_token(self,instance): path = '../'+instance.current_ex+'/token.txt' try: credentials = open(path) - instance.email = credentials.readline().split() - instance.token = credentials.readline().split() + instance.email = credentials.readline().split()[0] + instance.token = credentials.readline().split()[0] return True except Exception, e: return False @@ -155,8 +155,7 @@ def submit_assignment(self,*largs): def updateExercise(self,spinner,text): self.current_ex=text current_file = self.element.files(self.current_ex)[0] - if current_file.endswith('\n'): - current_file=current_file[:-1] + current_file=current_file.split()[0] self.current_file= current_file self.clear_widgets() self.draw_screen() @@ -231,8 +230,7 @@ def filebar(self): #Use bind to see how it works def update_currentFile(self,instance): - if instance.text.endswith('\n'): - instance.text=instance.text[:-1] + instance.text=instance.text.split()[0] self.current_file = instance.text self.clear_widgets() self.draw_screen() From f9f3dac0030284ba75a6882c23d7feddccf22761 Mon Sep 17 00:00:00 2001 From: Shubhojyoti Date: Tue, 3 Nov 2015 17:10:03 +0530 Subject: [PATCH 27/34] Minor changes --- gui/interface.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/gui/interface.py b/gui/interface.py index 33ae2d5..cd953ba 100644 --- a/gui/interface.py +++ b/gui/interface.py @@ -155,7 +155,8 @@ def submit_assignment(self,*largs): def updateExercise(self,spinner,text): self.current_ex=text current_file = self.element.files(self.current_ex)[0] - current_file=current_file.split()[0] + if current_file.endswith('\n'): + current_file=current_file[:-1] self.current_file= current_file self.clear_widgets() self.draw_screen() @@ -230,7 +231,8 @@ def filebar(self): #Use bind to see how it works def update_currentFile(self,instance): - instance.text=instance.text.split()[0] + if instance.text.endswith('\n'): + instance.text=instance.text[:-1] self.current_file = instance.text self.clear_widgets() self.draw_screen() From 65aa810b1b53095ebeb9f065bdf50ccf71693ab4 Mon Sep 17 00:00:00 2001 From: Shubhojyoti Date: Tue, 3 Nov 2015 18:15:24 +0530 Subject: [PATCH 28/34] spinner fixed --- gui/interface.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/gui/interface.py b/gui/interface.py index cd953ba..8437ac3 100644 --- a/gui/interface.py +++ b/gui/interface.py @@ -18,7 +18,7 @@ from Submission import Submission -class generate_elements(): +class resourceHandler(): def __init__(self, **args): pass @@ -67,7 +67,7 @@ def __init__(self, **kwargs): self.current_ex = 'ex1' self.current_file = 'warmUpExercise.py' self.submit_ob = Submission() - self.element=generate_elements() + self.element=resourceHandler() #popup = Popup(title='CourseraApp', content=Label(text='Hello World'),size_hint=(0.6, 0.35)) #popup.open() #sleep(10) @@ -99,7 +99,7 @@ def titlebar(self): run = Button(text='Run',size_hint=(0.4,1)) run.bind(on_press=self.run) - ex_dropdown = Spinner(text='Select Exercise',size_hint=(1,1)) + ex_dropdown = Spinner(text=self.current_ex,size_hint=(1,1)) ex_dropdown.values = os.listdir('./res/') ex_dropdown.bind(text=self.updateExercise) @@ -203,7 +203,7 @@ def saveAssignment(self,assignment,*largs): print 'INFO: Autosaved file' except Exception, e: raise e - #self.show_error(e) + self.show_error(e) def schedule_reload(self,instance,value): @@ -212,7 +212,7 @@ def schedule_reload(self,instance,value): self.callback = partial(self.saveAssignment,instance) Clock.schedule_interval(self.callback,5) else: - #When clicking on another file, both focus=False and filebar button callbacks are executed simultaneously leading to deadlock + #TODO:When clicking on another file, both focus=False and filebar button callbacks are executed simultaneously leading to deadlock Clock.unschedule(self.callback) #self.saveAssignment(instance) #Update now From 5db45820072fc772e646ed3cc545efa6f37e615c Mon Sep 17 00:00:00 2001 From: Shubhojyoti Date: Tue, 3 Nov 2015 20:36:52 +0530 Subject: [PATCH 29/34] Version 1 App complete --- gui/interface.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/gui/interface.py b/gui/interface.py index 8437ac3..7412ad5 100644 --- a/gui/interface.py +++ b/gui/interface.py @@ -27,8 +27,8 @@ def read_token(self,instance): path = '../'+instance.current_ex+'/token.txt' try: credentials = open(path) - instance.email = credentials.readline().split()[0] - instance.token = credentials.readline().split()[0] + instance.email = credentials.readline().strip() + instance.token = credentials.readline().strip() return True except Exception, e: return False @@ -150,6 +150,7 @@ def submit_assignment(self,*largs): print 'Token', self.submit_ob.__password self.submit_popup.dismiss() #TODO:submission call + #self.show_error(self.submit_ob.submit()) def updateExercise(self,spinner,text): @@ -166,7 +167,7 @@ def updateExercise(self,spinner,text): def run(self,instance): #TODO: Display output in popup - self.show_error('Cannot be run') + self.show_error('Cannot run') print('The button <%s> is being pressed' % instance.text) @@ -240,8 +241,9 @@ def update_currentFile(self,instance): def show_error(self, e): self.info_label.text = str(e) - anim = Animation(top=190.0, opacity=1, d=2) +\ - Animation(top=190.0, d=3) +\ + duration = len(self.info_label.text)/10 + anim = Animation(top=190.0, opacity=1, d=0.5) +\ + Animation(top=190.0, d=duration) +\ Animation(top=0, opacity=0, d=2) anim.start(self.info_label) From ad05afc1e0b96766d3722855343e11cfe1fed19f Mon Sep 17 00:00:00 2001 From: Shubhojyoti Date: Tue, 3 Nov 2015 20:40:39 +0530 Subject: [PATCH 30/34] App version 1 complete TODO: Directory structure --- gui/Submission.py | 109 ++++++++++++++++++++++ gui/interface.py | 2 +- gui/res/ex1/part_names.txt | 0 gui/res/ex1/{filelist.txt => sources.txt} | 0 gui/res/ex2/manual.md | 29 ++++++ gui/res/ex2/part_names.txt | 0 gui/res/ex2/sources.txt | 4 + 7 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 gui/Submission.py create mode 100644 gui/res/ex1/part_names.txt rename gui/res/ex1/{filelist.txt => sources.txt} (100%) create mode 100644 gui/res/ex2/manual.md create mode 100644 gui/res/ex2/part_names.txt create mode 100644 gui/res/ex2/sources.txt diff --git a/gui/Submission.py b/gui/Submission.py new file mode 100644 index 0000000..f3208ce --- /dev/null +++ b/gui/Submission.py @@ -0,0 +1,109 @@ +from urllib import urlencode +from urllib2 import urlopen +from json import loads, dumps +from collections import OrderedDict +import numpy as np +import os + + + +class Submission(): + + def __init__(self, homework, part_names, srcs, output): + self.__homework = homework + self.__part_names = part_names + self.__srcs = srcs + self.__output = output + self.__submit_url = 'https://www-origin.coursera.org/api/onDemandProgrammingImmediateFormSubmissions.v1' + self.__login = None + self.__password = None + + def __init__(self): + self.__submit_url = 'https://www-origin.coursera.org/api/onDemandProgrammingImmediateFormSubmissions.v1' + + + def submit(self): + print '==\n== Submitting Solutions | Programming Exercise %s\n==' % self.__homework + self.login_prompt() + + parts = OrderedDict() + for part_id, _ in enumerate(self.__srcs,1): + parts[str(part_id)] = {'output': self.__output(part_id)} + + result, response = self.request(parts) + response = loads(response) + try: + print response['errorMessage'] + return + except: + pass + print '==' + print '== %43s | %9s | %-s' % ('Part Name', 'Score', 'Feedback') + print '== %43s | %9s | %-s' % ('---------', '-----', '--------') + + + for part in parts: + partFeedback = response['partFeedbacks'][part] + partEvaluation = response['partEvaluations'][part] + score = '%d / %3d' % (partEvaluation['score'], partEvaluation['maxScore']) + print '== %43s | %9s | %-s' % (self.__part_names[int(part)-1], score, partFeedback) + + evaluation = response['evaluation'] + + + totalScore = '%d / %d' % (evaluation['score'], evaluation['maxScore']) + print '== --------------------------------' + print '== %43s | %9s | %-s\n' % (' ', totalScore, ' ') + print '==' + + if not os.path.isfile('token.txt'): + with open('token.txt', 'w') as f: + f.write(self.__login + '\n') + f.writelines(self.__password) + return response + + def login_prompt(self): + try: + with open('token.txt', 'r') as f: + self.__login = f.readline().strip() + self.__password = f.readline().strip() + except IOError: + pass + + if self.__login is not None and self.__password is not None: + reenter = raw_input('Use token from last successful submission (%s)? (Y/n): ' % self.__login) + + if reenter == '' or reenter[0] == 'Y' or reenter[0] == 'y': + return + + if os.path.isfile('token.txt'): + os.remove('token.txt') + self.__login = raw_input('Login (email address): ') + self.__password = raw_input('Token: ') + + def request(self, parts): + + params = { + 'assignmentSlug': self.__homework, + 'secret': self.__password, + 'parts': parts, + 'submitterEmail': self.__login} + + params = urlencode({'jsonBody': dumps(params)}) + f = urlopen(self.__submit_url, params) + try: + return 0, f.read() + finally: + f.close() + +def sprintf(fmt, arg): + "emulates (part of) Octave sprintf function" + if isinstance(arg, tuple): + # for multiple return values, only use the first one + arg = arg[0] + + if isinstance(arg, (np.ndarray, list)): + # concatenates all elements, column by column + return ' '.join(fmt % e for e in np.asarray(arg).ravel('F')) + else: + return fmt % arg \ No newline at end of file diff --git a/gui/interface.py b/gui/interface.py index 7412ad5..7d8f56b 100644 --- a/gui/interface.py +++ b/gui/interface.py @@ -36,7 +36,7 @@ def read_token(self,instance): def files(self,excercise): - path = 'res/'+excercise+'/filelist.txt' + path = 'res/'+excercise+'/sources.txt' filehandler = open(path) filelist=[] while True: diff --git a/gui/res/ex1/part_names.txt b/gui/res/ex1/part_names.txt new file mode 100644 index 0000000..e69de29 diff --git a/gui/res/ex1/filelist.txt b/gui/res/ex1/sources.txt similarity index 100% rename from gui/res/ex1/filelist.txt rename to gui/res/ex1/sources.txt diff --git a/gui/res/ex2/manual.md b/gui/res/ex2/manual.md new file mode 100644 index 0000000..0517a54 --- /dev/null +++ b/gui/res/ex2/manual.md @@ -0,0 +1,29 @@ +#Exercise 1: Linear Regression +>Coursera Assignment 1 of linear regression + + +I have always been fascinated by people - their impromptu, unconditioned actions governed by preconceived perceptions rising from base emotions and past experiences; the innumerous masks that they put on to hide a trivial truth; their insatiable hunger for causes that mean nothing to them. +This had made me curious if it was possible to understand all the underlying foundations for a person's actions tracing it back to the baser emotions or experiences and whether it was possible to influnce people with crafted experiences which could lead to a possible action in an unforseeable future. + + +In my quest for understanding people, I quickly concluded that there was no singular governing cause that drives all mankind. Each person is unique in his own way and there can be no generalization in human behaviour. But, there does exist a general structure in which people construct their behaviour and build upon it. So, to see people for what they really are it is important to understand the thought process of people rather than the thoughts itself. + +To understand these thought processes, I devised carefully crafted situations and tactfully let myself and my peers get involved in my game without their knowledge while I silently noted down each person's reactions and how they interacted and gained profound knowledge about their most innate proclivities. In due course, I was so consumed in this game that I lost all connection to myself. To truly understand what everyone is going through, I had to involve myself in this game and yet remain unattached to my own emotions so as to remain in full control of my senses. Slowly and steadily, I had detached myself from all worldly emotions. Finally, there came a moment when I realized. +>Blocking emotions is like wearing an armour. I will be safe from the bullets but I will never feel the breeze. + +There was a wave of understanding that hit me like thunder and I realized I haven't learned anything. When people were reacting to a situation that I created, they were influenced by my thoughts indirectly and as a result all of their actions henceforth was a product of my thought pattern. The true variability and randomness in every person's thought pattern was lost and there was no way to predict their unique thought process as the process had become rigged. +To truly understand someone's thought person, I can't influence them but I need to be influenced by them. Only then can I dwelve into the various unique thought processes in order to gain deep knowledge about them. + +Thereby, I set upon a new milestone in my quest where I needed to collect as many minds as I can until I can accurately understand the nature of human thought. I needed to relate to people in the most basest form possible and build up upon them. Sadly, I do not have a very active social life or sibblings whom I can experiment. Naturally, I chose facebook and other social media my means of finding people who can open up to me and I to them so that I can relate to them in the deepest way. + +It was no mere coincidence that I found my way amongst female company a lot as girls tend to get very emotional and are looking for someone to open up to and I was a guy looking for people to open up to me. In due course, I became very good at it and I did learn a get deal, no doubt. But this post is not about my findings but rather my psyche and how I dealt with whatever I found. + +No sooner than later, I became acquainted with so many different types of psychologies and thought processes that I could relate to new people by fitting them to a psychology from my existing reservoir. Added to this my observational skills and I could tell lot about a person with just one glance. Progressively and with subsequent encounters I could not just tell about a person but I could replicate their entire thought process in my brain. With time, I got so good at it that this replication was nearly flawless and it was like harbouring a new mind in my old brain. I was like mirroring the person who was closest to me. I was so drawn into it that this had become my habbit and I could do this subconsciously until it finally reached to a point when I could no longer control it but rather it controlled me. + +>The painful realization hit me that I had no mind of my own. Like a snake changes skins and moves on to survive, I change personalitites to keep moving. I have become a sum of everyone around me while I lost myself from within me. + +The reaction of people to my uniqueness was something I couldn't fathom. Though, every person immediately related to me when they saw similarities to themselves yet they became very self-aware when the similarities became more vivid and as I became more like a reflection of themselves. It was very disturbing for most of them to see a version of themselves with all the perfection and imperfection that they have but within a different body. People with even a slightly low self esteem could not reconcile to the reality of the reflection that they were seeing in front of them. Finally, in order to save them from themselves, I had to distance myself from them and it was my time to move on. I could have no friends no people with whom I can share my life. + +>Was loneliness the price for wisdom? + +I am filled with fear of the unknown. I don't know what I have become. Am I good or evil? In my search, have I let myself become something I do not want to face? Can I recover? \ No newline at end of file diff --git a/gui/res/ex2/part_names.txt b/gui/res/ex2/part_names.txt new file mode 100644 index 0000000..e69de29 diff --git a/gui/res/ex2/sources.txt b/gui/res/ex2/sources.txt new file mode 100644 index 0000000..0d1d3ee --- /dev/null +++ b/gui/res/ex2/sources.txt @@ -0,0 +1,4 @@ +costFunction.py +costFunctionReg.py +sigmoid.py +gradientFunction.py \ No newline at end of file From 1f107d5597146a0208e85d94ef0c13a0693d1508 Mon Sep 17 00:00:00 2001 From: Shubhojyoti Date: Wed, 4 Nov 2015 12:26:15 +0530 Subject: [PATCH 31/34] some improvements tried and todos added --- gui/interface.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/gui/interface.py b/gui/interface.py index 7d8f56b..c0042a7 100644 --- a/gui/interface.py +++ b/gui/interface.py @@ -10,7 +10,9 @@ from kivy.uix.rst import RstDocument from kivy.uix.textinput import TextInput from kivy.uix.spinner import Spinner +from kivy.uix.togglebutton import ToggleButton from kivy.uix.splitter import Splitter +from kivy.uix.scrollview import ScrollView from kivy.uix.popup import Popup from kivy.clock import Clock from functools import partial @@ -79,7 +81,11 @@ def __init__(self, **kwargs): def draw_screen(self): self.add_widget(self.titlebar()) self.add_widget(self.maineditor()) - self.add_widget(self.filebar()) + scrollbar = ScrollView(size_hint=(1,None)) + #TODO: Make filebar scrollable for smaller screens and many files + #scrollbar.add_widget(self.filebar()) + #self.add_widget(scrollbar) + self.add_widget(self.filebar()) self.add_widget(self.console()) def titlebar(self): @@ -139,6 +145,7 @@ def accept_credentials(self): return main_layout def submit_assignment(self,*largs): + #Make submit_ob local if not used anywhere else if len(largs)>1: self.submit_ob.__login = largs[0].text self.submit_ob.__password = largs[1].text @@ -224,13 +231,12 @@ def filebar(self): layout.orientation='horizontal' files = self.element.files(self.current_ex) for f in files: - button = Button(text=f) - button.bind(on_press=self.update_currentFile) - layout.add_widget(button) - + button = ToggleButton(text=f,group = self.current_ex,state='normal') + button.bind(on_press=self.update_currentFile) + layout.add_widget(button) + #TODO: Make file button toggle-able return layout - #Use bind to see how it works def update_currentFile(self,instance): if instance.text.endswith('\n'): instance.text=instance.text[:-1] From d13f57a2e70837cc2a445949fbd38cbddfa0495a Mon Sep 17 00:00:00 2001 From: Shubhojyoti Date: Wed, 4 Nov 2015 12:34:34 +0530 Subject: [PATCH 32/34] Filebar buttons made toggleable --- gui/interface.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/gui/interface.py b/gui/interface.py index c0042a7..4661508 100644 --- a/gui/interface.py +++ b/gui/interface.py @@ -231,10 +231,12 @@ def filebar(self): layout.orientation='horizontal' files = self.element.files(self.current_ex) for f in files: - button = ToggleButton(text=f,group = self.current_ex,state='normal') + if f.strip() == self.current_file: + button = ToggleButton(text=f,group = self.current_ex,state='down') + else: + button = ToggleButton(text=f,group = self.current_ex,state='normal') button.bind(on_press=self.update_currentFile) layout.add_widget(button) - #TODO: Make file button toggle-able return layout def update_currentFile(self,instance): From e0e83b7e40f660de5419c53443793a23af43b485 Mon Sep 17 00:00:00 2001 From: Shubhojyoti Date: Wed, 4 Nov 2015 13:22:35 +0530 Subject: [PATCH 33/34] reactive layout working --- gui/interface.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/gui/interface.py b/gui/interface.py index 4661508..a694a07 100644 --- a/gui/interface.py +++ b/gui/interface.py @@ -74,11 +74,10 @@ def __init__(self, **kwargs): #popup.open() #sleep(10) #popup.dismiss() - - self.draw_screen() - - - def draw_screen(self): + self.bind(size=self.draw_screen) + + def draw_screen(self,*args): + self.clear_widgets() self.add_widget(self.titlebar()) self.add_widget(self.maineditor()) scrollbar = ScrollView(size_hint=(1,None)) @@ -166,7 +165,6 @@ def updateExercise(self,spinner,text): if current_file.endswith('\n'): current_file=current_file[:-1] self.current_file= current_file - self.clear_widgets() self.draw_screen() print 'Current Exercise changed to: ', self.current_ex @@ -178,10 +176,11 @@ def run(self,instance): print('The button <%s> is being pressed' % instance.text) + + def maineditor(self): layout=BoxLayout() #TODO:reactive layout not working - if self.width < self.height: layout.orientation='vertical' else: @@ -243,7 +242,6 @@ def update_currentFile(self,instance): if instance.text.endswith('\n'): instance.text=instance.text[:-1] self.current_file = instance.text - self.clear_widgets() self.draw_screen() print 'Current file changed to: ', self.current_file From 079c426fba5f7423db82e1b91d3c35ba7435962b Mon Sep 17 00:00:00 2001 From: Shubhojyoti Date: Wed, 4 Nov 2015 14:21:22 +0530 Subject: [PATCH 34/34] welcome screen added --- gui/interface.py | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/gui/interface.py b/gui/interface.py index a694a07..7906dd3 100644 --- a/gui/interface.py +++ b/gui/interface.py @@ -63,19 +63,26 @@ def readFile(self,excercise,filename): class MainScreen(BoxLayout): - def __init__(self, **kwargs): + def __init__(self, welcome=False, **kwargs): super(MainScreen, self).__init__(**kwargs) self.orientation='vertical' self.current_ex = 'ex1' self.current_file = 'warmUpExercise.py' self.submit_ob = Submission() self.element=resourceHandler() - #popup = Popup(title='CourseraApp', content=Label(text='Hello World'),size_hint=(0.6, 0.35)) - #popup.open() - #sleep(10) - #popup.dismiss() - self.bind(size=self.draw_screen) + + if welcome: + welcome_popup = Popup(title='Coursera ML in Python', content=Label(text='Hello World'),size_hint=(1, 1)) + self.add_widget(welcome_popup) + welcome_popup.open() + Clock.schedule_once(self.start_app,3) + else: + self.bind(size=self.draw_screen) + def start_app(self,*args): + self.draw_screen() + self.bind(size=self.draw_screen) + def draw_screen(self,*args): self.clear_widgets() self.add_widget(self.titlebar()) @@ -180,7 +187,6 @@ def run(self,instance): def maineditor(self): layout=BoxLayout() - #TODO:reactive layout not working if self.width < self.height: layout.orientation='vertical' else: @@ -258,7 +264,7 @@ def show_error(self, e): class CourseraApp(App): def build(self): - return MainScreen() + return MainScreen(welcome=True) def on_pause(self): return True