All Stories

Ninayan W.I.P.(15)

  话说前天偶然发现了MacType和Gdipp,觉得这种功能对Ninayan之类偏阅读的应用非常有帮助,于是我在极限论坛上给MacType的作者私下发了个email询问是否可以提供专门的API以便集成此功能。不过到现在也没收到回应,估计是不愿意了。   今天看了一下MacType的安装目录,发现有个MacLoader.exe,而Gdipp的安装目录下也有个loader文件,这时才明白过来,可以通过把可执行文件的完整路径作为命令行参数传递给这loader,那么该可执行文件会被启动运行,并被注入实现字体渲染增强效果。   经过简单的测试,Ninayan在我的XP SP3上使用微软雅黑字体,加上增强字体渲染效果,感觉确实更舒服了!而Gdipp是以GPLv3,最新的版本好像是用LGPL了,一起打包发布应该是木有问题的。我只要另外再写一个小小的启动程序,在安装包中把启动程序作为快捷方式添加到开始菜单和桌面等位置,可以自己调整是否使用增强字体渲染效果,使用什么样的渲染配置等等。   这样一来,似乎Windows上的效果都超过Mac上的了,一直没找到感觉特别好的Mac上的用于大段文字阅读的字体,微软雅黑只适合在Windows上用,而且至少要开了ClearType Tuner才行,有MacType或Gdipp最好。也许是因为我在Mac下用的是CRT的显示器的缘故,不止一个人对我说过那个视频信号转换后损失挺大的,也许用LCD的就要好些了!   今天心情不错,呼呼!

Ninayan W.I.P.(14)

  前面说到内存泄漏的问题。后来通过逐段屏蔽代码,终于找到了最大一处泄漏源。这个办法比较笨,但这次真的有用,主要还是因为程序结构简单,流程也不复杂才能用吧。   程序大体上分为三部分,UI层,数据层,网络通信层。用户在UI层上操作,1、UI层向数据层请求数据,2、数据层根据不同情况直接查询本地数据库或通过网络通信层获取数据,3、网络通信层自己有一个定时轮循的任务,每分钟从远程服务器获取数据,4、有了数据就发送给数据层,5、数据层将数据经过简单处理发送给UI层,6、然后显示,就是这么简单。   我开始主要怀疑UI显示调用的Qt/QML也许MM有问题,于是把最终UI显示的代码屏蔽掉。发现仍然泄漏的情况基本没有变化,说明跟UI显示的关系不大。后来发现Mem Usage的增长是有周期,大概是1分钟1次,那么可以确定是在4和5两步有问题。这时把第5步中代码全部屏蔽掉,果然Mem Usage就不增长了。然后逐步缩小范围,一点点放出代码,最后发现竟然是QSqlQuery查询本地数据库时,select出来的东西需要程序员自己clear掉!内牛满面啊,果然是Qt用得有问题!   今天偶然发现一个叫MacType的东东,可以在Windows下以进程注入的方式给指定进程增强字体渲染效果。跟微软官方的ClearType Tuner是一类东西,不过MacType的选项更丰富。于是我想到,我这个以阅读为主的工具,要是集成这么个美仑美奂的功能,该是多酷啊。在极限论坛翻了一遍帖子,貌似MacType是闭源的,另外有个新生的Gdipp项目,倒是在googlecode上开源了,不过听说它的配置复杂,而且目前不够稳定,尤其是32位系统上。好吧,反正这种功能对我有致命吸引力,一定要集成!

Ninayan W.I.P.(13)

  内存泄漏的问题,调得我心力交瘁,都有点神经衰弱了,甚至有点绝望,唉。以前还真没有过这种强烈的负面情绪出现过。   每次UI刷新,从任务管理器里看Mem Usage都会增加2-3MB,这得有多严重的泄漏啊!可是我自己的代码中new出来的对象都经过跟踪是销毁掉了的。于是又把矛头指向Qt内部,或者是QML中了。   本来怀疑是QML中的实现可能有问题,于是把Qt从4.7.0升级到4.7.1,貌似泄漏得更严重了。所以现在都已经不敢怀疑是Qt有问题了,开始怀疑是没有遵循Qt的用法。有些Qt返回的东西,需要程序员来负责销毁,比如QNetworkAccessManager在调用get或post后返回的QNetworkReply对象,这是多么操蛋的设计啊,指不定就是每次在哪里它自己创建出一堆对象出来要我来销毁我却不知道呢!   从CodeProject上下载了个Visual Leaks Detector,从说明上看,说是在msvc的jit debugger里会自动打印信息到debugging output window里的,可我实际上试了之后,发现屁都没输出一句,难道它是for MFC-based project only的?有可能的,唉!   简直走投无路了。

