BLOG > Zaurus / ARM > 修正了Justreader 2.0k在pdaXrom上的Bug

修正了Justreader 2.0k在pdaXrom上的Bug

Justreader是一款非常棒的电子书阅读软件,它是一个基于QT3的应用程序。在pdaXrom上,不知道是因为QT的兼容问题还是什么别的原因,导致了Justreader有一部分功能不能正常使用。例如,无法设置颜色和控制键等等,给使用上带来了诸多的不便。

幸好Justreader是一个开源软件,我下载了它的源代码,仔细研究,折腾了三天,终于被我修正了这些Bug,并重新编译打包,做了个改进版出来给大家使用。在这个新的版本里(我称之为Justreader 2.0k-fiX版,大写的X表示是针对X环境下使用的改进),还应ccpaging的要求,增加了在进度栏显示翻页时时间的小功能。因为这个家伙,经常全屏看书太投入,结果忘了时间,哈哈。

看看这个fiX版的 改变吧:
  • 修正了无法打开中文文件名的PDB文件的Bug(这个是在网上看来的前人的修正方法,不过那家伙没有编译,我顺便把它改了)
  • 修正了无法设置/保存颜色设定的Bug
  • 修正了无法设置/保存键盘控制设定的Bug
  • 新增了在进度条显示翻页时的时间的功能
下面说说修正的细节。

修正了无法打开中文文件名的PDB文件的Bug

打开StreamPalm*.cpp文件,一共有五个,找到它们的 openFile() 方法,在里面都可以看到有这样一行代码:
C代码:
  1. strncpy(plucker_file, (filepath+"\0").latin1(), (filepath+"\0").length() + 1);

在这里latin1会丢弃UTF-8的中文字符,所以导致了无法打开中文文件名的PDB文件。把这些文件里的openFile方法里的这一句都改成
C代码:
  1. qstrcpy(plucker_file, QTextCodec::codecForName( "UTF-8" )->fromUnicode(filepath));

这样就能解决问题啦。

修正了无法设置/保存颜色设定和键盘控制的Bug


颜色设定的问题比较多,第一是原来根本无法显示颜色选择框。仔细分析代码后,发现Justreader的颜色选择框是使用了自定义的继承了QComboBox的ColorComboBox类。打开ColorComboBox.cpp文件,可以发现这样一段代码:
C代码:
  1. QFont defaultFont = QApplication::font();
  2.     int x = defaultFont.pixelSize();
  3.     setMaximumWidth(x * 8);
  4.     //setFixedSize(64,24);

经过分析,发现是因为QT无法获得默认字体的大小,导致变量x为0,而在下面的程序段,绘制ColorComboBox有时要依靠x来计算大小的(乘法),这就导致了无法画出正常大小的ColorComboBox。
由于Zaurus设备的分辨率是固定的,我们大可在这里设定固定的x的值,我把它设置成了默认字体的大小16。把代码改成这样,颜色选择框就能正常显示了
C代码:
  1. QFont defaultFont = QApplication::font();
  2.     //int x = defaultFont.pixelSize();
  3.     int x = 16;
  4.     setMaximumWidth(x * 8);
  5.     //setFixedSize(64,24);


修改完了不显示颜色选择框的问题,但是发现,即使我们选择了新的颜色,确定后也不会生效。同样,我们设置了新的控制键也不会生效。这两个问题很是怪。开始的时候,我怀疑是保存设定的函数的问题,但后来发现,在SettingsDlg.cpp中的保存设定的函数有保存这些信息的部分。后来想到,为什么通用设之中的信息可以保存,而这两个使用自定义的继承于QComboBox控件的设定的信息就不能保存了呢?问题一定出在这两个控件的代码中。

