Monday, April 11, 2011

TurboGears 2.1 Admin System Plural Name

I really do not like the way TG2.1 Admin System force developer to use plural name. Because in my language we do not use the same grammar. Totally different, so it's a terrible idea to put 's's on every model/table name.

To solve this issue, there are two major area that we need to change. The first one is the genshi template, and the other one is the class that is responsible to parse the model/table REST urls.

Fortunately the issue resides on one class tgext.crud.controller.CrudRestController. There are some methods which use genshi templates located in tgext.admin.templates. So, you might want to copy the templates and make appropriate changes. Done with one area.

Next is to change the way CrudRestController uses the template and perform lookup for the model/table REST urls. The way to change the template is to change the value of @expose decorator.
Another thing to do is to override _lookup method.
Inside, you can see code like the following:
model_name = model_name[:-1]
The code above assumes that the model/table REST url is in plurals. No good. Don't like it at all. Simply remove that particular line of code and we're done.

TurboGears 2.1 Admin System Change Date Format and Other Values

I have been working a lot with TG2.1 Admin System lately. If you have worked with django, you know that there is automatic admin page generation. In TG2.1 this functionality is based on tgext.admin, tgext.crud, and sprox.

For those you already enjoying TG2.1 Admin System, perhaps you realized that the date format in the admin system is fixed to m-d-Y format. What if you want to change the format? Unfortunately the format is hardcoded inside the TableFiller. Its exact location is sprox.fillerbas.TableFiller.
When you checked the source code of that particular class, you will see that the date format is hardcoded in get_value(self, values=None, **kw) method. So, what you need to do is subclass TableFiller and override get_value method.
Now, after changing the date format, then I needed to format some numbers with grouping. So, I added some more logic to check if the data in 'value' is int/float/Decimal and format it properly.

Next step is to understand that TableFiller can be used in CrudRestControllerConfig (tgext.admin.config.CrudRestControllerConfig), under variable 'table_filler_type'. So, write the appropriate code to set TableFiller inside CrudRestControllerConfig.

CrudRestControllerConfig itself can be used in tgext.admin.tgadminconfig.TGAdminConfig / tgext.admin.config.AdminConfig.
So, put the CrudRestControllerConfig inside *AdminConfig, with the appropriate dbfield variable.

AdminConfig itself can be used as config_type parameter for tgext.admin.controller.AdminController.

Now, everything is set and ready to use.

I want to give you a little hint, that AdminController's _lookup method assumes that all your model's REST url is in plural format. If you don't like or need it, you need to do something about it. I will write about this in the next post.

In my opinion, spending time understanding the layer of TG2.1 framework is really worth it. There are many things that already handled by TG2.1 (plus the plugins/extensions), and if there is not enough, simply extend it by subclass the necessary class. The framework is well designed. The only drawback is the lack (I mean really lacking complete, integrated) documentations.

Friday, April 8, 2011

TurboGears 2 Editable Primary Key Field

TG2.1, nice web app framework. I just with it has better documentations. Compare to django, TG2.1 documentations are way behind. But, still it is much more flexible.

I encountered problem that TG2 Admin Page, created with TG Administration System, automatically set the (html) input field of the model's PK to disabled. Sprox assumes that your model's PK is auto-generated.

Some one already reported the issue here
and then created the proper tickets to sprox here

Got a good clue where to check, so after taking a look inside sprox.formbase source code, below is the reason why PK fields are non-editable.
class EditableForm(FormBase):
"..."
def _do_get_disabled_fields(self): fields = self.disable_fields[:]
fields.append(self.provider.get_primary_field(self.entity))
# automatically set PK field disabled return fields

same goes with: class AddRecordForm(FormBase)

I wrote it in here.

Hopefully useful for those who need it.

DOS Error 4

Again, working with old system, 64MB memory, DOS only. Ouch! The OS got corrupted somehow and it was not possible to redirect lpt1 to com1, using c:> mode lpt1=com1.
I had to backup all the data and reinstall the OS. Ouch! Where can I find DOS? Another thing is the bios was way outdated too. No PXE-Boot, no USB boot, no CD-ROM device,and broken floppy disk. Quaduple ouch!

