Pogopixels’ Blog http://pogopixels.com/blog Just another WordPress weblog Thu, 17 Mar 2016 13:29:10 +0000 en-US hourly 1 https://wordpress.org/?v=4.7.9 Easy Hanzi 2.1 – Chinese character stroke animations and dictionary http://pogopixels.com/blog/easy-hanzi-21-chinese-character-stroke-animations-and-dictionary/ Wed, 14 Dec 2011 03:43:15 +0000 http://pogopixels.com/blog/?p=178 I’ve just released a new version of Easy Hanzi, the Chinese flashcard application. It features among others a new Chinese-English dictionary, flashcard animations and various other minor new features and improvements. It can be downloaded from there:

Download Easy Hanzi, the Chinese flashcard application

]]>
Greasemonkey script to remove redirections from Google result pages http://pogopixels.com/blog/greasemonkey-script-to-remove-redirections-from-google-result-pages/ http://pogopixels.com/blog/greasemonkey-script-to-remove-redirections-from-google-result-pages/#comments Mon, 12 Dec 2011 14:55:38 +0000 http://pogopixels.com/blog/?p=169 This little Greasemonkey script cleans up Google’s result page by replacing the unnecessary redirections by real links. So long links such as http://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0CDkQFjAA&url=http%3A%2F%2Fwww.wired.com%2F&ei=DhDmTsjsBa3NmQX_861Y&usg=AFQjCNFHgSSEjuDwVNzzn3fXd7YJysmFGQ&sig2=0t1GLYrrHjniRivye-Jb1Q will be replaced by just http://www.wired.com

Why install this script?

– It allows copying a link directly from Google’s result page (otherwise you need to open the link, then copy it in the browser’s bar).

– In some countries, Google can be very slow so not only you have to wait a long time for the search page to load, but you then have to wait for Google to do its redirection. This script makes Google slightly faster by skipping this unnecessary step.

The script can be downloaded there:

Download Google Links Cleanser script

And the source code is below:

// ==UserScript==

// @name          Google Links Cleanser

// @namespace     http://pogopixels.com

// @description   Convert the redirection links in Google's search results to direct links.

// @include       http://*.google.*
// @include       https://*.google.*

// ==/UserScript==

// parseUri 1.2.2
// (c) Steven Levithan <stevenlevithan.com>
// MIT License
function parseUri(a){var b=parseUri.options,c=b.parser[b.strictMode?"strict":"loose"].exec(a),d={},e=14;while(e--)d[b.key[e]]=c[e]||"";d[b.q.name]={};d[b.key[12]].replace(b.q.parser,function(a,c,e){if(c)d[b.q.name][c]=e});return d}parseUri.options={strictMode:false,key:["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],q:{name:"queryKey",parser:/(?:^|&)([^&=]*)=?([^&]*)/g},parser:{strict:/^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,loose:/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/}}

function isMangledLink(url) {
	var parsed = parseUri(url);
	if (url.indexOf("/url?") < 0) return false;
	if (url.indexOf("&url=") < 0) return false;
	return true;
}

parseUri.options.strictMode = true;

// Get all the anchors
var tags = document.getElementsByTagName('a');

for (i = 0; i < tags.length; i++) {
	var tag = tags[i];
	var href = tag.getAttribute("href");
	
	// Remove the onmousedown events used for tracking
	var onmousedownAttribute = tag.getAttribute("onmousedown");
	if (onmousedownAttribute && onmousedownAttribute.indexOf("return rwt") >= 0) tag.removeAttribute("onmousedown");
	
	if (!isMangledLink(href)) continue;	
	
	// Try to extract the real URL
	var parsed = parseUri(href);	
	var realUrl = "";
	var query = parsed.query.split("&");
	for (var j = 0; j < query.length; j++) {
		var items = query[j].split("=");
		if (items[0] == "url") { // We found the real URL
			realUrl = unescape(items[1]);
			break;
		}
	}
	
	if (realUrl == "") continue; // Skip it if we didn't find the real URL
	
	tag.setAttribute("href", realUrl);
}

Update 2012-02-16:

Script has been updated so that full URLs are not required (thanks to anonymous in the comments).

]]>
http://pogopixels.com/blog/greasemonkey-script-to-remove-redirections-from-google-result-pages/feed/ 2
Integrating WordPress into a Kohana application (or any other framework) http://pogopixels.com/blog/integrating-wordpress-into-a-kohana-application-or-any-other-framework/ Fri, 09 Dec 2011 15:45:40 +0000 http://pogopixels.com/blog/?p=160 I recently tried to integrate a WordPress blog into a Kohana application, and it turned out to be relatively easy. The method that follows was implemented with Kohana but the same principles can be applied to any other PHP frameworks.

