News aggregator

Andrew Savory: Super markets

Planet ALUG - Sat, 25/01/2014 - 11:11

I’ve been using our local Lidl recently, because their policy of regularly baking throughout the day means I can pick up fresh croissants and pains au chocolat whenever I go, whereas the local Tesco, Sainsburys, and Waitrose have usually run out by mid-morning. Are the so-called discount supermarkets really cheaper than the mainstream supermarkets? Here’s the result of one unscientific survey.

This morning I checked my till receipt against Tesco online. There are some items that cost the same regardless of which supermarket (fabric softener, fresh orange juice). There are some items that don’t have direct equivalents across stores, so price comparisons aren’t possible. And there are some items where the price is not significantly different (fresh milk, toilet paper). On today’s basket of comparable items, Lidl was £10.62 cheaper (costing £18.46 instead of £29.08). There are some real eye-openers. Eggs are 1.5x more expensive at Tesco. Fresh vegetables were often almost twice the price at Tesco. And what about my fresh croissants and pains au chocolat? £0.29 and £0.39 at Lidl, vs £0.80 each at Tesco. Over twice the price — on today’s shop, buying just these alone saved me £4.70. And they were fresh from the oven, still warm when I got them home.
Categories: LUG Community Blogs

Alan Pope: January 2014 Core Apps Hack Day One – Reminders and Music

Planet HantsLUG - Fri, 24/01/2014 - 11:58

As David blogged yesterday, we’re having another round of Core Apps Hack Days for our Ubuntu Phone Core Apps

Each day we’re focussing on two apps, today that’s Reminders and Music, but as always we welcome contributions to any app on any day of the week!

In order to get started we’ve come up with some suggestions for new developers.

First off get your development environment setup as documented at http://developer.ubuntu.com/apps/create/get-the-sdk/ which you can do either natively on Ubuntu 13.10 or 14.04 or in a Virtual Machine if you prefer.
If you have a Nexus device, you could either replace the legacy OS with Ubuntu using either of these guides – https://wiki.ubuntu.com/Touch/Install or https://wiki.ubuntu.com/Touch/DualBootInstallation.

Next up take a look at some of these suggestions based on your area of interest and skill level.

We welcome translations for all our Core Apps. If that’s if interest you can find everything you need at https://translations.launchpad.net/reminders-app and https://translations.launchpad.net/music-app.

If you find bugs in the apps you can look for existing bugs to confirm or fix at https://bugs.launchpad.net/reminders-app/+bugs and https://bugs.launchpad.net/music-app/+bugs, or file new bugs at https://bugs.launchpad.net/reminders-app/+filebug and https://bugs.launchpad.net/reminders-app/+filebug

You may find some bugs which have yet to be confirmed or triaged, we’d love your help there too.

You’ll find out-standing merge proposals on launchpad at https://code.launchpad.net/reminders-app/+activereviews and https://code.launchpad.net/music-app/+activereviews.

If you’d like to take on a task then we have some work items in the blueprints which you can assign to yourself and get cracking on at https://blueprints.launchpad.net/ubuntu-phone-commons/+spec/reminders-app-development and https://blueprints.launchpad.net/ubuntu-phone-commons/+spec/coreapps-1404-music-dev

You can find out more about the Core Apps Hack Days at the links at the top, and you’ll find all of us hanging out on #ubuntu-app-devel on freenode.

Categories: LUG Community Blogs

Aq: Saving the current state of your Ubuntu SDK app, with no effort

Planet WolvesLUG - Thu, 23/01/2014 - 19:14

Earlier today I gave an example of how to use U1DB to save the state of your Ubuntu app. Now, U1DB is useful for actually storing actual data, right enough. But if you want to save state — which tab was showing, what was being typed into a text field, what was chosen in a dropdown, where a list was scrolled to — then that’s built right in 1 to the Ubuntu SDK.

It’s called StateSaver.

This isn’t used to store data, long term. It’s used to make your app automatically remember what position things were in. So quitting the app and restarting it, or switching to another and then switching back, means the app doesn’t reset to the front screen, doesn’t forget what you were halfway through typing in, doesn’t forget where you’d scrolled to.

To use it, just add StateSaver.properties to the Item you want to save things for. So, for example, if you want your ListView to remember the position it was scrolled to, do this:

ListView { id: mylistview model: someModel delegate: ListItem.Standard { text: "row " + model.index } StateSaver.properties: "contentY" }