After sometimes, I managed to install DOS and restore the data. It was time to run the application, and all I got was DOS Error 4. :(

To make the long story short, I got some good information from http://www.cms-track.com/Support/webhelp/html/idh_dos_error_4.htm

The solution is:
1. SET CLIPPER=F99 in autoexec.bat
2. In config.sys, put FILES= and BUFFERS=, where
The FILES= must be at least 61. (FILES=61)
The BUFFERS= must be at least 41. (BUFFERS=41)

No more old system please!!!

Tuesday, April 5, 2011

Qt Designer, Add Toolbar

Taken from the official website itfself:
Qt is a cross-platform application and UI framework. Using Qt, you can write web-enabled applications once and deploy them across desktop, mobile and embedded operating systems without rewriting the source code.

Totally awesome! After working a bit with GTK, now it's time for Qt. Of course, the first thing that I work is with the 'Designer'. Now, I really love designing with this tool. Took a bit to adjust with the way to design the UI with it, specially after working with Glade GTK UI Designer. Once, I got used to it, it just felt more natural designing with Designer.

I would like to share how to add toolbar in the Designer. It is not so obvious how to add toolbar, so I hope it is useful.

The way to add a toolbar is by right-clicking on a form, main_window, or what have you, and choose 'add toolbar.'


Right this point, you will not get a functional toolbar, since you only have the container, without any buttons.

Next step is to add resources to the project, using 'Resource Browser'. If you don't have it, you can activate it from the menu bar, under view menu. Then from resource browser, click on the 'Gear' button to open 'Edit Resources' dialog.





Once, you have it opened, add resource file, by click the 'New Resource File' button. Then, click add prefix, and after that add the image files for toolbar icons, by clicking 'Add Files' button.

Now, to add the buttons in the toolbar, simply drag and drop from 'Resource Browser' onto the toolbar, and that is it.

Friday, April 1, 2011

Epson POS TM T81

This is my second pos printer device that I have worked with. The previous one was dot matrix, RS-232, and has no independent power supply adaptor, so it depends on the PC which has that particular of power outlet. Not so good. Terrible, actually.
Epson POS TM T81 is using usb adapter and has its own power supply adapter. So, it is more portable.

The issue is how to communicate with. Previously, I send all the data (with ESC POS commands) directly. The problem with that approach is with the buffer limitation and flow control (handshake). When I send the data too quickly, some data will be discarded when the buffer is full.

After googling for quite a while, I found cups driver for Epson POS TM T88v, tmt-cups-1.2.1.0.tar.gz. Okay, some progress, I thought. I could choose the driver from cups admin and select the ppd provided. The thing is, when I tried to print some document and image, I kept getting error or the document just hang on the document printing queue. Even if I could get the documents printed, it has different font than the default printer font, and did not look good.
I found some error messages in the /var/log/messages, reporting like the following:
"gs[2599]: segfault at 0 ip 00ad346b sp bf9f4860 error 6 in libgs.so.8.71[74c000+46e000]"
Not sure what exactly the problem is, all I know is it failed. I had high hope for this 'official' driver. Back to square one.

So, then back again sending raw ESC/POS commands directly to the printer using lpr -o raw. The problem is again with the handshake, buffer full. Wow, too much work for printing text. The thing is that the communication is done via usb port. Okay, I tried to communicate to the device using pyUSB, but keep getting permission issue. Yeah, I had to manually change the permissions of the /dev/bus/usb/002/... file. Ouch! Another way is by writing udev rules. Again, too much work to be done. Because even if I solved the permission issue, I still have to read the device status. Not good at all. Too much work.

Fortunately, I found very good information from ubuntuforums. This guys solution is simple, which is by adding 'FileDevice Yes' in /etc/cups/cupsd.conf and add printer with Device URI: file:/dev/usblp0 and set it as Local Raw Printer for make and model. Done!

With that configuration, I could write all the ESC/POS command to a (spool) file and send it to cups using lpr. So, simple! No more issue with handhaking.

Next step is for me is to be able to print out image/logo. I could not do it with the official driver, so I have to find some other way. Back to ESC/POS command.
This guy is really nice. In his blog, he explained in detailed about converting image file to monochomre. This could be done by graphic app, but still interesting to know how to do it programmatically. Then from the monochorome image to bitarray and do some matrix transformation and translate it to byte and send those bits to the printer. Yeah... very-very interesting.
I translate his explanation to python code and, after having a bit confusion with calculating the high_byte and low_byte. I figured how to get those values, and everything works beautifully.

Full appreciation to two guys, I mentioned above, who lead me in good direction, and get what I wanted.