When integrating WordPress, what you really need most of the time is to style the blog so that it fits within your current website. You usually also want the same header and footer as in the rest of the website.

To do so, the idea is to create some API that will allow WordPress to retrieve the header and footer from your application. Then you use the PHP function file_get_contents to import and display this content.

1. Create an API controller in Kohana

First create a new controller in Kohana that will allow getting the header and footer, and output them as HTML. In my case, I simply created an “API” controller:

class Controller_Api extends Controller {
	
	public function action_header() {
		$view = View::factory('header');
		echo $view->render();
	}	
	
	public function action_footer() {
		$view = View::factory('footer');
		echo $view->render();	
	}

}

Once this is done, you can call “http://yourdomain.com/api/header” to get the header or “http://yourdomain.com/api/footer” to get the footer.

2. Install WordPress

Just install WordPress as you would normally do, in any folder at the root of your website (let’s call it “blog” in this example).

3. Create a new WordPress theme

Go to “/blog/wp-content/themes” and copy and paste the default WordPress theme (twentyeleven for 3.x) into a new folder. Rename the folder to the name of your website.

Then go into WordPress’s admin panel and select your new theme.

4. Load your own header and footer

Now you need to modify the footer and header files of the WordPress theme so that they load your own files. Something like that should work:

header.php:

<?php
$url = "http://yourdomain.com/api/header";
echo file_get_contents($url);
?>

<div class="wrapper-box">
	<div id="blog">

footer.php

<div class="clear"></div>
	</div><!-- #blog -->
		</div><!-- #wrapper-box -->

<?php echo file_get_contents("http://yourdomain.com/api/footer"); ?>

“wrapper-box” is the box where you would normally put the main content in your website. “#blog” will be the div containing WordPress’ content.

So just by doing that you should have a working WordPress blog. The main problem however is that by replacing the header you are going to lose WordPress styling. So the next section will explain how to get it back.

5. Bring back WordPress’s styling

In Kohana, modify the header template to load a style file specific for the blog (maybe disable or enable the style depending on the current URL). Don’t directly link to the theme’s style.css but rather create a new empty file (let’s call it “blog.css”). The best way is to start with an empty file and progressively add to it.

Add back WordPress’s style to “blog.css” by copying and pasting from the original theme’s “style.css”. There are some sections of the CSS file that are safe to copy and paste completely – Menu, Content, Images, Images Border, etc. Usually it’s clear from the name that the style is not going to cause any problem. Avoid the section titled “Global” or “Header” as they may change things site-wide and thus break the header, footer or other elements.

If some CSS rules conflict with your current style, just prefix them with #blog. For example, I changed the “a” styling to the following so that it doesn’t change the links in the header and footer:

#blog a {
	color: #1982D1;
	text-decoration: none;
}

#blog a:hover {
	color: #1982D1;
	text-decoration: underline;
}

Your might want to customize the CSS further to either remove some elements or change the margins to make it matches your website.

]]>
New Chinese flashcard application – Easy Hanzi http://pogopixels.com/blog/new-chinese-flashcard-application-easy-hanzi/ Sun, 18 Sep 2011 05:03:01 +0000 http://pogopixels.com/blog/?p=155 I’ve just released my new Chinese flashcard application – Easy Hanzi. The software has most of the features one might expect from a Chinese flashcard application, including a spaced repetition algorithm, support for both simplified and traditional Chinese characters, and it is shipped with a few lists of most common Chinese characters.

It features an easy-to-use interface to create and manage decks of cards. Finally, during practice sessions, the cards are displayed on a large area to make it easier to identify the various character strokes.

It is available at the following URL:

Easy Hanzi, the Chinese flashcard application.

Screenshot of Easy Hanzi, the flashcard application

]]>
How to create a custom model for a QListView in Qt 4 http://pogopixels.com/blog/how-to-create-a-custom-model-for-a-qlistview-in-qt/ http://pogopixels.com/blog/how-to-create-a-custom-model-for-a-qlistview-in-qt/#comments Tue, 02 Aug 2011 05:53:12 +0000 http://pogopixels.com/blog/?p=144 Qt 4 provides a powerful model / view pattern to display custom data in various views – QListView, QTableView, etc. The problem is that the documentation for model/view programming is massive and it’s difficult to find simple examples on how to create custom models, custom views, etc.

So below is a simple example on how to create a custom model for a QListView. The model takes a std::vector of custom objects, and provides all the necessary methods. I’ve only included the minimal code so that you can get something working quickly, but of course the model can be further customized (see QAbstractListModel reference for instance).

EmployeeListModel.h

class EmployeeListModel : public QAbstractListModel {
	
	Q_OBJECT

public:

	explicit EmployeeListModel(const std::vector<Employee*>& employees, QObject* parent = 0);
	int rowCount(const QModelIndex &parent = QModelIndex()) const;
	QVariant data(const QModelIndex &index, int role) const;
	
private:
	
