Actually about Kaldov, Kardov, and WebDef. And it's mostly intended for open source developers because I want to motivate them to implement those protocols. So actually, I will give a short overview of the protocol itself. I'm talking a bit about implementation, which exists today. I want to say a bit about how to write a Kaldov connector. So if you're a developer and want to provide a Kaldov client, I give some hints on how to work on that. And well, related to that, how I think you can help with getting better Kaldov support in open source clients. So as I said, Kaldov is a simple HTTP-based calen ring protocol. It's a standard since last year. It basically describes how an open or any groupware client, like, for example, Thunderbird or Evolution, can talk to a service system, like, for example, eGroupWare or OpenGroupWare or Serafa, of course. And another important thing to keep in mind is that Kaldov is just a transport protocol. So it doesn't describe how the actual data is formatted. For the actual data, the iCalender and vCard formats are used, which are in standard since, I think, more than 10 years. And the important thing is that all the open source clients, which exist today, like Evolution, Mozilla, Sunbird, and Contact are all internally based on iCalender and vCard. So it's a very natural fit. And this is why I don't like articles like that. You can read that for Contact or for Evolution. So there are announcements like Contact or Evolution support Microsoft Exchange. And, well, it's very annoying because they do not yet support open standards, but they put work into supporting Exchange. I can't understand that, especially because the clients itself are based on the data formats also used by Kaldov. So it would be very easy. A bit about the protocol. Actually, the whole stack is pretty complex, but you usually don't need that because Kaldov also targets web interfaces. So it has a lot of operations so that web interfaces can directly talk to a Kaldov client. That's not something I'm talking about today. I'm mostly interested on what needs to be implemented in a native client, like a KDE client or a genome client. They need much less operations. In fact, we have a small subset of that defined in the so-called group death standard. It's not really a standard. It's more like a document which contains the interoperability issues. I'll show that later. Well, to the parts, iCalendar is very common. Most developers probably know how that works because, as I said, it's used in the open source clients anyways. It's a very simple text-based format which contains the necessary information. Nothing particularly impressive. The same goes for Wecard, which is almost the same format except for contact data, like telephone numbers and email addresses and stuff like that. You can store birthdays in Wecard. Well, and the most important protocol for Kaldov is HTTP because almost everything needed to write a client service theme, which does calendaring, is already contained in HTTP. It provides operations to retrieve items, to store items, to delete items. Well, and there's a new buzzword for that, which is REST, which just means that HTTP is applied as it was originally intended, which is using those operations instead of using just post and some CGI scripts, which do other stuff. So this is how the HTTP looks like. This is for retrieving an item. You just use the get method to retrieve a URL which contains an event in this case. The if-no-match is actually an optimization. The number behind that, it can be anything. It's just a marker which says whether the item changed on the server. So if the client retrieves such an account event from the server and stores that into its own cache, it can put that version into the request. And the server will only return the content if it actually changed. So it's much faster. In this case, it changed and it actually embeds, it's a bad example, it didn't change, but it actually embeds an iCalender file and gives a new eTag in this case. It's the same. Changing an item is becoming realized more on the if-match header because the put operation is used for both, for changing an item and for creating an item. And in addition, a put operation, a write operation, must detect changes by other users. For example, if another user moved an appointment in his client, another user must be able to detect that so that he doesn't overwrite the changes of that other user. And this is what the eTag is used for again. So this basically means only writes this content if it didn't change. So if it changed, in the meantime, the server will issue a special HTTP status code which is for 19 conflict and the user can then decide whether the client should reissue the same request without the if-match or whether it somehow retrieves updated information and merges them or whatever choices the client gives the user. As I said, creating the item is basically the same thing, but to ensure that the event does not yet exist at that URL, you put that if-match star into the header. This means that this request will fail if the meeting ICS file already exists. In this case, the client needs to issue a new file name for that event and retry the request. So most clients actually use unique IDs for that, so it's a very rare error. Well, and final delete, it's also very simple. If you want, you can also add an eTag condition so that the delete only succeeds if no other user modified the event in the meantime. You can also remove that and the delete will always succeed. What we have seen before is just regular HTTP. It's in the standard HTTP specification and available for a long, long time. And it's the same as too for WebDef. It's quite available for a long time now. And the most important thing WebDef adds to HTTP is hierarchies. So HTTP itself, a URL, a uniform resource locator in the HTTP request is already kind of a hierarchy. The components in the URL can be split by slashes. But the important thing is that there is no HTTP operation to discover which children such a collection has. For example, if I want to know that the developer's folder contains the calendar and tasks, sub items, there is no HTTP operation to find that out. And this is what the prop find is for. It's the addition by WebDef. Another addition is that WebDef has a concept of metadata. They're called properties in WebDef. So by using the prop find, you can also discover stuff like when got the file modified, what is the eTag and other stuff. It's also the basis for WebDef extensions. It has a few other things like, for example, lock, which allows you to lock a collection for modification. But that's not really necessary because as we've seen before, HTTP already supports optimistic locking. So you can just attempt to write and it will only fail if it actually changed. So it's usually much better for the user instead of locking the whole collection. So that's what it looks like. It's a prop find operation, which goes to a calendar in this case. And the prop find instructions are contained in the body. As a get eTag, this says that we want to retrieve the eTag of all items contained in that calendar. And it always returns such a multi-status response, which is basically an XML representation of multiple HTTP responses. So in this case, the eTag is returned and then always embeds the thing in such a response element which contains URL to the item which is below that collection. In this case, calendar and some item. It's just a unique ID. The user usually doesn't see that. What else? For CalDef, just below CalDef, there's also another extension to WebDef, which is WebDef ACL. That's access control. So most important for CalDef are so-called principles resources. Principle resources are just a standard for representing an account in a calendaring system.  For example, principles, users, Helga, which represents that account. And this URL can be used to retrieve some information about that user. Usually, those principle resources are not stored in some file or something like that, but they are usually backed by some directory service, for example, LDAP. So for example, the Apple implementation, users open directory to store the actual principle information. But it's not just individual users, it's also groups and resources, like rooms, which can be represented by principle resources. The most common use in CalDef is that the so-called calendar home set property. There's the same thing for address books, which is called address book home set. And the way it works is that you do a prop find on the principle URL, and you get back those two properties and they contain the URL, which points to the server, which provides the calendaring and address book services. This is pretty nice because it allows you to scale very well. So you can distribute users to different servers, you can use different servers for address books and calendars and stuff like that. Well, it's about ACL. It also does a lot of commission thing, but that's not really relevant in calendaring that much. It's an extension. I really want to have the open source developers to implement the basics first. So CalDef, as I said, requires most of those protocols. If you want to do a full CalDef implementation, you would actually have to implement all those protocols or all those standards. In practice, almost no server does that. Most servers just implement the subset which is actually required to derive the Apple iKal client because this is the most known CalDef client and more or less the standard to test the CalDef features. But I come to clients later as well. CalDef, the most, or just one additional HTTP method which is introduced in ACL actually, but it's also used in CalDef which is called report. It's pretty similar to the prop find, but is a way to extend the protocol. So report, request is in the body. And well, because native clients which run on the desktop computer usually keep a cache for offline information and stuff like that. We do not really need the report because all the queries like give me a week of appointments or find a contact with name hello world are done on the client, not on the server. This is something which is important for web clients. For example, a web client could ask the server to return just a week of events. But for native clients, it's usually a useless feature because they have their own cache and do the queries in the cache. There's one report which is very useful and that's a so-called multi-get report. When you synchronize a server the first time and for example, it contains a thousand events, what happens is that the client issues of prop find, it discovers the thousand event URLs and then goes on to fetch a thousand or does a thousand request, get request to retrieve the item. Actually, that's not that bad as it sounds because HTTP 1.1 also supports pipelining and persistent connections. So issuing a thousand request isn't as slow as one might think, but still, especially in database-based servers, a multi-get can give performance advantages. It basically says that in the multi-get report you can specify a set of URLs and you get, for example, 50 events in one batch by just issuing one HTTP call. So it can be a major performance improvement. But for example, I'm also testing against Apache which doesn't implement report. It's very fast with get as well because it just pulls out the fires from the fire system and puts it on the socket. It's very, very fast. Could we do questions later, please? We seem to be just wondering about the server. I assume you've been missing with the server with no servers to do everything. As a server developer, I think it would be nice to know where to look. Exactly, and I come back to that later. It's actually a thing we want to document in group dev because we think that group dev is a subset of all those specifications which are needed to implement a client system. Everything else can be done on demand. For example, you can issue a report if it isn't implemented. You get back an error code, but I show that. Let's wait a minute. That's something I actually wrote just below. So why you can use a Kaldiff report to retrieve a bulk multiple events in one step. If the server says he doesn't support that, you can still fall back to get. It's not a lot of work for the client developer to do that because it's just an optimization. So, and the important thing is that the SCAT is again plain HTTP, so it works with servers which do not implement full Kaldiff or that particular report. As I mentioned, there are a lot of different reports. You can extract just subsets of the iCalendar fire and stuff like that, which are interesting if you want to write a web interface which directly interacts. Using the browser interacts with the web server, but I've never seen that, and I think it's pretty useless, actually. CardDef is basically the same like Kaldiff, just that it's for contacts. The contacts are stored in vCards. There's also such a multi-get report, but in any other way, it's the same thing like Kaldiff just for contacts. So, it's currently still in development. Well, actually, Syros Tabou is a guy who has written the draft, but I expect that this will be standardized during 2009, probably in July or something like that. So, here we are coming to GroupDef. With GroupDef, we try to formulate the absolute minimum of operations which are necessary to maintain a proper client cache so that a native client can be developed which interacts with such a GroupDef server. The reason is that, well, as I said, Kaldiff and even WebDef itself is pretty complex if you want to implement it. Very few people actually implement the full specification, but GroupDef is super simple. It's not even, it requires you to implement all of WebDef. If you do, it's great because you can use regular WebDef clients, but a real GroupDef client can interoperate with much simpler servers. So it's just one propfine query which we specified in part of that GroupDef document. I'm showing that later on. And, yeah, as per GroupDef specification, you are not allowed to issue different propfines. This way, it's 100% compatible to WebDef and Kaldiff. So every GroupDef client is automatically a full WebDef or a calendaring WebDef client and can talk to any Kaldiff server because any Kaldiff server by specification implements those things. Otherwise, it's just same thing like get, put, delete, everything plain HTTP. Content times are v-calibbed and i-calender. Folder discovery is used using the propfine. So in the result set, you get responses for the folders. We actually need to tag calender folders with a special type so that the client knows that this folder is a calender server. Well, the cool thing, or in my opinion, the coolest thing is that you do not need a GroupDef server at all. You can use just Apache WebDef support. You just need to enable the WebDef module of Apache you can use to store that in GroupDef environments. And it's not fishy or something. It's properly protected using the e-text, so concurrent edits and all that work. Disadvantage, okay. Now it works, okay, great. So the only real disadvantage is that of course you do not have a web interface or something like that. So it actually only works with real clients. So it isn't too difficult to write a small script or something which watches Apache directories for changes and just generates appropriate HTML files for that. You can do that using fire system callbacks and just generate a web interface aesthetic one which is very scalable, yes? No, not a CalDef client, a GroupDef client. You could use any GroupDef client. The CalDef client, or most on the market like for example ICAR really do use those report operation for example and have no callback. A GroupDef client could also attempt to use a report but would fall back to PropFind and the regular operations. But I show some, I also talk about the implementations. I'll come back to that later. Maybe check the time as well. Okay. In my opinion, it's very cool because everyone has an Apache web dev. It's included in the latest releases and it really works great. It's very fast even for larger collections. It doesn't scale to 100,000 events in one folder but for regular use cases, it's pretty nice actually. So GroupDef as I said is for offline clients only. We do not provide operations which are necessary for web interfaces like give me just one week of events. So we actually assume that the local client keeps a cache of the item it retrieved before because otherwise it would always need to retrieve all events, it wouldn't work. But GroupDef clients or local clients need to keep the cache locally anyway because you want to have offline capabilities. So it's not really an additional requirement. As I said, it's very simple, especially for the server vendors as well because they only need to implement that single prop find and the get and put operation. So it's really easy. And it also has a few hacks. We had added, we documented a few hacks which can be used to better support database-based servers like for example, e-groupware or open-groupware. Tests to do with the UI construction but I do not really have the time to go into detail. And top of CalDef, the committee added another specification which is CalDef scheduling. That's basically the same like IMIP which is used to exchange invitations. For example, if I'm a user and I want to invite another user to a meeting, I would, my client like evolution and contact almost anyone supports that. They send an IM, iCalender message embedded in a regular MIME mail to the other user and you can then accept the meeting and all the interaction in that is documented in iTIP and IMIP. Standard protocols which are widely deployed and standardized since a lot of years as well. And CalDef scheduling is almost the same thing just over HTTP. Well, if you are a client developer and you want to start adding GroupDef support or CalDef support to an open source client, please do not look into that. Yeah, it's quite complicated and it doesn't really buy you that much because the IMIP also works perfectly fine with calendars stored in CalDef. So you can just exchange invitations via email which is completely standard. Even Outlook and Lotus Notes support that quite well, not perfectly but quite well so you can actually interoperate with those people and schedule meetings. So, but we'll see. Scalability, I talked about that a bit before. Of course, especially a GroupDef system with a local cache is really scalable because it has that cache, does all the operations in that cache and doesn't need to call the server to perform operations like sorting events or search for context. So the actually processing work for searches is put on the client. So it's quite fast. Due to the architecture because it's based on HTTP, it's really super scalable. You have all the features of HTTP which are used to make websites scale and actually the events which are transferred by CalDef, the files are much smaller than an HTML page. So you can actually use caches like Squid if you have a really large system to reduce the load on the application servers and use e-tags with that because if the cache has the e-tag, he knows whether the cache needs to retrieve the file from the backend server. So there are a lot of features which make that very scalable. Well, as I said before, HTTP also supports persistent connections. So issuing a lot of requests isn't that bad as it sounds. But most importantly, HTTP itself also supports compression. So it's not so important for the events if they are transported because they are quite small but the XML of the prop find can become quite big. I put some numbers roughly. So a thousand items producing XML which is about 200K, which is quite a lot. But because the XML is so we're both, it also compresses very well. So if you enable a Gzip compression in the client, it just comes out as 12K, which is quite okay. And even for 10,000 events which is quite a lot for a single folder, it's just, well, it's not just, it's more, it's 130K, which is significant but acceptable in my opinion. But most extensions which exist to that protocol are trying to improve the situation with the XML overhead. And especially Apple is doing a lot of work on that. It's a Darwin epic calendar server which is completely open source. And it's written in Python more or less acts as a testbed for features. Developer of the Apple server, SyroStaboo which also worked on the Kalev specification and wrote the CardDev specification. And before he puts those into specifications, he usually implements that in the Apple server. And for reducing the prop find overheads, there are actually two things. The one thing which is already in production use is CTEX. CTEX are like ETEX. And ETEX says whether an event has changed by some other users or by some other means. It's CTEX is roughly the same except that it covers a whole collection, a whole folder. So if anything in the folder changes, the CTEX changes. So the client can check for the CTEX and only if it changed, it does a full prop find. The nice thing is, again, if you write a calendar in client, you can check for the CTEX and if it doesn't work, you can still do the regular prop find. So it's very easy to fall back to basic functionality if that's necessary. And very new, it just got into the Apple server trunk a few months ago with Java-based PubSub. That's a way to let the server inform you about changes. So it's actually an information triggered, a notification triggered by the server if something changed in the server. So the client only needs to do the prop find if something actually changed. And that's awesome. Everything standard space, it's a Java. And if it isn't available, the client can just fall back to CTEX and to regular prop find in the second row. It's really not bloating the code, actually. Well, and all the extensions, you can actually look at that. It's written in Python, it's okay to read and available from Apple. There are a set of known issues, but most issues, if you talk about Kaldaf and Kataf, are not related to the protocols. It's usually related to the data format, which is iCalender or vCard because especially iCalender can be quite complex. For example, if you have a recurring appointments and stuff like that, you can, in iCalender, you can build pretty complex recurrence worlds which are not supported by any client. But in the case of open source calendaring clients, it's no issue if you want to add Kaldaf support because those clients are based on iCalender and vCard anyway. So the developers of Mozilla, of Evolution and of Contact did all the hard work of doing the iCalender implementation, for example. The best iCalender implementation has contact, I would say. There are a few other issues, but you are not really heard by that in practice. You can, we can talk about that if you run into that. It shouldn't be a hurdle. Okay, I want to tell a bit about the implementations. That's about the situation mid of last year. There were those group effort, which I started personally about end of 2004. There are a few smaller vendors which support that like Open Group Fair, Citadel and eGroup Fair. There was a work on the Kaldaf standard, which was mostly done by, or was done by Oracle, by Apple and also Beta work, which is an educational calendaring system. It's written by an American university. But really, the huge amount of Group Fair system, Open Source Group Fair system, just invented an own protocol for their needs. So for example, if you have contact, you have something like, I think, 10 or 15 different plugins, which can connect to the Group Fair servers. And right now, I think in fresh meet, there are over 400 different Group Fair systems listed. So it can't be the solution. But surprisingly, in last year, the Kaldaf really got adopted by a huge amount of vendors. That's mostly because everyone, for some reason, wanted to support the Apple iCar client. And the Apple iCar client only used the Kaldaf protocol, which they probably put into an RFC. And so it's the first time, and as far as I know, that so many calendaring server vendors agreed on a single specification. So all of them either support full or partial Kaldaf necessary to derive the iCar client or GroupDef. But it's really a lot. For example, eGroup, we are also implemented GroupDef, but there are really a lot of projects, which are doing that. And I expect that this will be the standard, like IMAP, for example, is for email. Even Google and Yahoo support Kaldaf for calendar access last year. You can access the Google calendar using Kaldaf. So because there are so many implementations, I thought I should suggest some. It's mostly all of them are pretty good, but it's usually the developers have some affinity with the programming language. There's a Dev iCar, which was written in PHP. I think it's actually a standard package and a Debian as well. There's a Darwin calendar server. That's the Apple one, which is written in Python. There's scalable Ogo, which is written in Objective C. Beta work is that educational server, which is written in Java. There are a lot of alternatives to that. You can just browse FreshMiddy and find probably about 10 Java servers, which are doing that. Yeah, sorry? Apache? Okay. As a group dev server. For example, the Apple iCar client is not a group dev client because it uses extended Kaldaf methods. So to connect Apple iCar, you actually need a lot of Kaldaf operations. But I come to the client implementations later on, but for clients which are advertised as Kaldaf clients, you usually can't use Apache web dev. But I come back to that later. And I would like to have that changed. Actually, if they are developers from the client project, that's basically my, well, what I would like to see is that they can probably fall back to group dev so that Apache is supported. Well, if someone knows Ruby once, tell me. Write me an email. Well, as I said, I will suggest one of those servers. Well, my personal favorite, as I said, is Apache web dev. And I've put a lot of such Apache transaction which shows that how the fallbacks work. For example, the client in this case first tried to perform a report to fetch multiple events in one batch. And it gets a 405 return code which says that that method is not implemented. And the client falls back to just retrieving the individual events. And as you can see on the timestamps, it's pretty fast, yeah? Even if the next batch attempt starts, it's really fast. It's like, I don't know, two or five milliseconds to retrieve one item from the server. And actually, well, I come back to that later, evolution, and there's an implementation for Outlet. But I would really like to see that in all open source clients. To the client implementations, first as contact, we actually implemented a group dev in contact together with some KDE people. And at the end of 2004, we actually also specified that group dev during that session. It took about two days or a weekend. Well, the problem is that KDE just rewrote all their infrastructure, so they wrote a new client library, which is called Akonadi. And it will be used in some later contact versions. The contact still doesn't use that. And it doesn't provide any support for that dev yet. So it's quite crappy. But we really hope that we will be able to change that. Probably if contact is ported to Akonadi, we will have a development session with the Akonadi developers to add web dev, group dev, and KDEv support to contact. I hope that we will be able to do that until the end of the year. The second one is evolution, of course. We also provided group dev plugin for evolution. It was a noodle project. It was sponsored by Hunter de Andalusia in Spain. Unfortunately, it didn't really pick up at this time. So the connector just became unused, unsupported, unmaintained, so it can't be really used today. It's still in the CVS repository, but it's not really useful. But evolution actually has reasonable web dev support. For one, you can configure Caldev calendars, so you can use Caldev together with a real Caldev server, but it doesn't provide group dev for that. So Apache, for example, doesn't work as a backend for evolution, but evolution actually supports plain web dev address books. So you can store a set of contacts in vCard format on an Apache web dev server, and evolution can probably display them, edit them, and it works very, very well. So it's quite good. So I showed a bit of collection browsing. This is a dialogue of evolution for adding a web dev address book. The thing which I do not like about that one is that you need to specify the URL to the actual address book collection. What I would like to see is that you just enter some URL and then would be able to browse through the server like in a file browser, because that's what web dev is all about. It supports hierarchies, and you can browse through them using the appropriate prop friend requests. So actually, if there's an evolution developer, please add a browsing module which allows you to select the address books on the server you want to subscribe. That would be much nicer. But even this address book is pretty nice. I just discovered that about two months ago, and it's really working very, very well. And as I said, it supports KALDAF. Well, it's a panel for adding KALDAF. It basically has the same complaint. You can browse the server for calendars. But otherwise, it works quite okay. So it's quite usable. But as I said, you need a real KALDAF server. And finally, Mozilla, the Mozilla Kaliens, which are Sunbird and the Lightning module for Thunderbird. They are actually very good because first, a few of the Mozilla Sunbird developers actually work on KALDAF implementation. So it's unlike an evolution or contact, the core developers are actually into KALDAF and support that. So it's a lot of work on getting that working well. And in addition, there's a scalable ogre project, which is just another groupware server. And the scalable ogre project provides plugins for Mozilla. So it's just regular Mozilla extensions. And those extensions are not specific to scalable ogre. They are real group daf clients and real calendaring service extensions. So it's quite good. And it's also very easy to hack. In the address book, for example, it also misses the collection browsing again. So you can actually browse a server for address books or calendars. What other clients are there? First, there's a Funnambool group daf plugin. Funnambool is a synchronization server which can synchronize web daf servers with mobile devices. So it's a Java application server. And there's a plugin for that, which is a group daf plugin, which can basically synchronize a group daf backend with any mobile device supported by Funnambool. Personally, I haven't tried it, but I'm told that it works. There are other clients, Mulberry, for example. I don't like the user interface, but it's actually a pretty powerful Kalev and IMAP client. There's Chandler, which is by the Open Source Applications Foundation, which also is based on web daf. There's, of course, API call. There's another one which is called EMClient and Outlook. Actually, there's even an Open Source project called OpenConnector, which implements Kalev protocol, but it's not very far. So if you are a developer, which is into Windows development, they need a lot of help. So my section about actually writing such a connector. As I said, it's not that or shouldn't be that hard because all the Open Source clients already implement the hard stuff, which is parsing and processing i-calender and recards. This is all done, all of the clients can do that. So what we need to add is basically a simple cache, which keeps items retrieved by the server together with the e-tech and the URL. So it's pretty easy. And well, as I said, if you want to start such a connector, please just do the group daf part working first because you shouldn't really look into Kalev extensions until the group daf stuff works. It's very simple and if that works, you can start adding Kalev features with appropriate fallbacks to improve performance or provide additional features. But even if we just have group daf, it's quite good already. It can be used in a lot of sharing scenarios. There are also quite a few libraries for doing Kalev. For example, Kalev for Java, it's a Java library to do Kalev, Kalev client library for Python, Open Group, it has a library for Kalev stuff, vObject is also a Python library, the mulberry client also has a lot of Kalev functionality package and various languages as well. So, but still, I would say you don't need to use that because the XML you need to pass is just the response from the profine query. It's just one XML format you need to pass and it would be completely overblown to use in a separate client library for that. It doesn't make any sense. So, you should just use your favorite HTTP library to retrieve the items from the server, write one XML parser which parses that propfined and that's it debugging towards. Well, if you're developing something, it's nice to have some stuff that you can use to actually try the thing and I check where I can show you two. One is CUR, probably many people if you know that client, it's just a command line client to retrieve HTTP servers using get or any other option. Let me just check. It's a bit, does it work here? It's a bit small as a screen, but actually I've written myself a small shell script and the essential stuff is basically the bottom. So, stuff at the top is just for collecting the password and stuff like that and the bottom actually issues a propfined and the properties which are requested are in that propfined XML file. This actually contains the standardized propfined of GroupDef and it looks like that. So, it's just the core set of properties which are necessary to implement the client. It actually contains some KALDAF and CARTAF properties. So, if the server actually supports those KALDAF protocols, the full or more of the KALDAF protocol and can actually respond with data, a plain GroupDef server would just not return anything. And for example, we can try that against some server. Actually, let it come up. Anyways, let's see iPhone. Let me check, let's print it. So, it's very convenient to see what the server actually responds with. So, that's actually the Google Calendar which is requested using GroupDef. As you can see, it probably responds to that with a propfined response. That's the one you need to be able to pass. For example, the root URL, the Google Mail thing is a root collection and it contains additional stuff below. If there are any features it doesn't know, it puts them in such a four or four section. For example, this collection doesn't have a display name or a specific content type. So, it's quite nice. So, that's a CURL. It's quite easy to use to check what the server returns and what you need to pass. It's quite convenient. The other tool is Cadeva. Cadeva is a command line client for WebDef. Let's see what I have. Okay, let's try the better work server for example. So, it's an interactive client. I can log in and I can just go like through a file system. I can explore the server and it's basically the functionality I would like to have in GroupDef clients as well. For example, here's a calendar of the user and there are the ICS files. I can just select one and make a cat and you see the icon in there. So, you can use any WebDef client to browse such a server. That's pretty nice and I can show you other servers. It's pretty easy. Let's check. For example, Scalable Ogo. I can just log into that. So, it actually has address books. For example, you can go to Contacts and those are all my address books. For example, any. It's just regular vCard files. Oops. Didn't copy. So, it's just a vCard contained inside. So, it's very useful for debugging. So, well, actually almost done. Well, California, as I said, I would really like to get the open source client developers to support more of that because I find it just ridiculous that they have very good exchange connectors but no connector for GroupDef or CalDef because it's so easy for them. They already have iCalend and vCard and they just need to implement. They even have the HTTP libraries for doing that. They just need to implement the proper requests. Well, I've printed some features for OpenConnector which is the open source outlook integration. They need a lot of help. That's just one guy which is working on that. Well, and so, if you have any questions you can write me email or the GroupDef list is a good one to ask questions. There are CalDef and CalDef lists and of course you can go to the website. So, questions. Scheduling isn't part of GroupDef. That would be a CalDef scheduling but it's usually done using IMAP anyway. So, it's scheduling based on email but groups are basically just regular folders. The server can choose anything. He can choose to provide any hierarchy likes and most servers I know also represent the groups and the group calendars as subfolders and collision is perfectly detected. This is what HTTP eTags are about which allow optimistic locking. So, there's no chance that writes collide. That's impossible. No, the server does that. It's standard HTTP. That's done in the HTTP server. Yeah, of course the client needs to handle collisions. That's true. But the server actually checks whether there could be a collision. Now it has something like an eTag which I explained before.  There are no concurrency issues in that. There are also test suites for CalDef. I know that. I never use them but there's a test suite also at the Apple site I think which is in Wooden and Python. So there are, I don't remember the name but you can check on the CalDef website. It has a lot of implementations and even the test suite a link to that. So, sorry. There are links to implementations. So, sorry I can't follow you anymore. Yeah, I thought you were asking for a test suite or something like that. Yeah, and there is a test suite, yeah. But not all servers implement everything in a test suite. So most servers just implement what is required for iCar. Sorry, I understand. Okay. Yeah, thank you. Or any more questions? No? Okay.