Ninayan W.I.P.(12)

  本来排除在计划外的事情,今天又去搞了,就是支持Twip4。前一天也折腾过一下,没弄好,这回问了一下Twip4的作者@yegle,他开始说是计算数字签名时用https://api.twitter.com/作为base string就行了。我试了下不行,后来他又说试试T模式吧,有几个客户端是经过实践T模式没问题的。于是一下子就明白过来了。   Twip4有T模式和O模式两种工作模式。T模式是完全的透明转发,Twip基本上不做任何处理,所以要请求oauth token和oauth token secret时原本是向https://api.twitter.com/oauth/access_token请求的,同时也是拿https://api.twitter.com/oauth/access_token作为base string计算数字签名的,在使用T模式的代理时,只要向http://www.myproxy.com/oauth/access_token请求就行了,仍然用https://api.twitter.com/oauth/access_token作为base string计算数字签名,这样就能无障碍获取oauth token和oauth token secret了。至于O模式,我看了下TweetDeck和Mixero的表现,发现它们也并不向O模式Twip请求oauth token和oauth token secret,或者请求了也没结果。所以我就推测其实O模式是没这功能的,O模式自己有consumer key和consumer secret,所以自己有一套oauth token和oauth token secret,但不是给客户端用的,即使客户端用自己有效的oauth token和oauth token secret发送给Twip请求,Twip也会把http header和url parameters里的东西处理一遍,用自己的那套oauth token和oauth token secret计算出来的东西替换掉。所以我想如果用O模式也要让用户可以无障碍认证的话,需要软件自己提供一个透明代理,软件先拿用户名和密码从那透明代理处获取oauth token和oauth token secret,然后在其他发布消息,收取消息时用O模式代理,就可以解决这个问题了。...

Ninayan W.I.P.(11)

  好吧,其实没做什么,本来的计划是先做图片浏览和文章阅读的,可是饭否上的内容实在太单薄了点,呃,这纯粹是借口,于是今天实现了对Twitter的支持。   昨天晚上弄到1点半才基本搞好怎么用xAuth认证获取oauth token和oauth token secret,今天就把twitter的timeline浏览,direct message浏览以及消息发布实现了。这内容比饭否丰富了许多,比如有了3列跟retweet有关的内容。twitter居然没有像饭否那样可以一次请求把foing和foer列表取下来,而只能先获取那些id,再由id去获取其他信息!于是这个功能就还没实现。还有比较影响使用的没实现的功能包括不能看conversation,不支持list,不能用快捷键操作。   不过有点值得欣慰的是,又修正了几处内存泄漏的问题。   今天就不上图了,因为基本上界面上没啥变化。

Ninayan W.I.P.(10)

  脑袋混沌了一天,终于基本上搞定超链接处理的功能了。   最开始是由于我使用的处理流程的关系,选择一个合适的数据结构让我头疼了好久,最后决定使用一个list,每个元素是一个结构体,每个结构体由两部分组织,一部分是URL列表,该列表会按短网址还原后的处理顺序存储URL,另一部分则是对该URL的描述,描述的字段包括当前是否已经完成全部的还原操作,最后一个URL能不能被embed.ly拆成两个新的URL列表,代表视频的html和html5等信息。   中间调试过程也是经历了重重磨难啊!其实也是自己代码写得有问题。一开始我是用一个map来存储url list和附着属性的,指针乱飘,调试得没有信心了,才改成上面描述的那个方案。还是有很多问题,经过层层排查,终于把所有的问题都找出来并解决掉了。甚至以为Qt的signal不能随便emit,会有对象生命周期相关的问题,最后也确认其实是在前面的代码写得有问题,哇哈哈!   明天就看一下怎么把数据库中的已有记录读取出来当历史记录来处理超链接。然后就可以做图片浏览的功能了!图片浏览功能完成后就做Readability的功能,之后再做twitter的支持,这就可以发布第一个版本了!