还是以颜色设定为例,打开ColorComboBox.cpp,看这段代码:
C代码:
  1. ColorComboBox::ColorComboBox(QWidget *parent, const char *name)
  2.     : QComboBox(parent, name)
  3. {
  4.     maxColors = sizeof(colorArray) / sizeof(colorArray[0]);
  5.     colorArray[0] = Qt::black;
  6.     colorArray[1] = Qt::white;
  7.     colorArray[2] = Qt::darkGray;
  8.     colorArray[3] = Qt::gray;
  9.     colorArray[4] = Qt::lightGray;
  10.     colorArray[5] = Qt::red;
  11.     colorArray[6] = Qt::green;
  12.     colorArray[7] = Qt::blue;
  13.     colorArray[8] = Qt::cyan;
  14.     colorArray[9] = Qt::magenta;
  15.     colorArray[10] = Qt::yellow;
  16.     colorArray[11] = Qt::darkRed;
  17.     colorArray[12] = Qt::darkGreen;
  18.     colorArray[13] = Qt::darkBlue;
  19.     colorArray[14] = Qt::darkCyan;
  20.     colorArray[15] = Qt::darkMagenta;
  21.     colorArray[16] = Qt::darkYellow;
  22.  
  23.     QFont defaultFont = QApplication::font();
  24.     //int x = defaultFont.pixelSize();
  25.     int x = 16;
  26.     setMaximumWidth(x * 8);
  27.     //setFixedSize(64,24);
  28.    
  29.     for (int i = 0;i<maxColors;i++)
  30.     {
  31.         QPixmap p(x * 8, x, -1);
  32.         p.fill(colorArray[i]);
  33.         insertItem(p,i);
  34.     }
  35.     connect(this, SIGNAL(activated(int)), this, SLOT(setColor(int)));
  36. }
  37.  
  38. void ColorComboBox::setColor(int i)
  39. {
  40.     color = colorArray[i];
  41. }


看到 connect(this,SIGNAL(activated(int)),this,SLOT(setColor(int))); 这一句了吗?这一句是说明,注册一个事件:当我们选择一个新的颜色时,调用setColor()方法,把我们选择的新的颜色赋予public的属性color。而在保存设置信息时,原来的代码是通过color这个属性来得到新的颜色值的。

经过我的测试,问题就出在这里。不知道为什么,可能是QT的兼容原因,这个事件并未如愿的在系统中注册成功,或者是在实际操作时,即使我们选择了新的颜色,也未能触发这个事件。因此color属性无法得到最新的颜色值,当我们确定保存设置时,通过color属性得到的还是旧的颜色值。

看来使用connect注册事件的方法是行不通了。如果我们不使用connect要如何做work around呢?ColorComboBox是继承于QComboBox的,QCombox有currentItem()这样一个方法可以得到目前的ComboBox中被选中项目的索引。我们可以在保存属性时利用这个方法,得到索引值,然后再通过索引值,查询ColorComboBox中的颜色数组,得到颜色值。

很方便的,我们在ColorComboBox中新增这样的一个方法:
C代码:
  1. QColor ColorComboBox::getColor(int i)
  2. {
  3.     return  colorArray[i];
  4. }

输入索引值,返回QColor类型的颜色值。别忘了,新增方法要到头文件ColorCOmboBox.h中去注册哦。

然后,我们修改SettingsDlg.cpp保存设定的那一段,让它通过我们的这个新方法来取的颜色值。
打开SettingsDlg.cpp,找到SettingsDlg::acceptChanges()方法,这就是保存设定的地方,我以背景色为例来说明如何修改。
找到保存背景色的代码,原来是这样的:
C代码:
  1. config.colors.bgColor = bgColorComboBox->color;

可以看到原来是通过color属性来获得颜色值的,color属性本应该在每次修改颜色时触发事件,通过ColorComboBox的setColor()方法被修改,但是上面我们说到,不知什么原因,事件并未触发,所以color就一直是原来的颜色值,所以就会表现为修改的内容并未生效。
我们这样改写代码,通过当前的索引值(这是由QComboBox继承而来的方法,经测试有效)从我们新增的getColor()方法获取颜色值。
C代码:
  1. //config.colors.bgColor = bgColorComboBox->color;
  2. config.colors.bgColor = bgColorComboBox->getColor(bgColorComboBox->currentItem());

保存其他的颜色设定的代码也同样做类似的修改。

修改完成后,颜色设定不能保存的问题就得到了解决。

键盘控制的问题也是类似,同样是因为connect注册事件实效导致。也作类似的修改就可以解决了,在此就不再赘述。

新增了在进度条显示翻页时的时间的功能

