[yc]为qterm-0.4.0增加彩色存盘功能

本文介绍如何为qterm增加彩色存盘功能,通过修改源代码实现从菜单、右键菜单或工具栏按钮调用,并修复了python模块中的bug。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

附qterm-0.4.0源代码和补丁:
源代码:
http://www.newsmth.net/att.php?p.69.206347.6850.bz2
补丁:
http://www.newsmth.net/att.php?s.69.206347.2253.patch

    使用方法:
    下载qterm-0.4.0源代码。解压。下载补丁qterm-0.4.0-copy_colorful_article.patch,放在源代码同一个目录下。
    tar jxvf qterm- 0.4 . 0 . tar . bz2   
    
cd  qterm- 0.4 . 0 /
    
patch  -p1 <   ../ qterm- 0.4 . 0 -copy_colorful_article . patch
    
./ configure
    make
    make install

    增加的功能:
    1.选择主菜单中的Edit->Copy with color,然后点击右键菜单中的copy article或者点击工具栏中的copy article按钮(右起第7个),会彩色存盘。
    2.修正了qterm提供的python模块"qterm"中的getAttrText方法的一个bug,原来这个方法返回的彩色字符中的控制字符少了一个"[",现在正常了。
    3.在qterm提供的python模块"qterm"中的copyArticle方法中增加了一个bool类型的参数colorful可以指定是否要彩色存盘。如果为True则彩色存盘,否则则为普通存盘。该接口是向下兼容的,如果没有指定colorful的值,默认就是False.测试代码如下:
   
import  qterm
import  sys, time

f
= open( " /home/study/prog/python/qterm/test.txt " , " w " )
lp
= long(sys.argv[0])
f.write(qterm.copyArticle(lp, True))
f.close()


保存为.py文件,然后在qterm主菜单中选择script->run,当前文章就会被彩色保
存到test.txt。
原理:
    QTermTextLine类中有两个方法getText()和getAttrText()分别用来获得普通文本和彩色文本。QTermWindow类中有个属性叫m_bCopyColor,可以根据它的值来决定是普通复制还是彩色复制,即调用getText()还是getAttrText()。
    class QTermTextLine类中的getAttrText声明中,默认控制字符是"/x1b/x1b"而不是"/x1b/x1b/x5b",即少了一个"[".
QCString getAttrText( int index = -1, int len = -1, const QCString& escape="/x1b/x1b" );
    如果直接调用默认参数的getAttrText()就会少一个"["
    由于不同的BBS的控制字符可能不同,所以最保险的办法就是从配置文件里读控制字符。
    此外,我把原代码的改动尽量地减少到最低限度。代码中原来的函数接口都不变(qterm提供的python接口是个例外,但是也是与原来的接口兼容的。)只在代码中根据pWin->m_bCopyColor的值来决定是调用getText还是getAttrText。
    若有其它bug,欢迎广大网友fix它们或者和我联系。


过程如下:
    一开始我想写一个python脚本来实现彩色存盘的功能。好不容易在qterm的源代码中找到qterm模块的文档和测试程序,发现qterm只提供了copyArticle功能。虽然有getAttrText方法,但实现起来会比较麻烦。当时不知道有embeding python这回事,于是满世界找qterm.py,希望能找到copyArticle的python代码,加以参考。结果没找到。后来在诸位大牛们的指点下,发现qterm提供的python模块是embeding的。