Hi, I'm Tytivus with GitLab here today to show you how to set up a GitLab to Elastian Jira integration using Jira's automation triggers. We'll get right into it here, showing how we can set up a trigger with a commit that moves a transition from open to in progress or in progress to close. You can also set up triggers that shows the merge request and the branch as well in the dev panel within the Jira issue. Let's go. So we start inside the Elastian Marketplace. I'm gonna go search for the GitLab app. And once we pull this up, we're gonna go ahead and download GitLab for Jira. Quickly get that app. Get it now. It's gonna be adding GitLab for Jira. Go to manage app. And once this is loaded up, we go ahead and get started. And this is where we're gonna add the namespace from GitLab. So if we go over to GitLab, we can see that I have the namespace highlighted. I'm gonna copy and paste what's after GitLab.com backslash. I can be as specific as I need to be. I wanted to do tech marketing here. All the subgroups underneath would take on this integration. But in this case, health care provider and corporate is the only one that's gonna be synced with Jira. For Jira, we're gonna go down to project settings, go to automation, and then inside of automation, this is where we're gonna be able to create some rules. And you can see that there's several different triggers located inside of Jira. We're gonna scroll down until we get to DevOps and we'll select commit created, save that. And then we're gonna create a new action. Again, scroll down and we're gonna click transition issue. We're gonna click in progress, save. Let's name this automation. We'll just call it the commit created, create committed move issue. And then turn that on. And now that automation piece has been turned on using that trigger. Go back to the project and we're looking at HPI-43 here. As a user, I want two important versions. We're gonna dive into that. Copy the link to that indicator, the ID. And then if we go inside of GitLab, we'll click over to Jira issues. Look at the issue list and we can see here that we have that exact issue pulling over. If I click onto that, it takes me back over to Jira. So the Jira view list inside of GitLab is just a mirror. Scale back to the project here and once again, looking at that specific issue over in Jira. We're gonna go into our repository and then click into the web IDE. For here, we're gonna make just a quick change. It's a very simple code chain on a very simple project. So in this case, we're just changing the background color for demo purposes, but we're gonna go ahead and commit that. This is where on the commit message, I'm gonna reference that key from Jira and put HPI-43 pound sign in front of that. It's important and just write a commit message to test your automation. As well, I'm gonna put this in the branch so that we have consistency across both. I'll commit that. Then I'm gonna go back into the issue as a user. I want to import versions, actually I'm gonna refresh and then we'll see here that's now moved to the in progress. So based on that trigger that I had, that just moved it to in progress quickly. You can see the web link there to the commit on the development panel side there. You see that that commits now showing. There you have triggers.