Ninayan W.I.P.(9)

  根据@zhangh109的建议,修改了一下界面,浏览文章有三种模式,在启动界面现在就只有一个入口Article View,在Article View中再添加切换浏览模式的入口。另外了加个图片浏览的视图,在启动界面中把原来About的入口替换掉了,About则移到原来的Quit按钮处。   URL处理部分今天还是没有搞定,不过思路清晰了很多,估计明天就可以完成总体的框架,到时候图片浏览部分应该就可以很快实现,而文章浏览部分需要把Readability的JavaScript代码移植过来,本来如果可以直接用它的那些JavaScript代码是最好的方案,可是之前我曾尝试过,不知道为什么内嵌的Webkit在装载完页面后,直接运行那个代码是没有作用的。所以干脆也不研究它了,直接移植成C++的,用Qt的接口操作Webkit的DOM树来解决吧。想来这移植工作需要花一些时间吧。   贴两张修改后的截图吧。

Ninayan W.I.P.(8)

  今天在处理超链接的问题,这是最重要的一环。   Ninayan提供给用户的信息分两大类:图片/视频和文章,微博消息只算是附属品。所以从微博消息中得到一个URL后,最终要能正确识别出它是一个图片/视频,还是一篇文章(当然,文章中也可以有图片和视频,但重点是它有文字),对于其他不可识别的类型,比如zip,则忽略。   我设计了如下的处理流程:   1、将URL与embed.ly可处理的类型用正则表达式匹配一下,如果可以匹配上,则用embed.ly处理,不能匹配上,则假设它是个短网址,将其还原成长网址。   2、embed.ly处理后,会返回缩略图和原图(如果是视频,则是一段HTML,可能还会有一段HTML5代码)的URL,假设这URL也是个短网址,也将其还原成长网址。   3、还原成长网址后,与原来的短网址比较,如果两者不相等,则假设该长网址仍然是个短网址,继续还原,如此循环迭代,直到还原失败或两者相等,最后还原的最终长网址与embed.ly可处理的类型用正则表达式匹配一下,如果可以匹配上,则用embed.ly处理。   4、如果第3步最终的长网址不能与embed.ly匹配上,则认为该网址是真正的最终应该由Ninayan处理的网址,可分为前面说的两类,图片/视频和文章。   至于怎么辨别出属于哪一类,我决定采用一个很粗糙的办法,如果前面经过embed.ly处理过的,那么肯定是图片/视频,或者URL最后是以诸如.jpg/.png/.gif等known的图片/视频文件扩展名结尾,那么也是图片/视频,其他的则都划入文章类型。而文章类型其实是个很粗糙的结果,网页是要经过像Readability那样的处理才是最终显示给用户的,而在Readability处理的过程中,可以过滤掉诸如.zip等不支持的文件类型的。   这个方案也只是考虑到了URL在网络交互上的处理过程。还有这处理结果怎么通知本地数据存储模块和UI显示模块,也是个问题。而这个问题涉及到何时通知,通知时采用什么数据结构,以及本地存储时采用什么数据结构。

Ninayan W.I.P.(7)

  添加了个图片本地缓存的功能,结果发现不是很好用。在Windows下实际使用时发现有时候装载本地文件仍然很慢,甚至不如直接从网络上加载的快。在Mac下发现压根就装载不上。初步估计是因为多处同时读写文件时有冲突,需要再仔细看看。   把删除消息,去fav后的响应也添加上了。   另外还有些细节方便的调整,比如所有显示图片的地方都添加了等待动画。   最后发现个奇怪的问题,在Mac下读取Friends列表有问题,json解析失败,这太诡异了。   今天听@shellexy说,用HTML5的话,配合JS/CSS这些东东,可以实现跨iOS/Android/WebOS/Symbian/MeeGo,呃,这也太强大了吧,而且据说Hotot移植到这些平台已经是在计划中了。得好好考察一番这种开发方案了。