Just that one thing. Now your ListView remembers where it was scrolled to after a restart. You can do the same with a set of Tabs (just add StateSaver.properties: "selectedTabIndex") or a TextField (StateSaver.properties: "text").

NB: this isn’t really for data saving. It might, or might not, be appropriate to use it for whether a switch is flipped or not. That’s a setting; when the switch is changed, you ought to be doing something with that information. Ideally you could drive everything, declaratively, off of whether the switch.checked is true, and if you can do that then StateSaver is the ideal place to have that info. But if you run a function when a switch is changed, then don’t use StateSaver to remember its state: use U1DB, and store the other stuff that changed alongside it. It’s about saving state, hence the name.

Saving the state of your app like this is an idea so good that other ideas gather at its feet to pray. I think that this should be turned on automatically for the “relevant” properties of each type of Ubuntu SDK widget, and if for some reason you don’t like it you can turn it off. Not for every single property, but for the ones where state makes sense: the scroll position for a ListView, the entered text for a TextField, the visible tab for Tabs. Small things like this are what make the difference between great apps and merely good ones. Any one individual app isn’t particularly harmed by not remembering this stuff; so many apps do not, on other platforms, that people are used to the idea of having their state thrown away. But if almost all the apps do do this, then the ones that don’t get called out on it and then it gets fixed, and that makes the whole platform better. It’s really important that we create a culture of desire for finished, polished apps for Ubuntu. If your app throws away where I was scrolled to, I want the developer to feel a bit embarrassed about that and immediately go to fix it. That’s what will make our platform feel consistent, feel tight, feel together, feel fun to use; the culture of pushing back on unfinished and unpolished and half-ready apps. Open source has historically not had that culture, but I’d really like to use a platform which does.

Importantly, though, for it to be reasonable for we users to require this of app developers, it has to not be really hard for app developers to do. This, taking complicated things and making them easy for app developers to implement, is what the platform is for. And StateSaver is a great example of it; the platform provides! I’m really impressed that this exists and is part of the SDK. (I’d be even more impressed if it did it automatically, as noted.) Good work, Ubuntu SDK team. This stuff needs more publicity!

Longer code example, which remembers which tab you were looking at, where the list is scrolled to, and what was typed in the text field:

import QtQuick 2.0 import Ubuntu.Components 0.1 import Ubuntu.Components.ListItems 0.1 as ListItem MainView { id: root width: units.gu(40) height: units.gu(70) Tabs { id: tabs StateSaver.properties: "selectedTabIndex" Tab { id: t1 title: "StateSaver, 1" page: Page { id: pg ListView { id: lv model: 40 clip: true anchors.fill: parent StateSaver.properties: "contentY" delegate: ListItem.Standard { text: "This is row " + model.index + ". Scroll to wherever." } } } } Tab { id: t2 title: "StateSaver, 2" Column { width: parent.width id: col2 spacing: units.gu(1) anchors.centerIn: parent Label { text: "Enter your favourite pie" horizontalAlignment: Text.AlignHCenter anchors.horizontalCenter: parent.horizontalCenter } TextField { id: tf width: parent.width - units.gu(2) StateSaver.properties: "text" anchors.horizontalCenter: parent.horizontalCenter } } } } }

Notes:

  1. how did I not know this existed! Big thanks to Florian for cueing me in
Categories: LUG Community Blogs

Aq: Saving the current state of your Ubuntu SDK app, with no effort

Planet WolvesLUG - Thu, 23/01/2014 - 19:14

Earlier today I gave an example of how to use U1DB to save the state of your Ubuntu app. Now, U1DB is useful for actually storing actual data, right enough. But if you want to save state — which tab was showing, what was being typed into a text field, what was chosen in a dropdown, where a list was scrolled to — then that’s built right in1 to the Ubuntu SDK.

It’s called StateSaver.

This isn’t used to store data, long term. It’s used to make your app automatically remember what position things were in. So quitting the app and restarting it, or switching to another and then switching back, means the app doesn’t reset to the front screen, doesn’t forget what you were halfway through typing in, doesn’t forget where you’d scrolled to.

To use it, just add StateSaver.properties to the Item you want to save things for. So, for example, if you want your ListView to remember the position it was scrolled to, do this:

ListView { id: mylistview model: someModel delegate: ListItem.Standard { text: "row " + model.index } StateSaver.properties: "contentY" }

Just that one thing. Now your ListView remembers where it was scrolled to after a restart. You can do the same with a set of Tabs (just add StateSaver.properties: "selectedTabIndex") or a TextField (StateSaver.properties: "text").