ccpaging是个爱书之人(电子书),否则怎么会提出这样的需求呢,呵呵。这个东西应该也不是很难,在Frame.cpp中找到了绘制ProgressBar的代码。
找到Frame::printPage()方法,在里面有这样一段代码:
C代码:
  1. if (progressBarVisible)
  2. {
  3.     painter->setPen(progressBarTextColor);
  4.     painter->setFont(QFont("helvetica", progressBarHeight, QFont::Bold, FALSE));
  5.     painter->fillRect(0,height - progressBarHeight, width*progressBarPercent / 100, progressBarHeight, progressBarFgColor);
  6.    painter->fillRect(width * progressBarPercent / 100, height -progressBarHeight, width - width * progressBarPercent / 100,progressBarHeight, progressBarBgColor);
  7.     if (progressBarPercentShow)
  8.     {
  9.         painter->drawText(width/2 - 10,height - 1,QString().setNum(progressBarPercent) + "%");
  10.     } else {
  11.         painter->drawText(width/2 - 10,height - 1,QString().setNum(progressBarPage) + " ( "+QString().setNum(progressBarPages)+" )");
  12.     }
  13. }

这就是判断如果打开了显示进度条的开关,则绘制两种形式的进度条(页数或百分比)。我们在其中插入获得时间和显示时间的代码。把这段代码修改成这样:
C代码:
  1. if (progressBarVisible)
  2. {
  3.     //利用tm struct获得系统的时间,精确到秒,并格式化成字符串
  4.     time_t now;
  5.     struct tm *timenow;
  6.     time(&now);
  7.     timenow = localtime(&now);
  8.     timeStr = QString().setNum(1900 + timenow->tm_year) + "-" + QString().setNum(1 + timenow->tm_mon).rightJustify(2,'0') + "-" + QString().setNum(timenow->tm_mday).rightJustify(2,'0') + " " + QString().setNum(timenow->tm_hour).rightJustify(2,'0') + ":" + QString().setNum(timenow->tm_min).rightJustify(2,'0') + ":" + QString().setNum(timenow->tm_sec).rightJustify(2,'0');
  9.     ////
  10.  
  11.     painter->setPen(progressBarTextColor);
  12.     painter->setFont(QFont("helvetica", progressBarHeight, QFont::Bold, FALSE));
  13.     painter->fillRect(0,height - progressBarHeight, width*progressBarPercent / 100, progressBarHeight, progressBarFgColor);
  14.     painter->fillRect(width * progressBarPercent / 100, height - progressBarHeight, width - width * progressBarPercent / 100, progressBarHeight, progressBarBgColor);
  15.     if (progressBarPercentShow)
  16.     {
  17.         //显示的进度值位置前移20pixel
  18.         //painter->drawText(width/2 - 10,height - 1,QString().setNum(progressBarPercent) + "%");
  19.         painter->drawText(width/2 - 30,height - 1,QString().setNum(progressBarPercent) + "%");
  20.         ////
  21.                
  22.     } else {
  23.         //显示的进度值位置前移20pixel
  24.         //painter->drawText(width/2 - 10,height - 1,QString().setNum(progressBarPage) + " ( " + QString().setNum(progressBarPages) + " )");
  25.         painter->drawText(width/2 - 30,height - 1,QString().setNum(progressBarPage) + " ( " + QString().setNum(progressBarPages) + " )");
  26.         ////
  27.     }
  28.         //在右侧显示时间
  29.         painter->drawText(width-140,height - 1, timeStr);
  30.         ////
  31.     }

修改成这样后,记得还要修改头文件Frame.h哦,因为这里我们用到了一个QString类型的变量timeStr,别忘了在头文件里注册一下:)。

全部修改完成后,重新编译,就得到了这个修正版的Justreader 2.0k-fiX啦!



我编译后已经打包了,大家如果需要的话可以在这里下载,直接用软件包安装器或者使用ipkg install 安装就可以使用了:),有什么问题也可以反馈给我哦。



如果您喜欢这篇文章,您可以点击下列链接收藏
Del.icio.us Yahoo书签 365Key网摘 天极网摘 我摘 POCO网摘 YouNote网摘 和讯网摘 博啦网
发布时间 发布于 2007-03-08 22:47:22 | 阅读次数 阅读过2723次 | 分类 Zaurus / ARM | 评论 3条评论