January / 15
Tasks, Notes, Events
> Inspired by http://bulletjournal.com/
> Inspired by http://bulletjournal.com/
Here is a simple quine in Lua:
stop programming and start living start programming on Android but hate Java have no Java skills? It's easy!
Just go to Google Play Market and install QPython on your device. QPython is Python implementation for Android. It is based on Scripting Layer for Android (SL4A), but as for me, it is a bit more comfortable.
After you installed QPython, start it in the usual way by tapping its icon in the menu. Screenshot on the top of this post shows what you should see when QPython just started.
By tapping the big button with Python logo in the center of the screen you can (1) launch any local script or project, (2) get script from QR code (funny brand new way to share and distribute your code).
If you swipe to the left instead of tapping, you will see another (second) main screen of QPython. As for me, it is much more useful and comfortable for developer.
Tools available here:
Next, let's see the console and the editor.
As I said before, there is an ordinary Python console. Many people usually use it to explore objects' properties, consult about syntax and test their ideas. You can type your commands directly and Python interpreter will execute them. You can open additional consoles by tapping the plus button (1) and use drop-down list on the upper left corner to switch between consoles (2). To close the console just tap the close button (3).
Please note, there will be notification in the notification bar unless you explicitly close the console and you always can reach the open console by tapping the notification.
The editor allows you obviously (hello Cap!) enter and modify text. Here you can develop your scripts, save them and execute. The editor supports Python syntax highlighting and shows line numbers (there is no ability to go to the line by number though).
When typing, you can easily control indentation level (which is critical for Python code) using two buttons on the toolbar (1). Next buttons on the toolbar are Save and Save As (2), then goes Run (3), Undo, Search, Recent Files and Settings buttons. Also there are two buttons on the top: Open and New (5).
When saving, don't forget to add
.py estension to the file name since the editor don't do it for you.
That's it for now. Next time we'll try to write a short "helloworld" program and test it using QPython.
Well, after you became a bit more familiar with QPython, let's create our first program in QPython. Obviously, it will be
Start QPython, open editor and enter the following code:
No wonder, it's just similar to any other hello-world program. When executed, it just shows pop-up message on the screen (see screenshot on the top). Anyway, it's a good example of QPython program.
It begins with
import androidhelper — the most useful module in QPython, which encapsulates almost all interface with Android, available in Python. Any script developed in QPython starts with this statement (at least if it claims to communicate with user). Read more about Python library here and import statement here.
By the way, if you're going to make your script compatible with SL4A, you should replace the first line with the following code (and use
androidhelper further in the program):
Ok, next we're creating an object
droid (actually a class), it is necessary to call RPC functions in order to communicate with Android.
And the last line of our code calls such function,
droid.makeToast(), which shows a small pop-up message (a "toast") on the screen.
Well, let's add some more functionality. Let it ask the user name and greet them.
We can display a simple dialog box with the title, prompt, edit field and buttons Ok and Cancel using
dialogGetInput call. Replace the last line of your code and save it as
Well, I think it should return any response, any user reaction. That's why I wrote
response = .... But what does the call actually return? Let's check. Just add
Then save and run it...
Oops! Nothing printed? Don't worry. Just pull notification bar and you will see "QPython Program Output: hello1.py" — tap it!
As you can see,
droid.dialogGetInput() returns a JSON object with three fields. We need only one —
result which contains an actual input from user.
Let's add script's reaction:
Last two lines (1) format the message and (2) show the message to the user in the toast. See Python docs if you still don't know what
Wow! It works! ;)
Now I'm going to add a bit of logic there. Think: what happen if the user clicks Cancel button, or clicks Ok leaving the input field blank?
You can play with the program checking what contains
response variable in every case.
First of all, I want to put text entered by user to a separate variable:
name = response.result. Then I'm going to check it, and if it contains any real text, it will be considered as a name and will be used in greeting. Otherwise another message will be shown. Replace fifth line
message = 'Hello, %s!' % response.result with the following code:
First of all, we put user input to the variable
name. Then we check if
name contains anything? In case the user left the line blank and clicked Ok, the return value is empty string
''. In case of Cancel button pressed, the return value is
None. Both are treated as false in if-statement. So, only if
name contans anything meaninful, then-statement is executed and greeting "Hello, ...!" shown. In case of empty input the user will see "Hey! And you're not very polite, %Username%!" message.
Ok, here is the whole program:
Next time we will have closer look to
androidhelper package. Stay tuned! :)
Ну вот, наконец-то появилось нормальное, полноценное, нативное (и бесплатное!) приложение для Инстаграма на BlackBerry 10! iGrann позволяет смотреть ленту, лайкать, оставлять комментарии, искать и, конечно же, постить свои фоточки в Инстаграм.
В отличие от портированной с Андроида версии самого Инстаграма, не глючит. Отсутствуют инстаграмовские родные фильтры (ну и фиг с ними — я ими все равно почти никогда не пользуюсь). Не поддерживается загрузка видео и Instagram Direct. В остальном очень приятное приложение, умеющиее, кроме всего прочего, уведомлять штатным для Блэкберри способом и меняющее картинки в Active Frame (период обновления, как и тему, и некоторые другие параметры можно настроить).
iGrann is the first full native and free client for Instagram™ on BlackBerry 10. It is not just a viewer, it is a fully featured app. You can browse feed, like and comment photos and videos, receive notifications, follow/unfollow people, search users and hashtags and, of course, upload photos!
Instagram Direct, upload videos, apply IG filters are not available in the current version but will be implemented soon. And it's free! :)
Almost any program ask user for file or folder names. Android does not provide file dialog by default. Let's create our own.
It should be simple enough, but it should allow user to browse throuh the file system and select file. Also it should allow user to refuse selection by clicking Cancel button. Our function will take two arguments: text prompt (title) and initial folder to browse:
See here if you don't know how to define functions in Python.
Both parameters have default values — they will be used if you don't indicate an argument when calling the function.
'.' means "current folder".
You will use it as follows:
So, first of all we should list of files in the given directory (folder). There are several ways to do it in Python. We will use function
glob in module glob. This function returns list of paths matching a pattern given. For instance, if you need to get list of all Python files in the current directory, you can get it using
glob('*.py'). We need a list of the whole contents of the directory, so we will use
'*' pattern, which means "any file or folder name".
The item selected by user (folder or filename) will be kept in a variable
d. In case of filename it will be returned, otherwise we will show the directory's contents to the user. Initially we set it from argument
Then we should get the list of items of the directory
d. In order to do it, we join the file pattern
'*' with the directory name before passing it to the function
glob. We can do it using
os.path.join() function (os.path is extremely useful module, and we're going to use other functions from it). By the way, you can always get help on every module, every class, object or function in python. Just ask help(...):
This show you short help message about the function
Help function is the most useful features of Python and probably the most often used in the console.
So, let's check in the console what we are going to do:
Ok, there are three files in the current directory (obviously, you will see another file names). And we are ready now to show them to the user. But I don't really like these
./ at the beginning of each name showed to user. I want to show local file names without any path. Let's cut off them. There is a function split in the module
os.path, which splits a pathname and returns tuple "(head, tail)" where "tail" is everything after the final slash — this "tail" is what we need! So, assuming
fn contains any pathname, we could get the last portion as
os.path.split(fn) (tuples' and lists' index starts with 0, so
x is the second item in a tuple or list).
Stop! We need to cut off each item in our list which was returned by
glob()! And here is one thing I love in Python very much:
flist receives the list of last parts ("tails") of pathnames returned by
glob(). This line equals to the following code but much shorter and expressive:
See more about list comprehensions here.
Ok, even if you didn't understand how it works,
flist variable already contains the list of files and folders ready to display to user. ;)
Just one little thing:
glob() returns folders/files which is inside the certain directory. How a user can go outside? Let's add a "special item", indicating "upper, parent directory". It's a common practice to indicate this special item as two dots:
... Only root directory (
/) has no parent, so we should check before adding:
If you don't know how
insert() works, type in the console:
Now, I propose to move platform-specific code to the separate function. In this case we could port our code to another system much more easily just replacing this function. Let a function
_dialog() draws dialog box itself and shows it to the user. It should take two arguments: title and filelist to show, and return selected item's index in the list. It should return None in case the user clicked "Cancel". So, our
chooseFile() function should call this function this way:
I'll show this functions later. And now we are going to analize what it has returned. First of all, we must check is it
None, or no, and return
None if yes:
Then, in case of not
None value, we should understand what the user selected. Since
selected is just a number, indicating selected position in the list,
flist[selected] gives us the item (filename) itself. Then we are going to get full, absolute path of the selected item. First of all, we're joining it with the current directory name:
os.path.join(d, flist[selected]), then we're using os.path.abspath() function to convert the value to the absolute path. Since
".." as a parent directory as well, we don't worry about this "special case". Finally, this absolute path should become a new value of
d, and if it is not a directory, it should be returned:
d now contains directory (folder) name, we must go back and repeat the whole process. So, I'm wrapping the whole code to "infinite" loop using while True: (it is not actually infinite since there is an "exit" — return operator).
Here is the whole code of our function:
Well, let's talk about user interface. We agreed to move it to the separate function
_dialog(). It must be placed before
chooseFile since it is called from the last. Here is the function:
The code is really simple and self-explaining. The first line after the function's definition and documentation string imports
androidhelper, the next one creates an object
droid (see my previous post if you don't know what is it), then we construct a dialog box with title, scrollable list of selectable items and a cancel button. There can be up to three buttons in a dialog: "positive" (i.e. "Ok"), "negative" ("Cancel") and "neutral". We need only negative button.
Then we show the dialog to the user (
droid.dialogShow()), get response (
resp = droid.dialogGetResponse()) and finally we must dismiss the dialog (
The last portion of the code analizes the response. If the user seleted one of the items in the list, the item's index returned as
'item' element of
rezult dictionary. Otherwise (the user clicked "Cancel"),
resp.result has no
'item' at all. Condition
True if dictionary
resp.result has a key "
False otherwise. In the first case we return the value of
resp.result['item'] — index of selected item in the list, and in the second case we return
None indicating that the user refused selection.
That's it. I understand that it's a bit hard to understand such long code. Believe me, it's hard to explain it as well! :) That's why I provide links to different explanations in Pythons documentation. If you are really new to Python, please read Python Tutorial first of all.
Finally, you can get the whole code of the file chooser here to use in your own programs. To test it just run — it should ask you for the file name. And the selected file name will be shown in the program's output.
Next time I'm going to make this code portable (so, we could use the same module on different platforms with different GUIs). Stay tuned! :)