NB: this isn’t really for data saving. It might, or might not, be appropriate to use it for whether a switch is flipped or not. That’s a setting; when the switch is changed, you ought to be doing something with that information. Ideally you could drive everything, declaratively, off of whether the switch.checked is true, and if you can do that then StateSaver is the ideal place to have that info. But if you run a function when a switch is changed, then don’t use StateSaver to remember its state: use U1DB, and store the other stuff that changed alongside it. It’s about saving state, hence the name.

Saving the state of your app like this is an idea so good that other ideas gather at its feet to pray. I think that this should be turned on automatically for the “relevant” properties of each type of Ubuntu SDK widget, and if for some reason you don’t like it you can turn it off. Not for every single property, but for the ones where state makes sense: the scroll position for a ListView, the entered text for a TextField, the visible tab for Tabs. Small things like this are what make the difference between great apps and merely good ones. Any one individual app isn’t particularly harmed by not remembering this stuff; so many apps do not, on other platforms, that people are used to the idea of having their state thrown away. But if almost all the apps do do this, then the ones that don’t get called out on it and then it gets fixed, and that makes the whole platform better. It’s really important that we create a culture of desire for finished, polished apps for Ubuntu. If your app throws away where I was scrolled to, I want the developer to feel a bit embarrassed about that and immediately go to fix it. That’s what will make our platform feel consistent, feel tight, feel together, feel fun to use; the culture of pushing back on unfinished and unpolished and half-ready apps. Open source has historically not had that culture, but I’d really like to use a platform which does.

Importantly, though, for it to be reasonable for we users to require this of app developers, it has to not be really hard for app developers to do. This, taking complicated things and making them easy for app developers to implement, is what the platform is for. And StateSaver is a great example of it; the platform provides! I’m really impressed that this exists and is part of the SDK. (I’d be even more impressed if it did it automatically, as noted.) Good work, Ubuntu SDK team. This stuff needs more publicity!

Longer code example, which remembers which tab you were looking at, where the list is scrolled to, and what was typed in the text field:

import QtQuick 2.0 import Ubuntu.Components 0.1 import Ubuntu.Components.ListItems 0.1 as ListItem MainView { id: root width: units.gu(40) height: units.gu(70) Tabs { id: tabs StateSaver.properties: "selectedTabIndex" Tab { id: t1 title: "StateSaver, 1" page: Page { id: pg ListView { id: lv model: 40 clip: true anchors.fill: parent StateSaver.properties: "contentY" delegate: ListItem.Standard { text: "This is row " + model.index + ". Scroll to wherever." } } } } Tab { id: t2 title: "StateSaver, 2" Column { width: parent.width id: col2 spacing: units.gu(1) anchors.centerIn: parent Label { text: "Enter your favourite pie" horizontalAlignment: Text.AlignHCenter anchors.horizontalCenter: parent.horizontalCenter } TextField { id: tf width: parent.width - units.gu(2) StateSaver.properties: "text" anchors.horizontalCenter: parent.horizontalCenter } } } } }
  1. how did I not know this existed! Big thanks to Florian for cueing me in
Categories: LUG Community Blogs

Aq: Using U1DB in ListViews in Ubuntu SDK apps

Planet WolvesLUG - Thu, 23/01/2014 - 17:24

After explaining how to use U1DB to store simple bits of information in Ubuntu SDK apps, and saying that that caters for 80% of my need for data storage, I should explain the other thing I do, which is to store dynamic data; documents created from user data.

To understand more about how to retrieve data from U1DB through Indexes and Queries, you can read the core U1DB documentation. Its code examples are for the Python implementation, and QML works differently for creating documents (as we’ve seen, QML is declarative; there’s no code to write, you just describe a document and it all works), but indexing and querying documents have the same underlying philosophy regardless of implementation, and the core docs explain what an index is, what a query is, and how they work.

First, a simple code example.