Here at The Conversation, we have a unique editorial process that ensures we can get the best, most reliable information to our readers. Our authors are people who really know what they're talking about. Academics and researchers writing in their area of expertise. Ideas for stories come from our readers, authors and editors. Most often, an editor scans the news to find a topic on which an academic might shed some light, and then finds the right person to answer the questions that readers might have about the larger story. Other times, academics send in ideas via our website. Often these ideas are about new research. Our editors work with academics to take work made for a highly educated, niche audience into articles that all kinds of people will want to read, understand and share. When an editor accepts an idea, the first step is to create a brief which outlines major points the article will address. Then the academic author writes an article that follows that brief. Hmm. Once the article is submitted, it goes into our content management system and editors add images, charts, sound, vision and links. Next, the editor works with the academic to polish the writing and ensure the facts are right. Authors and editors work on a shared version of the article using our custom-built editing platform. The software has a readability index that goes green when the article hits the reading level of an educated 16-year-old. This makes our content a great resource for high school students. Before we publish, we ask the academic to approve the final article. This ensures errors are not added in the editing process. Authors also disclose any conflicts of interest, such as funders or political party memberships. These disclosures are published alongside the article to ensure full transparency. Once published, articles are made available through Creative Commons license to thousands of media sites that republish our content, such as the ABC, CNN, National Geographic and the New Zealand Herald. And we make it easy for media, researchers and others to contact authors after publication, which regularly leads to TV, radio and print interviews as well as other opportunities for collaboration. Throughout this process, all authors and editors are covered by our editorial charter, which protects us from commercial or political influence. Plus, there's no paywall, no sponsored content and no native advertising. We have no ideological position. Our only agenda is to inform the public and share academic expertise. Visit theconversation.com for more.


