LibreOffice Tree with columns - libreoffice

I am writing an extension for LibreOffifce.
A tree with columns on my sidebar is needed. (example - https://doc.qt.io/qt-5/qtwidgets-itemviews-simpletreemodel-example.html)
I found information about Tree Control and module "tree", e.g. here
https://wiki.openoffice.org/wiki/Treecontrol
https://www.openoffice.org/api/docs/common/ref/com/sun/star/awt/tree/module-ix.html
But I couldn't find anything about writing a tree with columns.
There is a quote "You can provide your own model which must at least support the interface com.sun.star.awt.XTreeModel." in the article "Tree control", but I also couldn't find any information about providing of my own models...
Please, help me find information and examples, if it is possible to provide tree with columns for LibreOffice extension.

Here is some Python-UNO code (as tagged in your question) that shows how to implement the XTreeDataModel UNO interface. You'll have to write a lot more code in order to render the nodes in multiple columns and do everything else you want. It may be required to create another class that implements XTreeNode.
import uno
import unohelper
from com.sun.star.awt.tree import XTreeDataModel
def myTree():
document = XSCRIPTCONTEXT.getDocument()
ctx = XSCRIPTCONTEXT.getComponentContext()
smgr = ctx.getServiceManager()
dlgprov = smgr.createInstanceWithArgumentsAndContext(
"com.sun.star.awt.DialogProvider", (document,), ctx)
dlg = dlgprov.createDialog(
"vnd.sun.star.script:Standard.Dialog1?location=application")
treeCtrl = dlg.getControl("TreeControl1")
treeModel = treeCtrl.getModel()
mutableTreeDataModel = smgr.createInstanceWithContext(
"com.sun.star.awt.tree.MutableTreeDataModel", ctx)
rootNode = mutableTreeDataModel.createNode("Root", True)
mutableTreeDataModel.setRoot(rootNode)
myTree = MyTreeDataModel(rootNode)
model = mutableTreeDataModel
childNode1 = model.createNode("Parent 1", True)
rootNode.appendChild(childNode1)
subChildNode = model.createNode("Child 1", True)
childNode1.appendChild(subChildNode)
treeModel.setPropertyValue("DataModel", myTree)
dlg.execute()
dlg.dispose()
class MyTreeDataModel(unohelper.Base, XTreeDataModel):
def __init__(self, root):
self.rootNode = root
def getRoot(self):
return self.rootNode
def addTreeDataModelListener(self, listener):
pass
def removeTreeDataModelListener(self, listener):
pass
More information for working with trees is at https://wiki.openoffice.org/wiki/Going_further_with_Dialog_and_Component#The_New_Tree_Control.
If it turns out that there is no convenient way to do this directly with UNO, I once did this with a JTreeTable in Java. LibreOffice extensions can be written in Java, so perhaps that would solve your needs instead.

Related

roxygen2 docstrings for Reference Classes overriding base class

I have an abstract base class that looks like this:
#' An Abstract Base Class
Filter <- setRefClass(
Class = "Filter",
methods = list(
train = function(x) {
"Override this method to train any associated parameters for the filter on the supplied data"
print("no learning to be done")
})
)
and the following class that extends this class:
#' Filter class that leverages the prcomp R method.
PcaFilter <- setRefClass(
"PcaFilter",
contains="Filter",
fields=list(
d="numeric",
model="ANY"
),
methods=list(
train=function(x) {
"train PCA model, store result to model attribute of obj"
model <<- prcomp(x)
})
)
After I run
roxygen2::roxygenize()
Then I get two man files but in the man file for the second class the docstring for the overridden class does not come through- I get the docstring for the base class. Am I doing something wrong or is this a bug with roxygen2 ?
Also is there any better way of doing this? I would like to be able to use multi-line docstrings.
Having searched through the Issues on the roxygen github repo. Found that there's already an active Issue pertaining to this:
https://github.com/klutometis/roxygen/issues/433
In summary: the support and documentation for Reference Classes in roxygen is not great as of v5.0. The suggested method is still to use docstrings and it's impossible to override the docstrings of parents.

Multi Object View Behaviour - Creating an Editor for a HasTraits subclass

I am currently trying to make a traitsUI GUI for a class that contains many instances of a single object. My problem is very similar to the one solved in MultiObjectView Example TraitsUI.
However, I don't like the idea of using a context as it requires me to write out the same view many times for each object I have (and I might have a lot). So I tried to edit the code to make it so that each Instance of the House object would default to looking like its normal view when it is viewed from the Houses object. It almost worked, except now I get a button that takes me to the view I want rather than seeing the views nested in one window (like the output of the TraitsUI example above).
Is there a way to adapt the below to get the desired output? I think I have to further edit the create_editor function but I can find very little documentation on this - only many links to different trait editor factories...
Thanks,
Tim
# multi_object_view.py -- Sample code to show multi-object view
# with context
from traits.api import HasTraits, Str, Int, Bool
from traitsui.api import View, Group, Item,InstanceEditor
# Sample class
class House(HasTraits):
address = Str
bedrooms = Int
pool = Bool
price = Int
traits_view =View(
Group(Item('address'), Item('bedrooms'), Item('pool'), Item('price'))
)
def create_editor(self):
""" Returns the default traits UI editor for this type of trait.
"""
return InstanceEditor(view='traits_view')
class Houses(HasTraits):
house1 = House()
house2= House()
house3 = House()
traits_view =View(
Group(Item('house1',editor = house1.create_editor()), Item('house2',editor = house1.create_editor()), Item('house3',editor = house1.create_editor()))
)
hs = Houses()
hs.configure_traits()
Would something like this work?
It simplifies things a little bit and gives you a view that contains the list of views for your houses.
# multi_object_view.py -- Sample code to show multi-object view
# with context
from traits.api import HasTraits, Str, Int, Bool
from traitsui.api import View, Group, Item,InstanceEditor
# Sample class
class House(HasTraits):
address = Str
bedrooms = Int
pool = Bool
price = Int
traits_view =View(
Group(
Item('address'), Item('bedrooms'), Item('pool'), Item('price')
)
)
class Houses(HasTraits):
house1 = House()
house2= House()
house3 = House()
traits_view =View(
Group(
Item('house1', editor=InstanceEditor(), style='custom'),
Item('house2', editor=InstanceEditor(), style='custom'),
Item('house3', editor=InstanceEditor(), style='custom')
)
)
if __name__ == '__main__':
hs = Houses()
hs.configure_traits()

How to execute tests on the argument that a controller passes to the view in Play Framework

In our play application every controller function fetches data from the database (or some other way) and passes these values to the result
def index = Action { implicit request =>
val newsItems: List[String] = fetchNewsFromDB()
Ok(views.html.home.index(newsItems))
}
def fetchNewsFromDB() = List("Headline1", "Headline2")
I am writing tests using specifiactions (based on the documentation http://www.playframework.com/documentation/2.2.x/ScalaTest)
According to this documentation by controller as follows. In the next test I want to make sure that the index page contains a headline. I do this by checking if there exists a div with the class "headline"
"Example Page#index" should {
"should contain a headline" in {
val controller = new TestController()
val result: Future[SimpleResult] = controller.index().apply(FakeRequest())
val bodyText: String = contentAsString(result)
bodyText.toLowerCase must contain("<div class=\"headline\"")
}
}
However I would rather check whether the list newsItems which the controller passes to the view is nonempty.
What is the best way to do this?
Is it possible to this in a generic way for which little modification of the controllers is required?
I too was frustrated that I couldn't intercept the parameters on their way to the template - and in fact it can become extremely difficult to even get the template to render at all in tests if you have a lot of "state" in your pages (for example, implicits that provide the user object, navigation helpers etc).
What I ended up doing was putting in an extra "seam" for testability in my controllers; in my tests, I extend the controller under test, replacing the HTML rendering function with a mocked one, which I can then use to verify the parameters.
Here's a simple example based on your "news" Action; first, the controller, which is no longer an object so we can extend it:
object Application extends ApplicationController
trait ApplicationController extends Controller {
def newsAction = Action {
Ok(renderNews("this is the news"))
}
def renderNews(s:List[String]):Html = html.sandbox(s)
}
The renderNews method gives us the all-important "test seam". I think it also actually improves the readability of controller methods too, which is nice :-)
Now, the unit test:
class ApplicationSpec extends Specification with Mockito {
val mockedNewsRenderer = mock[List[String] => Html]
val controller = new ApplicationController {
override def renderNews(s:List[String]) = mockedNewsRenderer(s)
}
"Application News Controller" should {
"Pass a non-empty list of news items to the template" in {
val result = controller.newsAction(FakeRequest())
status(result) must beEqualTo(200)
val captor = ArgumentCaptor.forClass(classOf[List[String]])
there was one(mockedNewsRenderer).apply(captor.capture())
val theArgument = captor.getValue
theArgument.isEmpty must beFalse
}
}
}
We create a mock to stand-in for the renderNews function, extend the controller so that we can substitute it in (note that we don't change anything else about it of course), and then call the action as normal. Note that we still get a standard Play Result so we can still check status codes etc, but then, we can use the Mockito verify functionality that's built into Specs2, together with Mockito's ArgumentCaptor facility to assert that our template was indeed called, and that it was supplied with a non-empty list of strings.
This approach has worked well for me - it makes it possible to get really good code coverage of your controllers with fast-running and easy-to-write unit tests.
You have a very good question and a very valid point on testing controllers, but I'm afraid it can't be done easily. The problem is that the views compile to Scala functions meaning when you call views.html.home.index(newsItems) it will return an object of Html, which already has the Html put together and compiled. If you would like to test what get's passed in you need to intercept it before the view is called.
To solve this you would have to rewrite your controllers, by moving all your business logic out of the controller and only have the necessary request handling code there. That would almost be easier to test.

While creating Object, setting values to methods or variable without using def or val keyword

I come from a Java background and as expected, am having problem understanding some patterns used in Scala (see below). Every time I feel that I have a good understanding of Scala patterns or programming methodology, something pops up that is beyond my programming understanding and puts me back in learning mode. I guess that's a beauty of scala that always inspires me to keep learning :)
Anyway I trying to do some sample programming in scala swing.............
val frame = new MainFrame {
title = "Electronic Classroom"
contents = new BorderPanel {
layout += new GridPanel(1, 2) {
contents += new ScrollPane(semesterList)
contents += new ScrollPane(courseList)
} -> West
}
menuBar = new MenuBar {
contents += new Menu("File") {
contents += new MenuItem("Login") {
action = Action("Login"){
login
user match{
case Some(inst:Instructor) => instructorMenu.enabled = true
enabled = false
case Some(_) => instructorMenu.enabled = false
enabled = false
case _ =>
}
}
}
contents += new Separator
contents += new MenuItem(Action("Exit")(sys.exit(0)))
}
}
contents += instructorMenu
}
size = new Dimension(1000, 600)
centerOnScreen
}
Here we are setting values to def and val without using def or val keyword while defining them (like title, size, contents etc) and it's now looking more like a body script which is different that the way we do in java where all the assignments etc takes place in a method body.. I guess I am missing a big design pattern here
Can someone help, abd explain to me the Scala design pattern??
This is actually not very different from Java—instead of creating an instance and then customising it, you are creating anonymous sub classes. E.g.
val frame = new MainFrame {
title = "Electronic Classroom"
}
instead of
val frame = new MainFrame
frame.title = "Electronic Classroom"
The difference to Java is that since Scala doesn't have dedicated constructor methods but treats all expressions within the body of a class part of the constructor, your anonymous sub class kind of "overrides" the constructor.
To compare directly with Java, lets say it wasn't anonymous:
class MyMainFrame extends MainFrame {
title = "Electronic Classroom"
}
In Java, this would be roughly equivalent to:
public class MyMainFrame extends JFrame {
public MyMainFrame() {
super();
setTitle("Electronic Classroom");
}
}
(I hope this is valid Java syntax, I'm a bit rusty)
This is the same case for MenuBar, Menu, MenuItem. Only Action { ... } is not subclassing but calling method apply on the Action companion object, making the syntax a bit more succinct (this way you won't have "constructor" statements, e.g. you couldn't write accelerator = None and so forth).
I subscribe to 0__'s explanation, just wanting to add that if I recall correctly you can do the same in java with
JFrame frame = new JFrame {{
title = "Electronic Classroom";
}};
This should create an anonymous subclass with the additional code appended to the constructor

Django-Nonrel with Mongodb listfield

I am trying to implement manytomany field relation in django-nonrel on mongodb. It was suggessted at to:
Django-nonrel form field for ListField
Following the accepted answer
models.py
class MyClass(models.Model):
field = ListField(models.ForeignKey(AnotherClass))
i am not sure where the following goes, it has been tested in fields.py, widgets,py, models.py
class ModelListField(ListField):
def formfield(self, **kwargs):
return FormListField(**kwargs)
class ListFieldWidget(SelectMultiple):
pass
class FormListField(MultipleChoiceField):
"""
This is a custom form field that can display a ModelListField as a Multiple Select GUI element.
"""
widget = ListFieldWidget
def clean(self, value):
#TODO: clean your data in whatever way is correct in your case and return cleaned data instead of just the value
return value
admin.py
class MyClassAdmin(admin.ModelAdmin):
form = MyClassForm
def __init__(self, model, admin_site):
super(MyClassAdmin,self).__init__(model, admin_site)
admin.site.register(MyClass, MyClassAdmin)
The following Errors keep popping up:
If the middle custom class code is used in models.py
name 'SelectMultiple' is not defined
If custom class code is taken off models.py:
No form field implemented for <class 'djangotoolbox.fields.ListField'>
You just need to import SelectMultiple by the sound of it. You can put the code in any of those three files, fields.py would make sense.
Since it's pretty usual to have:
from django import forms
at the top of your file already, you probably just want to edit the code below to:
# you'll have to work out how to import the Mongo ListField for yourself :)
class ModelListField(ListField):
def formfield(self, **kwargs):
return FormListField(**kwargs)
class ListFieldWidget(forms.SelectMultiple):
pass
class FormListField(forms.MultipleChoiceField):
"""
This is a custom form field that can display a ModelListField as a Multiple Select GUI element.
"""
widget = ListFieldWidget
def clean(self, value):
#TODO: clean your data in whatever way is correct in your case and return cleaned data instead of just the value
return value
You probably also want to try and learn a bit more about how python works, how to import modules etc.