import QtQuick 2.0 import Ubuntu.Components 0.1 import U1db 1.0 as U1db import Ubuntu.Components.ListItems 0.1 as ListItem MainView { width: units.gu(40) height: units.gu(71) /* ---------------------------------------------------- Set up the U1DB database Declare a named document ---------------------------------------------------- */ U1db.Database { id: db; path: "simpleu1dbdemo2.u1db" } U1db.Index { database: db id: by_type /* You have to specify in the index all fields you want to retrieve The query should return the whole document, not just indexed fields https://bugs.launchpad.net/u1db-qt/+bug/1271973 */ expression: ["things.type", "things.placename"] } U1db.Query { id: places index: by_type query: ["*", "*"] } Page { title: "U1DB ListModel" Column { id: col width: parent.width spacing: units.gu(1) Label { width: parent.width text: "Enter a place to add to list" horizontalAlignment: Text.AlignHCenter } Rectangle { id: ta width: parent.width - units.gu(2) color: "white" height: inp.height * 2 anchors.horizontalCenter: parent.horizontalCenter radius: 5 TextInput { id: inp width: parent.width - units.gu(2) anchors.centerIn: parent onAccepted: inp.adddoc() function adddoc() { /* Indexes do not work on top-level fields. So put everything in the document in a dict called "things" so that they're not top-level fields any more. https://bugs.launchpad.net/u1db-qt/+bug/1271972 */ db.putDoc({things: {type: "place", placename: inp.text}}) inp.text = "" } } } Button { text: "Add" width: ta.width anchors.horizontalCenter: parent.horizontalCenter onClicked: inp.adddoc() } } ListView { anchors.top: col.bottom anchors.bottom: parent.bottom width: parent.width model: places clip: true delegate: ListItem.Standard { text: model.contents.placename control: Button { text: "x" width: units.gu(4) onClicked: { /* To delete a document, you currently have to set its contents to empty string. There will be db.delete_doc eventually. https://bugs.launchpad.net/u1db-qt/+bug/1243395 */ db.putDoc("", model.docId); } } } } } }

You type in a place name and say “Add”; it gets added to the list. The list is stored in U1DB, so it persists; close the app and open it again and you still have your place names. Click a place to delete it.

This covers almost all the remaining stuff that I need to do with data storage. There are a few outstanding bugs still with using U1DB from QML, which I’ve annotated in the source above, and at the moment you have to work around those bugs by doing things that you ought not to have to; once they’re fixed, this becomes more intuitive to use.

Categories: LUG Community Blogs

Aq: Using U1DB in ListViews in Ubuntu SDK apps

Planet WolvesLUG - Thu, 23/01/2014 - 17:24

After explaining [how to use U1DB to store simple bits of information in Ubuntu SDK apps][], and saying that that caters for 80% of my need for data storage, I should explain the other thing I do, which is to store dynamic data; documents created from user data.

To understand more about how to retrieve data from U1DB through Indexes and Queries, you can read the core U1DB documentation. Its code examples are for the Python implementation, and QML works differently for creating documents (as we’ve seen, QML is declarative; there’s no code to write, you just describe a document and it all works), but indexing and querying documents have the same underlying philosophy regardless of implementation, and the core docs explain what an index is, what a query is, and how they work.

First, a simple code example.

import QtQuick 2.0 import Ubuntu.Components 0.1 import U1db 1.0 as U1db import Ubuntu.Components.ListItems 0.1 as ListItem MainView { width: units.gu(40) height: units.gu(71) /* ---------------------------------------------------- Set up the U1DB database Declare a named document ---------------------------------------------------- */ U1db.Database { id: db; path: "simpleu1dbdemo2.u1db" } U1db.Index { database: db id: by_type /* You have to specify in the index all fields you want to retrieve The query should return the whole document, not just indexed fields https://bugs.launchpad.net/u1db-qt/+bug/1271973 */ expression: ["things.type", "things.placename"] } U1db.Query { id: places index: by_type query: ["*", "*"] } Page { title: "U1DB ListModel" Column { id: col width: parent.width spacing: units.gu(1) Label { width: parent.width text: "Enter a place to add to list" horizontalAlignment: Text.AlignHCenter } Rectangle { id: ta width: parent.width - units.gu(2) color: "white" height: inp.height * 2 anchors.horizontalCenter: parent.horizontalCenter radius: 5 TextInput { id: inp width: parent.width - units.gu(2) anchors.centerIn: parent onAccepted: inp.adddoc() function adddoc() { /* Indexes do not work on top-level fields. So put everything in the document in a dict called "things" so that they're not top-level fields any more. https://bugs.launchpad.net/u1db-qt/+bug/1271972 */ db.putDoc({things: {type: "place", placename: inp.text}}) inp.text = "" } } } Button { text: "Add" width: ta.width anchors.horizontalCenter: parent.horizontalCenter onClicked: inp.adddoc() } } ListView { anchors.top: col.bottom anchors.bottom: parent.bottom width: parent.width model: places clip: true delegate: ListItem.Standard { text: model.contents.placename control: Button { text: "x" width: units.gu(4) onClicked: { /* To delete a document, you currently have to set its contents to empty string. There will be db.delete_doc eventually. https://bugs.launchpad.net/u1db-qt/+bug/1243395 */ db.putDoc("", model.docId); } } } } } }