实现的代码在qtermpython.cpp中。
//  copy current artcle for back compatible use only
//  for new coder please use getArticle
static  PyObject  * qterm_copyArticle(PyObject  * , PyObject  * args)
{
        
long lp;
        
if (!PyArg_ParseTuple(args, "l"&lp))
                
return NULL;

        QTermWindow 
*pWin=(QTermWindow*)lp;

        QStringList strList;
        QCString cstrArticle;
        
while(1)
        
{
                
// check it there is duplicated string
                
// it starts from the end in the range of one screen height
                
// so this is a non-greedy match                QString strTemp = pWin->stripWhitespace(
                                pWin->m_pBuffer->screen(0)->getText());
                
int i=0;
                
int start=0;
                
for(QStringList::Iterator it=strList.fromLast();
        it
!=strList.begin(), i < pWin->m_pBuffer->line()-1// not exce eeding the last screen
                        --it, i++)
                
{
                        
if(*it!=strTemp)
                                
continue;
                        QStringList::Iterator it2 
= it;
                        
bool dup=true;
                        
// match more to see if its duplicated
                        for(int j=0; j<=i; j++, it2++)
                        
{
                                QString str1 
= pWin->stripWhitespace(
                                        pWin
->m_pBuffer->screen(j)->getText());
                                
if(*it2!=str1)
                                
{
                                        dup 
= false;
                                        
break;
                                }

                        }

                        
if(dup)
                        
{
                                
// set the start point
                                start = i+1;
                                
break;
                        }

                }

                
// add new lines
                for(i=start;i<pWin->m_pBuffer->line()-1;i++)
                        strList
+=pWin->stripWhitespace(
                        pWin
->m_pBuffer->screen(i)->getText());

                
// the end of article
                if( pWin->m_pBuffer->screen(
                pWin
->m_pBuffer->line()-1)->getText().find("%"== -1 )
                        
break;
                
// continue
                pWin->m_pTelnet->write(" "1);

                
if(!pWin->m_wcWaiting.wait(10000))      // timeout
                        break;
        }

        
#if defined(_OS_WIN32_) || defined(Q_OS_WIN32)
        cstrArticle 
= strList.join(" ");
        
#else
        cstrArticle 
= strList.join(" ");
        
#endif

        PyObject 
*py_text = PyString_FromString(cstrArticle);

        Py_INCREF(py_text);
        
return py_text;
}

对比qterm_getText和qterm_getAttrText发现关键在于调用的是pWin->m_pBuffer->screen(i)对象的getText还是getAttrText,前者没有色彩而后者有。而且也没有必要把所有的getText都改成getAttrText。参考一下注释,只有一处地方真正下载,那就是add new line处。改了一下,测试效果良好。
    于是进一步考虑添加菜单功能。毕竟用脚本不方便。
    从Copy Article入手,这个功能的菜单项就是Copy Article,grep一下"Copy Article",发现在qtermframe.cpp和qtermwindow.cpp中都有这个命令项的设置,看到了QT中熟悉的SLOT宏。于是找到与它相关联的函数是QTermWindow::copyArticle()和
QTermFrame::copyArticle()。QTermFrame::copyArticle()是调用QTermWindow::copyArticle()的。而QTermWindow::copyArticle()的代码如下:

void  QTermWindow::copyArticle( )
{
        
if(!m_bConnected)
                
return;

        m_pDAThread 
= new QTermDAThread(this);
        m_pDAThread
->start();

}

