Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • docs/extend-widgets/rst/settings.rst

    r11408 r11424  
    176176state so that when the user changes a check box, the attribute changes 
    177177and vice-versa. Although you can create such a link manually, you 
    178 should always use the module :doc:`OWGUI <owgui.rst>` instead; 
     178should always use the module :doc:`OWGUI <owgui>` instead; 
    179179for instance, for a check box, use :obj:`OWGUI.checkBox` and not 
    180180simply the Qt's :obj:`QCheckBox`. 
     
    183183the data, while other are context-dependent. For the first to be saved 
    184184properly, you only need to list them in the :obj:`settingsList` 
    185 in the widget definition, as already described :doc:`elsewhere <settings.rst>` 
     185in the widget definition, as already described :doc:`elsewhere <settings>` 
    186186 
    187187************************** 
     
    237237In general, the function should go like this. 
    238238 
    239 * Do any clean-up you need, but without clearing any of the settings that need to be saved. Scatter plot needs none. 
    240 * Call :obj:`self.closeContext`; this ensures that all the context dependent settings (e.g. attribute names from the list boxes) are remembered. 
    241 * Get the data (or whatever you do) and set the controls to some defaults as if there were no context retrieving mechanism. Scatter plot does it by calling :obj:`initAttrValues()` which assigns the first two attributes to the x and y axis and the class attribute to the color. At this phase, you shouldn't call any functions that depend on the settings, such as drawing the graph. 
    242 * Call :obj:`self.openContext` (more about the arguments later). This will search for a suitable context and assign the controls new values if one is found. If there is no saved context that can be used, a new context is created and filled with the default values that were assigned at the previous point. 
    243 * Finally, adjust the widget according to the retrieved controls. Scatter plot now plots the graph by calling :obj:`updateGraph`. 
    244  
    245  
    246 :obj:`closeContext` has an argument, the name of the context. If omitted (like above), the default name (:obj:`""`) is used. When opening the context, we give the name and some arguments on which the context depends. In case of :obj:`DomainContextHandler`, which scatter plot uses, we can give it a domain or any object that has a field :obj:`domain` containing a domain. Whether a saved context can be reused is judged upon the presence of attributes in the domain. 
    247  
    248 If the widget is constructed appropriately (that is, if it strictly uses OWGUI controls instead of the Qt's), no other administration is needed to switch the context. 
    249  
    250 Except for declaring the context settings, that is. Scatter plot has this just below the :obj:`settingsList`:: 
     239* Do any clean-up you need, but without clearing any of the settings that need 
     240  to be saved. Scatter plot needs none. 
     241* Call :obj:`self.closeContext()`; this ensures that all the context dependent 
     242  settings (e.g. attribute names from the list boxes) are remembered. 
     243* Get the data (or whatever you do) and set the controls to some defaults as 
     244  if there were no context retrieving mechanism. Scatter plot does it by 
     245  calling :obj:`initAttrValues()` which assigns the first two attributes to 
     246  the x and y axis and the class attribute to the color. At this phase, you 
     247  shouldn't call any functions that depend on the settings, such as drawing 
     248  the graph. 
     249* Call :obj:`self.openContext` (more about the arguments later). This will 
     250  search for a suitable context and assign the controls new values if one is 
     251  found. If there is no saved context that can be used, a new context is 
     252  created and filled with the default values that were assigned at the previous 
     253  point. 
     254* Finally, adjust the widget according to the retrieved controls. Scatter plot 
     255  now plots the graph by calling :obj:`updateGraph`. 
     256 
     257 
     258:obj:`closeContext` has an argument, the name of the context. If omitted 
     259(like above), the default name (:obj:`""`) is used. When opening the context, 
     260we give the name and some arguments on which the context depends. In case of 
     261:obj:`DomainContextHandler`, which scatter plot uses, we can give it a domain 
     262or any object that has a field :obj:`domain` containing a domain. Whether a 
     263saved context can be reused is judged upon the presence of attributes in the 
     264domain. 
     265 
     266If the widget is constructed appropriately (that is, if it strictly uses OWGUI 
     267controls instead of the Qt's), no other administration is needed to switch the 
     268context. 
     269 
     270Except for declaring the context settings, that is. Scatter plot has this just 
     271below the :obj:`settingsList`:: 
    251272 
    252273    contextHandlers = {"": DomainContextHandler("", 
     
    257278       ("attrSize", DomainContextHandler.Optional)])} 
    258279 
    259 :obj:`contextHandlers` is a dictionary whose keys are contexts' names. Each widget can have multiple contexts; for an unrealistic example, consider a scatter plot which gets two data sets and uses one attribute from the first for the x axis, and an attribute from the other for y. Since we won't see this often, the default name for a context is an empty string. 
    260  
    261 The values in the dictionary are context handlers. Scatter plot declares that it has a DomainContextHandler with name "" (sorry for the repetition) with attributes "attrX", "attrY", "attrLabel", "attrShape" and "attrSize". The first two are required, while the other three are optional. 
     280:obj:`contextHandlers` is a dictionary whose keys are contexts' names. Each 
     281widget can have multiple contexts; for an unrealistic example, consider a 
     282scatter plot which gets two data sets and uses one attribute from the first 
     283for the x axis, and an attribute from the other for y. Since we won't see this 
     284often, the default name for a context is an empty string. 
     285 
     286The values in the dictionary are context handlers. Scatter plot declares that 
     287it has a DomainContextHandler with name "" (sorry for the repetition) with 
     288attributes "attrX", "attrY", "attrLabel", "attrShape" and "attrSize". The 
     289first two are required, while the other three are optional. 
    262290 
    263291********************************* 
     
    265293********************************* 
    266294 
    267 What we said above is not exactly 
    268 true. :obj:`DomainContextHandler.Required` is the default flag, 
    269 so :obj:`("attrX", DomainContextHandler.Required)` can be 
    270 replaced by simply :obj:`"attrX"`. And the latter three have the 
     295What we said above is not exactly true. :obj:`DomainContextHandler.Required` 
     296is the default flag, so :obj:`("attrX", DomainContextHandler.Required)` can 
     297be replaced by simply :obj:`"attrX"`. And the latter three have the 
    271298same flags, so they can be grouped into :obj:`(["attrLabel", 
    272299"attrShape", "attrSize"], DomainContextHandler.Optional)`. So 
     
    277304       (["attrLabel", "attrShape", "attrSize"], DomainContextHandler.Optional)])} 
    278305 
    279 What do "optional" and "required" mean? Say that you used the 
     306What do ``Optional`` and ``Required`` mean? Say that you used the 
    280307scatter plot on the data with attributes A, B, C and D; A and B are 
    281308used for the x and y axis and D defined the colors of examples. Now 
     
    295322:obj:`DomainContextHandler`. 
    296323 
    297 DomainContextHandler's constructor has the following arguments 
    298  
    299 contextName 
    300 The name of the context; it should consist of letters and digits (it is used as a prt of a variable name). In case the widget has multiple contexts, they should have unique names. In most cases there will be only one context, so you can leave it empty. 
    301  
    302 fields 
    303 The names of the attributes to be saved and the corresponding flags. They are described in more details below. 
    304  
    305 cloneIfImperfect 
    306 states that when the context doesn't match perfectly, that is, unless the domain is exactly the same as the domain from which the context was originally created, :obj:`openContext` shouldn't reuse a context but create a copy of the best matching context instead. Default is :obj:`True`. 
    307  
    308 loadImperfect 
    309 tells whether the contexts that do not match perfectly (see above) should be used or not. Default is :obj:`True`. 
    310  
    311 findImperfect 
    312 tells whether imperfect contexts match at all or not (this flag is somewhat confused with :obj:`loadImperfect`, but it may come useful some day. Default is :obj:`True` again. 
    313  
    314 syncWithGlobal 
    315 tells whether instances of this widget should have a shared list of contexts (default). The alternative is that each keeps its own list; each individual list is merged with the global when the widget is deleted from the canvas (or when the canvas is closed). This setting only applies to canvas, while in saved applications widgets always have separate settings lists. 
    316  
    317 maxAttributesToPickle 
    318 To keep the size of the context file small, settings for domains exceeding a certain number of attributes are not pickled. Default is 100, but you can increase (or decrease this) if you need to. 
     324:class:`DomainContextHandler`'s constructor has the following arguments 
     325 
     326`contextName` 
     327   The name of the context; it should consist of letters and digits (it is 
     328   used as a part of a variable name). In case the widget has multiple 
     329   contexts, they should have unique names. In most cases there will be only 
     330   one context, so you can leave it empty. 
     331 
     332`fields` 
     333   The names of the attributes to be saved and the corresponding flags. They 
     334   are described in more details below. 
     335 
     336`cloneIfImperfect` 
     337   States that when the context doesn't match perfectly, that is, unless the 
     338   domain is exactly the same as the domain from which the context was 
     339   originally created, :obj:`openContext` shouldn't reuse a context but create 
     340   a copy of the best matching context instead. Default is :obj:`True`. 
     341 
     342`loadImperfect` 
     343   tells whether the contexts that do not match perfectly (see above) should 
     344   be used or not. Default is :obj:`True`. 
     345 
     346`findImperfect` 
     347   Tells whether imperfect contexts match at all or not (this flag is 
     348   somewhat confused with :obj:`loadImperfect`, but it may come useful some 
     349   day). Default is :obj:`True` again. 
     350 
     351`syncWithGlobal` 
     352   Tells whether instances of this widget should have a shared list of 
     353   contexts (default). The alternative is that each keeps its own list; 
     354   each individual list is merged with the global when the widget is deleted 
     355   from the canvas (or when the canvas is closed). This setting only applies 
     356   to canvas, while in saved applications widgets always have separate settings 
     357   lists. 
     358 
     359`maxAttributesToPickle` 
     360   To keep the size of the context file small, settings for domains exceeding 
     361   a certain number of attributes are not pickled. Default is 100, but you can 
     362   increase (or decrease this) if you need to. 
    319363 
    320364 
     
    326370name (just like in :obj:`settingsList`) and a flag. Here are the possible flags: 
    327371 
    328 * :obj:`DomainContextHandler.Optional`, :obj:`DomainContextHandler.SelectedRequired` and :obj:`DomainContextHandler.Required` state whether the attribute is optional or required, as explained above. Default is :obj:`Required`. :obj:`DomainContextHandler.SelectedRequired` is applicable only if the control is a list box, where it means that the attributes that are selected are required while the other attributes from the list are not. 
    329 * :obj:`DomainContextHandler.NotAttribute` the setting is not an attribute name. You can essentially make a check box context dependent, but we very strongly dissuade from this since it can really confuse the user if some check boxes change with the data while most do not. 
    330 * :obj:`DomainContextHandler.List` tells that the attribute corresponds to a list box. 
     372* :obj:`DomainContextHandler.Optional`, 
     373  :obj:`DomainContextHandler.SelectedRequired` and 
     374  :obj:`DomainContextHandler.Required` state whether the attribute is optional 
     375  or required, as explained above. Default is :obj:`Required`. 
     376  :obj:`DomainContextHandler.SelectedRequired` is applicable only if the 
     377  control is a list box, where it means that the attributes that are selected 
     378  are required while the other attributes from the list are not. 
     379 
     380* :obj:`DomainContextHandler.NotAttribute` the setting is not an attribute 
     381  name. You can essentially make a check box context dependent, but we very 
     382  strongly dissuade from this since it can really confuse the user if some 
     383  check boxes change with the data while most do not. 
     384 
     385* :obj:`DomainContextHandler.List` tells that the attribute corresponds to a 
     386  list box. 
    331387 
    332388 
     
    348404But the tuples are actually a shortcut for instances of 
    349405:obj:`ContextField`. When you say :obj:`"attrX"` this is actually 
    350 :obj:`ContextField("attrX", DomainContextHandler.Required)` (you should 
    351 appreciate the shortcurt, right?). But see this monster from widget "Select 
    352 Attributes" (file OWDataDomain.py):: 
    353  
    354     contextHandlers = {"": DomainContextHandler("", 
    355         [ContextField("chosenAttributes", 
    356                        DomainContextHandler.RequiredList, 
    357                        selected="selectedChosen", reservoir="inputAttributes"), 
    358          ContextField("classAttribute", 
    359                        DomainContextHandler.RequiredList, 
    360                        selected="selectedClass", reservoir="inputAttributes"), 
    361          ContextField("metaAttributes", 
    362                        DomainContextHandler.RequiredList, 
    363                        selected="selectedMeta", reservoir="inputAttributes") 
    364     ])} 
    365  
    366  
    367 :obj:`ContextField`'s constructor gets the name and flags and a list of 
    368 arguments that are written directly into the object instance. To follow the 
    369 example, recall what Select Attributes looks like: it allows you to select a 
    370 subset of attributes, the class attribute and the meta attributes that you 
    371 want to use; the attributes in the corresponding three list boxes are stored 
    372 in the widget's variables :obj:`chosenAttributes`, :obj:`classAttribute` 
    373 and :obj:`metaAttributes` respectively. When the user selects some attributes 
    374 in any of these boxes, the selection is stored in :obj:`selectedChosen`, 
    375 :obj:`selectedClass` and :obj:`selectedMeta`. The remaining attributes 
    376 - those that are not in any of these three list boxes - are in the leftover 
    377 listbox on the left-hand side of the widget, and the content of the box is 
    378 stored in the widget's variable :obj:`inputAttributes`. 
    379  
    380 The above definition tells that the context needs to store the contents of 
    381 the three list boxes by specifying the corresponding variables; the list of 
    382 attributes is given as the name of the field and the list of selected 
    383 attributes is in the optional named attribute :obj:`selected`. By 
    384 :obj:`reservoir` we told the context handler that the attributes are taken 
    385 from :obj:`inputAttributes`. So, when a context is retrieved, all the 
    386 attributes that are not in any of the three list boxes are put into 
    387 :obj:`inputAttributes`. 
    388  
    389 Why the mess? Couldn't we just store :obj:`inputAttributes` as the fourth 
    390 list box? Imagine that the user first loads the data with attributes A, B, 
    391 C, D, E and F, puts A, B, C in chosen and D in class. E and F are left in 
    392 :obj:`inputAttributes`. Now she loads another data which has attributes A, 
    393 B, C, D, E, and G. The contexts should match (the new data has all the 
    394 attributes we need), but :obj:`inputAttributes` should now contain E and 
    395 G, not E and F, since F doesn't exist any more, while G needs to be made 
    396 available. 
    397  
    398 You can use :obj:`ContextField` (instead of tuples and strings) for 
    399 declaring any fields, but you will usually need them only for lists or, 
    400 maybe, some complicated future controls. 
     406:obj:`ContextField("attrX", DomainContextHandler.Required)` 
     407 
     408.. 
     409   But see this monster from widget "Select Attributes" (file OWDataDomain.py):: 
     410 
     411       contextHandlers = {"": DomainContextHandler("", 
     412           [ContextField("chosenAttributes", 
     413                          DomainContextHandler.RequiredList, 
     414                          selected="selectedChosen", reservoir="inputAttributes"), 
     415            ContextField("classAttribute", 
     416                          DomainContextHandler.RequiredList, 
     417                          selected="selectedClass", reservoir="inputAttributes"), 
     418            ContextField("metaAttributes", 
     419                          DomainContextHandler.RequiredList, 
     420                          selected="selectedMeta", reservoir="inputAttributes") 
     421       ])} 
     422 
     423 
     424   :obj:`ContextField`'s constructor gets the name and flags and a list of 
     425   arguments that are written directly into the object instance. To follow the 
     426   example, recall what Select Attributes looks like: it allows you to select a 
     427   subset of attributes, the class attribute and the meta attributes that you 
     428   want to use; the attributes in the corresponding three list boxes are stored 
     429   in the widget's variables :obj:`chosenAttributes`, :obj:`classAttribute` 
     430   and :obj:`metaAttributes` respectively. When the user selects some attributes 
     431   in any of these boxes, the selection is stored in :obj:`selectedChosen`, 
     432   :obj:`selectedClass` and :obj:`selectedMeta`. The remaining attributes 
     433   - those that are not in any of these three list boxes - are in the leftover 
     434   listbox on the left-hand side of the widget, and the content of the box is 
     435   stored in the widget's variable :obj:`inputAttributes`. 
     436 
     437   The above definition tells that the context needs to store the contents of 
     438   the three list boxes by specifying the corresponding variables; the list of 
     439   attributes is given as the name of the field and the list of selected 
     440   attributes is in the optional named attribute :obj:`selected`. By 
     441   :obj:`reservoir` we told the context handler that the attributes are taken 
     442   from :obj:`inputAttributes`. So, when a context is retrieved, all the 
     443   attributes that are not in any of the three list boxes are put into 
     444   :obj:`inputAttributes`. 
     445 
     446   Why the mess? Couldn't we just store :obj:`inputAttributes` as the fourth 
     447   list box? Imagine that the user first loads the data with attributes A, B, 
     448   C, D, E and F, puts A, B, C in chosen and D in class. E and F are left in 
     449   :obj:`inputAttributes`. Now she loads another data which has attributes A, 
     450   B, C, D, E, and G. The contexts should match (the new data has all the 
     451   attributes we need), but :obj:`inputAttributes` should now contain E and 
     452   G, not E and F, since F doesn't exist any more, while G needs to be made 
     453   available. 
     454 
     455   You can use :obj:`ContextField` (instead of tuples and strings) for 
     456   declaring any fields, but you will usually need them only for lists or, 
     457   maybe, some complicated future controls. 
    401458 
    402459 
     
    405462***************************** 
    406463 
    407 Avoid it if you can. If you can't, here's the list of the methods you may need to implement. You may want to copy as much from the :obj:`DomainContextHandler` as you can. 
    408  
    409  
    410 __init__ 
    411 Has the same arguments as the :obj:`DomainContextHandler`'s, except for the :obj:`fields`. 
    412  
    413 newContext 
    414 Creates and returns a new context. In :obj:`ContextHandler` is returns an instance of :obj:`Context`; you probably won't need to change this. 
    415  
    416 openContext 
    417 The method is given a widget and some additional arguments based on which the contexts are compared. In case of :obj:`DomainContextHandler` this is a domain. There can be one or more such arguments. Note that the method :obj:`openContext` which we talked about above is a method of :obj:`OWBaseWidget`, while here we describe a method of context handlers. Actually, :obj:`OWBaseWidget(self, contextName, *args)` calls the context handler's, passing it's :obj:`self` and :obj:`*args`. 
    418  
    419 It needs to find a matching context and copy its settings to the widget or construct a new context and copy the settings from the widget. Also, when an old context is reused, it should be moved to the beginning of the list. :obj:`ContextHandler` already defines this method, which should usually suffice. :obj:`DomainContextHandler` adds very little to it. 
    420  
    421 closeContext 
    422 Copies the settings from the widget by calling :obj:`settingsFromWidget`. You probably won't need to overwrite it. 
    423  
    424 match 
    425 The method is called by :obj:`openContext` to find a matching context. Given an existing context and the arguments that were given to :obj:`openContext` (for instance, a domain), it should decide whether the context matches or not. If it returns 2, it is a perfect match (e.g. domains are the same). If it returns 0, the context is not applicable (e.g. some of the required attributes are missing). In case it returns a number between 0 and 1 (excluding 0), the higher the number the better the match. :obj:`openContext` will use the best matching context (or the perfect one, if found). 
    426  
    427 settingsToWidget/settingsFromWidget 
    428 Copy the settings to and from the widget. 
    429  
    430 fastSave 
    431 This function is called by the widget's :obj:`__setattr__` each time any widget's variable is changed to immediately synchronize the context with the state of the widget. The method is really needed only when :obj:`syncWithGlobal` is set. When the context is closed, :obj:`closeContext` will save the settings anyway. 
    432  
    433 cloneContext 
    434 Given an existing context, it prepares and returns a copy. The method is optional; :obj:`copy.deepcopy` can be used instead. 
     464Avoid it if you can. If you can't, here's the list of the methods you may need 
     465to implement. You may want to copy as much from the :obj:`DomainContextHandler` 
     466as you can. 
     467 
     468 
     469:obj:`__init__` 
     470   Has the same arguments as the :obj:`DomainContextHandler`'s, except for the 
     471   :obj:`fields`. 
     472 
     473:obj:`newContext()` 
     474   Creates and returns a new context. In :obj:`ContextHandler` it returns an 
     475   instance of :obj:`Context`; you probably won't need to change this. 
     476 
     477:obj:`openContext(widget, *args)` 
     478   The method is given a widget and some additional arguments based on which 
     479   the contexts are compared. In case of :obj:`DomainContextHandler` this is 
     480   a domain. There can be one or more such arguments. Note that the method 
     481   :obj:`openContext` which we talked about above is a method of 
     482   :obj:`OWBaseWidget`, while here we describe a method of context handlers. 
     483   Actually, :obj:`OWBaseWidget.openContext(self,contextName, *args)` calls 
     484   the context handler's, passing it's :obj:`self` and :obj:`*args`. 
     485 
     486   It needs to find a matching context and copy its settings to the widget or 
     487   construct a new context and copy the settings from the widget. Also, when an 
     488   old context is reused, it should be moved to the beginning of the list. 
     489   :obj:`ContextHandler` already defines this method, which should usually 
     490   suffice. :obj:`DomainContextHandler` adds very little to it. 
     491 
     492:obj:`closeContext` 
     493   Copies the settings from the widget by calling :obj:`settingsFromWidget`. 
     494   You probably won't need to overwrite it. 
     495 
     496:obj:`match` 
     497   The method is called by :obj:`openContext` to find a matching context. 
     498   Given an existing context and the arguments that were given to 
     499   :obj:`openContext` (for instance, a domain), it should decide whether the 
     500   context matches or not. If it returns 2, it is a perfect match (e.g. 
     501   domains are the same). If it returns 0, the context is not applicable 
     502   (e.g. some of the required attributes are missing). In case it returns a 
     503   number between 0 and 1 (excluding 0), the higher the number the better the 
     504   match. :obj:`openContext` will use the best matching context (or the 
     505   perfect one, if found). 
     506 
     507:obj:`settingsToWidget` / :obj:`settingsFromWidget` 
     508   Copy the settings to and from the widget. 
     509 
     510:obj:`fastSave` 
     511   This function is called by the widget's :obj:`__setattr__` each time any 
     512   widget's variable is changed to immediately synchronize the context with 
     513   the state of the widget. The method is really needed only when 
     514   :obj:`syncWithGlobal` is set. When the context is closed, 
     515   :obj:`closeContext` will save the settings anyway. 
     516 
     517:obj:`cloneContext` 
     518   Given an existing context, it prepares and returns a copy. The method is 
     519   optional; :obj:`copy.deepcopy` can be used instead. 
    435520 
    436521 
     
    440525 
    441526Settings can be saved in two different places. Orange Canvas save 
    442 settings in .ini files in directory 
    443 Orange/OrangeWidgets/widgetSettings. Each widget type has its separate 
    444 file; for instance, the scatter plot's settings are saved in 
     527settings in .ini files in its application data directory. Each widget type has 
     528a separate file; for instance, the scatter plot's settings are saved in 
    445529:obj:`ScatterPlot.ini`. Saved schemas and applications save 
    446530settings in .sav files; the .sav file is placed in the same directory 
     
    451535Saving and loading is done automatically by canvas or the 
    452536application. In a very rare case you need it to run these operations 
    453 manually, the functions involved are :obj:`loadSettings(self, file = 
    454 None)`, :obj:`saveSettings(self, file = None)`, 
    455 :obj:`loadSettingsStr(self, str)`, 
     537manually, the functions involved are :obj:`loadSettings(self, file=None)`, 
     538:obj:`saveSettings(self, file=None)`, :obj:`loadSettingsStr(self, str)`, 
    456539:obj:`saveSettingsStr(self)`. The first two load and save from 
    457540the file; if not given, the default name (widget's name + 
Note: See TracChangeset for help on using the changeset viewer.