What's going on everyone? Sam here with Layton's Forge Cards. We are ripping one box of 2022 top scurron platinum anniversary light baseball for Robert O. So good luck here Robert. Do a little dust off quick. Thank you Kyle. Good luck. 22 TCPA light. Four exclusive black and white mini diamond. TCPA light definitely sounds like a beer. It does. It definitely does. Montana, Andy Rosarino. Gary Carter refractor. His base Correa and trade turner. That is Dantro Willis. Nice. So the color match teal lava for the Marlins 299. That's fire. D-Train. That is a jersey I need to draw. Tyler O'Neill refractor Ryan McMahon and Johnny Damon is a royal. That Johnny Damon is a ray and a tier one or museum. Greg Diekman black and white mini diamonds. Zika and Otto Lopez. Dave Stewart black and white mini diamond. Tentamayeda, Yanni Hernandez. Herb and Castro. Byron Buxton. Green Toil 299. It's nice to be the Yankees. You said you were just going to start your adventures in some good hitters and you just go by. Yeah, true. The raids if they need those things.  We waited like six years. Yeah.  And we just, the Yankees just sit there punching the air. Walker Bueller, nice one there. If we can't develop anybody.  There's Mike Schmidt because they can't pitch in a big market. Like I'm not to say that Chicago, O'Neill Cruz Rookie, not to say that Chicago and San Francisco aren't big markets, but it's not the pressure pitching in New York that there is in those two places. X-Rac, your Lou Boudreau, nice one there. Stephen with a couple of select draft picks, very nice. Very Larkin, Stan Musial. Two of five. That is Alex Verdugo on the red. Congrats on that. I don't think I pulled a red out of this yet. You're nice. That's awesome. Congrats. Nice color match too. Makes me can't believe it. So I can't believe Jay bought the Mingo shirt. Did he really? This is always perfect. Oh no. Always perfect.  Oh no. Forever perfect. One of those two. Morning on Sunday, I was like, is that? Do I could? Please. Sponsor Torcal Sin Rookie. Please dude. Oh no. That is a Andre Jackson mini diamonds to, or white speckled 150 Rookie for the Dodgers, Kyle Lewis, and a Dantro Willis. That'll do it for the break for you there. Robert, thanks again for the sport buddy. We've got those right out to you my man.