You type in a place name and say “Add”; it gets added to the list. The list is stored in U1DB, so it persists; close the app and open it again and you still have your place names. Click a place to delete it.

This covers almost all the remaining stuff that I need to do with data storage. There are a few outstanding bugs still with using U1DB from QML, which I’ve annotated in the source above, and at the moment you have to work around those bugs by doing things that you ought not to have to; once they’re fixed, this becomes more intuitive to use.

[how to use U1DB to store simple bits of information in Ubuntu SDK apps]: http://kryogenix.org/days/2014/01/23/a-simple-u1db-example-for-ubuntu-sdk-apps

Categories: LUG Community Blogs

Dick Turpin: Definition

Planet WolvesLUG - Thu, 23/01/2014 - 13:01
Email #1 "What is the screen definition of the three laptops you are selling?"

Me: "What do you mean by 'definition'? the screen sizes are two @ 14.1" inches and one @ 15.6" inches."

Email #2 "Not size, definition like 1260x800!"

Me: "Oh you mean 'Resolution' here are the links to the spec sheets."

Email #3 "Precisely"

Aye? I knew I should have become a Gibbon trainer.

Categories: LUG Community Blogs

Aq: A simple U1DB example for Ubuntu SDK apps

Planet WolvesLUG - Thu, 23/01/2014 - 12:42

On Reddit, Aaron Hastings said:

One of the features I’d really like to implement is for the app [a timetable viewer for trains] to save state upon exit. In other words, if a user selected the “Abbey Street” stop, then exited, the app should remember to load Abbey Street on next launch. I’ll have to look into how that’s implemented in Ubuntu.

I’d use U1DB to do that. A simple example:

import QtQuick 2.0 import Ubuntu.Components 0.1 import U1db 1.0 as U1db MainView { width: units.gu(40) height: units.gu(71) /* ---------------------------------------------------- Set up the U1DB database Declare a named document ---------------------------------------------------- */ U1db.Database { id: db; path: "simpleu1dbdemo.u1db" } U1db.Document { id: lastPlace database: db docId: "lastPlace" create: true defaults: { placename: "" } } Page { title: "Simple U1DB demo" Column { width: parent.width spacing: units.gu(1) Label { width: parent.width text: "Enter a place" horizontalAlignment: Text.AlignHCenter } Rectangle { width: parent.width - units.gu(2) color: "white" height: inp.height * 2 anchors.horizontalCenter: parent.horizontalCenter radius: 5 TextInput { id: inp width: parent.width - units.gu(2) anchors.centerIn: parent /* ---------------------------------------------------- Important part number one Retrieve the value from the declared U1DB document ---------------------------------------------------- */ text: lastPlace.contents.placename || "" /* ---------------------------------------------------- Important part number two Save a changed value back to the U1DB document ---------------------------------------------------- */ onTextChanged: lastPlace.contents = {placename: text} } } } } }

This mechanism fulfils about 80% of my data storage needs for Ubuntu SDK apps. You declare a database and a named document; you use the values in that document (documentQMLid.contents.fieldname) declaratively, and to save values, just set documentQMLid.contents.

Of course, you could do this with QML LocalStorage, but do you really want to be constructing SQL statements all day? I don’t. And if you use U1DB now, it keeps the door open for more complicated things later, such as syncing this data between devices, or storing more dynamic data and then querying it, which I should probably write another blog post about if there’s interest.

Categories: LUG Community Blogs

Aq: A simple U1DB example for Ubuntu SDK apps

Planet WolvesLUG - Thu, 23/01/2014 - 12:42

On Reddit, Aaron Hastings said:

One of the features I’d really like to implement is for the app [a timetable viewer for trains] to save state upon exit. In other words, if a user selected the “Abbey Street” stop, then exited, the app should remember to load Abbey Street on next launch. I’ll have to look into how that’s implemented in Ubuntu.

I’d use U1DB to do that. A simple example:

