/srv/irclogs.ubuntu.com/2015/08/21/#ubuntu-app-devel.txt

=== salem_ is now known as _salem
=== _salem is now known as salem_
=== salem_ is now known as _salem
davidcalleMorning all07:34
robin-herohi all! I'm trying to build ubuntu clock app from bzr. But got this error: "/ubuntu-clock-app/app/ubuntu-clock-app.qml:20 module "DateTime" is not installed"08:12
robin-heroWhich package I need to install?08:12
Mirvhow do I list available click chroots from command line?08:28
Mirvis it supposed to be done just via schroot -l ?08:28
popeywith sudo, yes08:29
popeyhttp://paste.ubuntu.com/12139782/08:29
Mirvthank you, right. it's a bit confusing there's click chroot create / destroy but no list08:34
karnianyone seen dpm recently? trying to get a hold of him :)08:48
didrockszsombi: hey, I would really appreciate if you talk with kenvandine and can coordinate between people who wrote that code for bug #1485222. I don't think I can add any value to the discussion other than ping-ponging on that bug as I already gave a simple reproducer.08:49
ubot5bug 1485222 in ubuntu-ui-toolkit (Ubuntu) "Using ContentStore disables silently any StateSaver capability" [Undecided,New] https://launchpad.net/bugs/148522208:49
zsombididrocks: well, I wrote the code...08:50
didrocksI'm happy to create the simple qml file which is failing if needed, it's only taking a minute for it (as per my instructions)08:51
zsombididrocks: I am surprised that it only appeared now...08:51
didrockszsombi: I can't tell you if that worked on vivid though, I didn't use the ContentStore back then08:51
zsombididrocks: if the ContentStore alters APP_ID or application name in some way, then StateSaver will be screwed, it won;t find the state database anymore08:52
zsombididrocks: but as said, unless it is getting priority for OTA, I cannot do much08:52
didrocksdo we have a process for that, is that pinging Pat basically?08:53
didrocksso, it does mean that any bug opened and not getting management priority for the sdk are never going to be fixed?08:54
zsombididrocks: also, but i also means that the bug is critical, meaning it blocks core apps from being released etc08:54
zsombididrocks: dude, noone said that, it's just not righ tnow08:54
popeykarni: he's on vacation this week and next, can I help?08:55
didrocksI'll then try to get it in the list, the other 30 bugs I opened were workaroundable at least, (even if not elegant), that one can't though, and it seems it's a pretty basic developer case08:56
karnipopey: I think it can wait. But have you perhaps seen any app that allows interface language switching (other than via global phone setting)? I know how to add that, but I'm not sure how well it could fit with our i18n.tr / gettext story.08:57
popeykarni: i haven't seen such an app08:58
karnipopey: okay, no prob :) cheers08:59
Mirvso I'm getting stage=setup-start error every time I use the armhf in Qt Creator, and the schroot command there fails in mounting..09:00
Mirvon this new machine I don't have the ecryptfs anymore, but I guess the mounts part is still somehow broken09:00
t1mpzsombi: I cannot override Item's visible, so we need another property for Header.visible10:16
t1mpI had "opened" for the toolbar before, but it doesn't seem like the perfect property name10:17
t1mpfor now I'll go with readonly property opened, and functions open() and close()10:23
t1mphmm10:23
t1mpor readonly property hidden, and functions show() and hide()10:23
zsombit1mp: exposed?10:36
t1mpzsombi: maybe "hidden" is not so bad. Basically the Header Item is visible, but you cannot see it because it hide off the edge of the screen ;)10:37
t1mpso there is a header but you don't see it10:37
zsombit1mp: that's opposite of visible, so not good10:37
t1mpunless you scroll or call show()10:37
t1mpzsombi: yeah, kind of the opposite.. maybe not 100% the opposite10:38
t1mpzsombi: you are visible but you can still hide ;)10:38
zsombit1mp: uhm.. yoiu can be visible but hidden?10:38
zsombit1mp: well, visible and not exposed... almost the same10:39
zsombit1mp: flippedIn10:39
t1mpzsombi: I could use visible: header.y + header.height > 010:41
t1mpzsombi: but I cannot make that property readonly10:41
zsombit1mp: you cannot even override, it's final, ain't it?10:41
t1mpyes10:41
t1mpso developers can say visible = false and the header disappears, without the animation10:41
zsombit1mp: so you can only override it in cpp10:42
t1mpeven if I can override, it is probably confusing to do so10:42
t1mpbecause the visible acts different from the visible of other Items then10:42
zsombit1mp: not really, because you'll document the property in the component, and will be RO10:43
t1mpI wonder whether you ever want to set Item's visible on Header10:46
t1mpso if the Header is part of a Page that is made not visible, qt changes the Header.visible to false as well10:46
t1mpzsombi: header.visible would basically mean header.y + header.height > 010:48
t1mpI'm thinking if there are cases where you want to use header.visible instead of header.height10:48
zsombit1mp: so you don't want to go for cpp10:49
t1mpzsombi: no, not for now. Needs to be done next week ;) maybe later for performance, but I still think we should not override the visible property10:50
zsombit1mp: the problem with overriding visible is that you won't be able to keep the prev visible with the new one...10:50
zsombit1mp: but hidden is not really a good name10:50
t1mphmm10:51
t1mpzsombi: this seems to work fine actually --- visible: header.y + header.height > 010:51
t1mpzsombi: so I can access the visible property if I need it10:52
t1mpand I use show() and hide() to animate the header in and out10:52
t1mpI'm not sure if the binding breaks when Header.parent.visible is set to false and then true again10:52
zsombit1mp: so idf someone changes visible, you'll get the header in/out?10:52
t1mpzsombi: no, it is just the Item.visible, so no animation10:53
t1mpthey must use show() and hide()10:53
zsombit1mp: what binding? on the property not, as the paret change is controlled under the hood10:53
t1mpzsombi: if item.parent.visible is set to false, item.visible also becomes false10:54
zsombit1mp: the problem is that if parent is hidden, and the header visible evaluates to true, teh Header will be shown/rendered10:54
zsombit1mp: yes, it does, but that happens under the hood not thru setVisible() calls10:54
t1mpzsombi: hiding the parent will override the header.visible10:54
zsombit1mp: check the source code, you'll see no setVisible() on child items when you set the poroperty10:55
zsombit1mp: so child item bindings on visible won't get broken10:55
t1mpzsombi: ok, so then using Item.visible in Header would work fine as long as apps don't set Header.visible10:55
zsombiyep10:55
zsombit1mp: but10:55
zsombiwith visible you could change the shown/hidden animations without calling show() hide()10:56
zsombit1mp: is there a use case when you need funcs to show/hide?10:56
t1mpzsombi: let's call Item.visible ivis and Header.visible hvis for now10:57
t1mpzsombi: you mean if I really need the function instead of setting hvis?10:57
zsombit1mp: yes10:58
t1mpno, but using the functions and treating hvis as readonly avoid some issues with the binding10:58
zsombit1mp: what issues?10:58
t1mpbecause setting hvis must show/hide the header, and scrolling a flickable may change the value of hvis again10:58
zsombit1mp: and?10:59
zsombit1mp: aaah, I remember now10:59
zsombit1mp: when Header is hidden intentionally, scrolling should not bring it back10:59
t1mpzsombi: depends on header.locked11:00
t1mpinternally I need the show() and hide() functions for sure11:00
zsombit1mp: I'd rather use property than functions :(11:00
t1mpwhen you are scrolling and release the flickable when the header is half-shown,11:00
t1mpI need to call show() or hide() depending on the position of the header11:01
t1mpsetting hvis won't help, because its value might not even change11:01
t1mphvis would be true if only part of the header is visible11:01
t1mpbut show() always opens the header completely. And hide() hides it completely11:01
t1mpivis always must be true except if the header is completely hidden11:01
zsombit1mp: yes, I remembered it11:02
t1mpwe also have header.enabled == false when the header is not fully opened11:03
t1mphmm11:04
t1mpI was thinking to use header.enabled = false to also hide the header, but maybe you don't want that as an app developer11:04
t1mpok let's not mix the visibility with enabled11:04
zsombit1mp: and even that is controlled under the hood by parent being disabled :)11:04
t1mpHeader.active?11:05
t1mpheader.active = false would animate the header out11:06
t1mpnot super obvious11:06
t1mpHeader.on11:06
zsombit1mp: kalikiana: oppinnion pls> should we have multiple ActionContexts active the same time or not11:07
t1mpdialogs have open() and close() functions11:07
t1mpzsombi: yes11:08
t1mpI didn't check how you are doing ActionContexts, but could a Page have an ActionContext?11:08
zsombit1mp: kalikiana: AdaptivePageLayout can have multiple pages open, so in that sense we should... unless AdaptivePage layout IS keeping the ActionContext and not the Pages....11:08
t1mpthen if you have multiple pages open (AdaptivePageLayout), you want all of those ActionContexts active11:08
zsombit1mp: yes, that's the way it is now11:09
t1mpzsombi: yeah you could have one ActionContexts that contains the actions of all the pages, but that will get complicated11:09
zsombit1mp: yes, it will11:09
t1mpwhen we had the unity action contexts, there was a global ActionContexts in the MainView, and local ActionContexts from the Pages11:09
t1mpthe global one was always active, and the local ones depending on the active page11:09
zsombit1mp: anyways, Actions get registered into the closest ActionContext found in th ehierarchy11:09
zsombit1mp: we have 3 now :)11:09
t1mp3?11:09
t1mpa global one and two pages?11:10
zsombit1mp: we have sharedContext as well, which is always inactive11:10
zsombit1mp: global, shared and local ones11:10
t1mpzsombi: I think the ActionContext will be easiest to use if multiple can be active at the same time11:10
zsombit1mp: so all Action items you declare in MainView not under an ActionManager for instance will end up in sharedContext11:10
zsombit1mp: we have the Dialog problem11:11
t1mpwhy is sharedContext not active?11:11
t1mpso in the Dialog you want only the Dialog's ActionContext active..11:11
zsombit1mp: because the actions in that context can be triggered only if they are used in active contexts11:11
zsombit1mp: let's get back to shared a bit11:11
zsombit1mp: so, you don't want an action in shared pool to get triggered no matter if those are used or not11:12
t1mpahh, all actions are automatically added to a Context?11:13
zsombit1mp: at least that's how I thought....11:13
zsombit1mp: we can get rid of the shared pool11:13
zsombit1mp: each action keeps track of the contexts it was added11:13
t1mpI was thinking you have to put them in an ActionContext explicitly11:14
t1mphmm11:14
t1mpinstead of the sharedContext you could have the action by default in no context?11:14
zsombit1mp: no, otherwise we'd have a pile of apps not working at all when we introduce this11:14
t1mpright11:14
zsombit1mp: so I have to find a context for them11:14
zsombibut11:14
zsombiif I don't put the action anywhere, that may actually work11:15
* zsombi thinks why it introduced shared context11:15
zsombit1mp: basically having no context or being in shared is the same11:15
t1mpyeah11:15
zsombit1mp: but a bit simplier codewise11:15
t1mpmaybe there was a sharedContext for listing them all in HUD11:16
t1mpI haven't seen the code, but probably I would prefer no context over a disabled sharedContext that is not used11:16
zsombit1mp: fair enough!!!11:16
* zsombi noted11:16
zsombit1mp: so, if an action is not registered in any context, it cannot be triggered11:17
zsombit1mp: trigger() wont emit the signal11:17
zsombineither shortcuts, hotkeys are going to work11:18
zsombit1mp: but the action is still enabled11:18
zsombit1mp: now, the wiestion is whether should it be enabled at all....11:18
zsombiquestion11:18
zsombit1mp: and there I am too, handling enabled under the hood...11:19
zsombit1mp: so I need oppinion on that11:19
kalikianazsombi: let's count, 1 context per visible page in each column, 1+ global context(s), 1 component-specific context(s), popover open that's not modal, makes 5 seems like a good average number11:22
zsombikalikiana: you can have 2 pages active11:23
zsombior even more11:23
kalikianazsombi: see my calculation :-)11:23
zsombikalikiana: yes11:23
zsombikalikiana: all active11:23
zsombikalikiana: then comes the Dialog11:23
zsombit1mp: ^11:23
zsombikalikiana: t1mp: I have the "overlay" property for that11:23
kalikianazsombi: the Dialog will disable all contexts, though11:23
zsombithere cannot be more than one overlay active at a time11:24
zsombikalikiana: yes, that's what overlay is doing11:24
kalikianazsombi: so "overlay" is looked up in the hierarchy of parents?11:24
zsombikalikiana: the Action's isActive() checks whether there is an active overlay set, if yes, and the action does not belong to it, it won't trigger11:25
kalikianazsombi: looking at the branch I don't see how a Dialog with multiple context would work at all11:27
zsombikalikiana: right now I'm not looking up in the hierarchy, but that may make sense...11:28
zsombikalikiana: yes, the Dialog's overlay basically disables all its child contexts too... so this needs more love11:28
zsombikalikiana: perhaps a lookup in the hierarchy would be needed each time the action is activated11:29
kalikianazsombi: I would expect that it acts more like a container. if Dialog is visible all of the contexts inside it are enabled, but nothing else11:30
zsombikalikiana: yes, but somehow the other containers should be disabled in Dialog case11:31
* zsombi thinks he will restart the work on this11:31
kalikianazsombi: might make sense to figure out at the same time as what happens to Action's declared with no explicit ActionContext11:33
zsombikalikiana: see above discussion with t1mp11:33
zsombikalikiana: so far it works the way that Action detects the actionContext property and if found, registers itself in that context11:34
zsombikalikiana: if none found, it registers in a sharedContext, which we just discussed there's no reason to have, as it is disabled, and that means practically like not being registered anywhere11:35
kalikianazsombi: so if I declare an Action will it be in the context of the page, or dialog respectively?11:35
zsombikalikiana: if the Action is declared in teh Page, it will be in the Page's one, if in Dialog, it'll be in Dialog's11:36
zsombikalikiana: if declared in MainView, it will be "orphan"11:36
zsombikalikiana: those are the shareable actions11:36
zsombikalikiana: so if added to Header actions, Header will have to register those to the context11:37
kalikianazsombi: okay, so the immediate problem is that you may have declared actions globally for re-use and they will stop working11:37
zsombikalikiana: I was thinking to somehow add this logic somewhere so we can apply it without any pain11:37
kalikianazsombi: hmmm Header should work as if they are in the Page probably11:38
zsombikalikiana: if an action si declared as global (ActionMaanger.actions are those) those will never stop working11:38
kalikianazsombi: you just said they will stop working if declared outside of a Page11:39
zsombikalikiana: yes, but the thing is that Header needs to do this per action, because Header doesn't know whether the actoins properties re locally declared or shared ones11:39
zsombikalikiana: there are 3 types of actions: global, shared and local ones11:39
zsombikalikiana: globals are registered in ActionManger's global context11:39
zsombikalikiana: that is always active, thus it is active no matter of where are used11:39
zsombikalikiana: the shared ones are declared in MainView or other common place, outside of any ActionManager11:40
zsombikalikiana: local actions are declared in place if use11:40
zsombikalikiana: like Button { action: Action {...} }11:40
kalikianazsombi: so the shared actions are the ones that must be treated equally to global actions then, because otherwise they will silently stop working11:41
zsombikalikiana: well, not11:41
zsombikalikiana: if we follow the principle that an action is only active if in an active context, then not11:42
zsombikalikiana: shared (orphan) actions are not in any context11:42
zsombikalikiana: so then shared actions must be registered11:42
zsombikalikiana: they become active when they are in an active context11:43
kalikianazsombi: yet they work just fine right now11:44
t1mpzsombi: the "overlay" disables previous action contexts?11:44
zsombikalikiana: because they trigger no matter if they are active or not11:44
t1mpzsombi: you could also have an ActionContext.exclusive property11:44
kalikianazsombi: yes. and changing that will break them silently11:45
zsombikalikiana: we were talking at some point that even the action triggering should not happen if it is not in an active context11:45
t1mpzsombi, kalikiana: I'm doing some header work, and it more and more looks like we should move Header inside the Page11:45
t1mpI think we can even do that in 1.3 without breaking APIs11:46
kalikianazsombi: when I'm looking at existing code I'm not expecting a perfect world. I only care that apps already out in the wild still do their job :-)11:46
zsombikalikiana: if we put ActionContexts in 1.2 toolkit, than they'll work11:48
kalikianazsombi: I don't understand that sentence11:50
kalikianacan you phrase it differently?11:50
zsombi[14:41:26] <kalikiana> zsombi: so the shared actions are the ones that must be treated equally to global actions then, because otherwise they will silently stop working11:50
zsombikalikiana: shared actions are used somewhere11:51
zsombikalikiana: we have to update the components so they all register actions11:51
zsombikalikiana: we can do that for 1.2 apps as well, actually we have to11:51
t1mpzsombi: so the actions see where they are declared and then add themselves to a context?11:52
zsombit1mp: yes, they do11:52
t1mpzsombi: that can give problems if you use references to the actions somewhere else, right?11:52
zsombit1mp: but like Header.actions can have shared actions11:52
zsombiyes11:52
zsombit1mp: unless Header declares a context inside and add the actions to that context11:53
t1mpzsombi: for an ActionBar you can say actions: [ Action { id: ac1 }; Action { id; ac2 } ], or actions: [ac1, ac2] with ac1/2 defined somewhere else11:53
zsombit1mp: like I did with Sections11:53
kalikianazsombi: you defined shared actions as those that are neither in Page, Dialog nor MainView.actionManager11:53
kalikianazsombi: how would we know where those are declared?11:53
t1mpI think in these cases the ActionBar or Sections needs to add the actions to a context11:53
zsombikalikiana: you dont' know that11:53
t1mpzsombi, kalikiana: let's go to the hangout already, easier talking :)11:54
zsombikalikiana: you have to add the action to the closest context11:54
kalikianayeah, let's use the hangout11:54
=== _salem is now known as salem_
nik90zsombi: Hi, You were right! Bug 1486008 turned out to be a device specific issue affecting only Nexus 4.12:18
ubot5bug 1486008 in ubuntu-ui-toolkit (Ubuntu) "leading actions width is too small making it very difficult to press on Nexus 4 (mako)" [Undecided,Confirmed] https://launchpad.net/bugs/148600812:18
zsombimzanetti: ^12:18
zsombinik90: thx12:18
nik90I seriously thought I was going paranoid about it :P12:19
tsdgeoszsombi: he is off today12:20
* tsdgeos goes for late lunch12:20
zsombinik90: LOL12:21
kenvandinezsombi, i don't see how creating a ContentStore object could alter the APP_ID12:39
kenvandineit's a simple object with a couple properties12:39
kenvandineit actually does nothing12:39
zsombikenvandine: then I hav eno idea what can be the problem...12:40
kenvandinezsombi, yeah, it makes no sense12:41
seb128kenvandine, zsombi, should be easy to reproduce and poke a bit no?12:43
kenvandinecuc::Store{QStandardPaths::writableLocation(QStandardPaths::PicturesLocation)12:46
kenvandinethat's all that happens in creating a store12:46
kenvandinezsombi, any chance use QStandardPaths messes something up?12:46
kenvandineactually for the app scope it does this12:47
kenvandinenew cuc::Store{QStandardPaths::writableLocation(QStandardPaths::DataLocation)12:47
zsombikenvandine: not that I know of...12:47
kenvandinewritableLocation does need the appId to create the path12:47
kenvandinebut that's all internal in qt12:48
kenvandinethat's literally all that's done in creating the scope12:48
zsombikenvandine: none of the standard paths need the app name, the QSettings does need that12:48
kenvandinewhoops, store12:48
zsombikenvandine: and we use that to store the properties12:48
kenvandineit does12:48
kenvandinethat creates a path like ~/.local/share/appId/12:48
kenvandinenot creates, uses12:48
kenvandineoh you're right... how does it get the appid in there12:49
kenvandinenever mind... it doesn't12:49
kenvandine~/.local/share12:49
kenvandineit's rather simple12:49
kenvandineso if that's causing the appId to get changed, it QStandardPaths doing it12:50
kenvandinewhich i doubt12:50
seb128get a simple example and print the value before/after?12:50
seb128I can do that if you want12:51
kenvandinezsombi, how did you figure out the appId changed?12:51
kenvandinei figured someone had done that12:51
zsombikenvandine: StateSaver not restoring the state can only happen if the state file is not found; state file nam euses app name12:51
kenvandinelets try to debug it with didrocks example12:52
kenvandinei've never used the StateSaver before myself12:52
zsombikenvandine: so if the ContentStore is missing, the states are restored, otherwise not, my first guess was the app name12:53
kenvandinei know messaging-app uses it, i would have thought this would have broken an app like that12:53
zsombiright12:53
didrocksdo they use a ContentStore?12:53
kenvandinemaybe not...12:53
zsombithey use ContentHub12:53
kenvandinethey do use ContentHub12:54
didrockszsombi: yeah, but you don't have to use the ContentStore necessarily5~12:54
didrocksand contentHub itself is fine12:54
kenvandinei really don't have time to debug this today though, i'm rather swamp cramming to get stuff done before the sprint12:54
didrocks$ grep -r ContentSt * | wc -l12:54
didrocks012:54
didrocksin messaging app12:55
kenvandineinstantiating a ContentStore is just the call to QStandardPaths::writableLocation12:55
kenvandineso it would have to be that12:55
seb128easy to swap those12:55
seb128I can have a try if you want12:55
kenvandinewe could just add a ContentStore to an app that we know uses StateSaver12:56
kenvandineseb128, if you have time :)12:56
seb128kenvandine, well, adding the ContentStore to an app that uses StateSaver isn't going to tell much, is it?12:56
seb128it's going to tell you that it stops working12:56
seb128then you are back at saying that it only call QStandardPaths::writableLocation12:57
seb128no?12:57
kenvandinei guess12:57
kenvandinethat call is done in libcontent-hub012:57
t1mpzsombi, kalikiana: Should we have a Title { property string text; property string subText" } property maybe?12:58
kenvandineso removing that would require a rebuild12:58
t1mpheader contents will be easy then: Header { ActionBar { }; Title { }; ActionBar { }; Sections { } }12:58
zsombit1mp: not a bad idea13:03
zsombit1mp: it's just thi doesn't tell how the blocks will be laid out13:03
seb128zsombi, is the statesaver a part of the process? where does it store the info?13:09
seb128or is that a service?13:09
zsombiseb128: it is part of it, yes, and stores under XDG_RUNTIME_DIR13:10
zsombiseb128: uses QSettings13:10
zsombiseb128: a piece of code from StateSaver http://pastebin.ubuntu.com/12140892/13:10
zsombiseb128: we are not using APP_ID though, we quesry the app name from QGuiApplication13:11
seb128right13:11
t1mpzsombi: yeah, it doesn't tell how they are layed out because that would be a lot of code for one line in irc :)13:43
t1mpzsombi: so then I'm still not sure if the Header should have some default content, or the app developers have to put the stuff in there themselves13:44
t1mpzsombi: basically it will be Header { Row { Column { ActionBar{}; Title{}; ActionBar{}; }; Sections } }13:46
t1mperrr13:46
t1mpI mixed up the Row and Column13:46
t1mpwe should have some default HeaderLayout13:48
t1mpputting the components is not so hard, but you also have to get all the margins etc right13:49
seb128zsombi, kenvandine, do you know what that is/does13:55
seb128    QObject::connect(&QuickUtils::instance(), &QuickUtils::deactivated,13:55
seb128                     this, &StateSaverBackend::initiateStateSaving);13:55
seb128"QuickUtils::deactivated"13:55
seb128zsombi, kenvandine, so, debugged a bit more, issue is that http://bazaar.launchpad.net/~ubuntu-sdk-team/ubuntu-ui-toolkit/trunk/view/head:/src/Ubuntu/Components/plugin/statesaverbackend_p.cpp#L44 handle only SIG2/15 and not KILL=9, at least not with the UnixSignalHandler14:11
seb128that callback triggers on SIGKILL though14:11
seb128    QObject::connect(&QuickUtils::instance(), &QuickUtils::deactivated,14:11
seb128                     this, &StateSaverBackend::initiateStateSaving);14:11
seb128but doesn't once ContentStore is used14:11
seb128unsure how what that deactivated is and if it's normal to rely on it/why it stops triggering with content-hub14:11
seb128but it's not an env/dir issue14:11
kenvandineweird14:12
kenvandinei'm not familiar with QuickUtils14:12
seb128me neither14:12
seb128but so the proper handlers work with ContentStore14:12
kenvandineso something must be disconnecting that?14:12
seb128I guess14:12
kalikianat1mp: is Title a Row { Label {} Label {} } in that case? what happens if you have head.contents? what happens if you have title in the Page?14:14
kalikianaor would this be only exposed if you manually use ActionBar?14:14
t1mpkalikiana: Title would be something like that, yes. Only a bit more complex because when you have a lot of space horizontally, the subtitle will go to the right of the title instead of under it14:15
greybackseb128: I think QuickUtils::deactivated is fired when the app moves from foreground to background - it indicates that the app should save state now, as it will be suspended shortly, and possibly killed14:15
seb128greyback, kenvandine, is something in the sdk dealing with changing that in case of content-hub to avoid killing content hub "clients" in a transaction?14:16
kalikianat1mp: hmm so more like a Flow. and not easy to replace. say for example an app needs custom coloring it's not as trivial to put labels in there14:16
t1mpkalikiana: I'd say the default header in a Page would be header: Header { HeaderLayout { title: page.title } } }14:16
t1mpkalikiana: it is getting  a bit messy to put it here14:17
t1mpkalikiana: I'll try to work it out in the API doc https://docs.google.com/document/d/1wUUKtPmRmwbUELC1BUB9l0VOAwS_zAPRSCqMopUxR1c/edit#14:17
greybackseb128: nothing I'm aware of, but I'm no sdk expert14:17
kenvandineseb128, we do switch focus back to the requesting app, which would background the source app14:17
kenvandinebut it sounds like it's not listening for that anymore14:18
seb128kenvandine, well, doing the object instanciation shouldn't lead to anything like that though14:18
kenvandinegetting disconnected from that signal14:18
kenvandinenope14:18
kenvandinebut14:18
kenvandineit wouldn't save the state until it gets that deactivated signal14:18
kalikianat1mp: oh, I need to look at that one. sorry, even in just 2 days off my inbox gets so full :-/14:19
kenvandineso when it goes back to the background it should still get that14:19
t1mpkalikiana: it is still very much work in progress14:19
t1mpkalikiana: the HeaderLayoutStyle is tricky14:25
t1mpkalikiana: so the HeaderLayout will have ActionBar, Title, Sections14:25
t1mpkalikiana: all of their properties are defined in ActionBarStyle, TitleStyle (TODO), SectionsStyle14:25
t1mpshould I somehow link to those from the HeaderLayoutStyle?14:26
t1mpzsombi: ^14:26
t1mpfaenil: how are you doing that with the ListItem layouts?14:26
* faenil reads backlog14:26
t1mpfaenil: or are you not using other styled components inside the ListItem layouts?14:26
faenilnope, not styled14:27
t1mpfaenil: to summarize, I'm thinking of APIs for the new new new Header in https://docs.google.com/document/d/1wUUKtPmRmwbUELC1BUB9l0VOAwS_zAPRSCqMopUxR1c/edit#14:27
t1mpfaenil: ok.. maybe HeaderLayout is not the correct name then14:27
t1mpit is not just the layout, but the full contents14:27
t1mpHeaderContentsPreset maybe.. :s14:28
faenilmmm, don't know :/14:28
t1mpgood, I see more people are looking at the document14:28
t1mpeverybody feel free to comment/suggest/ask questions. Now is the time. After we land it it becomes really difficult to change the API14:29
t1mpoh. After I ask for comments everybody closed the document.. ;)14:30
t1mpkalikiana: I can simply put the components that I want inside the HeaderLayout, and have aliases to them to expose them to the app developer14:31
t1mpbut like that you'll have to set for example the actions like this: header.layout.trailingActionBar.actions: [ action1, action2 ]14:32
t1mpwell I can add some more aliases so that header.trailingActions would work, but only in the default Header of the Page14:32
t1mpcustom headers will need Page.header: Header { // all the contents }14:33
t1mpkalikiana: instead of the HeaderLayout we could also have a subclass of Header that has the contents14:42
kalikianat1mp: I'm actually starting to think, if you're basically exposing some two dozen properties, why not make it one component. since otherwise the API is just a number of aliases to almost an entire component14:48
faenil+114:48
t1mpkalikiana: what do you mean?14:49
t1mpkalikiana: I have the Sections and ActionBar components14:49
t1mpkalikiana: those can now be used by themselves. And I like to re-use them in the Header14:49
t1mpkalikiana: so if I put them in one component, to expose its properties, that component will need to have all the aliases14:50
t1mpkalikiana: but, right. I don't like having so many aliases either...14:50
kalikianat1mp: I mean that almost all of the alias seem to point tat the layout14:50
kalikianaat which point you could just use that14:50
t1mpkalikiana: but the layout has the subcomponents,14:51
t1mpkalikiana: so you have to say header.layout.leadingActionBar.actions: [] to set the leading actions14:51
t1mpthat's clear, but ugly I think14:51
t1mpif there was a DefaultHeader that includes the subcomponents, instead of the HeaderLayout, it would be a bit shorter14:52
t1mpbut still header.leadingActionBar.actions14:52
t1mpmaybe it is not *that* bad ;)14:53
kalikianat1mp: API-wise you're basicalling exposing a fake Header subclass through aliases14:53
t1mpyeah, right14:53
t1mpah, so you meant to have the DefaultHeader which inherits from Header14:53
t1mpyes, maybe that's good14:53
t1mpor Header--> EmptyHeader, DefaultHeader --> Header14:54
t1mpmeh14:54
t1mpDefaultHeader --> PageHeader?14:54
kalikianahmm I get confused by terminology now14:54
kalikianawhat is default?14:54
t1mpHeader has no contents, but takes care of scrolling/showing/hiding/..14:54
t1mpDefaultHeader: Header { ActionBar{}; Title{}; ActionBar{}; Sections{} }14:55
t1mpso DefaultHeader would replace Header { HeaderLayout{} }14:55
t1mpthe naming is no good14:55
t1mpI'll update the doc14:56
t1mpkalikiana: ok the doc got better now :)14:56
kenvandineElleo, do you have any thoughts on https://bugs.launchpad.net/ubuntu/+source/content-hub/+bug/148522215:00
ubot5Ubuntu bug 1485222 in ubuntu-ui-toolkit (Ubuntu) "Using ContentStore disables silently any StateSaver capability" [Undecided,New]15:00
kalikianat1mp: will navigationActions become public? if not, where do you set them?15:01
kalikianaassuming Tabs gets replaced and there will be a new API for it15:01
t1mpkalikiana: yeah.. I'm still thinking about that one15:02
t1mpkalikiana: AdaptivePageLayout internally can determine for each page whether there should be a back button15:02
t1mpkalikiana: it would be nice if it can somehow set that for the page header, but only if the app developer doesn't give a custom back action15:02
kalikianat1mp: should page.header.leadingActionBar.actions15:03
t1mpkalikiana: how does your sentence end?15:03
kenvandinezsombi, the hub client does have an event filter, but that would effect anything using the content-hub15:04
kenvandinehttp://bazaar.launchpad.net/~phablet-team/content-hub/trunk/view/head:/src/com/ubuntu/content/hub.cpp#L8215:04
kalikianat1mp: work with the header subclass? that would be one (awkward) way to set the navigation actions then. otherwise it'd have to be for example Page.navigationActions15:04
t1mpkalikiana: currently the headerstyle looks for some special properties that were attached by the AdaptivePageLayout, or PageStack/Tabs and then gets the action from there, if there is no backAction defined15:04
kenvandinezsombi, it's used so if an application needs to respond to a transfer request, and it's already running it calls the handler when activated15:04
Elleokenvandine: my guess is it's the hub installing an event filter15:05
kalikianat1mp: unlike the back action there is no new API for navigation actions15:05
kenvandineElleo, but it only breaks with a ContentStore15:05
Elleokenvandine: contentstore instantiates a hub object, and it looks like the hub install an event filter15:05
kenvandinenot with anything else15:05
kenvandineyeah, but anything with a hub instance does that15:05
kenvandinenot just a ContentStore15:05
Elleokenvandine: oh, so this doesn't happen if you have other things? that's odd :/15:05
t1mpkalikiana: right. It needs more thought. And also designs. I don't even know if only Actions will be enough, what if they need something completely different in the overflow panel on the left15:06
kenvandinedidrocks said it works if you use the hub without a content store15:06
Elleobecause the contentstore barely does anything15:06
kenvandinei know right?15:06
kenvandineit literally just calls QStandardPaths::writablePath15:06
kalikianat1mp: yeah. you'd potentially want a property PageHeader.leadingPanel15:07
Elleokenvandine: I'd suggest double checking that, the hub's event filter looks like it swallows QEvent::ApplicationDeactivate15:07
kenvandineyeah15:07
Elleokenvandine: which from the bug report sounds like is the underlying issue15:07
kenvandinedidrocks, are you sure it works without a ContentStore but using the content-hub?15:07
didrocksI'm sure, I did test that explicitely15:07
kenvandinereturn QObject::eventFilter(obj, event);15:07
kenvandinei'm thinking on deactive it should return that15:07
didrocks(and spent some extensive time to find the exact component failing it)15:08
kalikianat1mp: which might be a component that uses list item layouts rather than just actions15:08
kenvandinedidrocks, all very puzzling15:08
kenvandineit's like the simplest component we have :)15:08
didrocksI guess reading from the discussion here :p15:08
kenvandinewith no logic15:08
Elleokenvandine: yeah, that's what it does for all other events, was there some explicit reason for swallowing the deactivate signal though?15:08
t1mpkalikiana: I plan to add delegate and overflowDelegate properties to the ActionBar15:08
kenvandineElleo, i don't think so15:08
didrocksbut it's really easily reproduceable, like less than a minute to setup the example15:08
didrocksand seb128 confirmed :)15:09
t1mpkalikiana: that would solve custom panels, except if there need to be subtitles grouping the actions in the panel15:09
kenvandineElleo, but it does check for that explicitly15:09
* kenvandine wonders why15:09
kenvandinedidrocks, yeah, thanks to seb128's debugging we found it's not getting this signal15:10
kenvandinethat was super helpful15:10
t1mpkalikiana: so, page.header.leadingActionBar.overflowDelegate can then be used to change the looks of the leading panel15:10
kenvandinebut now i'm thinking any hub client should fail to save state...15:10
kenvandinethis has nothing to do with ContentStore15:10
kenvandineanything with a hub instance15:10
didrockshowever, they do work in my case (I really just disabled this component)15:10
didrockslike, commenting only that15:10
kenvandineElleo, i probably shouldn't be returning true there even on activated15:11
didrocksand not the whole ContentHub other's components15:11
kenvandinejust HandlerActive and move on15:11
kenvandinedidrocks, i'll get a build of the hub with this not swallowing the event15:11
didrockswould be an interesting data point15:12
t1mpkalikiana: for even more custom panels, they don't have to use the PageHeader, but they can use an empty Header where they put their own buttons and panels15:12
Elleokenvandine: well maybe you should be calling Object::eventFilter on activated as well unless it's deliberately not wanting to do anything from the QObject event handler there?15:12
kenvandineElleo, do you agree that i should just remove that return true when ApplicationActivate ?15:12
t1mpkalikiana: of course, more custom stuff will require more work for the apps15:12
kenvandineElleo, so you do agree :)15:12
kenvandinei can just remove that return true15:12
Elleokenvandine: yeah15:13
kenvandineand remove the deactivate too15:13
kalikianat1mp: the main drawback would be to mimic the rest of the header, especially the title/subtitle which is getting more complex15:15
t1mpkalikiana: let me add the Title component to the doc :)15:15
kalikianathat wouldn't be very nice if it becomes common15:15
kenvandinehttps://code.launchpad.net/~ken-vandine/content-hub/dont_swallow_deactivate/+merge/26877015:16
kenvandinewe can test the debs from that15:16
kalikianat1mp: on a side note, I'm intimidated by that penguin who is staring at me now hile I'm reading your doc15:17
Elleokenvandine: okay, cool15:17
Elleokenvandine: might it be worth keeping that warning?15:17
t1mpkalikiana: http://www.lowbyte.com/albums/2006-01-27-GaAquarium/web_PenguinStare_30_5037.sized.jpg15:17
kalikianahaha, that is not helping :-D15:18
kalikianat1mp: so, even if Title is a component, I'm still not sure how you would place it. as soon as you don't use the ActionBar on the left you're forced to build all of the header15:19
zsombi[16:55:51] <seb128> zsombi, kenvandine, do you know what that is/does15:19
zsombi[16:55:52] <seb128>     QObject::connect(&QuickUtils::instance(), &QuickUtils::deactivated,15:19
zsombi[16:55:52] <seb128>                      this, &StateSaverBackend::initiateStateSaving);15:19
zsombi[16:55:59] <seb128> "QuickUtils::deactivated"15:19
zsombiseb128: kenvandine: initiates state saving when teh app deactivates15:19
zsombii.e. goes background15:19
seb128zsombi, so when it's sigkilled nothing is saving state?15:19
kalikianat1mp: ie since the type is leadingActionBar you need to have a custom component doing anchoring or other means to place all the components15:19
t1mpkalikiana: no, if the left actionbar has no actions it is invisible15:20
kenvandinezsombi, i think the hub client instance was swalling the deactivated signal15:20
ogra_seb128, the sigkill comes from the kernels OOM killer ...15:20
kenvandinewhich means it wouldn't work with anything that uses the content-hub15:20
ogra_you would have to inject the state saving in the kernel somehow for that15:20
t1mpkalikiana: PageHeader will position all its contents15:20
seb128ogra_, right, but statehandler doesn't have an handler for 9, just for 2 and 1515:20
kenvandinebut didrocks says it does work15:20
t1mpkalikiana: I don't see the problem with that15:20
zsombikenvandine: ahha.... QuikcUtils::deactivated comes when the application state changes...15:20
kalikianat1mp: you're saying you would use PageHeader and put a DekkoPanel (made up the name) inside? how then do you know its size and margins?15:21
t1mpkalikiana: it will have two ActionBars, a Title, and a Sections. But the ActionBars and Sections will be invisible when they don't have contents15:21
kenvandinezsombi, i'm not sure my eventFilter is keeping you from seeing the signal though15:21
kenvandinehttps://code.launchpad.net/~ken-vandine/content-hub/dont_swallow_deactivate/+merge/26877015:21
kenvandinezsombi, that's my attempt to fix it15:21
kenvandinebut really, if that was eating it, it would eat it for all content-hub use15:21
kenvandinenot just ContentStore15:21
t1mpkalikiana: right. If you want a completely custom panel like Dekko, then you have to use the empty Header and do all the layouting yourself.15:21
t1mpkalikiana: hold on, there is a way around that15:22
kenvandineseb128, the state should have been saved before it was killed15:22
ogra_seb128, though i think we can assume that a foreground app doesnt get killed ... which means the state saver kicked in already when you de-focused it15:22
zsombikenvandine: ahha, here you go: http://bazaar.launchpad.net/~ubuntu-sdk-team/ubuntu-ui-toolkit/staging/view/head:/src/Ubuntu/Components/plugin/quickutils.cpp#L4715:22
kalikianat1mp: that is what I mean. and note I only want to replace the leading action bar in this example, nothing else. but I see no way to only replace that..15:22
t1mpkalikiana: page.header.leadingActionBar.delegate: DekkoButton { onClicked: popups.open("DekkoPanel.qml") }15:23
seb128ogra_, right, expect when you try on a desktop with xkill ;-)15:23
ogra_desktops ... pfft :P15:23
seb128ogra_, same on a phone in windows mode I guess15:23
ogra_yeah, but there we turn off the lifecycle, dont we ?15:23
kalikianat1mp: hmmm I didn't think of that. so that would allow you to have a special button as well as a panel easily. I like it15:24
zsombiogra_: when an app goes background, it saves the states, yes15:24
zsombiI mean StateSaver does it15:24
ogra_right15:24
t1mpkalikiana: ActionBar.delegate property still needs to be added, but we'll probably need that anyway15:25
seb128kenvandine, didrocks, zsombi, similar problem if you add a ContentPeer isntead of a ContentStore15:25
seb128so not specific to ContentStore15:26
t1mpkalikiana: I think I will need about 10 MRs to get all the new features in ;)15:26
zsombiseb128: so the event is consumed there too? (accepted)15:26
Elleoseb128: that's good, makes much more sense then :)15:26
seb128yes15:26
zsombi:)15:26
Elleozsombi: it's consumed by the main hub object, so anything that creates a hub object should cause this15:26
zsombiobviously15:26
zsombit1mp: then go ahead with15:27
zsombit1mp: are you trying to do similar layouting as for the ListItemLayout?15:27
kenvandineseb128, that makes sense then15:28
kalikianat1mp: I can already picture a certain someone going "is it ready" yet every week? ;-)15:28
zsombikalikiana: evry designer will :D15:29
zsombi+e15:29
kalikianat1mp: maybe the delegate isn't even that urgent, at least for now, as long as showing the custom overflow can be done by trigger from an action15:29
kenvandineseb128, didrocks: i just confirmed statesaving doesn't seem to be working in messaging-app anymore15:32
t1mpzsombi: I was trying, but after discussing with kalikiana above we thought it is simpler to have a Header without contents, and a PageHeader that includes the standard layout for the header15:32
t1mpkalikiana: you need the delegate, because the popover needs a reference to the button that it should be pointing to15:33
seb128kenvandine, let's see what it does once your fix is built ;-)15:33
t1mpkalikiana: it cannot point to the Action15:33
t1mpkalikiana: adding the delegate is a small addition for the ActionBar15:33
t1mpzsombi: see https://docs.google.com/document/d/1wUUKtPmRmwbUELC1BUB9l0VOAwS_zAPRSCqMopUxR1c/edit#15:34
kalikianat1mp: oh. I was sort of assuming an overflow that would cover the buttons anyway. but actually I can think of a ways where the design would require it depending on how it's shown15:34
kalikianaso that would indeed be needed15:34
kenvandineseb128, nevermind... the messaging-app statesaver support never landed15:35
kenvandineso that explains why that's not saving :)15:35
seb128k, shame :-/15:35
seb128but yeah, the content hub issue only blocks saving when the app is swapped out15:36
seb128the unix signal handler still work15:36
t1mpkalikiana: what do you mean with an overflow that would cover the buttons?15:36
seb128which is what closing from the switcher or oom does15:36
t1mpkalikiana: ah, right..15:36
t1mpkalikiana: got it. If the popup does not have a pointer pointing at the button then you don't need the delegate15:36
kenvandineseb128, right, but it should get the deactivate before that15:37
seb128right15:37
* t1mp gotta go. Feel free to comment on the API doc.15:38
kalikianat1mp: at least the current dekko opens it below the sections. but it could be they only do that because there's no otherway15:38
t1mpkalikiana: most of the stuff in dekko is custom, so I guess it is intended like that15:41
kalikianat1mp: I'm not sure the header is. but anyway, a delegate would be good to have15:41
* t1mp off now. Have a nice weekend :)15:46
t1mpI guess I'll read comments on the API doc in the weekend ;)15:46
nik90ahayzen, kenvandine: It seems the ghost shadow related to content-hub stuff is fixed in https://trello.com/c/qikMnVBM/2215-215-ubuntu-landing-017-qtmir-qtmir-gles-mzanetti and approved by QA :)16:21
kenvandinenik90, yup16:21
ahayzen\o/16:21
balloonspopey, can all those reboot branches be merged if they pass jenkins?17:07
balloonsthere's like 4 of them. IF you want / need them merged before the switch, I can manually do it. If you can wait, it'll just happen17:08
popeyballoons: they'll need review.17:08
balloonsok, so I'll let them be17:08
ahoneybunrpadovani: ping17:46
anna__hello there, I am having trouble with Linitan on all my Ubuntu pbuilders up and including to Vivid17:54
anna__It says: Skipping dist/deb_dist/nuitka_0.5.14~pre9+ds-1_amd64.changes: Can't locate Date/Parse.pm in @INC (you may need to install the Date::Parse module)17:54
anna__It seems though as the package libtimedate-perl is installed17:54
anna__And it was working, sometimes for years, Quantal e.g. also stopped working17:55
anna__with the same error, was there an update across the board that broke lintian through some missing dependency... help appreciated. I am nuitka upstream btw17:56
rpadovaniahoneybun, o/17:58
ahoneybunnot sure if this link will work: https://docs.google.com/document/d/12oQYdl5mFpaJZ4NxRT0D1fZbN2EkwtoIClx5cBZImFY/edit17:58
ahoneybunI'm about half way done17:58
rpadovaniahoneybun, you can't edit the original doc? Anyway, no, it says I don't have the permission... thanks for the help meanwhile :-)17:59
ahoneybunI see it17:59
ahoneybunI'm writing it side by side18:00
ahoneybunrpadovani: you may enter :)18:00
rpadovaniahoneybun, thanks so much :-)18:00
ahoneybunyep18:01
ahoneybunyour english grammar is getting better18:01
ahoneybunyour just confused with past, present and future18:01
rpadovaniI live in a different spacetime, maybe? :-)18:02
ahoneybuntimezone more likely lol18:03
rpadovaniaha18:04
nik90ahayzen: hey, do you mind testing my branch one last time, I am seeing some strange which I swear were working few hours back ;)18:05
nik90ahayzen: once I get your everythign works fine signal, I will merge it18:06
* nik90 grabs dinner quicky18:06
=== javiercrowsoft1 is now known as javiercrowsoft
ahoneybunrpadovani: I'll finish it at some point today lol18:53
ahoneybunif not tomorrow as a I have a long trip18:53
rpadovaniahoneybun, take your time, thanks :-)19:07
ahayzennik90, i think its been merged already :-) but i can still double check things19:13
nik90ahayzen: yeah I just noticed it now..sry. I am reflashing my phone clean to see if everything is okay.19:13
nik90ahayzen: for some reason, I couldnt set a custom sound as the alarm sound. And I kept hitting the bug you had yesterday where you couldn't save an alarm.19:14
ahayzeninteresting19:14
ahayzenanything in the logs ?19:14
nik90ahayzen: although I did notice that indicator-sound just mysteriously died, and the logs showed line103 repeatedly as an error.19:14
nik90I will investigate more19:14
ahayzenmaybe pulse/mh dies or something?19:15
nik90yes could be19:15
nik90but that doesn't explain why I couldn19:15
nik90I couldn't set a custom alarm sound though19:15
nik90anyway I will start testing once the flashing is complete19:15
nik90ahayzen: just noticed that we changed the default alarm tone which only lands in OTA-6. I am preparing a branch right now to be backwards compatible.20:59
ahayzennik90, is that why it freezes ?21:00
nik90ahayzen: I doubt it..since it was freezing previously for the alarm label and not the alarm sound name.21:00
ahayzenah21:01
nik90ahayzen: I am kind of cursing at QML FolderListModel at the moment...it introduces a race condition which causes another sound bug. I am fixing that as well.21:02
ahayzenugh :-/21:02
nik90they don't have any property to indicate that the folderlistmodel has fully loaded21:02
ahayzenhah, more suggestions for them :-)21:02
nik90so the onCompleted() signal is practically useless here and I have to rely on the count property to check if it is more than 0.21:03
ahayzenhaha21:03
nik90Do you guys use a Timer{} anywhere in the music app to wait for the music list to be fully loaded?21:03
ahayzenno but we do for other racy reasons :-)21:04
nik90that's what I am doing at the moment. Waiting for 500ms atm before I do such checks.21:04
nik90Although I want to see how low I can take that number21:04
ahayzenas our models are now ms2 models so they are loaded directly from that21:04
nik90ah ok21:04
ahayzennik90, we have this hacky timer :-) http://bazaar.launchpad.net/~music-app-dev/music-app/refactor/view/head:/app/ui/Playlists.qml#L6421:05
nik90ah ok..21:05
ahayzenbasically if you on a page that is created in a delegate and then that delegate is deleted (due to you reloading the model) it causes the page to freeze, so we have to delay reloads of the model until you've popped back to that page21:06
vthompsonDoes anyone know if it's possible to have an app change orientation with the screen, but when the screen is in landscape, have the app sidestage? I can't seem to get such a thing working.21:14
=== salem_ is now known as _salem
kivivthompson, good question21:18
vthompsonnik90, I don't think allowing the app to both rotate and go into sidestage mode is supported.21:26
vthompsonLooks like the unity8 guys talked about allowing sidestage->landscape mainstage transitions... not sure what the end decision was21:35
vthompsonsorry, sidestage -> portrait mainstage21:35
nik90vthompson: ah ok21:37
nik90We can check with mzanetti on Monday to know about the end decision.21:38
nik90vthompson: does the desktop file still support X-Canonical-SideStage key? That's what I remember seeing in the old clock app desktop file21:38
nik90or is that overridden by the new portrait key we now include21:38
vthompsonnik90, I was using X-Ubuntu-StageHint=SideStage21:39
vthompsonIt seems that the StageHint overrides the orientation21:40
nik90yes that's the one..(i was trying to remember from memory)21:40
nik90oh :/21:40
popeyvthompson: i think the whole sidestage stuff has taken a back seat until we have a tablet on the .. table22:09
vthompsonpopey, while I enjoy your pun. I do have a tablet on my table ;)22:13
popey:)22:14
* popey ensleepens22:15
popeyBon weekend all...22:15
ahayzeno/22:15
nik90o/22:15
=== _salem is now known as salem_
vthompsono/22:21
=== salem_ is now known as _salem
=== chihchun_afk is now known as chihchun

Generated by irclog2html.py 2.7 by Marius Gedminas - find it at mg.pov.lt!