可见是新开一个线程去下载文章。
于是寻找QTermDAThread类的代码。
QTermDAThread类有个方法叫run(),这令人联想起Java的线程类。所以关键在这个
函数:
void  QTermDAThread::run()
{
        QStringList strList;
        
while(1)
        
{
                
// check it there is duplicated string
                
// it starts from the end in the range of one screen height
                
// so this is a non-greedy match
                QString strTemp = pWin->stripWhitespace(pWin->m_pBuffer
->screen(0)->getText());
                
int i=0;
                
int start=0;
                
for(QStringList::Iterator it=strList.fromLast();
                        it
!=strList.begin(), i < pWin->m_pBuffer->line(
)
-1// not exceeeding the last screen
                        --it, i++)
                
{
                        
if(*it!=strTemp)
                                
continue;
                        QStringList::Iterator it2 
= it;
                        
bool dup=true;
                        
// match more to see if its duplicated
                        for(int j=0; j<=i; j++, it2++)
                        
{
                                QString str1 
= pWin->stripWhitespace(
                                                                pWin
->m
_pBuffer
->screen(j)->getText());
                                
if(*it2!=str1)
                                
{
                                        dup 
= false;
                                        
break;
                                }

                        }

                        
if(dup)
                        
{
                                
// set the start point
                                start = i+1;
                                
break;
                        }

                }

                
// add new lines
                for(i=start;i<pWin->m_pBuffer->line()-1;i++)
                                strList
+=pWin->stripWhitespace(
                                pWin
->m_pBuffer->screen(i)->getText());


                
// the end of article
                if( pWin->m_pBuffer->screen(
                pWin
->m_pBuffer->line()-1)->getText().find("%"== -1 )
                        
break;
                
// continue
                pWin->m_pTelnet->write(" "1);

                
if(!pWin->m_wcWaiting.wait(10000))      // timeout
                {
                        postEvent(pWin, 
new QCustomEvent(DAE_TIMEOUT));
                        
break;
                }

        }

        
#if defined(_OS_WIN32_) || defined(Q_OS_WIN32)
        cstrArticle 
= strList.join(" ");
        
#else
        cstrArticle 
= strList.join(" ");
        
#endif
        postEvent(pWin, 
new QCustomEvent(DAE_FINISH));
}


这个函数与python 接口的copyArticle如出一辙。于是只要作类似的修改就行。
为了让QTermDAThread类既能下载普通文件,又能下载彩色文件。我在QTermDAThr
ead类中的run方法中,在add new lines时根据pWin->m_bCopyColor的值来决
定是调用getText还是getAttrText。

    这就是整个修改过程,不需要了解Qterm的架构,不需要了解telnet协议的细节,
只要抓住重点,依样画葫芦就OK了。这也得意于Qterm良好的架构和清晰的源代码风
格。
    改动的代码量其实不大,就二十多行代码:
diff  - uNr qterm - 0.4 . 0 / qterm / docs / script qterm - 0.4 . 0 - copy_colorful_article / qterm / docs / script
---  qterm - 0.4 . 0 / qterm / docs / script     2006 - 07 - 10   15 : 36 : 10.000000000   + 0800
+++  qterm - 0.4 . 0 - copy_colorful_article / qterm / docs / script     2008 - 01 - 07   19 : 57 : 57.000000000   + 0800
@@ 
- 9 , 8   + 9 , 8  @@
         download the current article 
in  given timeout seconds,
         
return  success = 0  when timeout, otherwise  1
     
-      string  copyArticle( long  lp) (obsolete)
-         download the current article
+      string  copyArticle( long  lp,  bool  colorful  =   false ) (obsolete)
+         download the current article, you can use it without setting colorful, and by  default  it  is   false ( in  order to back compatible ), if  colorful  is   true  ,the article  is  colorful. else  ,the article  is  not colorful
 
     
string  getText( long  lp,  int  line)         
         
get  text at line
diff 
- uNr qterm - 0.4 . 0 / qterm / qtermpython.cpp qterm - 0.4 . 0 - copy_colorful_article / qterm / qtermpython.cpp
---  qterm - 0.4 . 0 / qterm / qtermpython.cpp     2006 - 07 - 10   15 : 36 : 13.000000000   + 0800
+++  qterm - 0.4 . 0 - copy_colorful_article / qterm / qtermpython.cpp     2008 - 01 - 07   19 : 56 : 50.000000000   + 0800
@@ 
- 86 , 13   + 86 , 16  @@
 
 
//  copy current artcle for back compatible use only
 
//  for new coder please use getArticle
+ //  you can use it without setting colorful, and by default it is false(in order to back compatible ),if colorful is true ,the article is colorful.else ,the article is not colorful
  static  PyObject  * qterm_copyArticle(PyObject  * , PyObject  * args)
 
{
     
long lp;
-    if (!PyArg_ParseTuple(args, "l"&lp))
+    bool colorful = false;
+    if (!PyArg_ParseTuple(args, "l|b"&lp, &colorful))
         
return NULL;
 
     QTermWindow 
*pWin=(QTermWindow*)lp;
+    QCString escape = pWin->getParsedEscape();
 
     QStringList strList;
     QCString cstrArticle;
@@ 
-133,8 +136,12 @@
         }

         
//  add new lines
          for (i = start;i < pWin -> m_pBuffer -> line() - 1 ;i ++ )
-             strList += pWin -> stripWhitespace(
-             pWin -> m_pBuffer -> screen(i) -> getText());
+              if ( ! colorful)
+                 strList += pWin -> stripWhitespace(
+                 pWin -> m_pBuffer -> screen(i) -> getText());
+              else
+                 strList += pWin -> stripWhitespace(
+                 pWin -> m_pBuffer -> screen(i) -> getAttrText( - 1 - 1 , escape));
 
         
//  the end of article
          if ( pWin -> m_pBuffer -> screen(
@@ 
- 388 , 7   + 395 , 7  @@
     
if  ( ! PyArg_ParseTuple(args,  " li " & lp,  & line))
         
return  NULL;
 
-     QCString cstr  =  ((QTermWindow * )lp) -> m_pBuffer -> screen(line) -> getAttrText();
+     QCString cstr  =  ((QTermWindow * )lp) -> m_pBuffer -> screen(line) -> getAttrText( - 1 - 1 , ((QTermWindow * )lp) -> getParsedEscape());
 
     PyObject 
* py_text  =  PyString_FromString(cstr);
 
diff 
- uNr qterm - 0.4 . 0 / qterm / qtermwindow.cpp qterm - 0.4 . 0 - copy_colorful_article / qterm / qtermwindow.cpp
---  qterm - 0.4 . 0 / qterm / qtermwindow.cpp     2006 - 07 - 10   15 : 36 : 13.000000000   + 0800
+++  qterm - 0.4 . 0 - copy_colorful_article / qterm / qtermwindow.cpp     2008 - 01 - 07   19 : 56 : 38.000000000   + 0800
@@ 
- 91 , 6   + 91 , 7  @@
 
void  QTermDAThread::run()
 
{
     QStringList strList;
+    QCString escape = pWin->getParsedEscape();
     
while(1)
     
{
         
// check it there is duplicated string
@@ -127,8 +128,12 @@
         }

         
// add new lines
         for(i=start;i<pWin->m_pBuffer->line()-1;i++)
-            strList+=pWin->stripWhitespace(
-            pWin->m_pBuffer->screen(i)->getText());
+            if(!pWin->m_bCopyColor)
+                strList+=pWin->stripWhitespace(
+                pWin->m_pBuffer->screen(i)->getText());
+            else
+                strList+=pWin->stripWhitespace(
+                pWin->m_pBuffer->screen(i)->getAttrText(-1-1, escape));
 
         
// the end of article
         if( pWin->m_pBuffer->screen(
@@ 
-2217,4 +2222,8 @@
 
{
     pHttp
->deleteLater();
 }

+QCString QTermWindow::getParsedEscape()
+{
+    return parseString((const char *)m_param.m_strEscape);
+}

 #include 
<qtermwindow.moc>
diff 
-uNr qterm-0.4.0/qterm/qtermwindow.h qterm-0.4.0-copy_colorful_article/qterm/qtermwindow.h
--- qterm-0.4.0/qterm/qtermwindow.h    2006-07-10 15:36:12.000000000 +0800
+++ qterm-0.4.0-copy_colorful_article/qterm/qtermwindow.h    2008-01-07 19:56:34.000000000 +0800
@@ 
-85,6 +85,7 @@
     
void externInput(const QCString&);
     QCString stripWhitespace(
const QCString& cstr);
     
void getHttpHelper(const QString&bool);
+    QCString getParsedEscape();
 
 
protected slots:
     
// from QTermTelnet
diff -uNr qterm-0.4.0/qterm/script/copyColorfulArticle.py qterm-0.4.0-copy_colorful_article/qterm/script/copyColorfulArticle.py
--- qterm-0.4.0/qterm/script/copyColorfulArticle.py    1970-01-01 08:00:00.000000000 +0800
+++ qterm-0.4.0-copy_colorful_article/qterm/script/copyColorfulArticle.py    2008-01-07 19:58:44.000000000 +0800
@@ 
-0,0 +1,7 @@
+import qterm
+import sys, time
+
+f=open("/home/study/prog/python/qterm/test.txt","w")
+lp=long(sys.argv[0])
+f.write(qterm.copyArticle(lp, True))
+f.close()

    最后,感谢adoal,BSD,macaulish,pluskid等网友的指点!



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值