	std::vector<Employee*> employees_;
	
};

EmployeeListModel.cpp

#include "EmployeeListModel.h"

EmployeeListModel::EmployeeListModel(const std::vector<Employee*>& employees, QObject *parent) : QAbstractListModel(parent) {
	employees_ = employees;
}

int EmployeeListModel::rowCount(const QModelIndex& parent) const {
	return employees_.size();
}

QVariant EmployeeListModel::data(const QModelIndex& index, int role) const {
	// Check that the index is valid and within the correct range first:
	if (!index.isValid()) return QVariant();
	if (index.row() >= decks_.size()) return QVariant();
	
	if (role == Qt::DisplayRole) {
		// Only returns something for the roles you support (DisplayRole is a minimum)
		// Here we assume that the "Employee" class has a "lastName" method but of course any string can be returned
		return QVariant(employees_.at(index.row())->lastName());
	} else {
		return QVariant();	
	}
}

Usage:

EmployeeListModel* model = new EmployeeListModel(employees);
ui->employeeListView->setModel(model);
]]>
http://pogopixels.com/blog/how-to-create-a-custom-model-for-a-qlistview-in-qt/feed/ 6
Installing ffmpeg on FreeBSD (or other Unix or Linux distributions) http://pogopixels.com/blog/installing-ffmpeg-on-freebsd-or-other-unix-or-linux-distributions/ Tue, 03 May 2011 07:56:02 +0000 http://pogopixels.com/blog/?p=141 Installing ffmpeg on FreeBSD couldn’t be simpler. Just type the following command:

pkg_add -r ffpmpeg

And that should install ffmpeg along with audio and video codecs and other dependencies.

Most likely, other Linux or Unix-based systems provide similar ways to install ffmpeg but unfortunately this is not well documented.

]]>
Setting up and using the Auth module in Kohana 3.1 http://pogopixels.com/blog/setting-up-and-using-the-auth-module-in-kohana-31/ http://pogopixels.com/blog/setting-up-and-using-the-auth-module-in-kohana-31/#comments Sat, 16 Apr 2011 15:02:00 +0000 http://pogopixels.com/blog/?p=124 The documentation about the Auth module in Kohana 3.1 is severely lacking, and the module has changed sufficiently that existing tutorials and documentations are no longer relevant.

So below is a quick tutorial on how to setup and use the module:

1) Enable the modules

If not done already, enable the needed modules in bootstrap.php. In particular, auth, database and ORM need to be enabled:

<?php
Kohana::modules(array(
    'auth'       => MODPATH.'auth',       // Basic authentication
    // 'cache'      => MODPATH.'cache',      // Caching with multiple backends
    // 'codebench'  => MODPATH.'codebench',  // Benchmarking tool
    'database'   => MODPATH.'database',   // Database access
    // 'image'      => MODPATH.'image',      // Image manipulation
    'orm'        => MODPATH.'orm',        // Object Relationship Mapping
    // 'unittest'   => MODPATH.'unittest',   // Unit testing
    // 'userguide'  => MODPATH.'userguide',  // User guide and API documentation
    ));
?>

2) Setup the database

– Copy the configuration file from modules/database/config/database.php to application/config/database.php
– Open it and set username, password, etc.
– Create the database schema using the SQL file in modules/orm/auth-schema-mysql.sql

You should now have a working database with all the required tables.

3) Setup the Auth module

– Copy the Auth config file from modules\auth\config\auth.php to your config folder in application/config.
– Open this file and change the driver to “ORM” and set a hash key. It can be any random value such as those generated by WordPress.
– Your file should then look like this:

<?php defined('SYSPATH') or die('No direct access allowed.');

return array(

    'driver'       => 'ORM',
    'hash_method'  => 'sha256',
    'hash_key'     => "4b 8?((~FKnpD))>8kb!B |#-uXIO24G3rc:&MG+FR{x;r#Uq4k{Ef@F4E9^-qS!",
    'lifetime'     => 1209600,
    'session_key'  => 'auth_user',

    // Username/password combinations for the Auth File driver
    'users' => array(
        // 'admin' => 'b3154acf3a344170077d11bdb5fff31532f679a1919e716a02',
    ),

);

In order for the Auth module to work, you must also set the cookie salt variable. So add this at the end of your bootstrap.php file:

Cookie::$salt = 'somerandomstring';

4) How to register a user

Once the database and Auth are setup, it is relatively easy to add a user to the database, although there are some pitfalls (see comments below). Here is the minimum code required to add a user:

<?php
$client = ORM::factory('user');
$client->email = "my@email.com";

/* Note that the username cannot contain
   certain characters such as"." or "@".
   If it does "$client->save()" is going
   to crash, and the error message is not
   helpful */