import QtQuick 2.0 import Ubuntu.Components 0.1 import U1db 1.0 as U1db MainView { width: units.gu(40) height: units.gu(71) /* ---------------------------------------------------- Set up the U1DB database Declare a named document ---------------------------------------------------- */ U1db.Database { id: db; path: "simpleu1dbdemo.u1db" } U1db.Document { id: lastPlace database: db docId: "lastPlace" create: true defaults: { placename: "" } } Page { title: "Simple U1DB demo" Column { width: parent.width spacing: units.gu(1) Label { width: parent.width text: "Enter a place" horizontalAlignment: Text.AlignHCenter } Rectangle { width: parent.width - units.gu(2) color: "white" height: inp.height * 2 anchors.horizontalCenter: parent.horizontalCenter radius: 5 TextInput { id: inp width: parent.width - units.gu(2) anchors.centerIn: parent /* ---------------------------------------------------- Important part number one Retrieve the value from the declared U1DB document ---------------------------------------------------- */ text: lastPlace.contents.placename || "" /* ---------------------------------------------------- Important part number two Save a changed value back to the U1DB document ---------------------------------------------------- */ onTextChanged: lastPlace.contents = {placename: text} } } } } }

This mechanism fulfils about 80% of my data storage needs for Ubuntu SDK apps. You declare a database and a named document; you use the values in that document (documentQMLid.contents.fieldname) declaratively, and to save values, just set documentQMLid.contents.

Of course, you could do this with QML LocalStorage, but do you really want to be constructing SQL statements all day? I don’t. And if you use U1DB now, it keeps the door open for more complicated things later, such as syncing this data between devices, or storing more dynamic data and then querying it, which I should probably write another blog post about if there’s interest.

Categories: LUG Community Blogs

Jono Bacon: On Accountability

Planet WolvesLUG - Thu, 23/01/2014 - 02:12

Every so often I see a scenario play out that I find rather disappointing.

It works like this: someone posts a topic to their blog that is critical or controversial. This person can either be a community member, commentator, employee or otherwise; it doesn’t matter who the person is. Then what happens is a series of comments are posted to that blog entry from readers that are critical of the post, thus challenging the author on their views. The author then either deletes the blog entry or disables the comments based on the feedback. In other words, a viewpoint is shared, an invitation for comment is provided, but that invitation is then revoked when the author of the blog post is dissatisfied with the response from their readers.

I have seen this happen countless times over the years and I don’t like this.

I believe we should all be accountable for our words. Our words have the ability to inspire, to entertain, to challenge, but to also hurt. Actions have consequences, and so do words.

As such, when I see someone openly share their thoughts on their blog and invite their readers to provide comments, I see that as a wonderful demonstration of accountability and engagement; debate is a beautiful thing when executed with politeness and respect. To then close that door, seemingly because people disagree with you, is in my mind the equivalent of walking out of a room in the middle of a debate. The excuse when folks are criticized of this behavior is typically “it is my blog and I can run it how I like“.

This is true: it is your blog, and you can run it how you like, but the true measure of a person is not just in what they say, but also in the conversation and discourse that follows.

Now, there are two very important caveats to my view here. Firstly, abusive, threatening, or otherwise offensive content is a perfect candidate for removal and the commentator for banning. We should never tolerate this. Secondly, I can understand the removal of a blog post if there is a legal requirement to do so. In the majority of cases where I have seen posts removed or comments disabled though, it has been for neither of these reasons.

Speaking personally, I have never, ever, switched off comments on my blog posts or deleted posts. Even when the Internet has seemingly come to get me, or when the press pick up on something and are critical, or when I have made a mistake and felt embarrassed at the outcome…I have never switched off comments and never deleted a blog post. This is because I feel I should be and I am accountable for my words.

For me, this is an ethical issue; in the same way I won’t go and re-write or edit a blog post if I get criticism for it (outside of minor grammatical/spelling fixes). My posts are a time-capsule of my thinking at that point in my life. For me to go and edit them would be me re-writing history. A blog is not a regularly updated record of your views (like a book), it is chronological diary of your views and progression as a person. Consequently, my blog is filled with moments from my past that don’t reflect my views, experience, or ideas of today. Some of those posts are even embarrassing. But you know what, those posts stay unchanged, and I am proud that I have never compromised on this accountability.

So with this in mind, I have a simple suggestion for those of you who run blogs: either switch your comments off entirely or always leave them on, but don’t turn them off when you don’t like the reaction from your readers. Polite and respectful debate helps us grow as human beings, helps us evolve our ideas and perspectives, and makes us better people. Let history be our record, not our edited version of history.

Categories: LUG Community Blogs

Mick Morgan: dis-unity

Planet ALUG - Wed, 22/01/2014 - 21:13

The “cloud” is achingly trendy at the moment and new companies offering some-bollocks-as-a-service (SBaaS) keep popping up all over the ‘net. Personally I am extremely unlikely to use any of the services I have seen, I just don’t trust that particular business model.

