root/lang/python/crochet/crochet.py @ 28600

Revision 28600, 26.4 kB (checked in by showyou, 4 years ago)

auto chdir/30char newline/Add time to List(tima)

  • Property svn:executable set to *
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3
4import sys,os,time,re
5import wx
6import wx.lib.ClickableHtmlWindow
7import main_icon
8import urllib
9
10import twitter3
11import simplejson
12import Image
13
14import thread
15import toDate2
16from wx.lib.mixins.listctrl import ListCtrlAutoWidthMixin
17
18import config
19
20"""自動で chdirし,working directory を crochet のあるディレクトリにする"""
21dir = os.path.split(sys.argv[0])[0]
22os.chdir(dir)
23
24
25g_config = {}
26g_config['mycolor'] = wx.Color(240,248,255)
27g_config['listIcon'] = False
28g_config['popup'] = True
29g_config['narrowmsg'] = True
30
31"""自動リサイズするListCtrl"""
32class ListCtrlAutoWidth(wx.ListCtrl, ListCtrlAutoWidthMixin):
33        def __init__(self, parent):
34                wx.ListCtrl.__init__(self,parent,style=wx.LC_REPORT|wx.LC_HRULES|wx.LC_SINGLE_SEL)
35                ListCtrlAutoWidthMixin.__init__(self)
36
37"""タブ振り分けフィルタ"""
38class BranchFilter():
39        def __init__(self,tabName,idFilter,bodyFilter,
40                                        moveFrom,searchBoth,regexEnable,setMark):
41                self.tabName = tabName
42                self.idFilter = idFilter
43                if bodyFilter != "":
44                        if regexEnable == True: #正規表現あり
45                                try:
46                                        self.bodyFilter = re.compile(bodyFilter)
47                                except:
48                                        print "invalid bodyFilter %s" % bodyFilter
49                                        self.bodyFilter = False
50                        else:
51                                self.bodyFilter = bodyFilter
52                else:
53                                self.bodyFilter = False
54                self.bodyF = bodyFilter
55                self.moveFrom = moveFrom
56                self.searchBoth = searchBoth
57                self.regexEnable = regexEnable
58                self.setMark = setMark
59        """ 振り分け処理を行う。
60                適合すれば振り分けタブ名を、失敗すれば空文字列を返す """
61        def doFilter(self,id,body):
62                matchFlag = False
63                if self.idFilter != "" and self.idFilter == id:
64                        print "id hit",self.idFilter
65                        matchFlag = True
66                elif self.bodyFilter:
67                        if self.regexEnable:
68                                if self.bodyFilter.search(body):
69                                        matchFlag = True
70                        else:
71                                if body.find(self.bodyFilter) != -1:
72                                        matchFlag = True
73                if matchFlag == True:
74                        return self.tabName,self.moveFrom,self.setMark
75                return "",False,False
76
77
78"""リスト用画像リスト"""
79class ListImageList(wx.ImageList):
80        def __init__(self):
81                wx.ImageList.__init__(self,16,16)
82        def Add(self,imageUrl):
83                imageData = urllib.urlopen(imageUrl).read()
84                image_pil = Image.open(StringIO(imageData))
85                image_pil.thumbnail((16,16))
86
87                image_wx = wx.EmptyImage(image_pil.size[0],image_pil.size[1])
88                image_wx.SetData(image_pil.convert('RGB').tostring())
89                wx.ImageList.Add(self,image_wx.ConvertToBitmap())
90                return self.GetImageCount()-1
91
92"""wx.ImageListが辞書使えなさそうなので辞書使うためのプロキシクラス"""
93class ImageListProxy():
94        def __init__(self):
95                self.list = {}
96                self.imageList = ListImageList()
97        def GetIndex(self,imageName):
98                if self.list.has_key(imageName):
99                        return self.list[imageName]
100                else:
101                        try:
102                                p=self.imageList.Add(imageName)
103                                self.list[imageName]=p
104                        except:
105                                print "ILP Error"
106                                return -1
107                        return p
108
109"""画像取得用スレッド"""
110class ImageGetFrame(wx.Frame):
111        def __init__(self,url,callbackFunc,result,lock):
112                self.url = url
113                self.func = callbackFunc
114                self.result = result
115                self.lock = lock
116        def start(self):
117                thread.start_new_thread(self.run, ())
118                pass
119        def run(self):
120                #ここに通信処理を書く
121                imagePath =urllib.urlopen(self.url).read()
122                try:
123                        #time.sleep(1)
124                        self.lock.acquire()
125                        self.func(imagePath,self.result)
126
127                except:
128                        print "image read error",
129                finally:
130                        self.lock.release()
131        def __del__(self):
132                pass
133                #print "end ImageGetFrame"
134"""
135twitterにhttpRequestを投げるスレッド
136"""
137class TwDMHttpFrame(wx.Frame):
138        def __init__(self,tw,func,lock):
139                self.tw = tw
140                self.func = func
141                self.lock = lock
142        def start(self):
143                thread.start_new_thread(self.run, ())
144        def run(self):
145                #ここに通信処理を書く
146                self.lock.acquire()
147                try:
148                        a = self.tw.getDM("")
149                        self.func(a)
150                except:
151                        print "Error:TwDMHttpFrame", sys.exc_info()[0]
152                finally:
153                        self.lock.release()
154"""
155twitterにhttpRequestを投げるスレッド
156"""
157class TwReplyHttpFrame(wx.Frame):
158        def __init__(self,tw,func,lock):
159                self.tw = tw
160                self.func = func
161                self.lock = lock
162        def start(self):
163
164                thread.start_new_thread(self.run, ())
165       
166        def run(self):
167                #ここに通信処理を書く
168                self.lock.acquire()     
169                try:
170                        a = self.tw.getReplies("")
171                        self.func(a)
172                except:
173                        print "Error:TwReplyHttpFrame", sys.exc_info()[0]
174                finally:
175                        self.lock.release()
176"""
177twitterにhttpRequestを投げるスレッド
178"""
179class TwHttpFrame(wx.Frame):
180        def __init__(self,tw,func,lock):
181                self.tw = tw
182                self.func = func
183                self.lock = lock
184        def start(self):
185                thread.start_new_thread(self.run, ())
186
187        def run(self):
188                #ここに通信処理を書く
189                self.lock.acquire()
190                try:
191                        a = self.tw.getWithScraping("")
192                        self.func(a)
193                except:
194                        print "Error:TwHttpFrame", sys.exc_info()[0]
195                finally:
196                        self.lock.release()
197        def __del__(self):
198                pass#print "delete HTTP Thread"
199
200
201try:
202        import Growl
203        g_growl = True
204
205except:
206        print "not exist:Growl sdk"
207        g_growl = False
208
209"""
210全てのnotebookpageの基になるページクラス
211"""
212class TmpTwitPage(wx.NotebookPage):
213        def __init__(self, title, parent, threadLock):
214
215                self.dataList = []
216                self.hiddenDataList = []
217                self.tmpDataList = []
218                self.tmpHiddenDataList = []
219                self.count = 0
220                self.selectedRow = 0
221                self.title = title
222                self.owner = parent
223                self.lock = threadLock
224                self.dataListLock = thread.allocate_lock()
225                wx.NotebookPage.__init__(self,parent.getNotebook(),-1)
226                parent.getNotebook().AddPage(self,title)
227                list = self.list = ListCtrlAutoWidth(self)
228                list.Bind(wx.EVT_KEY_DOWN, self.myKeyHandler)
229                list.Bind(wx.EVT_LIST_ITEM_ACTIVATED,self.OnDoubleClick)
230
231                a = self.imageListProxy = ImageListProxy()
232                self.list.AssignImageList( a.imageList, wx.IMAGE_LIST_SMALL)   
233               
234                list.InsertColumn(0," ",1,20)
235                list.InsertColumn(1,u"ユーザ")
236                list.InsertColumn(2,u"発言",width=300)
237                list.InsertColumn(3,u"時刻",width=60);
238                list.Bind(wx.EVT_LIST_ITEM_SELECTED,self.OnTwitListSelect)
239               
240                if g_growl == True:
241                        self.g = parent.g
242                        self.img = parent.img
243        def OnTwitListSelect(self,event):
244                selectedRow = self.selectedRow = event.GetIndex()
245                dataList = self.dataList
246                label = self.owner.userName
247                text = self.owner.messageText
248                twittime = self.owner.twitTime
249                mainText = dataList[selectedRow][2]
250                mainText = mainText.replace("href=\"/","href=\"http://twitter.com/")
251
252                """ 30文字折り返し"""
253                if g_config['narrowmsg']:
254                        tmpTextLen = len(mainText);
255                        tmpText = mainText;
256                        tmpTagRe = re.compile("(<.+?>)")
257                        tmpTagSplit = tmpTagRe.split(tmpText);
258                        mainText = ""
259                        tb = 30
260                        tbc = 0
261                        for s in tmpTagSplit:
262                                tmplen = len(s);
263                                print "s:",s,",",tmplen,",",tbc
264                                if tmpTagRe.match(s) != None:
265                                        mainText += s
266                                        continue
267                                if tbc != 0:
268                                        if  tb <= tbc+tmplen:
269                                                mainText+=s[0:tb-tbc]
270                                                mainText += u"<BR>"
271                                                i = tb-tbc
272                                                tbc = 0
273                                        else:
274                                                mainText+=s
275                                                tbc += tmplen
276                                                continue
277                                else: i=0
278                               
279                                while i<tmplen-tb:
280                                        mainText += s[i:i+tb]
281                                        mainText += u"<BR>"
282                                        i+=tb
283                                if i<tmplen:
284                                        mainText += s[i:tmplen]
285                                        tbc+=tmplen-i;
286                                       
287                print "mainText",mainText
288               
289                text.SetValue(mainText)
290                label.SetLabel(dataList[selectedRow][1])
291                twittime.SetLabel(dataList[selectedRow][3])
292                self.owner.SetImage(dataList[selectedRow][4])
293                #選択したユーザに関する発言の色を変えてみる
294                               
295                user = self.owner.tw.user['user']
296                p = re.compile(dataList[selectedRow][1])
297                for i in range(0,self.list.GetItemCount()):
298                        if p.search(dataList[i][1]):
299                                self.list.SetItemBackgroundColour(i,wx.Color(225,225,225))             
300                        elif p.search(self.dataList[i][2]) :
301                                self.list.SetItemBackgroundColour(i,wx.Color(192,225,225))             
302                        else:
303                                self.list.SetItemBackgroundColour(i,wx.Color(255,255,255))
304
305                        if re.match(user,self.dataList[i][1]):
306                                self.list.SetItemBackgroundColour(i,g_config['mycolor'])
307
308                        if re.search(user,self.dataList[i][2]):
309                                self.list.SetItemBackgroundColour(i,wx.Color(255,153,153))
310
311        def ResetCount(self):
312                self.count = 0
313        # 後で多分実装       
314        def ChangeItemColour(self,index,data,re,color):
315                pass   
316        def OnDoubleClick(self,event):
317                selectedRow = event.GetIndex()
318                user = "@" + self.dataList[selectedRow][1] + ' '
319                self.owner.addUser2Inputbox(user)
320
321        def myKeyHandler(self,evt):
322                print evt.GetKeyCode(),
323                if self.selectedRow != -1:
324                        if evt.GetKeyCode() in [ord('k'),ord('K'),wx.WXK_UP]:
325                                print ('up')
326                                if self.selectedRow > 0:
327                                        self.MoveList(self.selectedRow-1)
328                        if evt.GetKeyCode() in [ord('j'),ord('J'),wx.WXK_DOWN]:
329                                print ('down')
330                                if self.selectedRow < self.list.GetItemCount()-1:
331                                        self.MoveList(self.selectedRow+1)
332                        if evt.GetKeyCode() in [ord('h'),ord('H'),wx.WXK_LEFT]:
333                                print ('left')
334                                leftcol = self.GetPrevItem(self.selectedRow)
335                                if leftcol != -1:
336                                        self.MoveList(leftcol)
337                        if evt.GetKeyCode() in [ord('l'),ord('L'),wx.WXK_RIGHT]:
338                                print ('right')
339                                rightcol = self.GetNextItem(self.selectedRow)
340                                if rightcol != -1:
341                                        self.MoveList(rightcol)
342                        if evt.GetKeyCode() in [ord('s'),ord('S')]:
343                                print("favorite")
344                                id = self.hiddenDataList[self.selectedRow][0]
345                                self.owner.tw.createFavorite(id)
346                                self.owner.SetStatusBar(u"fav登録しました")
347                if evt.GetKeyCode() in [ord('q'), ord('Q')]:
348                        wx.Exit()
349
350        # 今のユーザ名を含む、前の発言を検索
351        def GetPrevItem(self,row):
352                print ('getprevItem')
353
354                userName = self.dataList[row][1]
355                p = re.compile(userName)
356                currentRow = row-1
357                while currentRow >= 0 :
358                        if (p.search(self.dataList[currentRow][1])):
359                                return currentRow
360                        currentRow-=1
361                return -1
362       
363        # 今のユーザ名を含む、後ろの発言を取得
364        def GetNextItem(self,row):
365                print ('getnextItem')
366                userName = self.dataList[row][1]
367                p = re.compile(userName)
368                currentRow = row+1
369                while currentRow < len(self.dataList) :
370                        if (p.search(self.dataList[currentRow][1])):
371                                return currentRow
372                        currentRow+=1
373                return -1
374
375        def MoveList(self,newRow):
376                self.list.Select(self.selectedRow,0)
377                self.list.Select(newRow)
378                self.list.Focus(self.selectedRow)
379        def CallGrowl(self,gtitle,gdescription,img=False):
380                if( img != False ):
381                        self.g.notify(noteType='newTwit',title=gtitle,
382                                        description=gdescription,icon = img,sticky=False)
383                else:
384                        self.g.notify(noteType='newTwit',title=gtitle,
385                                        description=gdescription,sticky=False)
386        def RemoveATag(self,text):
387                regATagBegin = re.compile("<a href=.*?>")
388                text2 = regATagBegin.sub("",text)
389                text3 = text2.replace("</a>","")
390                return text3   
391        def InsertData(self,data,hiddenData):
392                #print ("start insert data")
393                i = self.count
394                #ここでロック
395                self.dataListLock.acquire()
396                self.tmpDataList.insert(i,data)# + self.dataList
397                self.tmpHiddenDataList.insert(i,hiddenData)# + self.hiddenDataList
398                self.dataListLock.release()
399                #ここでアンロック
400                self.count += 1
401
402                #print ("end insert data")
403        #InsertDataで追加されてるかどうか確認して、あればリストに入れる
404        def CheckUpdate(self):
405                self.dataListLock.acquire()
406                if len(self.tmpDataList) < 1 or len(self.tmpHiddenDataList) < 1:
407                        self.dataListLock.release()
408                        return False
409
410                user = self.owner.tw.user['user']
411                i = 0
412                for b in self.tmpDataList:
413       
414                        self.list.InsertStringItem(i,"")
415                        b2 = []
416                        b2.append(b[0])
417                        b2.append(b[1])
418                        b2.append(self.RemoveATag(b[2]))
419                        b2.append(b[3]);
420                        for j in range(4):
421                                self.list.SetStringItem(i,j,b2[j])
422               
423                        if re.match(user,b[1]):
424                                self.list.SetItemBackgroundColour(i,g_config['mycolor'])
425
426                        if re.search(user,b[2]):
427                                self.list.SetItemBackgroundColour(i,wx.Color(255,153,153))
428               
429                        #import time
430                        #time.sleep(1)         
431                        #if 先読み=on
432                        #try:   
433                        """リストに画像入れて割り当てる"""
434                        try:
435                                """ToDo:ここで負荷がかかっているので、
436                                        スレッドに分けるとか64x64のリストとうまく兼用できないのか"""
437                                if(g_config['listIcon']):
438                                        imageIndex = self.imageListProxy.GetIndex(b[4])
439                                        if( imageIndex != -1):self.list.SetStringItem(i,0,"", imageIndex)
440                        except:
441                                print "Error:smallImage"
442
443                        self.owner.GetImageListElement(b[4])
444                        #except:
445                        #       print "Error:GetImageListElement"
446                        #       pass
447                        i += 1
448
449                self.dataList[:0] =self.tmpDataList
450                self.hiddenDataList[:0] = self.tmpHiddenDataList
451                self.tmpDataList = []
452                self.tmpHiddenDataList = []
453                self.dataListLock.release()
454                self.ResetCount()
455                self.list.Refresh()
456                self.selectedRow+=i
457                return True
458"""
459カスタムページ(自分でフィルタリングする)
460"""
461class CustomPage(TmpTwitPage):
462        def __init__(self,title, parent,threadLock):
463                self.dataList = []     
464                TmpTwitPage.__init__(self,title,parent, threadLock)     
465       
466"""
467最近のfriendsの発言一覧を表示するページ
468customPageは上に移った
469"""
470
471class RecentPage(TmpTwitPage):
472        def __init__(self, parent,threadLock,filter):
473                TmpTwitPage.__init__(self,u"最新",parent,threadLock)
474
475                #self.dataList = []
476                #self.hiddenDataList = []
477                self.customPages = {}# フィルタリングページの固まり?
478                self.filter = filter
479
480        def ResetCount(self):
481                TmpTwitPage.ResetCount(self)           
482                for p in self.customPages:
483                        self.customPages[p].ResetCount()
484       
485        def AppendCustomPage(self, customPage,customPageId):
486                self.customPages[customPageId] = customPage
487
488        def Refresh(self):
489                t = TwHttpFrame(self.owner.tw,self.RefreshList,self.lock)
490                t.start()
491                #t.run()
492
493        def RefreshList(self,a):
494                #print "start recent:refreshList"
495                #lockかけた方がいいのかも。。
496                self.ResetCount()
497
498                outString = ""
499                outCount = 0
500                for x in a:
501                        flag = 0
502                        # 重複発言チェック
503                        for d in self.dataList:
504                                if d[2] == x[1]:
505                                        flag = 1
506                                        break
507
508                        for p in self.customPages:
509                                for d in self.customPages[p].dataList:
510                                        if d[2] == x[1]:
511                                                flag = 1
512                                                break
513                                if flag == 1: break
514
515                        if flag == 0 :
516                                dataListElement = []
517                                dataListElement.append("")
518                                dataListElement.append(x[0])
519                                dataListElement.append(x[1])
520                                x2 = toDate2.toDate2(x[2]).strftime("%b %d %H:%M:%S")
521                                dataListElement.append(x2)
522                                dataListElement.append(x[3])
523
524                                hiddenDataListElement = []
525                                hiddenDataListElement.append(x[4])#発言id
526                               
527                                moveFrom = False
528                                for f in self.filter:
529                                        tabName,moveFrom,setMark = f.doFilter(x[0],x[1])
530                                        if tabName != "":
531                                                print "tabHit",tabName,x[1]
532                                                self.customPages[tabName].InsertData(dataListElement,hiddenDataListElement)
533                                                break
534                                #print ("x3-1")
535                                if moveFrom == False:
536                                        self.InsertData(dataListElement,hiddenDataListElement)
537
538                                #print ("x3-2"),       
539                                if g_growl == True:
540                                        outCount += 1
541                                        x[1]= self.RemoveATag(x[1])
542                                        outString += x[0]+" : "+x[1]+"\n"
543
544                user = self.owner.tw.user['user']
545                if g_growl == True and g_config['popup'] and outCount > 0:
546                        if outString.find("@"+user) != -1:
547                                TmpTwitPage.CallGrowl(self,"Recent 新着"+str(outCount)+"件",
548                                        outString,self.img)
549                        else:
550                                TmpTwitPage.CallGrowl(self,"Recent 新着"+str(outCount)+"件",outString)
551
552                #print ("xe"),
553                #print self.owner,
554                #self.owner.SetNowTime2StatusBar()
555                #print ("end recent:refreshlist")
556
557class ReplyPage(TmpTwitPage):
558
559        def __init__(self, parent,threadLock):
560                TmpTwitPage.__init__(self,"Re",parent,threadLock)
561                #self.dataList = []
562                #self.hiddenDataList = []
563       
564        def Refresh(self):
565                t = TwReplyHttpFrame(self.owner.tw,self.RefreshList,self.lock)
566                t.start()
567                       
568        def RefreshList(self,a):
569                #lockかけた方がいいのかも。。
570                self.ResetCount()
571                outCount = 0
572                outString = ""
573                user = self.owner.tw.user['user']
574                for x in a:
575                        flag = 0
576                       
577                        # 重複発言チェック
578                        for d in self.dataList:
579                                if d[2] == x[1]:
580                                        flag = 1
581                                        break
582                        if flag == 0 :
583                                dataListElement = []
584                                dataListElement.append("")
585                                dataListElement.append(x[0])
586                                dataListElement.append(x[1])
587                                #x2 = toDate2.toDate2(x[2]).strftime("%y-%m-%d %H:%M:%S")
588                                x2 = "--"
589
590                                dataListElement.append(x2)
591                                dataListElement.append(x[3])
592
593                                hiddenDataListElement = []
594                                hiddenDataListElement.append(x[4])#発言id
595       
596                                self.InsertData(dataListElement,hiddenDataListElement) 
597
598                                if g_growl == True:
599                                        outCount += 1
600                                        x[1]= self.RemoveATag(x[1])
601                                        outString += x[0]+" : "+x[1]+"\n"
602
603                if g_growl == True and g_config['popup']:
604                        if(outCount > 0):
605                                TmpTwitPage.CallGrowl(self,"Reply 新着"+str(outCount)+"件",
606                                        outString,self.img)
607
608class DMPage(TmpTwitPage):
609
610        def __init__(self, parent,threadLock):
611                TmpTwitPage.__init__(self,"DM",parent,threadLock)
612                dataList = []
613        def Refresh(self):
614                t = TwDMHttpFrame(self.owner.tw,self.RefreshList,self.lock)
615                t.start()
616
617        def RefreshList(self,a):
618                #lockかけた方がいいのかも。。
619                self.ResetCount()
620                user = self.owner.tw.user['user']
621                outCount = 0
622                outString = ""
623                for x in a:
624                        flag = 0
625                       
626                        # 重複発言チェック
627                        for d in self.dataList:
628                                if d[2] == x[1]:
629                                        flag = 1
630                                        break
631                        if flag == 0 :
632                                dataListElement = []
633                                dataListElement.append("")
634                                dataListElement.append(x[0])
635                                dataListElement.append(x[1])
636                                #x2 = toDate2.toDate2(x[2]).strftime("%y-%m-%d %H:%M:%S")
637                                x2 = "--"
638                                dataListElement.append(x2)
639                                dataListElement.append(x[3])
640
641                                hiddenDataListElement = []
642                                hiddenDataListElement.append(x[4])#発言id
643       
644                                self.InsertData(dataListElement,hiddenDataListElement) 
645
646                                if g_growl == True:
647                                        outCount += 1
648                                        x[1]= self.RemoveATag(x[1])
649                                        outString += x[0]+" : "+x[1]+"\n"
650
651                if g_growl == True and g_config['popup']:
652                        if(outCount > 0):
653                                TmpTwitPage.CallGrowl(self,"DM 新着"+str(outCount)+"件",
654                                        outString,self.img)
655
656class TwitHtml(wx.lib.ClickableHtmlWindow.PyClickableHtmlWindow):
657        def __init__(self, parent):
658                wx.lib.ClickableHtmlWindow.PyClickableHtmlWindow.__init__(self,parent,-1,size=(90,50),style=wx.VSCROLL)
659
660        def SetValue(self, text):
661                self.SetPage(text)
662                pass
663
664
665from time import localtime, strftime
666from cStringIO import StringIO
667import wx.aui
668class MainFrame(wx.Frame):
669        """MainFrame class deffinition.
670        """
671        #binder = wx_utils.bind_manager()
672
673        TIMER_ID = 1
674        TIMER_ID2= TIMER_ID+1
675        TIMER_ID3= TIMER_ID2+1
676       
677        ID_MNU_VIEW_POPUP = 100
678        ID_MNU_VIEW_LISTICON = 101
679        imageList = {}
680        t = {}
681        def loadUserData(self, fileName):
682                #ファイルを開いて、データを読み込んで変換する
683                #データ形式は(user,password)
684                #try
685                file = open(fileName,'r')
686                a = simplejson.loads(file.read())
687                file.close()
688                return a
689                #catch exit(1)
690               
691        def __init__(self, parent=None):
692                #from pit import Pit
693                #twUserdata = Pit.get('twitter.com',{'require' : {'user':'','pass':''}})
694                try:
695                        twUserdata = self.loadUserData(".chat/twdata")
696                except:
697                        twUserdata = config.ConfigDialog(None, -1, 'crochet config').GetAccount()
698                        if twUserdata["user"] and twUserdata["pass"]:
699                                file = open(".chat/twdata","w")
700                                file.write("{\"user\":\""+twUserdata["user"]+
701                                           "\",\"pass\":\""+twUserdata["pass"]+"\"}\n")
702                                file.close()
703                        else:
704                                exit(1)
705                twTabConfig = self.loadUserData(".chat/tabconfig")
706
707                wx.Frame.__init__(self,None, -1, "crochet")
708               
709                if g_growl == True:
710                        self.g = Growl.GrowlNotifier(
711                                applicationName='crochet',notifications=['newTwit','newReply'])
712                        self.g.register()
713                        self.img = Growl.Image.imageFromPath('reply.png')       
714                self.CreateStatusBar()
715
716                self.selectedRow = -1
717                text = self.text = wx.TextCtrl(self,-1,style=wx.TE_PROCESS_ENTER)
718                text.Bind(wx.EVT_TEXT_ENTER, self.OnSendTW)
719                button = self.button = wx.Button(self, -1, "Send")
720                self.button.Bind(wx.EVT_BUTTON, self.OnSendTW)
721       
722                notebook = self.notebook = wx.aui.AuiNotebook(self,-1,style=wx.aui.AUI_NB_BOTTOM|wx.aui.AUI_NB_WINDOWLIST_BUTTON|wx.aui.AUI_NB_TAB_SPLIT)
723
724                self.imageThreadLock = thread.allocate_lock()
725                self.httpThreadLock = thread.allocate_lock()
726                self.dataListThreadLock = thread.allocate_lock()       
727                filter = []
728                for f in twTabConfig['tabFilter']:
729                        filter.append(BranchFilter(f[0],f[1],f[2],f[3],f[4],f[5],f[6])  )       
730               
731                self.recentPage = RecentPage(self,self.httpThreadLock,filter)
732                self.replyPage = ReplyPage(self,self.httpThreadLock)
733                self.directPage = DMPage(self,self.httpThreadLock)
734
735                for p in twTabConfig['tabName']:
736                        page = CustomPage(p,self,self.httpThreadLock)
737                        self.recentPage.AppendCustomPage(page,p)
738               
739                inputSizer = wx.BoxSizer(wx.HORIZONTAL)
740                inputSizer.Add(self.text,2)
741                inputSizer.Add(self.button,0)
742
743                #messageText=self.messageText = wx.TextCtrl(self,-1,style=wx.TE_MULTILINE|wx.TE_AUTO_URL|wx.TE_READONLY,size=(-1,65))
744                messageText = self.messageText = TwitHtml(self)
745                userIcon = self.userIcon = wx.StaticBitmap(self,-1,wx.NullBitmap,(0,0),(64,64))
746                userName = self.userName = wx.StaticText(self,-1,"test")
747                twitTime = self.twitTime = wx.StaticText(self,-1,"---")
748               
749                messageSizer3 = wx.BoxSizer(wx.HORIZONTAL)
750                messageSizer3.Add(userName,2,wx.EXPAND)
751                messageSizer3.Add(twitTime,3,wx.EXPAND,wx.ALIGN_RIGHT)
752
753                messageSizer2 = wx.BoxSizer(wx.VERTICAL)
754                messageSizer2.Add(messageSizer3,0,wx.EXPAND)
755                messageSizer2.Add(messageText,0,wx.EXPAND)
756               
757                messageSizer1 = wx.BoxSizer(wx.HORIZONTAL)
758                messageSizer1.Add(userIcon,0,wx.EXPAND)
759                messageSizer1.Add(messageSizer2,1,wx.EXPAND)
760       
761                messageSizer = wx.BoxSizer(wx.VERTICAL)
762                messageSizer.Add(messageSizer1,0,wx.EXPAND)
763                messageSizer.Add(inputSizer,0,wx.EXPAND)
764               
765                self.sizer = wx.BoxSizer(wx.VERTICAL)
766                self.sizer.Add(notebook,2,wx.EXPAND)
767                self.sizer.Add(messageSizer,0,wx.EXPAND)
768               
769                self.SetSizer(self.sizer)
770                self.SetAutoLayout(True)
771                inputSizer.Fit(self)
772                self.sizer.Fit(self)
773       
774                self.tw = twitter3.Twitter(twUserdata)
775                self.tw.setAuthService("twitter")
776                self.SetIcon(main_icon.getIcon())
777                self.SetSize((600,400))
778                self.timer = wx.Timer(self,self.TIMER_ID)
779                wx.EVT_TIMER(self,self.TIMER_ID,self.OnUpdate)
780                self.timer.Start(60000)
781               
782                self.timer11 = wx.Timer(self,self.TIMER_ID3+1)
783                wx.EVT_TIMER(self,self.TIMER_ID3+1,self.OnUpdate2)
784                self.timer11.Start(3000)
785
786                self.timer2 = wx.Timer(self,self.TIMER_ID2)
787                wx.EVT_TIMER(self,self.TIMER_ID2,self.OnReplyUpdate)
788                self.timer2.Start(300000)
789               
790                self.timer3 = wx.Timer(self,self.TIMER_ID3)
791                wx.EVT_TIMER(self,self.TIMER_ID3,self.OnDMUpdate)
792                self.timer3.Start(300000)
793               
794                self.RefreshTw()
795                self.replyPage.Refresh()
796                self.directPage.Refresh()
797
798                self.SetNowTime2StatusBar()
799                self.CreateMenu()       
800        def CreateMenu(self):
801                #表示メニュー項目作る
802                viewMenu = wx.Menu()
803                self.popupCheck = viewMenu.Append(self.ID_MNU_VIEW_POPUP,u"新着通知",u"新着表示",kind = wx.ITEM_CHECK)
804                self.listIconCheck = viewMenu.Append(self.ID_MNU_VIEW_LISTICON,u"リストアイコン",u"リストボックスの横のアイコンの表示/非表示を切り替えます",kind=wx.ITEM_CHECK)
805
806                viewMenu.Check(self.ID_MNU_VIEW_POPUP, g_config['popup'])
807                menuBar = wx.MenuBar()
808                menuBar.Append(viewMenu,u"表示")
809
810                wx.EVT_MENU(self, self.ID_MNU_VIEW_POPUP, self.OnMenuViewPopUp_Click)
811                wx.EVT_MENU(self, self.ID_MNU_VIEW_LISTICON, self.OnMenuViewListIcon_Click)
812                self.SetMenuBar(menuBar)
813
814        def OnMenuViewPopUp_Click(self,e):
815                g_config['popup'] = self.popupCheck.IsChecked();
816
817        def OnMenuViewListIcon_Click(self,e):
818                g_config['listIcon'] = self.listIconCheck.IsChecked();
819
820        def OnSendTW(self, event):
821                # 送信する
822                # コンボボックスの中身を空にする
823                combo = self.text
824                self.tw.put(combo.GetValue())   
825                combo.SetValue("")
826                self.RefreshTw()
827       
828        # チャットのログデータをListCtrlに表示
829        def RefreshTw(self):
830                self.recentPage.Refresh()       
831       
832        def OnUpdate(self, event):
833                self.SetStatusBar(u"新着取得中...")
834                self.RefreshTw()
835       
836        def OnUpdate2(self, event):
837                #self.SetStatusBar(u"新着取得中...")
838                b1 = self.recentPage.CheckUpdate()
839                for c in self.recentPage.customPages:
840                        b2 = self.recentPage.customPages[c].CheckUpdate()
841                self.replyPage.CheckUpdate()
842                self.directPage.CheckUpdate()
843                if b1 == True:
844                        self.SetNowTime2StatusBar()
845
846        def OnReplyUpdate(self, event):
847                       
848                self.SetStatusBar(u"Reply取得中")
849                self.replyPage.Refresh()
850
851        def OnDMUpdate(self, event):
852               
853                self.SetStatusBar(u"DM取得中...")
854                self.directPage.Refresh()
855
856        def SetStatusBar(self,str):
857                #print ("setstatusbar"+str,)   
858                sb = wx.GetApp().GetTopWindow().GetStatusBar()
859                sb.SetStatusText(str)
860
861        def SetNowTime2StatusBar(self):
862                #現在時刻を表示
863
864                nowtime = strftime("%H:%M:%S", localtime())
865                sb = wx.GetApp().GetTopWindow().GetStatusBar()
866                sb.SetStatusText(nowtime+u"に更新しました")
867       
868        def myKeyHandler(self,evt):
869                print evt.GetKeyCode(),
870                if self.selectedRow != -1:
871                        if evt.GetKeyCode() in [ord('k'),ord('K'),wx.WXK_UP]:
872                                print ('up')
873                                if self.selectedRow > 0:
874                                        self.MoveList(self.selectedRow-1)
875                        if evt.GetKeyCode() in [ord('j'),ord('J'),wx.WXK_DOWN]:
876                                print ('down')
877                                if self.selectedRow < self.list.GetItemCount()-1:
878                                        self.MoveList(self.selectedRow+1)
879                        if evt.GetKeyCode() in [ord('h'),ord('H'),wx.WXK_LEFT]:
880                                print ('left')
881                                leftcol = self.GetPrevItem(self.selectedRow)
882                                if leftcol != -1:
883                                        self.MoveList(leftcol)
884                        if evt.GetKeyCode() in [ord('l'),ord('L'),wx.WXK_RIGHT]:
885                                print ('right')
886                                rightcol = self.GetNextItem(self.selectedRow)
887                                if rightcol != -1:
888                                        self.MoveList(rightcol)
889                        if evt.GetKeyCode() in [ord('s'),ord('S')]:
890                                print "S"
891                                #id = self.hiddenDataList[self.selectedRow][0]
892                                #print "fav"+id
893                                #self.tw.createFavorite(id)
894                #print list.
895                if evt.GetKeyCode() in [ord('q'), ord('Q')]:
896                        wx.Exit()
897
898        """Web上の画像を読み込みImageListとして保持する。
899                既に読まれてるなら読みに行かない。ImageList['URL']という形で格納
900        """
901        def GetImageListElement(self,url):
902                unicodeUrl = url
903                if self.imageList.has_key(unicodeUrl):
904                        if self.imageList[unicodeUrl] == "":
905                                return None
906                        return self.imageList[unicodeUrl]
907                else:
908                        self.imageList[unicodeUrl] = ""
909                        self.WebImage2StringIO(url,unicodeUrl)
910                return None
911       
912        # Web上の画像を引っ張ってくる
913        def WebImage2StringIO(self,url,result):
914
915                try:
916                        urlName = urllib.quote_plus(url,':;/')
917                        t = ImageGetFrame(urlName,self.WebImageCallback,result,self.imageThreadLock)
918                        t.start()
919                        #t.run()
920                except:
921                        print "urlquote error"
922                        #print "urlName:"+urlName
923
924        def WebImageCallback(self,imageData,result):
925                image_pil = Image.open(StringIO(imageData))
926                image_pil.thumbnail((64,64))
927
928                image_wx = wx.EmptyImage(image_pil.size[0],image_pil.size[1])
929                image_wx.SetData(image_pil.convert('RGB').tostring())
930                self.imageList[result] = image_wx
931       
932        # 画像を読み込んで表示のテスト
933        def SetImage(self,imageName):
934                bmp = self.userIcon
935                image = self.GetImageListElement(imageName)
936                if image != None:
937                        bmp.SetBitmap(image.ConvertToBitmap())
938       
939        def addUser2Inputbox(self,user):
940               
941                text = self.text
942                value = text.GetValue()
943               
944                flag = 1
945                print value + ":" + user
946                if re.search(user,value):
947                        flag = 0
948
949                if flag == 1:
950                        text.SetValue(user+value)
951
952        def getNotebook(self):
953                return self.notebook
954
955# startup application.
956if __name__=='__main__':
957        app = wx.App(False)
958        frame = MainFrame()
959        app.SetTopWindow(frame)
960        frame.Show()
961        app.MainLoop()
Note: See TracBrowser for help on using the browser.