$client->username = "laurent";

/* Auth is going to automatically hash
   the password when saving the user,
   so don't do it manually */
$client->password = "mypa55word";

$client->save();
?>

After saving the user, assign a role to him (see this post comments).

5) Example login

Once this is all done, login a user is straightforwards:

<?php
$r = Auth::instance()->login("laurent", "mypa55word");
?>

You can also check if a user is currently logged in and, if so, retrieve it from the database:

<?php
$loggedIn = Auth::instance()->logged_in();
if ($loggedIn) {
    $user = Auth::instance()->get_user();
} else {
    echo "User is not logged in";
}
?>

For more information, have a look at the Auth Module API documentation.

]]>
http://pogopixels.com/blog/setting-up-and-using-the-auth-module-in-kohana-31/feed/ 7
Using Gettext with the Qt Framework http://pogopixels.com/blog/using-gettext-with-the-qt-framework/ Mon, 14 Jun 2010 19:14:34 +0000 http://pogopixels.com/blog/?p=113 The Qt Framework for some reason doesn’t provide any built-in support for Gettext, the quasi-standard for translating software programs. An alternative is provided, Qt Linguist, however there are several reasons why some may still prefer Gettext:

  • If your application is already partially translated using Gettext it’s much easier to keep on using it rather than converting all your mo/po files to Qt’s format.
  • Another significant advantage of Gettext is that it doesn’t have any dependencies (unlike Qt Linguist which creates a dependency to the Qt Framework) and thus allows creating more portable code.

So for these reasons, I’ve created a small library which parses and manages Gettext catalogues in Qt. The library includes a generic parser and a catalogue manager which can be used in any C++ project. On top of that, a Qt wrapper is provided for easy integration with the Qt framework.

The library can be downloaded from the Google Code project:

Download the Gettext library for the Qt Framework

Setting up and using the library is easy:

#include <QtGettext.h>

QtGettext::instance()->setLocale("cn_TW"); // Set the locale
QtGettext::instance()->setCatalogueName("catalogue"); // Set the name of the mo files
QtGettext::instance()->setCatalogueLocation("Data/Locales"); // Set the catalogue folder

QtGettext is now set to use the file in Data/Locales/cn_TW/catalogue.mo.

Also note that if this file is not available, QtGettext will try to load Data/Locales/cn/catalogue.mo (if available) as an alternative.

To mark a string for translation, simply call:

QtGettext::instance()->getTranslation("Some string to be translated");

Since this is rather long, a _() macro is also provided. It shortens the code to just:

_("Some string to be translated");
]]>
Get the URL of an iPod or HD quality YouTube video http://pogopixels.com/blog/get-the-url-of-a-iphone-or-hd-quality-youtube-video/ http://pogopixels.com/blog/get-the-url-of-a-iphone-or-hd-quality-youtube-video/#comments Thu, 19 Mar 2009 19:19:49 +0000 http://pogopixels.com/blog/?p=101 I’ve described in a previous post how to get the URL of a YouTube video in Flash. However this method only returns the low-resolution quality video at 320×240. Getting the high-res one is easy though – you just need to add a “fmt” parameter to the URL link.

These two values in particular can be interesting:

fmt=22: This is an MP4 video in HD quality. On my tests, the resolution can go up to 1280 x 720.

fmt=18: This is a 480 pixels wide version that can be used in portable devices such as iPods.

In order to use this additional parameter, just add an argument to the constructFLVURL method:

// Set "format" to 22 for the high resolution version, or 18 for the iPod one. Or just
// leave to -1 for the low res version.
private function constructFLVURL (video_id:String, t:String, format:Number = -1):String {
  var str:String = "http://www.youtube.com/get_video.php?";
  str += "video_id=" + video_id;
  str += "&t=" + t;
  if (format >= 0) {
    str += "&fmt=" + format;
  }
  return str;
}
]]>
http://pogopixels.com/blog/get-the-url-of-a-iphone-or-hd-quality-youtube-video/feed/ 1
Delete a file to the recycle bin from C++ http://pogopixels.com/blog/delete-a-file-to-the-recycle-bin-from-cp/ http://pogopixels.com/blog/delete-a-file-to-the-recycle-bin-from-cp/#comments Fri, 14 Nov 2008 21:16:34 +0000 http://pogopixels.com/blog/?p=57 Today, I was looking for a way to delete a file to the recycle bin using C++, but couldn’t find any simple example, so here it is:

SHFILEOPSTRUCT operation;
operation.wFunc = FO_DELETE;
operation.pFrom = "c:\\file\to\delete.txt";
operation.fFlags = FOF_ALLOWUNDO;

SHFileOperation(&operation);
]]>
http://pogopixels.com/blog/delete-a-file-to-the-recycle-bin-from-cp/feed/ 1