Archive for the ‘programming’ Category
* KDocker 4.4 Released
Posted on July 17th, 2010 by John. Filed under KDocker, Uncategorized.
I’ve released KDocker 4.4 today. It is mostly bug fixes and clean up. However, there is one major change. The feature to dock when the window decorator close button (the x in the upper corner) is clicked has been removed. This feature was introduced in 4.3 and I really like how it. It gives KDocker a feature that no similar application has. However, I was not able to keep it due to a number of issues it introduced.
The dock when closed feature was implemented via XEmbed. Basically I was creating my own window mimicking the window border of the application’s window. I would then remove the border from the application’s window and embed it into my window. Events would be passed from my window into the embedded window. This should work just fine in theory but it didn’t work out so nicely. Embedding caused five issues. The first four are serious and the last is only an annoyance.
The most serious issue was, it broke drag and drop. This looks to be an issue with X itself because I could recreate the problem using Qt and GTK’s embed support as well as writing the embed calls myself using xlib.
Another issue it caused related to support windows. When the main window was embedded it broke the connection between the main window and it’s support windows. So when docking the main window there were issues docking the applications other windows. This is an issue for applications such as XMMS and the Gimp.
Embedding didn’t get along very well with borderless windows. Applications like Chrome and XMMS draw their own window border in place of using the window manager’s decorations. These applications have special handling for moving when clicking and dragging their border. When they are embedded you end up with one of two situations. You can click and drag the window but only in the container window. So instead of moving the window you just move the window’s contents. The other situation is moving via the border doesn’t work at all. In this case resizing doesn’t work either. Oh, and the minimize, maximize, close buttons might not work either. In both cases you can still move the window using alt+left mouse button but this isn’t ideal.
Focus handling with embedded windows didn’t work correctly between different window managers and possibly different versions of Xorg. Some combinations it was fine. Others focus handling only followed the mouse. There were issues with the embedded window never getting focus or only getting focus when using alt+tab to select the window after it was docked.
The only annoying issue that I was okay with having was when undocking a window the window manager (compiz) would cause it to move a little bit. When undocking the position of the container window is recorded, the embedded window is removed from the container and moved to it’s location. Then the container window is destroyed. Compiz didn’t like placing two windows in the exact same place and kept moving the second window down and right by the size of the decoration and frame. This isn’t a very big issue but I really don’t want to have window manager specific work arounds in the code base.
The decision to remove iconify on close wasn’t taken lightly. It was only due to the large number of issues it created. There is not point in using KDocker if it is only going to make docked applications unusable. I have created a branch for iconify on close so I can hopefully get it working properly.
* Qt Remove Directory and Its Contents
Posted on June 8th, 2010 by John. Filed under programming.
When dealing with directories, Qt has a large number of functions to make manipulating them easy. However, it does not include a way to delete a non-empty directory. This little omission is easily solved.
Following is a recursive function that will delete a directory along with all of it’s contents. This will delete depth first. Meaning it will recurse into sub-directories and only start deleting once the directory has no sub-directories. Changing QDir::DirsFirst to QDir::DirsLast will change this into a breadth first search.
fileutils.h
#ifndef FILEUTILS_H #define FILEUTILS_H #include <QString> class FileUtils { public: static bool removeDir(const QString &dirName); }; #endif // FILEUTILS_H
fileutils.cpp
#include <QDir> #include <QFile> #include <QFileInfo> #include <QFileInfoList> #include "fileutils.h" /*! Delete a directory along with all of its contents. \param dirName Path of directory to remove. \return true on success; false on error. */ bool FileUtils::removeDir(const QString &dirName) { bool result = true; QDir dir(dirName); if (dir.exists(dirName)) { Q_FOREACH(QFileInfo info, dir.entryInfoList(QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::AllDirs | QDir::Files, QDir::DirsFirst)) { if (info.isDir()) { result = removeDir(info.absoluteFilePath()); } else { result = QFile::remove(info.absoluteFilePath()); } if (!result) { return result; } } result = dir.rmdir(dirName); } return result; }
* C++ Derived Classes and Object Destruction
Posted on May 29th, 2010 by John. Filed under programming.
While working on lebookread I realized that the the destructor for my reader classes would never be called. lebook read has a base class (FormatReader) that exports all of the necessary functionality for use by applications using the library. All of the readers are a subclass of FormatReader. The library will find the appropriate reader for the specified ebook create a reader object and return it as a FormatReader pointer.
When you are dealing with a pointer p of type base that points to an object of type derived you need to take special care. To have the destruction of p call the derived and base destructor the base class must have a virtual destructor. Otherwise only the base class’s destructor will be called. This is one of those little things to look out for when dealing with C++.
Here is some example code to demonstrate the above.
main.cpp
#include <iostream> #include "base.h" #include "deriv.h" using namespace std; int main(int argc, char** argv) { cout << "Base *b = new Base();" << endl; cout << "delete b;" << endl; Base *b = new Base(); cout << " --- " << endl; delete b; cout << " --- " << endl; cout << "b destroyed" << endl; cout << endl; cout << "Deriv *d = new Deriv();" << endl; cout << "delete d" << endl; Deriv *d = new Deriv(); cout << " --- " << endl; delete d; cout << " --- " << endl; cout << "d destroyed" << endl; cout << endl; cout << "Base *c = new Deriv();" << endl; cout << "delete c" << endl; Base *c = new Deriv(); cout << " --- " << endl; delete c; cout << " --- " << endl; cout << "c destroyed" << endl; return 0; }
#ifndef BASE_H #define BASE_H class Base { public: ~Base(); }; #endif /* BASE_H */
base.cpp
#include <iostream> #include "base.h" using namespace std; Base::~Base() { cout << "base dest" << endl; }
deriv.h
#ifndef DERIV_H #define DERIV_H #include "base.h" class Deriv : public Base { public: ~Deriv(); }; #endif /* DERIV_H */
deriv.cpp
#include <iostream> #include "deriv.h" using namespace std; Deriv::~Deriv() { cout << "deriv dest" << endl; }
The output of this will be:
$ ./a.out Base *b = new Base(); delete b; --- base dest --- b destroyed Deriv *d = new Deriv(); delete d --- deriv dest base dest --- d destroyed Base *c = new Deriv(); delete c --- base dest --- c destroyed
Notice that when destroying c only the Base’s destructor is called. To fix this and have both Base and Deriv’s destructors called just make Base’s destructor virtual.
#ifndef BASE_H #define BASE_H class Base { public: virtual ~Base(); }; #endif /* BASE_H */
This simple change will cause the output to become:
$ ./a.out Base *b = new Base(); delete b; --- base dest --- b destroyed Deriv *d = new Deriv(); delete d --- deriv dest base dest --- d destroyed Base *c = new Deriv(); delete c --- deriv dest base dest --- c destroyed
Now when destroying c the destructor for both Base and Deriv are called.
To compile
$ g++ base.cpp deriv.cpp main.cpp* lebookread
Posted on May 16th, 2010 by John. Filed under lebookread, programming.
I have been taking a short break from blogging again. The pressure at work has only increased and is eating into a lot of my time. I haven’t been motivated to work on personal projects because well they are work. However, this has recently changed a bit.
I’ve started a Qt based library for reading ebooks in a generic manner. It is called lebookread! It is it’s early stages. So far I have it supporting epub, palmdoc pdb, ztxt pdb, tcr, and rb files. I plan to support ereader pdb, mobi, and plucker files in the near future.
The main goal of this project is to make reading ebooks easy for Qt based projects. I’ve chose to write the library in C++. This is also my first attempt at writing a library and it shows. I hope that it will be used by Sigil.
The real motivation of writing lebook read is I really want a good light weight ebook reader. The current offering have issues. I want something that is a bit more advanced in it’s rendering than FBReader. I also didn’t want anything with as large a dependency list as calibre. So, I plan on using lebookread to write my own ebook viewer.
* Long time no see
Posted on March 10th, 2010 by John. Filed under calibre, site maintenance.
It’s been a while since I’ve made any posts. Mainly work and other matters have kept me away. I haven’t been working on very much recently.
This isn’t to say my participation with calibre has been abandoned. I’m still making regular bug fixes. I’ve also been working on a rather large change that is coming along much slower that I would like. Mainly metadata caching and muli way syncing. I was shooting for the end of March to complete the changes but it might not be done until the end of April.
I’ve also moved this blog off of the shared hosting package I was using. It’s now hosted on my own virtual private server. Attachments, images and the now reading list did not make it over in the transition. I’m still using WordPress but instead of having multiple separate installs of it all the blogs here are powered by one WordPress MU installation.
* Calibre Week In Review
Posted on January 10th, 2010 by John. Filed under calibre.
Kovid just tagged the 0.6.33 release so it should be out the door later today. Only one major feature from me this week. The PRS driver can new customize what gets turned into a collection. The default was and is series and tags. Now under the device interface configuration you can specify any metadata field. The main use for this change is so people who have a large number of tags can disable collections being created from them.
While it’s not coming out today I have been working on a major feature. Metadata caching for devices. Basically a file that specifies all of the metadata for the books on the reader will be created. It will be used when the device is connected and if any files have changed their metadata will be updated. This speeds up device detection dramatically. Also, takes up less space than a book so it won’t use too much space to store it. Right now it’s storing the data using json so other application can have easy access to the data too. Other than faster device detection this is the ground work that is required to implement syncing.
* Cybook 2.0 Firmware Calibre Fix
Posted on January 9th, 2010 by John. Filed under calibre.
I’ve committed a fix for the Cybook 2.0 firmware id issue I posted yesterday. In calibre I’ve combined the Gen 3 and Opus device interfaces into one generic Cybook interface. Both were very similar and the Opus was just a subclass of the Gen 3. Also, with the 2.0 firmware being for both the Gen 3 and Opus there should be no difference in the capabilities of the two devices. If you own an Opus you will still want to use the Opus profile however, when you connect the device it will just show as using the Cybook interface. Also, with the interfaces being combined into one, the device specific configuration is now Cybook / Opus.
There were two reasons for combining the interfaces. I was unable to find a way to differentiate the Gen 3 and the Opus with the 2.0 firmware. A Gen 3 with the 2.0 firmware reports itself as an Opus. I was unable to find a way around this and felt it was better to have a Cybook interface. Also, I have the unfortunate pleasure of owning a Gen 3 which, even before the 2.0 firmware, used the same device ids of the Opus. It however did not use the Opus device strings. Due to this I am unable to determine if the 2.0 firmware changes the ids or just the strings. Combining the two interfaces keeps all Gen 3′s working and keeps some Gen 3′s from being detected as the Opus.
* Cybook 2.0 Firmware Identity Issues
Posted on January 7th, 2010 by John. Filed under calibre.
On Christmas eve Bookeen finally released the long awaited 2.0 firmware for the Cybook Gen 3 and Cybook Opus. As soon as I returned from my Christmas vacation I upgraded my Gen 3 to the 2.0 version. Today while debugging a device issue for calibre I noticed that my Gen 3 kept being detected as an Opus. Doing a little digging I found this:
$ calibre-debug -d Version: 0.6.32 USB devices on system: ... ['0xbda', '0x703', '0x110', 'Bookeen', 'Cybook Opus', '600AB038CB09484'], ... Looking for CYBOOKG3 (3034, 1795, 272, 'Bookeen', 'Cybook Opus', '600AB038CB09484') ... Looking for CYBOOK_OPUS (3034, 1795, 272, 'Bookeen', 'Cybook Opus', '600AB038CB09484') ... Devices possibly connected: Cybook Opus Device Interface, Trying to open Cybook Opus Device Interface ... OK Main memory: '/media/Cybook Gen3/' Total space: (495251456L, 0, 0)
It seems Bookeen has once again screwed up the firmware release. They wanted one firmware so now every Gen 3 that has updated now has the product identifier set to Opus. The Gen 3 models use a number of different hex product and vendor ids and only the later ones are the same as the opus. Anyone on Linux or OS X with an earlier Gen 3 who is using the 2.0 (possibly 1.5 but I didn’t test it) firmware will not have their device detected by calibre any longer. This is because once the hex ids are matched there is further matching based on the text ids for Linux and OS X. This isn’t going to be fun to work around.
* Calibre Week In Review
Posted on January 2nd, 2010 by John. Filed under calibre.
There was a major change this week to the device infrastructure. Kovid merged (with some modification) my changes to allow “Send to device” to use custom device paths just like “Save to disk”. Kovid’s major change to my implementation are having a separate save template for “Send to device” and allowing for per device overrides of the template. Kovid and I spent yesterday testing and it is working well. Expect it in the next release. Oh, News and the / tags still work as expected.
I did a little bit of work on TXT and PML output. Now they both honor the “Remove spacing between paragraphs” option. Previously TXT output had TXT specific options for this behavior. I’ve removed them and just use that look and feel option. PML output previously ignored it but now it honors it. So you can have both look more like a printed book than a web page.
* Calibre Week in Review
Posted on December 28th, 2009 by John. Filed under calibre.
I spent a bit of time working on calibre this week. I worked on profiles, devices and a bug fix here and there.
A few new profiles were added. Specifically profiles for the Sony PRS 300 and 900. They have a different screen size and resolution than the 6″ models so they warranted their own profiles.
I added support for two new devices. The Airis Dbook and the Binatone Readme. Along with supporting new devices I also reorganized and renamed a few. The BeBook device interface is not called Hanlin. The BeBook is a rebraned Hanlin. The EZReader, LBook, Eco Reader are also rebranded Hanlins. They all were using the BeBook interface. So I renamed it to be a little more generic and avoid confusion.
One big bug fix this week. There was a typo in the tag map for PML output. It causes italics to be ignore. This has been corrected.
Tags
Archives
- July 2010 (4)
- June 2010 (1)
- May 2010 (2)
- March 2010 (1)
- January 2010 (8)
- December 2009 (5)
- November 2009 (6)
- October 2009 (4)
- September 2009 (2)
- August 2009 (6)
- July 2009 (6)
- June 2009 (4)
- May 2009 (6)
- April 2009 (4)
- March 2009 (2)
- February 2009 (4)
- January 2009 (4)
- December 2008 (7)
- November 2008 (2)