I checked out the website for one of these companies today following an article I read on El Reg. The company’s website says, in answer to its own question, “what can you do with younity?” that you can:

Spontaneously access any file, from any device, without planning ahead.

Browse all your devices at once.

It further says:

share any file.
ANY FILE STORED ON ANY COMPUTER WITHOUT PLANNING AHEAD, VIA YOUNITY OR PRIVATELY TO FACEBOOK.

(I love that “privately to facebook” bit.)

However, further down it says “Step 1, download younity for Windows or Mac, Step 2, install on iOS”. So, the “any file stored on any computer” claim is just not true if, like me you have a mixture of Linux machines, Android tablet and CyanogenMod ‘phone. I’m pretty sure that claim must breach some advertising standard and I’d complain if I cared about using the product. Fortunately I don’t.

Another “cloud” company making some interesting claims is Backblaze, the company whose blog commentary on consumer grade disks I referenced below. They supposedly offer a service with “unlimited storage”, which “automatically finds files” on your computer and then stores them in the Backblaze cloud with “military-grade encryption”. The website says that “everything except OS files” is backed up, so the system must have the freedom (and permissions) to ferret about on your local disk and then pass the files it finds out to Backblaze’s pods. Forgive me if I don’t like that idea.

The section about encryption is intriguing because it claims:

When you use Backblaze, data encryption is built in. Files scheduled for backup are encrypted on your machine. These encrypted files are then transferred over a secure SSL (https) connection to a Backblaze datacenter where they are stored encrypted on disk. We use a combination of proven industry standard public/private and symmetric encryption methods to accomplish this task. To a Backblaze customer all of this is invisible and automatic. For example, when you create your Backblaze account, we automatically generate your private key that is used to uniquely protect your data throughout our system.

They go on to say:

Upon arriving at a Backblaze datacenter, your data is assigned to one or more Storage Pods where it is stored encrypted. Access to your data is secured by your Backblaze account login information (your email address and password). When you provide these credentials, your private key is used to decrypt your data. At this point you can view your file/folder list and request a restore as desired.

A blog posting by Backblaze’s Tim Nufire gives some detail about how the company encrypts your data. On the face of it, the use of a 2048 RSA public/private key pair in conjunction with ephemeral 128 bit AES symmetric keys (to actually encrypt the data) looks impressive – particularly when the company claims that the private key can be further protected by encryption with a user provided passphrase. But given that the company is US based, that claim bothers me. I am particularly sceptical about any claims that the company is unable to decrypt private data because /they/ generate the public/private key pair and they admit (in the blog post) that they store the private key on their servers. Sorry, but if my data is private enough for me to wish to protect it with strong encryption, then I want to use keys I have generated myself, on a system which I control.

Backblaze’s description of the file restoration process does not give me any warm feeling either. Here is what they say:

When you request a data restore, we do what is known as a cloud restore. This simplifies the data restoration process. For example, let’s assume your hard drive crashes and you get a new hard drive or even a new computer. To restore your data you first log in to Backblaze using a web browser by providing your Backblaze account information (email address and password). Once you have logged in to the Backblaze secure web interface you can request a restore of your data. You do not have to install Backblaze to get your data back. To make this work, we decrypt your data on our secure restore servers and we then zip it and send it over an encrypted SSL connection to your computer. Once it arrives on your computer, you can unzip it and you have your data back.

So if I want my data back, they get a clear text copy of it all before sending it to me. Worse, they even offer to send it to me through the post on a USB disk.

I don’t call that a private recovery system.

Categories: LUG Community Blogs

Aq: Notes on footnotes

Planet WolvesLUG - Wed, 22/01/2014 - 17:53

I use footnotes quite a bit in my posts. Normally for snarky asides, I grant you, but I picked that habit up from Terry Pratchett.

They’re easy to add to WordPress; I use Andrew Nacin’s Simple Footnotes WP plugin, and then all you have to do is drop [ref]footnote text here[/ref] into the text of your post 1 and it takes care of numbering the footnote, displaying it at the bottom of the page, allowing you to link back and forth.

However, as Jake Archibald pointed out on Twitter, footnotes at the bottom of the page feel rather like a print media sort of thing. That’s useful, if someone prints your page out, or if they run it through some sort of “easy reading” service such as Readability or iOS Reader, or if your page gets turned into an ebook — we don’t want to remove that capability. But, as noted, scrolling down to the bottom of the page to read a footnote and then scrolling back up again is stupid. The Simple Footnotes plugin gets half a point for this by making the footnote number (a superscript 1, or whatever) be a link which jumps to the footnote for you, and each footnote has its own “return” link which takes you back to where you were. That’s great on a touch device. If you’ve got a pointer, we have the ability to hover, and this is what tooltips are for, so if we add title="text of the footnote" to the footnote number link, you can see the text of the footnote without having to click and jump around the page at all by just mousing over the number.