Hello and welcome to Scripting for Artists, my name is Sibethan and in this episode we'll visit a topic that many of you have asked for user interfaces. In the previous videos we created our own operator and then turned it into an add-on. The basics of creating your own user interface in Blender is pretty much the same.  So in this video we will look at the following. We'll be finding existing UI codes. So if you're wondering how did they do it, after this you'll know where to find it. We'll look at the ingredients of a panel before making our own monkey grid panel of course. What else? We'll be adding operator buttons to the panel and then tweaking the layout a little bit. Then we'll add scene and object properties to it and we'll also look at conditional drawing because sometimes there is no active object so you won't be able to draw properties from the active object and finally we'll look at adding your own operators to existing menus in Blender. Before we make your own let's take a look at existing panels in Blender. In the 3D viewport press and to show the panels and then let's look at the 3D cursor panel. Right click and choose edit source. If you don't see the edit source option go to preferences interface and enable developer extras and python tooltips and then it should show up. So let's see what happens if we click it. Blender now tells us here in the corner but it's a bit far away because of my scaling. Basically it tells us to go to a text editor and there we should find the file with the source but there's an easier way. If you split this window and make sure that there is a text editor right here you can click edit source and there you have the file it will be opened for you and even scrolls to the right line. Now let's scroll through this and see what we can find. As we've seen with operators as a class it has the same kind of naming it has the category in capitals and then pt for panel type instead of operator type and then in lower case the rest of the identifier and here you have the parent class in this case it's panel and not operator. You would expect bpi.types.panel here instead of just panel and we'll see why this is in a bit. Let's look for other commonalities first. We have BL label which is the panel's name in the user interface and then we have a category a region type and a space type. The space type and region type define where in the user face it will show up. In this case we're looking at 3D viewport and region type is UI which means it's right in the 3D viewport and not in a header or a footer. Then the category is view which is the name of the tab here and then we get to be a label which is the name of the panel. Where operators had an execute function that performs the task of the operator here we have a draw function that draws the panel. The drawing itself is done through self.layout which is a UI layout instance and you can find this with help and then python API reference and search for UI layout one word. There you'll find the class definition with everything that is possible. In this video I will show you the basics though and that will get you quite far already. Now let's go back to the class definition because we saw that panel here and this is a little bit different than we've seen before. As I said you would have expected something like bpi.types.panel and not just panel and this is because in this file it's imported in a different way. Let's scroll to the top and here you can see from bpi.types import header menu and panel and because of this you can just type panel instead of bpi.types.panel and it would refer to the same thing. Personally I would say be very careful with imports like this. It can save you some typing and that may sound like a good thing but you will read code way more often than you write it. I would always optimize for code readability and understandability rather than saving a few seconds of keystrokes. The only time where I would use an import like this is where it is very clear what's going on. In this case it's blender's user interface definition and there is only one header, there's only one menu, there's only one panel and they always come from bpi.types. So in this case I would find it acceptable. In general though I would avoid this and always use the full name of the thing so that once you see it it's clear where it comes from. Now that is out of the way. Let's just jump in and make our own panel for the monkey grid. Let's take a look at our adults code where we left off last time. So here we have the monkeygrid.py with the monkeygrid operator class and the register and unregister functions. Now to this we can add our monkey grid panel. So just like before we create our class, we name it properly. I kept the category view 3d because it's a view 3d panel anyway. We have the pt I called it monkey grid and we extend bpi.types.panel. I just copied these values from the 3d cursor panel. I named the category monkeys so that we get our own little tab there and I labeled it grid. And then the only thing that you really need to have is a draw function. For it to show up as a panel it needs to have a draw function even if that function does nothing and because a function in python always have to have something. I put pass here which is python code for don't do anything. Every code block after a colon is indented and every indented block needs a little bit of text there in order to make sure that python understands that it's indented in the first place. So that's why they have the pass keyword. Now the only thing that's left is to tell blender that this class exists in the first place which means registering it. So we can just copy the register and unregister class function calls and put in our new class and that should be it. Let's go to blender see what happens. Now all we have to do is reload the script. So go to system reload scripts and you'll see monkeys pop up here. This route also gives you access to right click and then add to quick favorites. So if you do that then you can just press q and reload scripts it will give you a fast way to reload them. When we go to the monkeys tab we can see that our grid panel is here it doesn't contain anything yet of course we don't draw anything there but at least it shows up. So let's put a button there for the operator. Let's go back to the code and here in draw cell.layout let's just draw things and to draw an operator you type operator and then you give the id name of the operator you want to have there. Let's copy paste that in go to blender reload the script and there you can see we have a monkey grip button in the grid panel and it actually works. To customize this button there's a few possibilities and let's go take a look at them. First of all we can change the text that is shown on the button. So let's call it the default grid because pressing this button will just give us the default properties. Save the file go back to blender, reload the scripts and now it's called default grid. The nice thing is that if we search for the monkey grid then it's still called monkey grid in the f3 panel because that is the name of the operator. It is just that on this particular spot in the user interface we have a different text on the button. Finally we can add an icon to it and then we have to know the name of the icon so you can either look at existing code to cheat off of that or you can activate the icon viewer add-on. It's bundled with blender but not activated by default and then in a Python console you get this button called icon viewer.  This is copied it onto the clipboard paste it there save go back to blender, reload the script and there you have the icon. In the tool tip you can also see the description and you can see that it will actually call our operator with all the default parameters. Let's tweak this and make some buttons that use specific values for these parameters rather than the default. So again we go back to the source let's copy this call and instead of just having this we can say props equals self.layout.operator, yadda yadda yadda. Let's change this to big grid self.layout.operator is a function that returns something and the thing that it returns represents the properties of our operator. So here we can say props dot and let's take a look we had count x count y and size so here we can say props dot count x equals 10 and count y equals 10 and size equals 0.8. So let's save go back to blender, reload the script we have a new button big grid and when you hover over it you can see that it has different values for those parameters delete the monkeys. If you click on big grid automatically it will take those values of course. Now to top this off we can also make a small grid and then we have a few more buttons to play around with. So for the small grid let's set count x is 1, count y is 1 and keep the size to the default so we just don't mention it here. Save, back to blender, reload and there we are of a small grid as well which is of course just one but in the redo panel we can extend this however we want. Now you can also see the value of being able to set the text on that button because it's all the same operator but with different behaviors. Now there's one more thing I don't like how these buttons are spaced so far apart from each other because they're basically doing the same thing they're creating a monkey grid and they should really be grouped together. Fortunately we can do this by laying in the mountain a column. Now I can hear you ask but Siebren they're already in a column so what are you on about? Well a function to create a column has some parameters that we can use to influence the layout so let's take a look at our code again. Right now each operator is drawn by calling self.layout.operator and we can change it. We can create a column first and then instead of calling operator on self.layout we call operator on call. Save the code, go back to blender, reload the script and you can see they're already squeezed together a little bit more and we can go a little bit further add align equals true here and then they are exactly as I wanted them to be nicely squeezed together. So beside the operators you can also draw properties on a panel and this can be pretty much any property that you want so you could use it to group together these properties that are strewn throughout blender's user interface but you use a lot so for your specific workflow you can add them to your own panel and make your life a little bit easier. So let's take two properties one a property of cycles so let's say the number of viewport samples in cycles and the other I want to have relative to the currently selected object so let's draw the viewport visibility there. So one of the properties is this guy here the number of viewport samples and the other property that we want to add is this one here disabling viewport. Before we go to the code let's see what blender already tells us so you hover over the viewport property there it says as the bottom of the tooltip bpi data scene scene dot cycles dot preview samples and this is almost what we want but if we were to use this we would hard code the name scene in our script so if we ever rename the scene then our script is broken already and also when you use multiple scenes it also wouldn't work anymore so rather than using this literally as it stands there even though for this case it might work well we use the context again and just get the current scene with context dot scene so the property that we want to show is actually context dot scene dot cycles dot preview samples now let's go to the code let's add another column and then we call call dot prop to render the property for us it takes minimum of two parameters the first one is the thing that contains the property and then it's the name of the property so the thing that contains the property is context dot scene dot cycles everything up to the last point and then the name is preview samples let's save go back to blender reload the script and there you have it preview samples 10 so we can change this and you can see that here it changes as well which indicates that we have the right property so here you can also add these text and icon parameters they work the same as with the operator call so in order to keep this video a bit to the point i'll leave that for you to toy with now let's take a look at the second property we wanted to add which is a property of the active object i want to be able to control the viewport visibility so that is this guy over here and there it says bpi data object susan dot hide viewport and again as with the scene we don't want to do this specifically for susan only we want to do this for the currently active object which means context dot active object so the property we're going for is context dot active object dot hide viewport let's just copy what we had change the thing that contains the property to context dot active object and change the property name to hide viewport and this should render that property let's take a look back at blender we reload and there is the property that we wanted to have now let's see if it works and there you go it's working but it's a bit weird because it disappears and here it doesn't so what's going on it turns out when you hide an object it's no longer active so that means that context dot active object becomes none instead of susan none doesn't have a property hide viewport so our code is actually causing problems now let's take a look at the terminal where it started blender and here you see a rather cryptic error message here at the bottom is the terminal where I started blender from and it's complaining about the monkey grid dot pie file line 82 which is of course the call that we just added and it says error with argument one data so apparently this argument is called data function dot data does not support a none assignment it's a bit vague description but it does match what I just said the active object is none and you cannot draw a property of nothing so we have to add a little bit of a guard around this code to make it always work we know that we know that context that active object can become none so let's check for it and in that case let's just add a label otherwise we'd rather property as we did before let's see how this works now reload the script and there you have it it says no active object instead of erroring out and all the code will keep working you could argue that this is a bit of a silly button because it only works once and you will be right but I wanted to have this example to show you how things can go wrong and how to resolve that it's also a demonstration of one thing that I find quite important and that is showing why something is not there so rather than not drawing the property at all and just silently skipping over it now we draw the text no active object which indicates to whoever is using your code why the option is gone I think that's quite important so that's why I wanted to have this example here anyway even though it's rather useless you now know how to draw your own properties so it's up to you to make it useful for your particular workflow before we end this video I want to show you one more thing which is adding operators to menus given what we've seen so far this is rather easy so this is why I kept it as the last step let's add our monkey grid operator to the mesh add menu so here we have add mesh and it would be nice if underneath monkey there was a monkey grid this means we have to add it to a menu and there's a trick for that I will show you but first we have to know which menu it is so you can hover here over add and it shows view 3d empty add and you'll probably already guessed empty stands for menu type now the thing is sub menus don't show this see you don't know what the mesh is but we can look around in the python console and see if we can find it anyway it is a type so it is part of b pi dot types dot view 3d empty now let's see if we can find something there you go mesh add so this is very likely to be our menu calling it here we'll just give an error so let's not do that but at least we have the name now view 3d empty mesh add in b pi dot types let's copy this and then go to the code as you would have guessed it we have to do something in the register and in the unregistered functions and this time is quite different than what we've seen so far first we have to make our own function that will draw whatever we want to add to the menu so that looks something like this a name that you can think of yourself and again self comma context for now let's put pass in there to make python happy and this function basically will be called after the draw function of that panel so where our own panel has this draw function with self and context this function will be called with the same self and the same context so self will refer to that menu in our case now let's register and unregister this function this is done by taking that b pi types view 3d yadda yadda yadda and saying dot append mesh add menu draw the opposite is remove so in the unregister we remove mesh add menu draw now what to put in here well that's the same as with a panel we can just call self dot layout dot operator copy the idea of the operator and this should work let's save and go back to blender reload the script add mesh and there we have a monkey grid it doesn't have an icon yet but now you know how to add one so i'll leave that for you now you've seen how to add your own panel how to add your own operators to existing menus but most importantly you've seen how to look at other code so when you see something that's interesting when you're wondering how did they do that you can just right click edit source and most of the user interface elements in blender are written in python and then this just works so this is it for this episode of scripting for artist if you have any questions or remarks please leave them in the comment below and i will see you soon


So again, this is a very similar problem to the one that we just did, the one that we just finished. This will be the last one we did before lunch. This one is similar but different because we're looking at the relative size of three particles except the three particles are essentially ions and parent atom of the same atom, right? So instead of looking at relative on the periodic table, we're trying to compare these forms of ion. So if you recall our discussion about the nucleus having an influence on the electron cloud, so it has more of an influence when the number of electrons is less than the number of protons because there's going to be a stronger pull inwards towards the nucleus, right? Then if you recall that, you often should also recall that cations, which these are, are going to have or be smaller than their parent. In that case, we know both of these are going to be smaller than this. So that's the biggest. So how do we determine which one is bigger here? Well it's the same principle. The nuclear charge three plus because it has one less electron than empty two plus. So in this case empty three plus.