diff --git a/fract4d/browser_model.py b/fract4d/browser_model.py index aec6c7eed..167864cfd 100644 --- a/fract4d/browser_model.py +++ b/fract4d/browser_model.py @@ -99,12 +99,12 @@ def __init__(self,compiler): TypeInfo(self, compiler, fc.FormulaTypes.TRANSFORM), TypeInfo(self, compiler, fc.FormulaTypes.GRADIENT) ] + self.current = None self.current_type = -1 self.type_changed = event.T() self.file_changed = event.T() self.formula_changed = event.T() - self.set_type(FRACTAL) - + def formula_type_to_browser_type(self,t): if t == fc.FormulaTypes.FRACTAL: return FRACTAL @@ -157,5 +157,3 @@ def get_contents(self): r = self.compiler.get_text(fname) return r - -instance = T(fc.instance) diff --git a/fract4d/cache.py b/fract4d/cache.py index 80c3a8e91..9ac82f21d 100644 --- a/fract4d/cache.py +++ b/fract4d/cache.py @@ -33,7 +33,6 @@ def save(self): self.createPickledFile(self._indexName(), self.files) def clear(self): - if not os: return # get 'NoneType not callable' sometimes otherwise, which seems weird for f in os.listdir(self.dir): try: os.remove(os.path.join(self.dir,f)) diff --git a/fract4d/fc.py b/fract4d/fc.py index 5db95a807..68a43e490 100755 --- a/fract4d/fc.py +++ b/fract4d/fc.py @@ -493,9 +493,6 @@ def __del__(self): if not self.leave_dirty: self.clear_cache() -instance = Compiler() -instance.update_from_prefs(fractconfig.instance) - def usage(): print("FC : a compiler from Fractint .frm files to C code") print("fc.py -o [outfile] -f [formula] infile") diff --git a/fract4d/test_browser_model.py b/fract4d/test_browser_model.py index 495702f8f..5e015ffd1 100755 --- a/fract4d/test_browser_model.py +++ b/fract4d/test_browser_model.py @@ -65,7 +65,8 @@ def testFuncMapping(self): def testSetType(self): bm = Wrapper() - self.assertEqual([], bm.type_changelist) + bm.set_type(browser_model.FRACTAL) + self.assertEqual([browser_model.FRACTAL], bm.type_changelist) self.assertEqual(browser_model.FRACTAL, bm.current_type) self.assertEqual( bm.typeinfo[bm.current_type], bm.current) @@ -73,11 +74,12 @@ def testSetType(self): bm.set_type(browser_model.INNER) self.assertEqual(browser_model.INNER, bm.current_type) self.assertEqual( - [browser_model.INNER], + [browser_model.FRACTAL, browser_model.INNER], bm.type_changelist) def testFileList(self): bm = browser_model.T(g_comp) + bm.set_type(browser_model.FRACTAL) self.assertNotEqual(bm.current.files, []) self.assertListSorted(bm.current.files) @@ -91,6 +93,7 @@ def testSetTypeTwice(self): def testSetTypeUpdatesFnames(self): bm = browser_model.T(g_comp) + bm.set_type(browser_model.FRACTAL) bm.current.fname = "fish" bm.current.formula = "haddock" @@ -107,6 +110,7 @@ def testSetTypeUpdatesFnames(self): def testSetFile(self): bm = Wrapper() + bm.set_type(browser_model.FRACTAL) bm.set_file("gf4d.frm") self.assertEqual("gf4d.frm",bm.current.fname) self.assertEqual( @@ -116,6 +120,7 @@ def testSetFile(self): def testSetBadFile(self): bm = browser_model.T(g_comp) + bm.set_type(browser_model.FRACTAL) self.assertRaises(IOError,bm.set_file,"nonexistent.frm") def assertListSorted(self,l): @@ -126,6 +131,7 @@ def assertListSorted(self,l): def testFormulasSorted(self): bm = browser_model.T(g_comp) + bm.set_type(browser_model.FRACTAL) bm.set_file("gf4d.frm") self.assertListSorted(bm.current.formulas) @@ -141,6 +147,7 @@ def testExcludeList(self): def testSetFormula(self): bm = Wrapper() + bm.set_type(browser_model.FRACTAL) bm.set_file("gf4d.frm") bm.set_formula("Mandelbrot") self.assertEqual("Mandelbrot",bm.current.formula) @@ -149,6 +156,7 @@ def testSetFormula(self): def testSetFileResetsFormula(self): bm = Wrapper() + bm.set_type(browser_model.FRACTAL) bm.set_file("gf4d.frm") bm.set_formula("Mandelbrot") bm.set_file("fractint-g4.frm") @@ -158,7 +166,9 @@ def testSetFileResetsFormula(self): def testUpdate(self): bm = Wrapper() - bm.update("gf4d.frm","Mandelbrot") + bm.set_type(browser_model.FRACTAL) + bm.set_file("gf4d.frm") + bm.set_formula("Mandelbrot") self.assertEqual("gf4d.frm",bm.current.fname) self.assertEqual("Mandelbrot", bm.current.formula) @@ -172,6 +182,7 @@ def testUpdate(self): def testApplyStatus(self): bm = browser_model.T(g_comp) + bm.set_type(browser_model.FRACTAL) self.assertEqual(False, bm.current.can_apply) bm.set_file("gf4d.frm") @@ -198,9 +209,7 @@ def testUgrPresent(self): files = bm.current.files self.assertEqual(1,files.count("blatte1.ugr")) - def testInstance(self): - x = browser_model.instance - + def suite(): return unittest.makeSuite(Test,'test') diff --git a/fract4d/test_fc.py b/fract4d/test_fc.py index 9d1d1bfa3..149e09747 100755 --- a/fract4d/test_fc.py +++ b/fract4d/test_fc.py @@ -247,7 +247,8 @@ def testPrefs(self): self.assertEqual(["wibble"], compiler.path_lists[3]) def testInstance(self): - compiler = fc.instance + compiler = fc.Compiler() + compiler.update_from_prefs(fractconfig.instance) self.assertNotEqual(None, compiler) self.assertEqual( compiler.flags, fractconfig.instance.get("compiler", "options")) diff --git a/fract4dgui/angle.py b/fract4dgui/angle.py index 24737d31b..936913804 100644 --- a/fract4dgui/angle.py +++ b/fract4dgui/angle.py @@ -1,14 +1,10 @@ -# Sort of a widget which controls an angle of the fractal -# I say sort of, because this doesn't actually inherit from Gtk.Widget, -# so it's not really a widget. This is because if I attempt to do that -# pygtk crashes. Hence I delegate to a member which actually is a widget -# with some stuff drawn on it - basically an ungodly hack. +# A widget which controls an angle of the fractal import math from gi.repository import Gtk, Gdk, GObject, Pango -class T(GObject.GObject): +class T(Gtk.DrawingArea): __gsignals__ = { 'value-changed' : ( (GObject.SignalFlags.RUN_FIRST | GObject.SignalFlags.NO_RECURSE), @@ -30,34 +26,33 @@ def __init__(self,text): self.adjustment.connect('value-changed', self.onAdjustmentValueChanged) - GObject.GObject.__init__(self) + Gtk.DrawingArea.__init__(self) - self.widget = Gtk.DrawingArea() - self.widget.set_size_request(40,40) + self.set_size_request(40,40) - self.widget.set_events( + self.set_events( Gdk.EventMask.BUTTON_RELEASE_MASK | Gdk.EventMask.BUTTON1_MOTION_MASK | Gdk.EventMask.POINTER_MOTION_HINT_MASK | Gdk.EventMask.ENTER_NOTIFY_MASK | - Gdk.EventMask.LEAVE_NOTIFY_MASK | + Gdk.EventMask.LEAVE_NOTIFY_MASK | Gdk.EventMask.BUTTON_PRESS_MASK | Gdk.EventMask.EXPOSURE_MASK ) self.notice_mouse = False - self.widget.connect('motion_notify_event', self.onMotionNotify) - self.widget.connect('button_release_event', self.onButtonRelease) - self.widget.connect('button_press_event', self.onButtonPress) - self.widget.connect('draw',self.onDraw) + self.connect('motion_notify_event', self.onMotionNotify) + self.connect('button_release_event', self.onButtonRelease) + self.connect('button_press_event', self.onButtonPress) + self.connect('draw',self.onDraw) def set_value(self,val): val = math.fmod(val + math.pi, 2.0 * math.pi) - math.pi self.adjustment.set_value(val) - self.widget.queue_draw() + self.queue_draw() - def update_from_mouse(self,x,y): - (w,h) = (self.widget.get_allocated_width(), self.widget.get_allocated_height()) + def update_from_mouse(self,x,y): + (w,h) = (self.get_allocated_width(), self.get_allocated_height()) xc = w//2 yc = h//2 @@ -73,39 +68,29 @@ def angle_from_xy(self,x,y): def onAdjustmentValueChanged(self,adjustment): val = adjustment.get_value() if val != self.old_value: - self.widget.queue_draw() + self.queue_draw() self.emit('value-slightly-changed', val) def onMotionNotify(self,widget,event): if not self.notice_mouse: return - dummy = widget.get_pointer() self.update_from_mouse(event.x, event.y) def onButtonRelease(self,widget,event): - if event.button==1: + if event.button == 1: self.notice_mouse = False - (xc,yc) = (widget.get_allocated_width()//2, widget.get_allocated_height()//2) current_value = self.adjustment.get_value() if self.old_value != current_value: self.old_value = current_value self.emit('value-changed',current_value) - self.widget.set_state(Gtk.StateType.NORMAL) + self.set_state(Gtk.StateType.NORMAL) - def onButtonPress(self,widget,event): if event.button == 1: self.notice_mouse = True self.update_from_mouse(event.x, event.y) - self.widget.set_state(Gtk.StateType.ACTIVE) - - - def __del__(self): - #This is truly weird. If I don't have this method, when you use - # one fourway widget, it fucks up the other. Having this fixes it. - # *even though it doesn't do anything*. Disturbing. - pass + self.set_state(Gtk.StateType.ACTIVE) def get_current_angle(self): value = self.adjustment.get_value() @@ -164,6 +149,3 @@ def redraw_rect(self, widget, cairo_ctx): self.two_pi) cairo_ctx.fill() cairo_ctx.stroke() - -# explain our existence to GTK's object system -GObject.type_register(T) diff --git a/fract4dgui/autozoom.py b/fract4dgui/autozoom.py index 2cd9e9e90..86a67046f 100644 --- a/fract4dgui/autozoom.py +++ b/fract4dgui/autozoom.py @@ -7,17 +7,13 @@ from . import dialog -def show_autozoom(parent,f): - AutozoomDialog.show(parent,f) - class AutozoomDialog(dialog.T): def __init__(self,main_window,f): dialog.T.__init__( self, _("Autozoom"), main_window, - (Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE), - destroy_with_parent=True + (Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE) ) self.f = f @@ -58,11 +54,8 @@ def change_entry(*args): self.table.attach(self.minsize_entry, 1,2,1,2, Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, 0, 2, 2) - - def show(parent, f): - dialog.T.reveal(AutozoomDialog, True, parent, None, f) - - show = staticmethod(show) + + self.vbox.show_all() def onResponse(self,widget,id): self.zoombutton.set_active(False) diff --git a/fract4dgui/browser.py b/fract4dgui/browser.py index 0b362982d..0e3c43417 100755 --- a/fract4dgui/browser.py +++ b/fract4dgui/browser.py @@ -2,43 +2,31 @@ # a browser to examine fractal functions -from gi.repository import Gtk +from gi.repository import Gtk, GObject from fract4d import browser_model from . import dialog, utils, gtkfractal -def show(parent, f, type=browser_model.FRACTAL): - BrowserDialog.show(parent,f,type) - -def update(file=None, formula=None): - browser_model.instance.update(file,formula) - -def set_type(type): - browser_model.instance.set_type(type) - -def guess_type(file): - return browser_model.instance.guess_type(file) - class BrowserDialog(dialog.T): RESPONSE_EDIT = 1 RESPONSE_REFRESH = 2 RESPONSE_COMPILE = 3 - def __init__(self,main_window,f): + def __init__(self,main_window,f,type=browser_model.FRACTAL): dialog.T.__init__( self, _("Formula Browser"), - main_window, + None, (#_("Co_mpile"), BrowserDialog.RESPONSE_COMPILE, Gtk.STOCK_REFRESH, BrowserDialog.RESPONSE_REFRESH, Gtk.STOCK_APPLY, Gtk.ResponseType.APPLY, Gtk.STOCK_OK, Gtk.ResponseType.OK, - Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE), - destroy_with_parent=True) + Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE) + ) self.set_default_response(Gtk.ResponseType.OK) - self.model = browser_model.instance + self.model = browser_model.T(main_window.compiler) self.model.type_changed += self.on_type_changed self.model.file_changed += self.on_file_changed self.model.formula_changed += self.on_formula_changed @@ -52,20 +40,14 @@ def __init__(self,main_window,f): self.compiler = f.compiler self.ir = None - self.main_window = main_window self.set_size_request(600,500) self.preview = gtkfractal.Preview(self.compiler) self.preview.f.auto_tolerance = False self.create_panes() - self.on_file_changed() + self.vbox.show_all() - def show(parent, f, type): - _browser = dialog.T.reveal(BrowserDialog,True, parent, None, f) - _browser.set_type(type) - _browser.populate_file_list() - - show = staticmethod(show) + self.set_type(type) def onResponse(self,widget,id): if id == Gtk.ResponseType.CLOSE or \ @@ -74,6 +56,8 @@ def onResponse(self,widget,id): self.hide() elif id == Gtk.ResponseType.APPLY: self.onApply() + # prevent dialog closing if being run + GObject.signal_stop_emission_by_name(self, "response") elif id == Gtk.ResponseType.OK: self.onApply() self.hide() @@ -100,6 +84,14 @@ def set_type_cb(self,optmenu): def on_type_changed(self): utils.set_selected(self.funcTypeMenu, self.model.current_type) + try: + self.set_file(self.f.forms[self.model.current_type].funcFile) + except IndexError: + pass + try: + self.set_formula(self.f.forms[self.model.current_type].funcName) + except IndexError: + pass self.populate_file_list() def set_type(self,type): @@ -154,10 +146,9 @@ def populate_file_list(self): # re-select current file, if any if current_iter: self.filetreeview.scroll_to_cell(index) - if sel: - sel.unselect_all() - sel.select_iter(current_iter) - self.populate_formula_list(self.model.current.fname) + sel.unselect_all() + sel.select_iter(current_iter) + self.populate_formula_list(self.model.current.fname) else: self.formula_list.clear() self.formula_selection_changed(None) @@ -284,6 +275,12 @@ def create_panes(self): panes1.add2(notebook) + def load_file(self, fname): + type = self.model.guess_type(fname) + self.set_type(type) + self.set_file(fname) + self.populate_file_list() + def file_selection_changed(self,selection): self.model.current.formula = None (model,iter) = selection.get_selected() diff --git a/fract4dgui/dialog.py b/fract4dgui/dialog.py index b5f649768..676b46b43 100644 --- a/fract4dgui/dialog.py +++ b/fract4dgui/dialog.py @@ -2,24 +2,25 @@ from gi.repository import Gtk -_dialogs = {} - -def make_container(title): +def make_label_box(parent, title): label_box = Gtk.HBox() label_box.set_name('dialog_label_box') label = Gtk.Label(label=title) label_box.pack_start(label, False, False, 0) close = Gtk.Button.new_from_stock(Gtk.STOCK_CLOSE) label_box.pack_end(close, False, False, 0) - frame = Gtk.VBox() - frame.pack_start(label_box, False, False, 1) + label_box.show_all() - close.connect('clicked', lambda x : frame.hide()) - return frame + close.connect('clicked', lambda x : parent.hide()) + return label_box class T(Gtk.Dialog): - def __init__(self, title=None, parent=None, buttons=None,**kwds): - Gtk.Dialog.__init__(self, title=title, transient_for=parent, **kwds) + def __init__(self, title=None, parent=None, buttons=None, modal=True): + Gtk.Dialog.__init__(self, + title=title, + transient_for=parent, + modal=modal, + destroy_with_parent=True) if buttons: self.add_buttons(*buttons) @@ -27,40 +28,6 @@ def __init__(self, title=None, parent=None, buttons=None,**kwds): self.set_default_response(Gtk.ResponseType.CLOSE) self.connect('response',self.onResponse) - self.connect('destroy-event', self.clear_global) - self.connect('delete-event', self.clear_global) - - def clear_global(self,*args): - global _dialogs - _dialogs[self.__class__] = None - - def reveal(type, dialog_mode, parent, alt_parent, *args): - global _dialogs - if not _dialogs.get(type): - _dialogs[type] = type(parent, *args) - if dialog_mode: - _dialogs[type].show_all() - _dialogs[type].present() - else: - if not hasattr(alt_parent, "dialogs"): - alt_parent.dialogs = {} - container = alt_parent.dialogs.get(type) - if not container: - dialog = _dialogs[type] - box = dialog.controls - title = dialog.get_title() - container = make_container(title) - box.reparent(container) - alt_parent.pack_start(container,True,True,0) - alt_parent.dialogs[type] = container - - container.show_all() - _dialogs[type].hide() - - return _dialogs[type] - - reveal = staticmethod(reveal) - def onResponse(self,widget,id): if id == Gtk.ResponseType.CLOSE or \ id == Gtk.ResponseType.NONE or \ @@ -68,7 +35,3 @@ def onResponse(self,widget,id): self.hide() else: print("unexpected response %d" % id) - -def get(type): - global _dialogs - return _dialogs.get(type) diff --git a/fract4dgui/director.py b/fract4dgui/director.py index 6b0999994..cb376be12 100644 --- a/fract4dgui/director.py +++ b/fract4dgui/director.py @@ -20,9 +20,6 @@ from . import PNGGen,AVIGen,DlgAdvOpt,director_prefs -def show(parent,alt_parent, f,dialog_mode,conf_file=""): - DirectorDialog.show(parent,alt_parent, f,dialog_mode,conf_file) - class UserCancelledError(Exception): pass @@ -33,11 +30,6 @@ def __init__(self,msg): class DirectorDialog(dialog.T,hig.MessagePopper): RESPONSE_RENDER=1 - def show(parent, alt_parent, f,dialog_mode,conf_file): - dialog.T.reveal(DirectorDialog, dialog_mode, - parent, alt_parent, f,conf_file) - - show = staticmethod(show) def check_for_keyframe_clash(self,keyframe,fct_dir): keydir=os.path.dirname(keyframe) @@ -445,22 +437,19 @@ def preferences_clicked(self,widget,data=None): res=dlg.show() #creating window... - def __init__(self, main_window, f,conf_file): + def __init__(self, main_window, f, conf_file=""): dialog.T.__init__( self, _("Director"), main_window, (_("_Render"), DirectorDialog.RESPONSE_RENDER, - Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE), - destroy_with_parent=True) + Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE) + ) hig.MessagePopper.__init__(self) self.animation=animation.T(f.compiler) self.f=f self.compiler = f.compiler - self.realize() - - self.main_window = main_window #main VBox self.box_main=Gtk.VBox(False,0) @@ -706,6 +695,7 @@ def __init__(self, main_window, f,conf_file): #--------------showing all------------------------------- self.vbox.add(self.box_main) + self.vbox.show_all() self.controls = self.vbox if conf_file!="": self.load_configuration(conf_file) diff --git a/fract4dgui/fourway.py b/fract4dgui/fourway.py index 05c4c7962..1703968db 100644 --- a/fract4dgui/fourway.py +++ b/fract4dgui/fourway.py @@ -1,12 +1,8 @@ -# Sort of a widget which controls 2 linear dimensions of the fractal -# I say sort of, because this doesn't actually inherit from Gtk.Widget, -# so it's not really a widget. This is because if I attempt to do that -# pygtk crashes. Hence I delegate to a member which actually is a widget -# with some stuff drawn on it - basically an ungodly hack. +# A widget which controls 2 linear dimensions of the fractal from gi.repository import Gtk, Gdk, GObject, Pango -class T(GObject.GObject): +class T(Gtk.DrawingArea): __gsignals__ = { 'value-changed' : ( (GObject.SignalFlags.RUN_FIRST | GObject.SignalFlags.NO_RECURSE), @@ -16,18 +12,17 @@ class T(GObject.GObject): None, (GObject.TYPE_INT, GObject.TYPE_INT)) } - def __init__(self,text): + def __init__(self,text): self.button = 0 self.radius = 0 self.last_x = 0 - self.last_y = 0 - self.text=text - GObject.GObject.__init__(self) - - self.widget = Gtk.DrawingArea() - self.widget.set_size_request(53,53) + self.last_y = 0 + self.text = text + Gtk.DrawingArea.__init__(self) + + self.set_size_request(53,53) - self.widget.set_events( + self.set_events( Gdk.EventMask.BUTTON_RELEASE_MASK | Gdk.EventMask.BUTTON1_MOTION_MASK | Gdk.EventMask.POINTER_MOTION_HINT_MASK | @@ -38,10 +33,10 @@ def __init__(self,text): ) self.notice_mouse = False - self.widget.connect('motion_notify_event', self.onMotionNotify) - self.widget.connect('button_release_event', self.onButtonRelease) - self.widget.connect('button_press_event', self.onButtonPress) - self.widget.connect('draw',self.onDraw) + self.connect('motion_notify_event', self.onMotionNotify) + self.connect('button_release_event', self.onButtonRelease) + self.connect('button_press_event', self.onButtonPress) + self.connect('draw',self.onDraw) def update_from_mouse(self,x,y): dx = self.last_x - x @@ -54,11 +49,10 @@ def update_from_mouse(self,x,y): def onMotionNotify(self,widget,event): if not self.notice_mouse: return - dummy = widget.get_pointer() self.update_from_mouse(event.x, event.y) def onButtonRelease(self,widget,event): - if event.button==1: + if event.button == 1: self.notice_mouse = False (xc,yc) = (widget.get_allocated_width()//2, widget.get_allocated_height()//2) dx = xc - self.last_x @@ -73,24 +67,16 @@ def onButtonPress(self,widget,event): self.last_y = widget.get_allocated_height()/2 self.update_from_mouse(event.x, event.y) - def __del__(self): - #This is truly weird. If I don't have this method, when you use - # one fourway widget, it fucks up the other. Having this fixes it. - # *even though it doesn't do anything*. Disturbing. - pass - def onDraw(self, widget, cairo_ctx): self.redraw_rect(widget, cairo_ctx) def redraw_rect(self, widget, cairo_ctx): style_ctx = widget.get_style_context() (w,h) = (widget.get_allocated_width(), widget.get_allocated_height()) - Gtk.render_background(style_ctx, - cairo_ctx, 0, 0, w-1, h-1) + Gtk.render_background(style_ctx, cairo_ctx, 0, 0, w-1, h-1) xc = w//2 yc = h//2 - radius = min(w,h)//2 -1 # Consider using gtk_render_arrow def triangle(points): @@ -104,7 +90,7 @@ def triangle(points): th = 8 tw = 6 - # Triangle pointing left + # Triangle pointing left points = [ (1, yc), (1+th, yc-tw), @@ -113,23 +99,23 @@ def triangle(points): # pointing right points = [ - (w -2, yc), - (w -2 -th, yc-tw), - (w -2 -th, yc+tw)] + (w-2, yc), + (w-2-th, yc-tw), + (w-2-th, yc+tw)] triangle(points) # pointing up points = [ (xc, 1), - (xc - tw, th), - (xc + tw, th)] + (xc-tw, th), + (xc+tw, th)] triangle(points) # pointing down points = [ - (xc, h - 2), - (xc - tw, h - 2 - th), - (xc + tw, h - 2 - th)] + (xc, h-2), + (xc-tw, h-2-th), + (xc+tw, h-2-th)] triangle(points) pango_ctx = widget.get_pango_context() @@ -146,7 +132,7 @@ def triangle(points): (text_width, text_height) = layout.get_pixel_size() # truncate text if it's too long - if text_width < (w - th *2) or len(drawtext) < 3: + if text_width < (w-th*2) or len(drawtext) < 3: break drawtext = drawtext[:-1] @@ -156,7 +142,3 @@ def triangle(points): xc - text_width//2, yc - text_height//2, layout) - - -# explain our existence to GTK's object system -GObject.type_register(T) diff --git a/fract4dgui/gtkfractal.py b/fract4dgui/gtkfractal.py index e95a219c5..e7c29d164 100644 --- a/fract4dgui/gtkfractal.py +++ b/fract4dgui/gtkfractal.py @@ -690,7 +690,7 @@ def add_complex_formula_setting( name = self.param_display_name(name,param) fway = fourway.T(name) tip = self.param_tip(name,param) - fway.widget.set_tooltip_text(tip) + fway.set_tooltip_text(tip) fway.connect('value-changed',self.fourway_released, order, form) @@ -699,7 +699,7 @@ def add_complex_formula_setting( 'value-slightly-changed', self.parent.on_drag_param_fourway, order, param_type) - table.attach(fway.widget,0,1,i,i+2, Gtk.AttachOptions.EXPAND|Gtk.AttachOptions.FILL,0, 0,0) + table.attach(fway,0,1,i,i+2, Gtk.AttachOptions.EXPAND|Gtk.AttachOptions.FILL,0, 0,0) def fourway_released(self,widget,x,y,order,form): form.nudge_param(order, x,y) diff --git a/fract4dgui/main_window.py b/fract4dgui/main_window.py index 7061c1ec2..d31d4d094 100644 --- a/fract4dgui/main_window.py +++ b/fract4dgui/main_window.py @@ -2,22 +2,18 @@ import sys import os -import signal -import copy import math import re -import urllib.request, urllib.parse, urllib.error from gi.repository import Gdk, Gtk -# If we haven't been installed (we're running from the dir we +# If we haven't been installed (we're running from the dir we # were unpacked in) this is where fract4d is. -from fract4d import fractal,fc,fract4dc,image, fracttypes, fractconfig - +from fract4d import fractal, fc, image, fracttypes, fractconfig from . import gtkfractal, model, preferences, autozoom, settings, toolbar -from . import undo, browser, fourway, angle, utils, hig, painter +from . import browser, fourway, angle, utils, hig, painter from . import icons, renderqueue, director re_ends_with_num = re.compile(r'\d+\Z') @@ -25,17 +21,15 @@ class MainWindow: def __init__(self, extra_paths=[]): - self.quit_when_done =False + self.quit_when_done = False self.save_filename = None self.compress_saves = True self.f = None self.use_preview = True self.four_d_sensitives = [] - # window widget - self.set_icon() - + # window widget self.window = Gtk.Window() self.window.set_default_size(900,700) self.window.connect('delete-event', self.quit) @@ -66,7 +60,8 @@ def __init__(self, extra_paths=[]): # create fractal compiler and load standard formula and # coloring algorithm files - self.compiler = fc.instance + self.compiler = fc.Compiler() + self.compiler.update_from_prefs(fractconfig.instance) for path in extra_paths: self.compiler.add_func_path(path) @@ -76,7 +71,7 @@ def __init__(self, extra_paths=[]): self.vbox = Gtk.VBox() self.window.add(self.vbox) - self.f = gtkfractal.T(self.compiler,self) + self.f = gtkfractal.T(self.compiler,self) self.f.freeze() # create frozen - main prog will thaw us self.create_subfracts(self.f) @@ -98,20 +93,28 @@ def __init__(self, extra_paths=[]): 'image-preferences-changed', self.on_prefs_changed) - browser.update(self.f.forms[0].funcFile, self.f.forms[0].funcName) - self.create_ui() self.create_toolbar() - self.create_fractal(self.f) + self.panes = Gtk.Paned.new(Gtk.Orientation.HORIZONTAL) + self.vbox.add(self.panes) self.create_status_bar() + self.create_fractal(self.f) + self.panes.pack1(self.swindow, resize=True, shrink=True) + + # show everything apart from the settings pane + self.window.show_all() + + self.settingsPane = settings.SettingsPane(self, self.f) + self.panes.pack2(self.settingsPane, resize=False, shrink=False) + # create these properly later to avoid 'end from FAM server connection' messages self.saveas_fs = None self.saveimage_fs = None self.hires_image_fs = None - self.open_fs = None + self.open_fs = None - self.window.show_all() + self.renderQueue = renderqueue.T() self.update_subfract_visibility(False) self.populate_warpmenu(self.f) @@ -128,6 +131,9 @@ def __init__(self, extra_paths=[]): self.f.set_saved(True) + self.painterDialog = painter.PainterDialog(self.window, self.f) + self.renderqueueDialog = renderqueue.QueueDialog(self.window, self.f, self.renderQueue) + def create_rtd_widgets(self): table = Gtk.Table(n_rows=2,n_columns=3,homogeneous=False) table.width = width = Gtk.Entry() @@ -159,7 +165,7 @@ def create_rtd_widgets(self): 1, 2, 1, 2, Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, - 1,1) + 1,1) return table def get_file_save_chooser(self, title, parent, patterns=[]): @@ -188,14 +194,14 @@ def get_filter(self,name,patterns): return filter def add_filters(self,chooser): - param_patterns = [ "*.fct" ] + param_patterns = ["*.fct"] param_filter = self.get_filter( _("Parameter Files"), param_patterns) chooser.add_filter(param_filter) formula_patterns = ["*.frm", "*.ufm", "*.ucl", "*.cfrm", "*.uxf"] - formula_filter = self.get_filter( + formula_filter = self.get_filter( _("Formula Files"), formula_patterns) chooser.add_filter(formula_filter) @@ -205,7 +211,7 @@ def add_filters(self,chooser): chooser.add_filter(gradient_filter) all_filter = self.get_filter( - _("All Gnofract 4D Files"), + _("All Gnofract 4D Files"), param_patterns + formula_patterns + gradient_patterns) chooser.add_filter(all_filter) @@ -215,7 +221,7 @@ def add_filters(self,chooser): def get_file_open_chooser(self, parent): chooser = Gtk.FileChooserDialog( title, parent, Gtk.FileChooserAction.OPEN, - (Gtk.STOCK_OK, Gtk.ResponseType.OK, + (Gtk.STOCK_OK, Gtk.ResponseType.OK, Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL)) self.add_filters(chooser) @@ -223,7 +229,7 @@ def get_file_open_chooser(self, parent): return chooser def get_save_as_fs(self): - if self.saveas_fs == None: + if self.saveas_fs is None: self.saveas_fs = self.get_file_save_chooser( _("Save Parameters"), self.window, @@ -231,7 +237,7 @@ def get_save_as_fs(self): return self.saveas_fs def get_save_image_as_fs(self): - if self.saveimage_fs == None: + if self.saveimage_fs is None: self.saveimage_fs = self.get_file_save_chooser( _("Save Image"), self.window, @@ -239,7 +245,7 @@ def get_save_image_as_fs(self): return self.saveimage_fs def get_save_hires_image_as_fs(self): - if self.hires_image_fs == None: + if self.hires_image_fs is None: self.saveimage_fs = self.get_file_save_chooser( _("Save High Resolution Image"), self.window, @@ -251,15 +257,15 @@ def get_save_hires_image_as_fs(self): return self.saveimage_fs def get_open_fs(self): - if self.open_fs != None: + if self.open_fs is not None: return self.open_fs self.open_fs = Gtk.FileChooserDialog( - title=_("Open File"), transient_for=self.window, + title=_("Open File"), transient_for=self.window, action=Gtk.FileChooserAction.OPEN) self.open_fs.add_buttons( - Gtk.STOCK_OK, Gtk.ResponseType.OK, + Gtk.STOCK_OK, Gtk.ResponseType.OK, Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL) self.add_filters(self.open_fs) @@ -271,9 +277,9 @@ def on_update_preview(chooser, preview): try: preview.loadFctFile(open(filename)) preview.draw_image(False, False) - active=True + active = True except Exception as err: - active=False + active = False chooser.set_preview_widget_active(active) self.open_fs.set_preview_widget(self.open_preview.widget) @@ -281,16 +287,7 @@ def on_update_preview(chooser, preview): 'update-preview', on_update_preview, self.open_preview) return self.open_fs - - def set_icon(self): - return # can't get this to work - try: - Gtk.window_set_default_icon_list([icons.logo.pixbuf]) - except Exception as err: - print(err) - # not supported in this pyGtk. Oh well... - pass - + def update_subfract_visibility(self,visible): if visible: for f in self.subfracts: @@ -322,7 +319,7 @@ def update_subfracts(self): f.draw_image(aa,auto_deepen) def create_subfracts(self,f): - self.subfracts = [ None ] * 12 + self.subfracts = [None] * 12 for i in range(12): self.subfracts[i] = gtkfractal.SubFract( self.compiler,f.width//4,f.height//4) @@ -383,14 +380,8 @@ def create_fractal(self,f): f.connect('status_changed',self.status_changed) f.connect('stats-changed', self.stats_changed) - hbox = Gtk.HBox() - hbox.pack_start(self.swindow, True, True, 0) - self.control_box = Gtk.VBox() - hbox.pack_start(self.control_box, False, False, 0) - self.vbox.pack_start(hbox, True, True, 0) - - def draw(self): - nt = preferences.userPrefs.getint("general","threads") + def draw(self): + nt = preferences.userPrefs.getint("general","threads") self.f.set_nthreads(nt) self.f.draw_image() @@ -406,10 +397,12 @@ def update_image_prefs(self,prefs): (w,h) = (prefs.getint("display","width"), prefs.getint("display","height")) if self.show_subfracts: - w = w //2 ; h = h // 2 + w = w // 2 + h = h // 2 for f in self.subfracts: f.set_size(w//2, h//2) - w += 2; h += 2 + w += 2 + h += 2 self.f.set_size(w,h) self.f.set_antialias( @@ -427,13 +420,13 @@ def on_prefs_changed(self,prefs): self.draw() def display_filename(self): - if self.filename == None: + if self.filename is None: return _("(Untitled %s)") % self.f.get_func_name() else: return self.filename def base_filename(self, extension): - if self.filename == None: + if self.filename is None: base_name = self.f.get_func_name() base_name = re_cleanup.sub("_", base_name) + extension else: @@ -525,7 +518,7 @@ def status_changed(self,f,status): text = self.statuses[status] % self.f.maxiter elif status == 0: # done - text = self.statuses[status] + text = self.statuses[status] if self.save_filename: self.save_image_file(self.save_filename) if self.quit_when_done: @@ -573,7 +566,7 @@ def get_all_actions(self): def get_toggle_actions(self): return [ ('ToolsExplorerAction', icons.explorer.stock_name, _('_Explorer'), - 'E', _('Create random fractals similar to this one'), + 'E', _('Create random fractals similar to this one'), self.toggle_explorer) ] @@ -582,32 +575,32 @@ def get_main_actions(self): ('FileMenuAction', None, _('_File')), ('FileOpenAction', Gtk.STOCK_OPEN, _('_Open...'), None, _('Open a Parameter or Formula File'), self.open), - ('FileSaveAction', Gtk.STOCK_SAVE, None, + ('FileSaveAction', Gtk.STOCK_SAVE, None, None, _("Save current parameters"), self.save), ('FileSaveAsAction', Gtk.STOCK_SAVE_AS, None, 'S', _("Save current parameters in a new location"), self.saveas), ('FileSaveImageAction', None, _('Save Current _Image'), 'I', _('Save the current image'), self.save_image), ('FileSaveHighResImageAction', None, _('Save _High-Res Image...'), - 'I', _('Save a higher-resolution version of the current image'), + 'I', _('Save a higher-resolution version of the current image'), self.save_hires_image), # FIXME: UI merging would seem to be better, but it's a bit bloody complicated # There's a special widget in pygtk 2.10 for this but that's too new, not all # interesting distributions have it - ('FileRecent1Action', None, _('_1'), None, None, + ('FileRecent1Action', None, _('_1'), None, None, lambda *args : self.load_recent_file(1)), - ('FileRecent2Action', None, _('_2'), None, None, + ('FileRecent2Action', None, _('_2'), None, None, lambda *args : self.load_recent_file(2)), - ('FileRecent3Action', None, _('_3'), None, None, + ('FileRecent3Action', None, _('_3'), None, None, lambda *args : self.load_recent_file(3)), - ('FileRecent4Action', None, _('_4'), None, None, + ('FileRecent4Action', None, _('_4'), None, None, lambda *args : self.load_recent_file(4)), - ('FileQuitAction', Gtk.STOCK_QUIT, None, + ('FileQuitAction', Gtk.STOCK_QUIT, None, None, _('Quit'), self.quit), - ('EditMenuAction', None, _('_Edit')), + ('EditMenuAction', None, _('_Edit')), ('EditFractalSettingsAction', Gtk.STOCK_PROPERTIES, _('_Fractal Settings...'), 'F', _('Edit the fractal\'s settings'), self.settings), ('EditPreferencesAction', Gtk.STOCK_PREFERENCES, None, @@ -644,11 +637,11 @@ def get_main_actions(self): ('HelpCommandReferenceAction', None, _('Command _Reference'), None, _('A list of keyboard and mouse shortcuts'), self.command_reference), ('HelpFormulaReferenceAction', None, _('_Formula Reference'), - None, _('Reference for functions and objects in the formula compiler'), + None, _('Reference for functions and objects in the formula compiler'), self.formula_reference), ('HelpReportBugAction', icons.face_sad.stock_name, _('_Report a Bug'), '', _('Report a bug you\'ve found'), self.report_bug), - ('HelpAboutAction', Gtk.STOCK_ABOUT, _('_About'), + ('HelpAboutAction', Gtk.STOCK_ABOUT, _('_About'), None, _('About Gnofract 4D'), self.about) ] @@ -709,26 +702,29 @@ def create_ui(self): self.manager.get_widget("/MenuBar/FileMenu/Recent3"), self.manager.get_widget("/MenuBar/FileMenu/Recent4")] - def director(self,*args): """Display the Director (animation) window.""" - director.show(self.window,self.control_box, self.f, True) + dialog = director.DirectorDialog(self.window, self.f) + dialog.run() + dialog.destroy() def browser(self,*args): """Display formula browser.""" - browser.show(self.window,self.f) + dialog = browser.BrowserDialog(self, self.f) + dialog.run() + dialog.destroy() def randomize_colors(self,*args): """Create a new random color scheme.""" self.f.make_random_colors(8) def painter(self,*args): - painter.show(self.window,self.f) + self.painterDialog.show() def add_to_queue(self,name,w,h): - renderqueue.show(self.window,None,self.f) - renderqueue.instance.add(self.f.f,name,w,h) - renderqueue.instance.start() + self.renderqueueDialog.show() + self.renderQueue.add(self.f.f,name,w,h) + self.renderQueue.start() def toggle_explorer(self, action): """Enter (or leave) Explorer mode.""" @@ -839,7 +835,7 @@ def create_toolbar(self): self.add_fourway( _("pan"), - _("Pan around the image"), 0, True) + _("Pan around the image"), 0, False) self.add_fourway( _("warp"), _("Mutate the image by moving along the other 2 axes"), 2, True) @@ -859,7 +855,7 @@ def create_toolbar(self): self.toolbar.add_widget( res_menu, _("Resolution"), - _("Change fractal's resolution")) + _("Change fractal's resolution")) # undo/redo self.toolbar.add_space() @@ -932,12 +928,12 @@ def create_resolution_menu(self): self.resolutions = [ (320,240), (640,480), (800,600), (1024, 768), - (1280, 800), (1280, 960), (1280,1024), + (1280, 800), (1280, 960), (1280,1024), (1400, 1050), (1440, 900), - (1600,1200), (1680, 1050), + (1600,1200), (1680, 1050), (1920, 1200), (2560, 1600)] - res_names= [ "%dx%d" % (w,h) for (w,h) in self.resolutions] + res_names= ["%dx%d" % (w,h) for (w,h) in self.resolutions] res_menu = utils.create_option_menu(res_names) @@ -992,12 +988,12 @@ def create_angle_widget(self,name,tip,axis, is4dsensitive): my_angle.axis = axis self.toolbar.add_widget( - my_angle.widget, + my_angle, tip, tip) if is4dsensitive: - self.four_d_sensitives.append(my_angle.widget) + self.four_d_sensitives.append(my_angle) def update_angle_widget(self,f,widget): widget.set_value(f.get_param(widget.axis)) @@ -1027,7 +1023,6 @@ def on_drag_param_fourway(self, widget, dx, dy, order, param_type): def on_release_fourway(self,widget,dx,dy): self.f.nudge(dx/10.0, dy/10.0, widget.axis) - def populate_warpmenu(self,f): params = f.forms[0].params_of_type(fracttypes.Complex, True) if params == []: @@ -1035,9 +1030,10 @@ def populate_warpmenu(self,f): else: utils.set_menu_from_list(self.warpmenu, ["None"] + params) p = f.warp_param - if p == None: p = "None" + if p is None: + p = "None" utils.set_selected_value(self.warpmenu, p) - self.warpmenu.show() + self.warpmenu.show() def add_warpmenu(self,tip): self.warpmenu = utils.create_option_menu(["None"]) @@ -1047,7 +1043,7 @@ def update_warp_param(menu, f): if param == "None": param = None - f.set_warp_param(param) + f.set_warp_param(param) self.on_formula_change(f) #self.populate_warpmenu(self.f,warpmenu) @@ -1064,7 +1060,7 @@ def update_warp_param(menu, f): def add_fourway(self, name, tip, axis, is4dsensitive): my_fourway = fourway.T(name) self.toolbar.add_widget( - my_fourway.widget, + my_fourway, tip, None) @@ -1074,7 +1070,7 @@ def add_fourway(self, name, tip, axis, is4dsensitive): my_fourway.connect('value-changed', self.on_release_fourway) if is4dsensitive: - self.four_d_sensitives.append(my_fourway.widget) + self.four_d_sensitives.append(my_fourway) def update_recent_files(self, file): self.recent_files = preferences.userPrefs.update_list("recent_files",file,4) @@ -1096,10 +1092,10 @@ def load_recent_file(self, file_num, *args): self.load(self.recent_files[file_num-1]) def save_file(self,file): - fileHandle=None + fileHandle = None try: comp = preferences.userPrefs.getboolean("general","compress_fct") - fileHandle = open(file,'w') + fileHandle = open(file,'w') self.f.save(fileHandle,compress=comp) self.set_filename(file) self.update_recent_files(file) @@ -1109,12 +1105,12 @@ def save_file(self,file): _("Error saving to file %s") % file, err) return False finally: - if fileHandle != None: + if fileHandle is not None: fileHandle.close() def save(self,action): """Save the current parameters.""" - if self.filename == None: + if self.filename is None: self.saveas(action) else: self.save_file(self.filename) @@ -1150,7 +1146,7 @@ def confirm(self,name): transient_for=self.window, proceed_button=_("Overwrite")) - response = d.run() + response = d.run() d.destroy() return response == Gtk.ResponseType.ACCEPT else: @@ -1164,7 +1160,7 @@ def show_warning(self,message): d.destroy() def show_error_message(self,message,exception=None): - if exception == None: + if exception is None: secondary_message = "" else: if isinstance(exception,EnvironmentError): @@ -1215,11 +1211,13 @@ def save_image_file(self,filename): def settings(self,*args): """Show fractal settings controls.""" - settings.show_settings(self.window, self.control_box, self.f, False) + self.settingsPane.show() def preferences(self,*args): """Change current preferences.""" - preferences.show_preferences(self.window, self.f) + dialog = preferences.PrefsDialog(self.window, self.f) + dialog.run() + dialog.destroy() def undo(self,*args): """Undo the last operation.""" @@ -1269,7 +1267,9 @@ def set_wy_plane(self,*args): def autozoom(self,*args): """Display AutoZoom dialog.""" - autozoom.show_autozoom(self.window, self.f) + dialog = autozoom.AutozoomDialog(self.window, self.f) + dialog.run() + dialog.destroy() def contents(self,*args): """Show help file contents page.""" @@ -1282,7 +1282,7 @@ def formula_reference(self, *args): self.display_help("formref") def report_bug(self, *args): - url="https://github.com/edyoung/gnofract4d/issues" + url = "https://github.com/edyoung/gnofract4d/issues" utils.launch_browser( preferences.userPrefs, url, @@ -1312,7 +1312,7 @@ def display_help(self,section=None): _("Can't find help file '%s'") % abs_file) return - if section == None: + if section is None: anchor = "" else: anchor = "#" + section @@ -1320,20 +1320,19 @@ def display_help(self,section=None): if yelp_path: os.system("yelp ghelp://%s%s >/dev/null 2>&1 &" % (abs_file, anchor)) else: - url="file://%s%s" % (abs_file, anchor) + url = "file://%s%s" % (abs_file, anchor) utils.launch_browser( preferences.userPrefs, url, self.window) - - + def open(self,action): """Open a parameter or formula file.""" fs = self.get_open_fs() fs.show_all() while True: - result = fs.run() + result = fs.run() if result == Gtk.ResponseType.OK: if self.load(fs.get_filename()): break @@ -1354,7 +1353,6 @@ def load(self,file): fh.close() self.update_recent_files(file) self.set_filename(file) - browser.update(self.f.forms[0].funcFile, self.f.forms[0].funcName) return True except Exception as err: self.show_error_message(_("Error opening %s") % file,err) @@ -1363,10 +1361,10 @@ def load(self,file): def load_formula(self,file): try: self.compiler.load_formula_file(file) - type = browser.guess_type(file) - browser.set_type(type) - browser.update(file) - browser.show(self.window, self.f, type) + dialog = browser.BrowserDialog(self, self.f) + dialog.load_file(file) + dialog.run() + dialog.destroy() return True except Exception as err: @@ -1374,13 +1372,13 @@ def load_formula(self,file): return False def check_save_fractal(self): - "Prompt user to save if necessary. Return whether to quit" + "Prompt user to save if necessary. Return whether to quit" while not self.f.is_saved(): d = hig.SaveConfirmationAlert( document_name=self.display_filename(), parent=self.window) - response = d.run() + response = d.run() d.destroy() if response == Gtk.ResponseType.ACCEPT: self.save(None) @@ -1389,13 +1387,13 @@ def check_save_fractal(self): elif response == hig.SaveConfirmationAlert.NOSAVE: break - while not renderqueue.instance.empty(): + while not self.renderQueue.empty(): d = hig.ConfirmationAlert( primary=_("Render queue still processing."), secondary=_("If you proceed, queued images will not be saved"), proceed_button=_("Close anyway")) - response = d.run() + response = d.run() d.destroy() if response == Gtk.ResponseType.ACCEPT: break @@ -1426,7 +1424,7 @@ def quit(self,action,widget=None): finally: Gtk.main_quit() if 'win' == sys.platform[:3]: - exit(0); + exit(0) # return False def apply_options(self,opts): diff --git a/fract4dgui/painter.py b/fract4dgui/painter.py index a988946e2..2e6bf392f 100644 --- a/fract4dgui/painter.py +++ b/fract4dgui/painter.py @@ -3,29 +3,19 @@ from gi.repository import Gtk from . import dialog -from . import browser -from . import utils - -def show(parent,f): - PainterDialog.show(parent,f) class PainterDialog(dialog.T): - def show(parent, f): - dialog.T.reveal(PainterDialog, True, parent, None, f) - - show = staticmethod(show) - def __init__(self,main_window,f): dialog.T.__init__( self, _("Painter"), main_window, (Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE), - destroy_with_parent=True) + modal=False + ) - self.main_window = main_window self.f = f - self.paint_toggle = Gtk.ToggleButton(_("Painting")) + self.paint_toggle = Gtk.ToggleButton.new_with_label(_("Painting")) self.paint_toggle.set_active(True) self.paint_toggle.connect('toggled',self.onChangePaintMode) self.csel = Gtk.ColorSelection() @@ -42,4 +32,4 @@ def onResponse(self,widget,id): id == Gtk.ResponseType.NONE or \ id == Gtk.ResponseType.DELETE_EVENT: self.hide() - self.f.set_paint_mode(False,None) + self.f.set_paint_mode(False,None) diff --git a/fract4dgui/preferences.py b/fract4dgui/preferences.py index 1702c0494..3793dbeb2 100644 --- a/fract4dgui/preferences.py +++ b/fract4dgui/preferences.py @@ -1,14 +1,8 @@ # GUI for user settings -import os -import sys - -from gi.repository import Gtk -from gi.repository import GObject - -from . import dialog -from . import utils +from gi.repository import Gtk, GObject +from . import dialog, utils from fract4d import fractconfig class Preferences(GObject.GObject): @@ -67,10 +61,8 @@ def save(self): GObject.type_register(Preferences) userPrefs = Preferences(fractconfig.instance) - -def show_preferences(parent,f): - PrefsDialog.show(parent,f) - + + class PrefsDialog(dialog.T): def __init__(self,main_window,f): global userPrefs @@ -78,8 +70,8 @@ def __init__(self,main_window,f): self, _("Gnofract 4D Preferences"), main_window, - (Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE), - destroy_with_parent=True) + (Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE) + ) self.dirchooser = utils.get_directory_chooser( _("Select a Formula Directory"), @@ -94,14 +86,10 @@ def __init__(self,main_window,f): self.create_compiler_options_page() self.create_general_page() self.create_helper_options_page() + self.vbox.show_all() self.set_size_request(500,-1) - def show(parent, f): - dialog.T.reveal(PrefsDialog, True, parent, None, f) - - show = staticmethod(show) - def show_error(self,message): d = Gtk.MessageDialog(self, Gtk.DialogFlags.MODAL, Gtk.MessageType.ERROR, Gtk.ButtonsType.OK, @@ -125,7 +113,7 @@ def set_prefs(*args): except ValueError: Gtk.idle_add( self.show_error, - "Invalid value for width: '%s'. Must be an integer" % \ + "Invalid value for width: '%s'. Must be an integer" % entry.get_text()) return False @@ -157,7 +145,7 @@ def set_prefs(*args): except ValueError: utils.idle_add( self.show_error, - "Invalid value for height: '%s'. Must be an integer" % \ + "Invalid value for height: '%s'. Must be an integer" % entry.get_text()) return False @@ -235,11 +223,11 @@ def create_directory_list(self, section_name): self.path_list = Gtk.ListStore( GObject.TYPE_STRING) - path_treeview = Gtk.TreeView (model=self.path_list) + path_treeview = Gtk.TreeView(model=self.path_list) - renderer = Gtk.CellRendererText () - column = Gtk.TreeViewColumn (_('_Directory'), renderer, text=0) - path_treeview.append_column (column) + renderer = Gtk.CellRendererText() + column = Gtk.TreeViewColumn(_('_Directory'), renderer, text=0) + path_treeview.append_column(column) path_treeview.set_headers_visible(False) paths = self.prefs.get_list(section_name) @@ -247,7 +235,7 @@ def create_directory_list(self, section_name): iter = self.path_list.append() self.path_list.set(iter,0,path) - return path_treeview + return path_treeview def update_prefs(self,name, model): list = [] @@ -265,7 +253,7 @@ def browse_for_dir(self, widget, name, pathlist): if result == Gtk.ResponseType.OK: path = self.dirchooser.get_filename() - model = pathlist.get_model() + model = pathlist.get_model() iter = model.append() model.set(iter,0,path) @@ -305,10 +293,10 @@ def create_compiler_options_page(self): table.attach(flags_label,0,1,1,2,0,0,2,2) flags_label.set_mnemonic_widget(entry) - sw = Gtk.ScrolledWindow () - sw.set_shadow_type (Gtk.ShadowType.ETCHED_IN) - sw.set_policy (Gtk.PolicyType.NEVER, - Gtk.PolicyType.AUTOMATIC) + sw = Gtk.ScrolledWindow() + sw.set_shadow_type(Gtk.ShadowType.ETCHED_IN) + sw.set_policy(Gtk.PolicyType.NEVER, + Gtk.PolicyType.AUTOMATIC) form_path_section = "formula_path" @@ -331,8 +319,7 @@ def create_compiler_options_page(self): remove_button = Gtk.Button.new_from_stock(Gtk.STOCK_REMOVE) remove_button.connect('clicked', self.remove_dir, form_path_section, pathlist) table.attach(remove_button,0,1,4,5,Gtk.AttachOptions.EXPAND | Gtk.AttachOptions.FILL, 0, 2, 2) - - + def create_helper_options_page(self): table = Gtk.Table(n_rows=5,n_columns=2,homogeneous=False) label = Gtk.Label(label=_("_Helpers")) @@ -460,4 +447,3 @@ def create_image_options_page(self): aalabel.set_use_underline(True) aalabel.set_mnemonic_widget(optMenu) table.attach(aalabel,0,1,5,6,0,0,2,2) - diff --git a/fract4dgui/renderqueue.py b/fract4dgui/renderqueue.py index 096926158..57aea0103 100644 --- a/fract4dgui/renderqueue.py +++ b/fract4dgui/renderqueue.py @@ -4,12 +4,9 @@ import copy -from gi.repository import GObject -from gi.repository import Gtk +from gi.repository import Gtk, GObject -from . import gtkfractal -from . import dialog -from . import preferences +from . import dialog, gtkfractal, preferences class QueueEntry: def __init__(self, f, name, w, h): @@ -43,7 +40,7 @@ def add(self,f,name,w,h): self.emit('changed') def start(self): - if self.current == None: + if self.current is None: next(self) def empty(self): @@ -78,43 +75,30 @@ def onProgressChanged(self,f,progress): # explain our existence to GTK's object system GObject.type_register(T) -def show(parent, alt_parent, f): - QueueDialog.show(parent, alt_parent, f) - -instance = T() - class CellRendererProgress(Gtk.CellRendererProgress): def __init__(self): Gtk.CellRendererProgress.__init__(self) self.set_property("text", "Progress") class QueueDialog(dialog.T): - def show(parent, alt_parent, f): - dialog.T.reveal(QueueDialog,True, parent, alt_parent, f) - - show = staticmethod(show) - - def __init__(self, main_window, f): + def __init__(self, main_window, f, renderQueue): dialog.T.__init__( self, _("Render Queue"), main_window, - (Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE), - destroy_with_parent=True + (Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE) ) - self.main_window = main_window - - self.q = instance + self.q = renderQueue self.q.connect('changed', self.onQueueChanged) self.q.connect('progress-changed', self.onProgressChanged) self.controls = Gtk.VBox() self.store = Gtk.ListStore( - GObject.TYPE_STRING, # name - GObject.TYPE_STRING, # size - GObject.TYPE_FLOAT, # % complete + str, # name + str, # size + float # % complete ) self.view = Gtk.TreeView.new_with_model(self.store) @@ -130,6 +114,7 @@ def __init__(self, main_window, f): self.controls.add(self.view) self.vbox.add(self.controls) + self.vbox.show_all() def onQueueChanged(self,q): self.store.clear() @@ -140,4 +125,3 @@ def onProgressChanged(self,f,progress): iter = self.store.get_iter_first() if iter: self.store.set_value(iter,2,progress) - diff --git a/fract4dgui/settings.py b/fract4dgui/settings.py index ab9ed4453..9efc3756f 100644 --- a/fract4dgui/settings.py +++ b/fract4dgui/settings.py @@ -14,30 +14,20 @@ from fract4d import browser_model from fract4d.fc import FormulaTypes -def show_settings(parent,alt_parent, f,dialog_mode): - SettingsDialog.show(parent,alt_parent, f,dialog_mode) - -class SettingsDialog(dialog.T): - def show(parent, alt_parent, f,dialog_mode): - dialog.T.reveal(SettingsDialog,dialog_mode, parent, alt_parent, f) - - show = staticmethod(show) - +class SettingsPane(Gtk.Box): def __init__(self, main_window, f): - dialog.T.__init__( - self, - _("Fractal Settings"), - main_window, - (Gtk.STOCK_CLOSE, Gtk.ResponseType.CLOSE), - destroy_with_parent=True) + Gtk.Box.__init__(self) + self.set_orientation(Gtk.Orientation.VERTICAL) self.main_window = main_window self.f = f + + label_box = dialog.make_label_box(self, _("Fractal Settings")) self.notebook = Gtk.Notebook() self.notebook.set_name("settings_notebook") - self.controls = Gtk.VBox() - self.controls.pack_start(self.notebook, True, True, 0) - self.vbox.pack_start(self.controls, True, True, 0) + self.pack_start(label_box, False, False, 0) + self.pack_start(self.notebook, True, True, 0) + self.tables = [None,None,None,None] self.selected_transform = None @@ -49,6 +39,8 @@ def __init__(self, main_window, f): self.create_location_page() self.create_colors_page() + self.notebook.show_all() + def gradarea_mousedown(self, widget, event): pass @@ -549,7 +541,7 @@ def show_error_message(self,message,exception=None): d = hig.ErrorAlert( primary=message, secondary=secondary_message, - parent=self.main_window) + parent=self.main_window.window) d.run() d.destroy() @@ -696,7 +688,9 @@ def update_all_widgets(self, fractal, container): self.update_all_widgets(fractal,widget) # recurse def show_browser(self,button,type): - browser.show(self.main_window, self.f, type) + dialog = browser.BrowserDialog(self.main_window, self.f, type) + dialog.run() + dialog.destroy() def create_param_entry(self,table, row, text, param): label = Gtk.Label(label=text) diff --git a/fract4dgui/test_browser.py b/fract4dgui/test_browser.py index 93a3f42ef..e5ae4231b 100755 --- a/fract4dgui/test_browser.py +++ b/fract4dgui/test_browser.py @@ -20,14 +20,17 @@ from fract4d import fc, fractal, browser_model from fract4dgui import browser +class MockMainWindow: + def __init__(self): + self.window = None + self.compiler = fc.Compiler() + self.compiler.add_func_path("../formulas") + self.compiler.add_func_path("../fract4d") class Test(unittest.TestCase): def setUp(self): - self.compiler = fc.instance - self.compiler.add_func_path("../formulas") - self.compiler.add_func_path("../fract4d") - - self.f = fractal.T(self.compiler,self) + self.mainWindow = MockMainWindow() + self.f = fractal.T(self.mainWindow.compiler,self) def tearDown(self): browser._model = None @@ -40,17 +43,17 @@ def quitloop(self,f,status): Gtk.main_quit() def testCreate(self): - b = browser.BrowserDialog(None,self.f) + b = browser.BrowserDialog(self.mainWindow, self.f) self.assertNotEqual(b,None) - def testLoadFormula(self): - b = browser.BrowserDialog(None,self.f) + def testSetFormula(self): + b = browser.BrowserDialog(self.mainWindow, self.f) b.set_file('gf4d.frm') b.set_formula('Newton') self.assertEqual(b.ir.errors,[]) def testBadFormula(self): - b = browser.BrowserDialog(None,self.f) + b = browser.BrowserDialog(self.mainWindow, self.f) #print b.model.compiler.path_lists[0] b.set_file('test.frm') b.set_formula('parse_error') @@ -63,13 +66,20 @@ def testBadFormula(self): self.assertNotEqual(all_text,"") self.assertEqual(all_text[0:7],"Errors:") - def test_update(self): - b = browser.BrowserDialog(None,self.f) - b = browser.update(None) - m = browser_model.instance - self.assertEqual(None, m.current.fname) - self.assertEqual(None, m.current.formula) + def test_init(self): + b = browser.BrowserDialog(self.mainWindow, self.f) + m = b.model + self.assertEqual('gf4d.frm', m.current.fname) + self.assertEqual('Mandelbrot', m.current.formula) + def testLoadFormula(self): + b = browser.BrowserDialog(self.mainWindow, self.f) + m = b.model + # load good formula file + b.load_file("../formulas/fractint.cfrm") + self.assertEqual('fractint.cfrm', m.current.fname, "failed to load formula") + #load missing file + self.assertRaises(OSError, b.load_file, "/no_such_dir/wibble.frm") def suite(): return unittest.makeSuite(Test,'test') diff --git a/fract4dgui/test_director.py b/fract4dgui/test_director.py index e0351e426..0a90606a2 100755 --- a/fract4dgui/test_director.py +++ b/fract4dgui/test_director.py @@ -47,7 +47,7 @@ def testDirectorDialog(self): f = fractal.T(g_comp) dd=director.DirectorDialog(None,f,"") - dd.show(None,None,f,True,"") + dd.show() dd.animation.set_png_dir("./") dd.animation.set_fct_enabled(False) dd.animation.add_keyframe("../testdata/director1.fct",1,10,animation.INT_LOG) diff --git a/fract4dgui/test_fourway.py b/fract4dgui/test_fourway.py index caccf3669..30693e5b7 100755 --- a/fract4dgui/test_fourway.py +++ b/fract4dgui/test_fourway.py @@ -38,7 +38,7 @@ def testCreate(self): def testAddToWindow(self): w = Gtk.Window() f = fourway.T("wibble") - w.add(f.widget) + w.add(f) w.show() Gtk.main_iteration() diff --git a/fract4dgui/test_main_window.py b/fract4dgui/test_main_window.py index ad7579536..b56f556ec 100755 --- a/fract4dgui/test_main_window.py +++ b/fract4dgui/test_main_window.py @@ -9,10 +9,14 @@ import sys import random +import gi +gi.require_version('Gtk', '3.0') from gi.repository import Gtk + import gettext os.environ.setdefault('LANG', 'en') gettext.install('gnofract4d') + if sys.path[1] != "..": sys.path.insert(1, "..") from fract4d import fractal @@ -116,17 +120,6 @@ def testSaveImage(self): finally: if os.path.exists("mygood.png"): os.remove("mygood.png") - - def testLoadFormula(self): - # load good formula file - result = self.mw.load_formula("../formulas/fractint.cfrm") - self.assertEqual(result, True, "failed to load formula") - - #load missing file - result = self.mw.load_formula("/no_such_dir/wibble.frm") - self.assertEqual(result, False, "load bad formula succeeded") - self.assertEqual( - self.mw.errors[0][0], "Error opening /no_such_dir/wibble.frm") def testPreview(self): 'Check for problem where preview differs from main image' @@ -140,12 +133,8 @@ def testPreview(self): self.assertEqual(fct1, fct2) def testDialogs(self): - self.mw.director(None,None) self.mw.settings(None,None) - self.mw.preferences(None,None) - self.mw.autozoom(None,None) self.mw.contents(None,None) - self.mw.browser(None,None) self.mw.painter(None,None) def testFileDialogs(self): diff --git a/fract4dgui/test_painter.py b/fract4dgui/test_painter.py index c9ee1790e..cf0fad35f 100755 --- a/fract4dgui/test_painter.py +++ b/fract4dgui/test_painter.py @@ -8,10 +8,14 @@ import os import sys +import gi +gi.require_version('Gtk', '3.0') from gi.repository import Gtk + import gettext os.environ.setdefault('LANG', 'en') gettext.install('gnofract4d') + if sys.path[1] != "..": sys.path.insert(1, "..") from fract4d import fc, fractal diff --git a/fract4dgui/test_preferences.py b/fract4dgui/test_preferences.py index 56d0391b2..26dd5cc64 100755 --- a/fract4dgui/test_preferences.py +++ b/fract4dgui/test_preferences.py @@ -6,6 +6,9 @@ import sys import os +import gi +gi.require_version('Gtk', '3.0') + if sys.path[1] != "..": sys.path.insert(1, "..") from fract4dgui import preferences from fract4d import fractconfig diff --git a/fract4dgui/test_renderqueue.py b/fract4dgui/test_renderqueue.py index bc1147db2..343b3f2d8 100755 --- a/fract4dgui/test_renderqueue.py +++ b/fract4dgui/test_renderqueue.py @@ -66,13 +66,14 @@ def testRQ(self): def testQueueDialog(self): f = fractal.T(g_comp) - renderqueue.show(None,None,f) - rq = renderqueue.instance + rq = renderqueue.T() rq.add(f,"foo.png",124,276) rq.add(f,"foo2.png",204,153) rq.add(f,"foo3.png",80,40) rq.connect('done', self.quitloop) rq.start() + d = renderqueue.QueueDialog(None, f, rq) + d.show() self.wait() os.remove("foo.png"); os.remove("foo2.png"); os.remove("foo3.png") diff --git a/fract4dgui/test_settings.py b/fract4dgui/test_settings.py index abc680141..9778c7da4 100755 --- a/fract4dgui/test_settings.py +++ b/fract4dgui/test_settings.py @@ -29,7 +29,7 @@ def setUp(self): self.compiler.add_func_path("../fract4d") self.f = gtkfractal.T(self.compiler) - self.settings = settings.SettingsDialog(None,self.f) + self.settings = settings.SettingsPane(None,self.f) def tearDown(self): pass