Footnotes with a properly-sized hit target

That superscript 1 is a pretty tiny target though, either to click or to hover over. It would be nice if the mouse target were bigger, but we don’t want a bunch of white space around the number. So, a little CSS:

a.simple-footnote { text-decoration: none; position: relative; color: rgba(255,0,0,0.7); /* cater for WP putting too much left spacing in before footnote numbers */ margin-left: -.2em; } a.simple-footnote::after { content: " "; position: absolute; display: inline-block; padding: 1em; margin-left: -1.3em; margin-top: -.3em; border: 1px solid transparent; border-radius: 2px; } a.simple-footnote:hover::after { background: rgba(0,0,0,0.2); border: 1px solid rgba(0,0,0,0.4); }

which I added to Admin > Appearance > Edit CSS in WordPress. Now you get a nice large hit target for your mouse, which lights up when you’re over it, and a tooltip, but your page still contains its footnotes properly when run through Readability or printed (which it might not if you were to use some sort of JavaScript popover library rather than the stuff that’s just built in to the browser and understood by accessibility tools).

Notes:

  1. like this!
Categories: LUG Community Blogs

Aq: Notes on footnotes

Planet WolvesLUG - Wed, 22/01/2014 - 17:53

I use footnotes quite a bit in my posts. Normally for snarky asides, I grant you, but I picked that habit up from Terry Pratchett.

They’re easy to add to Wordpress; I use Andrew Nacin’s Simple Footnotes WP plugin, and then all you have to do is drop [ref]footnote text here[/ref] into the text of your post1 and it takes care of numbering the footnote, displaying it at the bottom of the page, allowing you to link back and forth.

However, as Jake Archibald pointed out on Twitter, footnotes at the bottom of the page feel rather like a print media sort of thing. That’s useful, if someone prints your page out, or if they run it through some sort of “easy reading” service such as Readability or iOS Reader, or if your page gets turned into an ebook — we don’t want to remove that capability. But, as noted, scrolling down to the bottom of the page to read a footnote and then scrolling back up again is stupid. The Simple Footnotes plugin gets half a point for this by making the footnote number (a superscript 1, or whatever) be a link which jumps to the footnote for you, and each footnote has its own “return” link which takes you back to where you were. That’s great on a touch device. If you’ve got a pointer, we have the ability to hover, and this is what tooltips are for, so if we add title="text of the footnote" to the footnote number link, you can see the text of the footnote without having to click and jump around the page at all by just mousing over the number.

[caption id=”attachment_2310” align=”aligncenter” width=”250”][]Footnotes with a properly-sized hit target Footnotes with a properly-sized hit target[/caption]

That superscript 1 is a pretty tiny target though, either to click or to hover over. It would be nice if the mouse target were bigger, but we don’t want a bunch of white space around the number. So, a little CSS:

a.simple-footnote { text-decoration: none; position: relative; color: rgba(255,0,0,0.7); /* cater for WP putting too much left spacing in before footnote numbers */ margin-left: -.2em; } a.simple-footnote::after { content: " "; position: absolute; display: inline-block; padding: 1em; margin-left: -1.3em; margin-top: -.3em; border: 1px solid transparent; border-radius: 2px; } a.simple-footnote:hover::after { background: rgba(0,0,0,0.2); border: 1px solid rgba(0,0,0,0.4); }

which I added to Admin > Appearance > Edit CSS in Wordpress. Now you get a nice large hit target for your mouse, which lights up when you’re over it, and a tooltip, but your page still contains its footnotes properly when run through Readability or printed (which it might not if you were to use some sort of JavaScript popover library rather than the stuff that’s just built in to the browser and understood by accessibility tools).

  1. like this!
Categories: LUG Community Blogs

Dick Turpin: Let me guess.

Planet WolvesLUG - Wed, 22/01/2014 - 12:16
Why do people ring without the most basic of information?

Customer: "Hi have you got an internal fan for a Dell Server?"
Me: "Tower or Rackmount?"
Customer: "Rackmount."
Me: "Which model?"
Customer: "Oh, I'll have to come back to you."
Categories: LUG Community Blogs
Syndicate content