mirror of
https://github.com/MCV-Software/TWBlue.git
synced 2025-08-25 09:29:22 +00:00
Compare commits
88 Commits
v2022.12.5
...
v0.50
Author | SHA1 | Date | |
---|---|---|---|
375cdd2528 | |||
![]() |
836675bfa1 | ||
![]() |
2b3c7601f2 | ||
eb2c315abb | |||
e12f440cf2 | |||
![]() |
57dc271fb0 | ||
193cafcc9d | |||
![]() |
e7b6c39f76 | ||
7df2441442 | |||
![]() |
aa687450f6 | ||
6e0ae38d4e | |||
![]() |
fa8c9f639c | ||
9502cef251 | |||
![]() |
982dd78f81 | ||
![]() |
4b98f27968 | ||
![]() |
ecb0fa8f2b | ||
ef2ff9dbfc | |||
![]() |
1fe94642a2 | ||
b232a0b0ad | |||
2ce59cf208 | |||
![]() |
ceb8266828 | ||
![]() |
21970f2c94 | ||
14965f73d3 | |||
![]() |
267b454fc6 | ||
c3dc00c241 | |||
![]() |
9fb67f01ae | ||
6d1cd0b1fc | |||
a7ef572d05 | |||
403784b77a | |||
d032a6d8f7 | |||
![]() |
231d43ab22 | ||
5e3bcfc82e | |||
8e92d97260 | |||
bb1ffa9ff1 | |||
104bc4ec8c | |||
![]() |
6ae555fe72 | ||
![]() |
dd51516c30 | ||
![]() |
4e18bb0721 | ||
![]() |
0492e65aa0 | ||
![]() |
a5fb59d7a7 | ||
f2fab29cb7 | |||
![]() |
f36accf89b | ||
a13536233e | |||
bc2d448464 | |||
60ec9ab215 | |||
20b5fc079b | |||
80e231b689 | |||
7137d437bd | |||
![]() |
a07b3c1829 | ||
![]() |
c062c10542 | ||
![]() |
0e7c070bd4 | ||
![]() |
9f35d079b1 | ||
![]() |
a3fca4d2a0 | ||
ada6f1fb0d | |||
79124810b0 | |||
fee7254d55 | |||
![]() |
c12902d011 | ||
2f7eb12104 | |||
855cefeb8d | |||
e649b883c6 | |||
![]() |
1a61f2d790 | ||
![]() |
6abfba317a | ||
![]() |
18ce92daab | ||
![]() |
84f729f42b | ||
![]() |
4e7666cf52 | ||
88e0fbb531 | |||
af32b3ceb6 | |||
94dc083650 | |||
acb3cce1d6 | |||
![]() |
2b3e1099f6 | ||
![]() |
60507e8f6b | ||
![]() |
75bfc17bb1 | ||
acb8c5acd3 | |||
![]() |
5bcf04fc94 | ||
0f2fbc775a | |||
1b684cd12c | |||
9d64901791 | |||
18f7cb6c96 | |||
7f673fb9de | |||
![]() |
f6f542fbec | ||
![]() |
a211e2e5e4 | ||
3ec8ac31a5 | |||
![]() |
dacbb19586 | ||
![]() |
55691cca20 | ||
0104b97df0 | |||
aa58e61e5e | |||
![]() |
fae204f3c2 | ||
d8149a4c96 |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1,12 +1,8 @@
|
||||
*.pyc
|
||||
*~
|
||||
windows-dependencies/*
|
||||
src/build/
|
||||
src/dist/
|
||||
src/config/
|
||||
src/config1/
|
||||
src/config2/
|
||||
src/config3/
|
||||
src/dropbox/
|
||||
src/logs/
|
||||
src/documentation/
|
||||
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
[submodule "windows-dependencies"]
|
||||
path = windows-dependencies
|
||||
url = https://github.com/jmdaweb/TWBlue_deps_windows.git
|
56
README.md
56
README.md
@@ -15,4 +15,58 @@ TW Blue is an app designed to use Twitter in a simple and fast way and avoiding,
|
||||
* Play various file and URL types which contain audio
|
||||
* and more!
|
||||
|
||||
See the [TWBlue's webpage](http://twblue.com.mx) for more details.
|
||||
See the [TWBlue's webpage](http://twblue.com.mx) for more details.
|
||||
|
||||
## Using TWBlue from sources
|
||||
|
||||
This document describes how to run tw blue from source, and, after that, how to build a binary version, which doesn't need Python and the other dependencies to run.
|
||||
|
||||
### Required dependencies.
|
||||
|
||||
The following dependencies need to be installed in your system. If you want to build tw blue for 32-bit versions of Windows, you will find the required software in the x86 folder, inside windows-dependencies directory. If you want to build tw blue for 64-bit windows versions, use the x64 folder.
|
||||
|
||||
In this document you will also find links to each dependency website.
|
||||
|
||||
If you want to build manually some of the following libraries, you need Microsoft Visual studio 2008 professional.
|
||||
|
||||
Dependencies list:
|
||||
|
||||
* [Python,](http://python.org) version 2.7.8
|
||||
* [wxPython](http://www.wxpython.org) for Python 2.7, version 3.0.0 (2.9.5 to avoid problems in windows xp)
|
||||
* [Python windows extensions (pywin32)](http://www.sourceforge.net/projects/pywin32/) for python 2.7, build 218
|
||||
* [ConfigObj,](http://www.voidspace.org.uk/python/configobj.html) version 4.7.2
|
||||
* [oauthlib](https://pypi.python.org/pypi/oauthlib/0.6.1) 0.6.1
|
||||
* [Pycurl](http://pycurl.sourceforge.net) 7.19.3.1 for Python 2.7: [32-bit downloads,](https://pypi.python.org/pypi/pycurl/7.19.3.1) [64-bit downloads](http://www.lfd.uci.edu/~gohlke/pythonlibs/)
|
||||
* [Requests](http://www.python-requests.org/en/latest/) 2.2.1: [Recommended download site](https://pypi.python.org/pypi/requests/2.2.1)
|
||||
* [Requests-oauthlib](https://github.com/requests/requests-oauthlib) 0.4.0
|
||||
* [Suds](https://fedorahosted.org/suds) 0.4: [Recommended download site](https://pypi.python.org/pypi/suds/0.4)
|
||||
* [Pygeocoder: ](http://code.xster.net/pygeocoder/wiki/Home) You can install this dependency by using pip or easy_install.
|
||||
* Bootstrap 1.2.1: included in dependencies directory.
|
||||
Copy the bootstrap.exe file corresponding to the desired platform in the windows folder, inside this repository.
|
||||
This dependency has been built using pure basic 4.61. Its source can be found at http://hg.q-continuum.net/updater
|
||||
* [oggenc2.exe,](http://www.rarewares.org/ogg-oggenc.php) version 2.87
|
||||
Copy the oggenc2.exe file corresponding to the desired platform in the windows folder, inside this repository.
|
||||
* Visual C++ 2008 dlls, included in vcredist-x86.7z and vcredist-x64.7z:
|
||||
Extract the file corresponding to your platform to the src folder.
|
||||
|
||||
If you want to build the binary version:
|
||||
|
||||
* [Py2exe](http://www.sourceforge.net/projects/py2exe/) for Python 2.7, version 0.6.9
|
||||
* [Setuptools](https://pypi.python.org/pypi/setuptools) 2.1
|
||||
- [7-zip](http://7-zip.org)
|
||||
|
||||
### How to run tw blue from source
|
||||
|
||||
Run the file main.py located in the src folder. If you have a x64 system, you can install both 32-bit and 64-bit python versions, and test tw blue in these platforms.
|
||||
|
||||
### How to build a binary version
|
||||
|
||||
You must type the following command. In this example, we will assume that python is the path to the python executable (x86 or x64) and that you have navigated to the src directory:
|
||||
|
||||
python setup.py py2exe
|
||||
|
||||
You will find the binary version in the dist directory. You can compress this folder using 7-zip and you will get the zip version.
|
||||
|
||||
### How to generate a translation template
|
||||
|
||||
You must run the gen_pot.bat file, located in the tools directory. Your python installation should be in your path environment variable. The pot file will appear in the tools directory too.
|
@@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
documentation = []
|
||||
documentation.append(_(u"""Documentation for TW Blue 0.46"""))
|
||||
documentation.append(_(u"""Documentation for TW Blue 0.50"""))
|
||||
# Translators: This is the new line character, don't change it in the translations.
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
@@ -47,16 +47,16 @@ documentation.append(_(u"""
|
||||
documentation.append(_(u"""First off, it's necessary to authorise the program so it can access your Twitter account and act on your behalf. The authorisation process is quite simple, and the program never gets data such as your username and password. In order to authorise the application, you just need to run the main executable file, called TWBlue.exe (on some computers it may appear simply as TWBlue)."""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""When executed, if you have not previously configured the program, it will show a dialogue box where it tells you'll be taken to Twitter in order to authorise the application as soon as you press OK. To begin the authorisation process, press the only available button on the box."""))
|
||||
#$documentation.append(_(u"""When executed, if you have not previously configured the program, it will show a dialogue box where it tells you'll be taken to Twitter in order to authorise the application as soon as you press OK. To begin the authorisation process, press the only available button on the box."""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""Your default browser will open on the Twitter page to request authorisation. Enter your user name and password if you're not already logged in, look for the authorise button, and press it."""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""Read the instructions you will get if the process is successful. In summary, you will be given a numeric code with several digits you must paste on an edit field open by the application on another window."""))
|
||||
#$documentation.append(_(u"""Read the instructions you will get if the process is successful. In summary, you will be given a numeric code with several digits you must paste on an edit field open by the application on another window."""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""Paste the verification code, and press the enter key. """))
|
||||
#$documentation.append(_(u"""Paste the verification code, and press the enter key. """))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""If all went well, the application will start playing sounds, indicating your data are being updated."""))
|
||||
@@ -65,10 +65,10 @@ documentation.append(_(u"""
|
||||
documentation.append(_(u"""When the process is finished,the program will play another sound, and the screen reader will say "ready"."""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""## The program's interface {#interface}"""))
|
||||
documentation.append(_(u"""## The program's interface"""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""The easiest way to describe the graphical interface of the application is a window with a menu bar with four menus (application, tweet, user and help), a list with several elements, and, in most cases, three buttons: tweet, retweet and reply. The actions available for each element are described below."""))
|
||||
documentation.append(_(u"""The easiest way to describe the graphical interface of the application is a window with a menu bar with five menus (application, tweet, user, buffer and help), a list with several elements, and, in most cases, three buttons: tweet, retweet and reply. The actions available for each element are described below."""))
|
||||
documentation.append(_(u"""
|
||||
"""))
|
||||
documentation.append(_(u"""Elements on the lists may be tweets, direct messages or users. TW Blue creates different tabs for each list, which can be sent tweets, main timeline tweets, favourites, or direct messages, and each tab contains a single type of tweet. These tabs are called lists or buffers."""))
|
||||
|
@@ -1,60 +0,0 @@
|
||||
tw blue build instructions for Windows
|
||||
|
||||
Introduction.
|
||||
This document describes how to run tw blue from source, and, after that, how to build a binary version, which doesn't need Python and the other dependencies to run.
|
||||
|
||||
Required dependencies.
|
||||
The following dependencies need to be installed in your system. If you want to build tw blue for 32-bit versions of Windows, you will find the required software in the x86 folder, inside dependencies directory. If you want to build tw blue for 64-bit windows versions, use the x64 folder.
|
||||
In this document you will also find links to each dependency website.
|
||||
If you want to build manually some of the following libraries, you need Microsoft Visual studio 2008 professional.
|
||||
|
||||
Dependencies list:
|
||||
- Python, version 2.7.6: http://www.python.org
|
||||
- wxPython for Python 2.7, version 3.0.0 (2.9.5 to avoid problems in windows xp): http://www.wxpython.org
|
||||
-Python windows extensions (pywin32) for python 2.7, build 218: http://www.sourceforge.net/projects/pywin32/
|
||||
- ConfigObj, version 4.7.2: http://www.voidspace.org.uk/python/configobj.html
|
||||
- oauthlib 0.6.1: https://pypi.python.org/pypi/oauthlib/0.6.1
|
||||
- Pycurl 7.19.3.1 for Python 2.7:
|
||||
Official website: http://pycurl.sourceforge.net/
|
||||
32-bit downloads: https://pypi.python.org/pypi/pycurl/7.19.3.1
|
||||
64-bit downloads: http://www.lfd.uci.edu/~gohlke/pythonlibs/
|
||||
- Requests 2.2.1:
|
||||
Official website: http://www.python-requests.org/en/latest/
|
||||
Recommended download site: https://pypi.python.org/pypi/requests/2.2.1
|
||||
- Requests-oauthlib 0.4.0: https://github.com/requests/requests-oauthlib
|
||||
- Suds 0.4:
|
||||
Official website: https://fedorahosted.org/suds
|
||||
Recommended download site: https://pypi.python.org/pypi/suds/0.4
|
||||
- Twython 3.1.2: https://pypi.python.org/pypi/twython/3.1.2
|
||||
- Bootstrap 1.2.1: included in dependencies directory.
|
||||
Copy the bootstrap.exe file corresponding to the desired platform in the windows folder, inside this repository.
|
||||
This dependency has been built using pure basic 4.61. Its source can be found at http://hg.q-continuum.net/updater
|
||||
- oggenc2.exe, version 2.87: http://www.rarewares.org/ogg-oggenc.php
|
||||
Copy the oggenc2.exe file corresponding to the desired platform in the windows folder, inside this repository.
|
||||
-Visual C++ 2008 dlls, included in vcredist-x86.7z and vcredist-x64.7z:
|
||||
Extract the file corresponding to your platform to the windows folder.
|
||||
|
||||
To build the binary version:
|
||||
- Py2exe for Python 2.7, version 0.6.9: http://www.sourceforge.net/projects/py2exe/
|
||||
- Setuptools 2.1: https://pypi.python.org/pypi/setuptools
|
||||
- 7-zip: http://7-zip.org
|
||||
|
||||
To generate the documentation:
|
||||
- Pandoc, version 1.12.3:
|
||||
Official website: http://johnmacfarlane.net/pandoc/
|
||||
Downloads site: http://code.google.com/p/pandoc/downloads/list
|
||||
|
||||
How to run tw blue from source
|
||||
Run the file main.py located in windows folder. If you have a x64 system, you can install both 32-bit and 64-bit python versions, and test tw blue in these platforms.
|
||||
|
||||
How to generate the documentation
|
||||
To generate quickly the documentation, a bash console is required. You can find bash in git for windows, cygwin, or MSYS, for example.
|
||||
You must navigate to the tools directory and run the script gen_doc.sh. It will generate and place all html documentation in windows\documentation directory.
|
||||
|
||||
How to build a binary version
|
||||
You must type the following command. In the following example, we will assume that python is the path to the python executable (x86 or x64) and that you have navigated to the windows directory:
|
||||
python setup.py py2exe
|
||||
You will find the binary version in the dist directory. You can compress this folder using 7-zip and you will get the zip version.
|
||||
|
||||
How to generate a translation template
|
||||
You must run the gen_pot.bat file, located in the tools directory. Your python installation should be in your path environment variable. The pot file will appear in the tools directory too.
|
@@ -1,83 +1,88 @@
|
||||
!include "MUI2.nsh"
|
||||
!include "LogicLib.nsh"
|
||||
!include "x64.nsh"
|
||||
CRCCheck on
|
||||
XPStyle on
|
||||
Name "TW Blue"
|
||||
OutFile "TWBlue_setup.exe"
|
||||
InstallDir "$PROGRAMFILES\twblue"
|
||||
InstallDirRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "InstallLocation"
|
||||
RequestExecutionLevel admin
|
||||
SetCompress auto
|
||||
SetCompressor /solid lzma
|
||||
SetDatablockOptimize on
|
||||
VIAddVersionKey ProductName "TW Blue"
|
||||
VIAddVersionKey LegalCopyright "Copyright 2014 Manuel Cortez."
|
||||
VIAddVersionKey ProductVersion "0.48"
|
||||
VIAddVersionKey FileVersion "0.48"
|
||||
VIProductVersion "0.48.0.0"
|
||||
!insertmacro MUI_PAGE_WELCOME
|
||||
!insertmacro MUI_PAGE_LICENSE "license.txt"
|
||||
!insertmacro MUI_PAGE_DIRECTORY
|
||||
var StartMenuFolder
|
||||
!insertmacro MUI_PAGE_STARTMENU startmenu $StartMenuFolder
|
||||
!insertmacro MUI_PAGE_INSTFILES
|
||||
!insertmacro MUI_PAGE_FINISH
|
||||
!insertmacro MUI_UNPAGE_CONFIRM
|
||||
!insertmacro MUI_UNPAGE_INSTFILES
|
||||
!insertmacro MUI_LANGUAGE "English"
|
||||
!insertmacro MUI_LANGUAGE "French"
|
||||
!insertmacro MUI_LANGUAGE "Spanish"
|
||||
!insertmacro MUI_LANGUAGE "Italian"
|
||||
!insertmacro MUI_LANGUAGE "Finnish"
|
||||
!insertmacro MUI_LANGUAGE "Russian"
|
||||
!insertmacro MUI_LANGUAGE "PortugueseBR"
|
||||
!insertmacro MUI_LANGUAGE "Polish"
|
||||
!insertmacro MUI_LANGUAGE "Hungarian"
|
||||
!insertmacro MUI_LANGUAGE "Turkish"
|
||||
!insertmacro MUI_LANGUAGE "Arabic"
|
||||
!insertmacro MUI_LANGUAGE "Galician"
|
||||
!insertmacro MUI_LANGUAGE "Catalan"
|
||||
!insertmacro MUI_LANGUAGE "Basque"
|
||||
!insertmacro MUI_RESERVEFILE_LANGDLL
|
||||
Section
|
||||
SetShellVarContext All
|
||||
SetOutPath "$INSTDIR"
|
||||
${If} ${RunningX64}
|
||||
File /r TWBlue64\*
|
||||
${Else}
|
||||
File /r TWBlue\*
|
||||
${EndIf}
|
||||
CreateShortCut "$DESKTOP\TW Blue.lnk" "$INSTDIR\TWBlue.exe" "-i"
|
||||
!insertmacro MUI_STARTMENU_WRITE_BEGIN startmenu
|
||||
CreateDirectory "$SMPROGRAMS\$StartMenuFolder"
|
||||
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\TW Blue.lnk" "$INSTDIR\TWBlue.exe" "-i"
|
||||
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\TW Blue on the web.lnk" "http://twblue.com.mx"
|
||||
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\Uninstall.lnk" "$INSTDIR\Uninstall.exe"
|
||||
!insertmacro MUI_STARTMENU_WRITE_END
|
||||
WriteUninstaller "$INSTDIR\Uninstall.exe"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "DisplayName" "TW Blue"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "UninstallString" '"$INSTDIR\uninstall.exe"'
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall" "InstallLocation" $INSTDIR
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall" "Publisher" "Manuel Cortez"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "DisplayVersion" "0.47"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "URLInfoAbout" "http://twblue.com.mx"
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "VersionMajor" 0
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "VersionMinor" 47
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "NoModify" 1
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "NoRepair" 1
|
||||
SectionEnd
|
||||
Section "Uninstall"
|
||||
SetShellVarContext All
|
||||
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue"
|
||||
RMDir /r /REBOOTOK $INSTDIR
|
||||
Delete "$DESKTOP\TW Blue.lnk"
|
||||
!insertmacro MUI_STARTMENU_GETFOLDER startmenu $StartMenuFolder
|
||||
RMDir /r "$SMPROGRAMS\$StartMenuFolder"
|
||||
SectionEnd
|
||||
Function .onInit
|
||||
${If} ${RunningX64}
|
||||
StrCpy $instdir "$programfiles64\twblue"
|
||||
${EndIf}
|
||||
!insertmacro MUI_LANGDLL_DISPLAY
|
||||
FunctionEnd
|
||||
!include "MUI2.nsh"
|
||||
!include "LogicLib.nsh"
|
||||
!include "x64.nsh"
|
||||
CRCCheck on
|
||||
XPStyle on
|
||||
Name "TW Blue"
|
||||
OutFile "TWBlue_setup.exe"
|
||||
InstallDir "$PROGRAMFILES\twblue"
|
||||
InstallDirRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "InstallLocation"
|
||||
RequestExecutionLevel admin
|
||||
SetCompress auto
|
||||
SetCompressor /solid lzma
|
||||
SetDatablockOptimize on
|
||||
VIAddVersionKey ProductName "TW Blue"
|
||||
VIAddVersionKey LegalCopyright "Copyright 2014 Manuel Cortez."
|
||||
VIAddVersionKey ProductVersion "0.50"
|
||||
VIAddVersionKey FileVersion "0.50"
|
||||
VIProductVersion "0.50.0.0"
|
||||
!insertmacro MUI_PAGE_WELCOME
|
||||
!define MUI_LICENSEPAGE_RADIOBUTTONS
|
||||
!insertmacro MUI_PAGE_LICENSE "license.txt"
|
||||
!insertmacro MUI_PAGE_DIRECTORY
|
||||
var StartMenuFolder
|
||||
!insertmacro MUI_PAGE_STARTMENU startmenu $StartMenuFolder
|
||||
!insertmacro MUI_PAGE_INSTFILES
|
||||
!define MUI_FINISHPAGE_LINK "Visit TW Blue website"
|
||||
!define MUI_FINISHPAGE_LINK_LOCATION "http://twblue.com.mx"
|
||||
!define MUI_FINISHPAGE_RUN "$INSTDIR\TWBlue.exe"
|
||||
!define MUI_FINISHPAGE_RUN_PARAMETERS "-i"
|
||||
!insertmacro MUI_PAGE_FINISH
|
||||
!insertmacro MUI_UNPAGE_CONFIRM
|
||||
!insertmacro MUI_UNPAGE_INSTFILES
|
||||
!insertmacro MUI_LANGUAGE "English"
|
||||
!insertmacro MUI_LANGUAGE "French"
|
||||
!insertmacro MUI_LANGUAGE "Spanish"
|
||||
!insertmacro MUI_LANGUAGE "Italian"
|
||||
!insertmacro MUI_LANGUAGE "Finnish"
|
||||
!insertmacro MUI_LANGUAGE "Russian"
|
||||
!insertmacro MUI_LANGUAGE "PortugueseBR"
|
||||
!insertmacro MUI_LANGUAGE "Polish"
|
||||
!insertmacro MUI_LANGUAGE "Hungarian"
|
||||
!insertmacro MUI_LANGUAGE "Turkish"
|
||||
!insertmacro MUI_LANGUAGE "Arabic"
|
||||
!insertmacro MUI_LANGUAGE "Galician"
|
||||
!insertmacro MUI_LANGUAGE "Catalan"
|
||||
!insertmacro MUI_LANGUAGE "Basque"
|
||||
!insertmacro MUI_RESERVEFILE_LANGDLL
|
||||
Section
|
||||
SetShellVarContext All
|
||||
SetOutPath "$INSTDIR"
|
||||
${If} ${RunningX64}
|
||||
File /r TWBlue64\*
|
||||
${Else}
|
||||
File /r TWBlue\*
|
||||
${EndIf}
|
||||
CreateShortCut "$DESKTOP\TW Blue.lnk" "$INSTDIR\TWBlue.exe" "-i"
|
||||
!insertmacro MUI_STARTMENU_WRITE_BEGIN startmenu
|
||||
CreateDirectory "$SMPROGRAMS\$StartMenuFolder"
|
||||
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\TW Blue.lnk" "$INSTDIR\TWBlue.exe" "-i"
|
||||
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\TW Blue on the web.lnk" "http://twblue.com.mx"
|
||||
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\Uninstall.lnk" "$INSTDIR\Uninstall.exe"
|
||||
!insertmacro MUI_STARTMENU_WRITE_END
|
||||
WriteUninstaller "$INSTDIR\Uninstall.exe"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "DisplayName" "TW Blue"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "UninstallString" '"$INSTDIR\uninstall.exe"'
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall" "InstallLocation" $INSTDIR
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall" "Publisher" "Manuel Cortez"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "DisplayVersion" "0.50"
|
||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "URLInfoAbout" "http://twblue.com.mx"
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "VersionMajor" 0
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "VersionMinor" 50
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "NoModify" 1
|
||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "NoRepair" 1
|
||||
SectionEnd
|
||||
Section "Uninstall"
|
||||
SetShellVarContext All
|
||||
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue"
|
||||
RMDir /r /REBOOTOK $INSTDIR
|
||||
Delete "$DESKTOP\TW Blue.lnk"
|
||||
!insertmacro MUI_STARTMENU_GETFOLDER startmenu $StartMenuFolder
|
||||
RMDir /r "$SMPROGRAMS\$StartMenuFolder"
|
||||
SectionEnd
|
||||
Function .onInit
|
||||
${If} ${RunningX64}
|
||||
StrCpy $instdir "$programfiles64\twblue"
|
||||
${EndIf}
|
||||
!insertmacro MUI_LANGDLL_DISPLAY
|
||||
FunctionEnd
|
||||
|
@@ -15,6 +15,7 @@ reverse_timelines = boolean(default=False)
|
||||
time_to_check_streams = integer(default=30)
|
||||
announce_stream_status = boolean(default=True)
|
||||
ask_at_exit = boolean(default=True)
|
||||
use_invisible_keyboard_shorcuts = boolean(default=False)
|
||||
|
||||
[sound]
|
||||
volume = float(default=1.0)
|
||||
@@ -35,11 +36,14 @@ timelines = list(default=list())
|
||||
tweet_searches = list(default=list())
|
||||
lists = list(default=list())
|
||||
favourites_timelines = list(default=list())
|
||||
trending_topic_buffers = list(default=list())
|
||||
muted_buffers = list(default=list())
|
||||
autoread_buffers = list(default=list())
|
||||
|
||||
[mysc]
|
||||
spelling_language = string(default="")
|
||||
save_followers_in_autocompletion_db = boolean(default=False)
|
||||
save_friends_in_autocompletion_db = boolean(default=False)
|
||||
|
||||
[services]
|
||||
dropbox_token=string(default="")
|
||||
@@ -86,3 +90,6 @@ search = string(default="control+win+-")
|
||||
edit_keystrokes = string(default="control+win+k")
|
||||
view_user_lists = string(default="control+win+l")
|
||||
get_more_items = string(default="alt+win+pageup")
|
||||
reverse_geocode = string(default="control+win+g")
|
||||
view_reverse_geocode = string(default="control+win+shift+g")
|
||||
get_trending_topics = string(default="control+win+t")
|
@@ -2,19 +2,19 @@
|
||||
name = 'TW Blue'
|
||||
snapshot = False
|
||||
if snapshot == False:
|
||||
version = "0.48"
|
||||
version = "0.50"
|
||||
update_url = 'http://twblue.com.mx/updates/tw_blue.json'
|
||||
else:
|
||||
version = "4"
|
||||
version = "6"
|
||||
update_url = 'http://twblue.com.mx/updates/snapshots.json'
|
||||
author = u"Manuel Cortéz"
|
||||
authorEmail = "info@twblue.com.mx"
|
||||
authorEmail = "manuel@manuelcortez.net"
|
||||
copyright = u"copyright (C) 2013-2014, Manuel cortéz"
|
||||
description = u"TW Blue is an app designed to use Twitter in a simple and fast way and avoiding, as far as possible, the consumtion of excessive resources of the machine where it’s running. With this app you’ll have access to most twitter features."
|
||||
translators = [u"Bryner Villalobos (English)", u"Mohammed Al Shara (Arabic)", u"Salva Doménech, Juan Carlos Rivilla(Catalan)", u"Manuel cortéz(Spanish)", u"Sukil Etxenike Arizaleta(Basque)", u"Jani Kinnunen(finnish)", u"Javier Currás, José Manuel Delicado, Alba Quinteiro(Galician)", u"Robert Osztolykan(Hungarian)", u"Paweł Masarczyk(Polish)", u"Odenilton Júnior Santos(Portuguese)", u"Alexander Jaszyn(Russian)", u"Burak (Turkish)"]
|
||||
translators = [u"Bryner Villalobos (English)", u"Mohammed Al Shara (Arabic)", u"Joan Rabat, Juan Carlos Rivilla(Catalan)", u"Manuel cortéz(Spanish)", u"Sukil Etxenike Arizaleta(Basque)", u"Jani Kinnunen(finnish)", u"Alba Quinteiro(Galician)", u"Robert Osztolykan(Hungarian)", u"Paweł Masarczyk(Polish)", u"Odenilton Júnior Santos(Portuguese)", u"Alexander Jaszyn(Russian)", u"Burak (Turkish)"]
|
||||
url = u"http://twblue.com.mx"
|
||||
#report_bugs_url = "http://twblue.com.mx/errores/api/soap/mantisconnect.php?wsdl"
|
||||
report_bugs_url = "http://twblue.com.mx/bugs/api/soap/mantisconnect.php?wsdl"
|
||||
|
||||
# Tokens
|
||||
app_key = '8pDLbyOW3saYnvSZ4uLFg'
|
||||
app_secret = 'YsgdrzY9B4yyYvYsyee78rKI3GshjHpenVS9LnFJXY'
|
||||
app_secret = 'YsgdrzY9B4yyYvYsyee78rKI3GshjHpenVS9LnFJXY'
|
@@ -8,7 +8,9 @@ group.add_argument("-p", "--portable", help="Use TW Blue as a portable aplicatio
|
||||
group.add_argument("-i", "--installed", help="Use TW Blue as an installed application. Config files will be saved on the user data directory", action="store_true")
|
||||
parser.add_argument("-d", "--data-directory", action="store", dest="directory", help="Specifies the directory where TW Blue saves the data files")
|
||||
args = parser.parse_args()
|
||||
if args.installed == True: paths.mode = "installed"
|
||||
if args.installed == True:
|
||||
paths.mode = "installed"
|
||||
elif args.portable == True:
|
||||
paths.mode = "portable"
|
||||
if args.directory != None: paths.directory = args.directory
|
||||
|
||||
|
@@ -16,6 +16,7 @@ class soundsTutorial(wx.Dialog):
|
||||
_(u"A bug has happened"),
|
||||
_(u"You've added a tweet to your favourites"),
|
||||
_(u"Someone's favourites have been updated"),
|
||||
_(u"The tweet has coordinates to determine its location"),
|
||||
_(u"There are no more tweets to read"),
|
||||
_(u"A list has a new tweet"),
|
||||
_(u"You can't add any more characters on the tweet"),
|
||||
|
1
src/extra/autocompletionUsers/__init__.py
Normal file
1
src/extra/autocompletionUsers/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
# -*- coding: utf-8 -*-
|
31
src/extra/autocompletionUsers/completion.py
Normal file
31
src/extra/autocompletionUsers/completion.py
Normal file
@@ -0,0 +1,31 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import storage
|
||||
import output
|
||||
import wx_menu
|
||||
|
||||
class autocompletionUsers(object):
|
||||
def __init__(self, window):
|
||||
super(autocompletionUsers, self).__init__()
|
||||
self.window = window
|
||||
|
||||
def show_menu(self):
|
||||
position = self.window.text.GetInsertionPoint()
|
||||
text = self.window.text.GetValue()
|
||||
text = text[:position]
|
||||
try:
|
||||
pattern = text.split()[-1]
|
||||
except IndexError:
|
||||
output.speak(_(u"You have to start writing"))
|
||||
return
|
||||
if pattern.startswith("@") == True:
|
||||
db = storage.storage()
|
||||
menu = wx_menu.menu(self.window.text, pattern[1:])
|
||||
users = db.get_users(pattern[1:])
|
||||
if len(users) > 0:
|
||||
menu.append_options(users)
|
||||
self.window.PopupMenu(menu, self.window.text.GetPosition())
|
||||
menu.Destroy()
|
||||
else:
|
||||
output.speak(_(u"There are not results in your users database"))
|
||||
else:
|
||||
output.speak(_(u"Autocompletion only works for users."))
|
43
src/extra/autocompletionUsers/manage.py
Normal file
43
src/extra/autocompletionUsers/manage.py
Normal file
@@ -0,0 +1,43 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import storage
|
||||
import wx
|
||||
import wx_manage
|
||||
|
||||
class autocompletionManage(object):
|
||||
def __init__(self, window):
|
||||
super(autocompletionManage, self).__init__()
|
||||
self.window = window
|
||||
self.dialog = wx_manage.autocompletionManageDialog()
|
||||
self.database = storage.storage()
|
||||
self.users = self.database.get_all_users()
|
||||
self.dialog.put_users(self.users)
|
||||
self.dialog.add.Bind(wx.EVT_BUTTON, self.add_user)
|
||||
self.dialog.remove.Bind(wx.EVT_BUTTON, self.remove_user)
|
||||
self.dialog.ShowModal()
|
||||
|
||||
def update_list(self):
|
||||
item = self.dialog.users.get_selected()
|
||||
self.dialog.users.clear()
|
||||
self.users = self.database.get_all_users()
|
||||
self.dialog.put_users(self.users)
|
||||
self.dialog.users.select_item(item)
|
||||
|
||||
def add_user(self, event=None):
|
||||
usr = self.dialog.get_user()
|
||||
if usr == False:
|
||||
return
|
||||
try:
|
||||
data = self.window.twitter.twitter.show_user(screen_name=usr)
|
||||
except:
|
||||
self.dialog.show_invalid_user_error()
|
||||
return
|
||||
self.database.set_user(data["screen_name"], data["name"], 0)
|
||||
self.update_list()
|
||||
|
||||
def remove_user(self, ev):
|
||||
ask = wx.MessageDialog(None, _(u"Are you sure you want to delete this user from the database? This user will not appear on the autocomplete results anymore."), _(u"Confirm"), wx.YES_NO|wx.ICON_QUESTION)
|
||||
if ask.ShowModal() == wx.ID_YES:
|
||||
item = self.dialog.users.get_selected()
|
||||
user = self.users[item]
|
||||
self.database.remove_user(user[0])
|
||||
self.update_list()
|
58
src/extra/autocompletionUsers/settings.py
Normal file
58
src/extra/autocompletionUsers/settings.py
Normal file
@@ -0,0 +1,58 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import storage
|
||||
import wx
|
||||
import config
|
||||
import wx_settings
|
||||
import manage
|
||||
import output
|
||||
from mysc.thread_utils import call_threaded
|
||||
|
||||
class autocompletionSettings(object):
|
||||
def __init__(self, window):
|
||||
super(autocompletionSettings, self).__init__()
|
||||
self.window = window
|
||||
self.dialog = wx_settings.autocompletionSettingsDialog()
|
||||
self.dialog.friends_buffer.SetValue(config.main["mysc"]["save_friends_in_autocompletion_db"])
|
||||
self.dialog.followers_buffer.SetValue(config.main["mysc"]["save_followers_in_autocompletion_db"])
|
||||
self.dialog.viewList.Bind(wx.EVT_BUTTON, self.view_list)
|
||||
if self.dialog.ShowModal() == wx.ID_OK:
|
||||
call_threaded(self.add_users_to_database)
|
||||
|
||||
def add_users_to_database(self):
|
||||
config.main["mysc"]["save_friends_in_autocompletion_db"] = self.dialog.friends_buffer.GetValue()
|
||||
config.main["mysc"]["save_followers_in_autocompletion_db"] = self.dialog.friends_buffer.GetValue()
|
||||
output.speak(_(u"Updating database... You can close this window now. A message will tell you when the process finishes."))
|
||||
database = storage.storage()
|
||||
if self.dialog.followers_buffer.GetValue() == True:
|
||||
buffer = self.window.search_buffer("people", "followers")
|
||||
for i in buffer.db.settings[buffer.name_buffer]:
|
||||
database.set_user(i["screen_name"], i["name"], 1)
|
||||
else:
|
||||
database.remove_by_buffer(1)
|
||||
if self.dialog.friends_buffer.GetValue() == True:
|
||||
buffer = self.window.search_buffer("people", "friends")
|
||||
for i in buffer.db.settings[buffer.name_buffer]:
|
||||
database.set_user(i["screen_name"], i["name"], 2)
|
||||
else:
|
||||
database.remove_by_buffer(2)
|
||||
wx_settings.show_success_dialog()
|
||||
self.dialog.Destroy()
|
||||
|
||||
def view_list(self, ev):
|
||||
q = manage.autocompletionManage(self.window)
|
||||
|
||||
|
||||
def execute_at_startup(window):
|
||||
database = storage.storage()
|
||||
if config.main["mysc"]["save_followers_in_autocompletion_db"] == True and config.main["other_buffers"]["show_followers"] == True:
|
||||
buffer = window.search_buffer("people", "followers")
|
||||
for i in buffer.db.settings[buffer.name_buffer]:
|
||||
database.set_user(i["screen_name"], i["name"], 1)
|
||||
else:
|
||||
database.remove_by_buffer(1)
|
||||
if config.main["mysc"]["save_friends_in_autocompletion_db"] == True and config.main["other_buffers"]["show_friends"] == True:
|
||||
buffer = window.search_buffer("people", "friends")
|
||||
for i in buffer.db.settings[buffer.name_buffer]:
|
||||
database.set_user(i["screen_name"], i["name"], 2)
|
||||
else:
|
||||
database.remove_by_buffer(2)
|
53
src/extra/autocompletionUsers/storage.py
Normal file
53
src/extra/autocompletionUsers/storage.py
Normal file
@@ -0,0 +1,53 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import sqlite3, paths
|
||||
from sessionmanager import manager
|
||||
|
||||
class storage(object):
|
||||
def __init__(self):
|
||||
self.connection = sqlite3.connect(paths.config_path("%s/autocompletionUsers.dat" % (manager.manager.get_current_session())))
|
||||
self.cursor = self.connection.cursor()
|
||||
if self.table_exist("users") == False:
|
||||
self.create_table()
|
||||
|
||||
def table_exist(self, table):
|
||||
ask = self.cursor.execute("SELECT name FROM sqlite_master WHERE type='table' AND name='%s'" % (table))
|
||||
answer = ask.fetchone()
|
||||
if answer == None:
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
def get_all_users(self):
|
||||
self.cursor.execute("""select * from users""")
|
||||
return self.cursor.fetchall()
|
||||
|
||||
def get_users(self, term):
|
||||
self.cursor.execute("""SELECT * FROM users WHERE user LIKE ?""", ('{}%'.format(term),))
|
||||
return self.cursor.fetchall()
|
||||
|
||||
def set_user(self, screen_name, user_name, from_a_buffer):
|
||||
self.cursor.execute("""insert or ignore into users values(?, ?, ?)""", (screen_name, user_name, from_a_buffer))
|
||||
self.connection.commit()
|
||||
|
||||
def remove_user(self, user):
|
||||
self.cursor.execute("""DELETE FROM users WHERE user = ?""", (user,))
|
||||
self.connection.commit()
|
||||
return self.cursor.fetchone()
|
||||
|
||||
def remove_by_buffer(self, bufferType):
|
||||
""" Removes all users saved on a buffer. BufferType is 0 for no buffer, 1 for friends and 2 for followers"""
|
||||
self.cursor.execute("""DELETE FROM users WHERE from_a_buffer = ?""", (bufferType,))
|
||||
self.connection.commit()
|
||||
return self.cursor.fetchone()
|
||||
|
||||
def create_table(self):
|
||||
self.cursor.execute("""
|
||||
create table users(
|
||||
user TEXT UNIQUE,
|
||||
name TEXT,
|
||||
from_a_buffer INTEGER
|
||||
)""")
|
||||
|
||||
def __del__(self):
|
||||
self.cursor.close()
|
||||
self.connection.close()
|
42
src/extra/autocompletionUsers/wx_manage.py
Normal file
42
src/extra/autocompletionUsers/wx_manage.py
Normal file
@@ -0,0 +1,42 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import wx
|
||||
from multiplatform_widgets import widgets
|
||||
|
||||
class autocompletionManageDialog(wx.Dialog):
|
||||
def __init__(self):
|
||||
super(autocompletionManageDialog, self).__init__(parent=None, id=-1, title=_(u"Manage Autocomplete users’ database"))
|
||||
panel = wx.Panel(self)
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
label = wx.StaticText(panel, -1, _(u"Editing TWBlue users database"))
|
||||
self.users = widgets.list(panel, _(u"Username"), _(u"Name"), style=wx.LC_REPORT)
|
||||
sizer.Add(label, 0, wx.ALL, 5)
|
||||
sizer.Add(self.users.list, 0, wx.ALL, 5)
|
||||
self.add = wx.Button(panel, -1, _(u"Add user"))
|
||||
self.remove = wx.Button(panel, -1, _(u"Remove user"))
|
||||
optionsBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
optionsBox.Add(self.add, 0, wx.ALL, 5)
|
||||
optionsBox.Add(self.remove, 0, wx.ALL, 5)
|
||||
sizer.Add(optionsBox, 0, wx.ALL, 5)
|
||||
ok = wx.Button(panel, wx.ID_OK)
|
||||
cancel = wx.Button(panel, wx.ID_CANCEL)
|
||||
sizerBtn = wx.BoxSizer(wx.HORIZONTAL)
|
||||
sizerBtn.Add(ok, 0, wx.ALL, 5)
|
||||
sizer.Add(cancel, 0, wx.ALL, 5)
|
||||
sizer.Add(sizerBtn, 0, wx.ALL, 5)
|
||||
panel.SetSizer(sizer)
|
||||
self.SetClientSize(sizer.CalcMin())
|
||||
|
||||
def put_users(self, users):
|
||||
for i in users:
|
||||
j = [i[0], i[1]]
|
||||
self.users.insert_item(False, *j)
|
||||
|
||||
def get_user(self):
|
||||
usr = False
|
||||
userDlg = wx.TextEntryDialog(None, _(u"Twitter username"), _(u"Add user to database"))
|
||||
if userDlg.ShowModal() == wx.ID_OK:
|
||||
usr = userDlg.GetValue()
|
||||
return usr
|
||||
|
||||
def show_invalid_user_error(self):
|
||||
wx.MessageDialog(None, _(u"The user does not exist"), _(u"Error!"), wx.ICON_ERROR).ShowModal()
|
18
src/extra/autocompletionUsers/wx_menu.py
Normal file
18
src/extra/autocompletionUsers/wx_menu.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import wx
|
||||
|
||||
class menu(wx.Menu):
|
||||
def __init__(self, window, pattern):
|
||||
super(menu, self).__init__()
|
||||
self.window = window
|
||||
self.pattern = pattern
|
||||
|
||||
def append_options(self, options):
|
||||
for i in options:
|
||||
item = wx.MenuItem(self, wx.NewId(), "%s (@%s)" % (i[1], i[0]))
|
||||
self.AppendItem(item)
|
||||
self.Bind(wx.EVT_MENU, lambda evt, temp=i[0]: self.select_text(evt, temp), item)
|
||||
|
||||
def select_text(self, ev, text):
|
||||
self.window.ChangeValue(self.window.GetValue().replace(self.pattern, text+" "))
|
||||
self.window.SetInsertionPointEnd()
|
25
src/extra/autocompletionUsers/wx_settings.py
Normal file
25
src/extra/autocompletionUsers/wx_settings.py
Normal file
@@ -0,0 +1,25 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import wx
|
||||
|
||||
class autocompletionSettingsDialog(wx.Dialog):
|
||||
def __init__(self):
|
||||
super(autocompletionSettingsDialog, self).__init__(parent=None, id=-1, title=_(u"Autocomplete users’ settings"))
|
||||
panel = wx.Panel(self)
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
self.followers_buffer = wx.CheckBox(panel, -1, _(u"Add users from followers buffer"))
|
||||
self.friends_buffer = wx.CheckBox(panel, -1, _(u"Add users from friends buffer"))
|
||||
sizer.Add(self.followers_buffer, 0, wx.ALL, 5)
|
||||
sizer.Add(self.friends_buffer, 0, wx.ALL, 5)
|
||||
self.viewList = wx.Button(panel, -1, _(u"See the users list"))
|
||||
sizer.Add(self.viewList, 0, wx.ALL, 5)
|
||||
ok = wx.Button(panel, wx.ID_OK)
|
||||
cancel = wx.Button(panel, wx.ID_CANCEL)
|
||||
sizerBtn = wx.BoxSizer(wx.HORIZONTAL)
|
||||
sizerBtn.Add(ok, 0, wx.ALL, 5)
|
||||
sizer.Add(cancel, 0, wx.ALL, 5)
|
||||
sizer.Add(sizerBtn, 0, wx.ALL, 5)
|
||||
panel.SetSizer(sizer)
|
||||
self.SetClientSize(sizer.CalcMin())
|
||||
|
||||
def show_success_dialog():
|
||||
wx.MessageDialog(None, _(u"TWBlue's database of users has been updated."), _(u"Done"), wx.OK).ShowModal()
|
@@ -7,4 +7,5 @@ from favourites import *
|
||||
from lists import *
|
||||
from people import *
|
||||
from tweet_searches import *
|
||||
from user_searches import *
|
||||
from user_searches import *
|
||||
from trends import *
|
@@ -27,6 +27,7 @@ import logging as original_logger
|
||||
import output
|
||||
import platform
|
||||
import datetime
|
||||
import menus
|
||||
from twitter import prettydate
|
||||
from multiplatform_widgets import widgets
|
||||
from mysc import event
|
||||
@@ -39,6 +40,8 @@ class basePanel(wx.Panel):
|
||||
def bind_events(self):
|
||||
self.Bind(event.MyEVT_OBJECT, self.update)
|
||||
self.Bind(event.MyEVT_DELETED, self.Remove)
|
||||
self.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.showMenu, self.list.list)
|
||||
self.Bind(wx.EVT_LIST_KEY_DOWN, self.showMenuByKey, self.list.list)
|
||||
self.list.list.Bind(wx.EVT_CHAR_HOOK, self.interact)
|
||||
if self.system == "Windows":
|
||||
self.list.list.Bind(wx.EVT_LIST_ITEM_FOCUSED, self.onFocus)
|
||||
@@ -147,7 +150,7 @@ class basePanel(wx.Panel):
|
||||
if config.main["general"]["relative_times"] == True:
|
||||
# On windows we need only put the new date on the column, but under linux and mac it isn't possible.
|
||||
if self.system == "Windows":
|
||||
original_date = datetime.datetime.strptime(tweet["created_at"], "%a %b %d %H:%M:%S +0000 %Y")
|
||||
original_date = datetime.datetime.strptime(self.db.settings[self.name_buffer][self.list.get_selected()]["created_at"], "%a %b %d %H:%M:%S +0000 %Y")
|
||||
date = original_date-datetime.timedelta(seconds=-self.db.settings["utc_offset"])
|
||||
ts = prettydate(original_date)
|
||||
self.list.list.SetStringItem(self.list.get_selected(), 2, ts)
|
||||
@@ -155,6 +158,8 @@ class basePanel(wx.Panel):
|
||||
self.list.list.SetString(self.list.get_selected(), " ".join(self.compose_function(self.db.settings[self.name_buffer][self.list.get_selected()], self.db)))
|
||||
if twitter.utils.is_audio(tweet):
|
||||
sound.player.play("audio.ogg", False)
|
||||
if twitter.utils.is_geocoded(tweet):
|
||||
sound.player.play("geo.ogg", False)
|
||||
|
||||
def start_streams(self):
|
||||
if self.name_buffer == "sent":
|
||||
@@ -181,18 +186,21 @@ class basePanel(wx.Panel):
|
||||
except TwythonError as e:
|
||||
output.speak(e.message)
|
||||
for i in items:
|
||||
if config.main["general"]["reverse_timelines"] == False:
|
||||
self.db.settings[self.name_buffer].insert(0, i)
|
||||
else:
|
||||
self.db.settings[self.name_buffer].append(i)
|
||||
if twitter.utils.is_allowed(i) == True:
|
||||
if config.main["general"]["reverse_timelines"] == False:
|
||||
self.db.settings[self.name_buffer].insert(0, i)
|
||||
else:
|
||||
self.db.settings[self.name_buffer].append(i)
|
||||
if config.main["general"]["reverse_timelines"] == False:
|
||||
for i in items:
|
||||
tweet = self.compose_function(i, self.db)
|
||||
self.list.insert_item(True, *tweet)
|
||||
if twitter.utils.is_allowed(i) == True:
|
||||
tweet = self.compose_function(i, self.db)
|
||||
self.list.insert_item(True, *tweet)
|
||||
else:
|
||||
for i in items:
|
||||
tweet = self.compose_function(i, self.db)
|
||||
self.list.insert_item(False, *tweet)
|
||||
if twitter.utils.is_allowed(i) == True:
|
||||
tweet = self.compose_function(i, self.db)
|
||||
self.list.insert_item(False, *tweet)
|
||||
output.speak(_(u"%s items retrieved") % (len(items)))
|
||||
|
||||
def put_items(self, num):
|
||||
@@ -200,7 +208,7 @@ class basePanel(wx.Panel):
|
||||
for i in self.db.settings[self.name_buffer]:
|
||||
tweet = self.compose_function(i, self.db)
|
||||
self.list.insert_item(False, *tweet)
|
||||
self.set_list_position()
|
||||
self.set_list_position()
|
||||
elif self.list.get_count() > 0:
|
||||
if config.main["general"]["reverse_timelines"] == False:
|
||||
for i in self.db.settings[self.name_buffer][:num]:
|
||||
@@ -278,10 +286,15 @@ class basePanel(wx.Panel):
|
||||
if self.name_buffer in config.main["other_buffers"]["autoread_buffers"]:
|
||||
output.speak(" ".join(tweet[:2]))
|
||||
|
||||
def get_tweet(self):
|
||||
""" Gets a tweet or retweet."""
|
||||
if self.db.settings[self.name_buffer][self.list.get_selected()].has_key("retweeted_status"): tweet = self.db.settings[self.name_buffer][self.list.get_selected()]["retweeted_status"]
|
||||
else: tweet = self.db.settings[self.name_buffer][self.list.get_selected()]
|
||||
return tweet
|
||||
|
||||
def interact(self, ev):
|
||||
try:
|
||||
if self.db.settings[self.name_buffer][self.list.get_selected()].has_key("retweeted_status"): tweet = self.db.settings[self.name_buffer][self.list.get_selected()]["retweeted_status"]
|
||||
else: tweet = self.db.settings[self.name_buffer][self.list.get_selected()]
|
||||
tweet = self.get_tweet()
|
||||
urls = twitter.utils.find_urls_in_text(tweet["text"])
|
||||
except:
|
||||
urls = []
|
||||
@@ -297,14 +310,21 @@ class basePanel(wx.Panel):
|
||||
ev.Skip()
|
||||
return
|
||||
if event == "audio" and len(urls) > 0:
|
||||
self.streamer(urls[0])
|
||||
if len(urls) == 1:
|
||||
self.streamer(urls[0])
|
||||
elif len(urls) > 1:
|
||||
urlList = gui.dialogs.urlList.urlList(urls)
|
||||
if urlList.ShowModal() == wx.ID_OK:
|
||||
self.streamer(urls[urlList.lista.GetSelection()])
|
||||
elif event == "url":
|
||||
if len(urls) == 0: return
|
||||
elif len(urls) == 1:
|
||||
output.speak(_(u"Opening URL..."), True)
|
||||
webbrowser.open(urls[0])
|
||||
elif len(urls) > 1:
|
||||
gui.dialogs.urlList.urlList(urls).ShowModal()
|
||||
urlList = gui.dialogs.urlList.urlList(urls)
|
||||
if urlList.ShowModal() == wx.ID_OK:
|
||||
webbrowser.open_new_tab(urls[urlList.lista.GetSelection()])
|
||||
elif event == "volume_down":
|
||||
if config.main["sound"]["volume"] > 0.05:
|
||||
config.main["sound"]["volume"] = config.main["sound"]["volume"]-0.05
|
||||
@@ -362,3 +382,18 @@ class basePanel(wx.Panel):
|
||||
self.list.select_item(len(self.db.settings[self.name_buffer])-1)
|
||||
else:
|
||||
self.list.select_item(0)
|
||||
|
||||
def showMenu(self, ev):
|
||||
if self.list.get_count() == 0: return
|
||||
if self.name_buffer == "sent":
|
||||
self.PopupMenu(menus.sentPanelMenu(self), ev.GetPosition())
|
||||
else:
|
||||
self.PopupMenu(menus.basePanelMenu(self), ev.GetPosition())
|
||||
|
||||
def showMenuByKey(self, ev):
|
||||
if self.list.get_count() == 0: return
|
||||
if ev.GetKeyCode() == wx.WXK_WINDOWS_MENU:
|
||||
if self.name_buffer == "sent":
|
||||
self.PopupMenu(menus.sentPanelMenu(self), self.list.list.GetPosition())
|
||||
else:
|
||||
self.PopupMenu(menus.basePanelMenu(self), self.list.list.GetPosition())
|
||||
|
@@ -19,6 +19,7 @@
|
||||
import wx
|
||||
import sound
|
||||
import gui.dialogs
|
||||
import menus
|
||||
import logging as original_logger
|
||||
from base import basePanel
|
||||
from mysc.thread_utils import call_threaded
|
||||
@@ -30,6 +31,7 @@ class dmPanel(basePanel):
|
||||
super(dmPanel, self).__init__(parent, window, name_buffer, function, argumento=argumento, sound=sound)
|
||||
self.retweetBtn.Disable()
|
||||
self.responseBtn.Disable()
|
||||
self.type = "direct_message"
|
||||
|
||||
def destroy_status(self, ev):
|
||||
index = self.list.get_selected()
|
||||
@@ -45,4 +47,13 @@ class dmPanel(basePanel):
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
call_threaded(self.twitter.api_call, call_name="send_direct_message", _sound="dm_sent.ogg", text=dlg.text.GetValue(), screen_name=dlg.cb.GetValue())
|
||||
if ev != None:
|
||||
self.list.list.SetFocus()
|
||||
self.list.list.SetFocus()
|
||||
|
||||
def showMenu(self, ev):
|
||||
if self.list.get_count() == 0: return
|
||||
self.PopupMenu(menus.dmPanelMenu(self), ev.GetPosition())
|
||||
|
||||
def showMenuByKey(self, ev):
|
||||
if self.list.get_count() == 0: return
|
||||
if ev.GetKeyCode() == wx.WXK_WINDOWS_MENU:
|
||||
self.PopupMenu(menus.dmPanelMenu(self), self.list.list.GetPosition())
|
||||
|
@@ -21,6 +21,7 @@ import sound
|
||||
import config
|
||||
import platform
|
||||
import gui.dialogs
|
||||
import menus
|
||||
import output
|
||||
import logging as original_logger
|
||||
from multiplatform_widgets import widgets
|
||||
@@ -36,6 +37,8 @@ class eventsPanel(wx.Panel):
|
||||
|
||||
def bind_events(self):
|
||||
self.Bind(event.MyEVT_OBJECT, self.update)
|
||||
self.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.showMenu, self.list.list)
|
||||
self.Bind(wx.EVT_LIST_KEY_DOWN, self.showMenuByKey, self.list.list)
|
||||
|
||||
def put_items(self, items):
|
||||
pass
|
||||
@@ -131,4 +134,13 @@ class eventsPanel(wx.Panel):
|
||||
try:
|
||||
ev.Skip()
|
||||
except:
|
||||
pass
|
||||
pass
|
||||
|
||||
def showMenu(self, ev):
|
||||
if self.list.get_count() == 0: return
|
||||
self.PopupMenu(menus.eventsPanelMenu(self), ev.GetPosition())
|
||||
|
||||
def showMenuByKey(self, ev):
|
||||
if self.list.get_count() == 0: return
|
||||
if ev.GetKeyCode() == wx.WXK_WINDOWS_MENU:
|
||||
self.PopupMenu(menus.eventsPanelMenu(self), self.list.list.GetPosition())
|
||||
|
@@ -30,7 +30,7 @@ class favsPanel(basePanel):
|
||||
self.type = "favourites_timeline"
|
||||
|
||||
def start_streams(self):
|
||||
num = twitter.starting.get_favourites_timeline(self.db, self.twitter, self.name_buffer, param=self.argumento, count=200)
|
||||
num = twitter.starting.get_favourites_timeline(self.db, self.twitter, self.name_buffer, param=self.argumento, count=config.main["general"]["max_tweets_per_call"])
|
||||
if self.sound != "" and num > 0:
|
||||
sound.player.play(self.sound)
|
||||
if self.list.get_count() > 0: self.put_items(num)
|
||||
|
@@ -35,7 +35,7 @@ class listPanel(basePanel):
|
||||
|
||||
def start_streams(self):
|
||||
self.retrieve_ids()
|
||||
num = twitter.starting.start_list(self.db, self.twitter, self.name_buffer, list_id=self.argumento)
|
||||
num = twitter.starting.start_list(self.db, self.twitter, self.name_buffer, list_id=self.argumento, count=config.main["general"]["max_tweets_per_call"])
|
||||
return num
|
||||
|
||||
def retrieve_ids(self):
|
||||
|
134
src/gui/buffers/menus.py
Normal file
134
src/gui/buffers/menus.py
Normal file
@@ -0,0 +1,134 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import wx
|
||||
|
||||
class basePanelMenu(wx.Menu):
|
||||
def __init__(self, parent):
|
||||
super(basePanelMenu, self).__init__()
|
||||
self.window = parent
|
||||
retweet = wx.MenuItem(self, wx.NewId(), _(u"&Retweet"))
|
||||
self.Bind(wx.EVT_MENU, self.window.onRetweet, retweet)
|
||||
self.AppendItem(retweet)
|
||||
reply = wx.MenuItem(self, wx.NewId(), _(u"Re&ply"))
|
||||
self.Bind(wx.EVT_MENU, self.window.onResponse, reply)
|
||||
self.AppendItem(reply)
|
||||
fav = wx.MenuItem(self, wx.NewId(), _(u"Add to &favourites"))
|
||||
self.Bind(wx.EVT_MENU, self.window.parent.fav, fav)
|
||||
self.AppendItem(fav)
|
||||
unfav = wx.MenuItem(self, wx.NewId(), _(u"Remove from favo&urites"))
|
||||
self.Bind(wx.EVT_MENU, self.window.parent.unfav, unfav)
|
||||
self.AppendItem(unfav)
|
||||
openUrl = wx.MenuItem(self, wx.NewId(), _(u"&Open URL"))
|
||||
self.Bind(wx.EVT_MENU, self.window.parent.url, openUrl)
|
||||
self.AppendItem(openUrl)
|
||||
play = wx.MenuItem(self, wx.NewId(), _(u"&Play audio"))
|
||||
self.Bind(wx.EVT_MENU, self.window.parent.audio, play)
|
||||
self.AppendItem(play)
|
||||
view = wx.MenuItem(self, wx.NewId(), _(u"&Show tweet"))
|
||||
self.Bind(wx.EVT_MENU, self.window.parent.view, view)
|
||||
self.AppendItem(view)
|
||||
copy = wx.MenuItem(self, wx.NewId(), _(u"&Copy to clipboard"))
|
||||
self.Bind(wx.EVT_MENU, self.window.parent.copy_to_clipboard, copy)
|
||||
self.AppendItem(copy)
|
||||
remove = wx.MenuItem(self, wx.NewId(), _(u"&Delete"))
|
||||
self.Bind(wx.EVT_MENU, self.window.parent.delete, remove)
|
||||
self.AppendItem(remove)
|
||||
userActions = wx.MenuItem(self, wx.NewId(), _(u"&User actions..."))
|
||||
self.Bind(wx.EVT_MENU, self.window.parent.onFollow, userActions)
|
||||
self.AppendItem(userActions)
|
||||
|
||||
class dmPanelMenu(wx.Menu):
|
||||
def __init__(self, parent):
|
||||
super(dmPanelMenu, self).__init__()
|
||||
self.window = parent
|
||||
reply = wx.MenuItem(self, wx.NewId(), _(u"Re&ply"))
|
||||
self.Bind(wx.EVT_MENU, self.window.onResponse, reply)
|
||||
self.AppendItem(reply)
|
||||
openUrl = wx.MenuItem(self, wx.NewId(), _(u"&Open URL"))
|
||||
self.Bind(wx.EVT_MENU, self.window.parent.url, openUrl)
|
||||
self.AppendItem(openUrl)
|
||||
play = wx.MenuItem(self, wx.NewId(), _(u"&Play audio"))
|
||||
self.Bind(wx.EVT_MENU, self.window.parent.audio, play)
|
||||
self.AppendItem(play)
|
||||
view = wx.MenuItem(self, wx.NewId(), _(u"&Show direct message"))
|
||||
self.Bind(wx.EVT_MENU, self.window.parent.view, view)
|
||||
self.AppendItem(view)
|
||||
copy = wx.MenuItem(self, wx.NewId(), _(u"&Copy to clipboard"))
|
||||
self.Bind(wx.EVT_MENU, self.window.parent.copy_to_clipboard, copy)
|
||||
self.AppendItem(copy)
|
||||
remove = wx.MenuItem(self, wx.NewId(), _(u"&Delete"))
|
||||
self.Bind(wx.EVT_MENU, self.window.parent.delete, remove)
|
||||
self.AppendItem(remove)
|
||||
userActions = wx.MenuItem(self, wx.NewId(), _(u"&User actions..."))
|
||||
self.Bind(wx.EVT_MENU, self.window.parent.onFollow, userActions)
|
||||
self.AppendItem(userActions)
|
||||
|
||||
class sentPanelMenu(wx.Menu):
|
||||
def __init__(self, parent):
|
||||
super(sentPanelMenu, self).__init__()
|
||||
self.window = parent
|
||||
openUrl = wx.MenuItem(self, wx.NewId(), _(u"&Open URL"))
|
||||
self.Bind(wx.EVT_MENU, self.window.parent.url, openUrl)
|
||||
self.AppendItem(openUrl)
|
||||
play = wx.MenuItem(self, wx.NewId(), _(u"&Play audio"))
|
||||
self.Bind(wx.EVT_MENU, self.window.parent.audio, play)
|
||||
self.AppendItem(play)
|
||||
view = wx.MenuItem(self, wx.NewId(), _(u"&Show tweet"))
|
||||
self.Bind(wx.EVT_MENU, self.window.parent.view, view)
|
||||
self.AppendItem(view)
|
||||
copy = wx.MenuItem(self, wx.NewId(), _(u"&Copy to clipboard"))
|
||||
self.Bind(wx.EVT_MENU, self.window.parent.copy_to_clipboard, copy)
|
||||
self.AppendItem(copy)
|
||||
remove = wx.MenuItem(self, wx.NewId(), _(u"&Delete"))
|
||||
self.Bind(wx.EVT_MENU, self.window.parent.delete, remove)
|
||||
self.AppendItem(remove)
|
||||
|
||||
class eventsPanelMenu(wx.Menu):
|
||||
def __init__(self, parent):
|
||||
super(eventsPanelMenu, self).__init__()
|
||||
self.window = parent
|
||||
view = wx.MenuItem(self, wx.NewId(), _(u"&Show event"))
|
||||
self.Bind(wx.EVT_MENU, self.window.parent.view, view)
|
||||
self.AppendItem(view)
|
||||
copy = wx.MenuItem(self, wx.NewId(), _(u"&Copy to clipboard"))
|
||||
self.Bind(wx.EVT_MENU, self.window.parent.copy_to_clipboard, copy)
|
||||
self.AppendItem(copy)
|
||||
remove = wx.MenuItem(self, wx.NewId(), _(u"&Delete"))
|
||||
self.Bind(wx.EVT_MENU, self.window.parent.delete, remove)
|
||||
self.AppendItem(remove)
|
||||
|
||||
class peoplePanelMenu(wx.Menu):
|
||||
def __init__(self, parent):
|
||||
super(peoplePanelMenu, self).__init__()
|
||||
self.window = parent
|
||||
reply = wx.MenuItem(self, wx.NewId(), _(u"&Mention"))
|
||||
self.Bind(wx.EVT_MENU, self.window.onResponse, reply)
|
||||
self.AppendItem(reply)
|
||||
lists = wx.MenuItem(self, wx.NewId(), _(u"&View lists"))
|
||||
self.Bind(wx.EVT_MENU, self.window.parent.view_user_lists, lists)
|
||||
self.AppendItem(lists)
|
||||
details = wx.MenuItem(self, wx.NewId(), _(u"Show user &profile"))
|
||||
self.Bind(wx.EVT_MENU, self.window.parent.details, details)
|
||||
self.AppendItem(details)
|
||||
view = wx.MenuItem(self, wx.NewId(), _(u"&Show user"))
|
||||
self.Bind(wx.EVT_MENU, self.window.parent.view, view)
|
||||
self.AppendItem(view)
|
||||
copy = wx.MenuItem(self, wx.NewId(), _(u"&Copy to clipboard"))
|
||||
self.Bind(wx.EVT_MENU, self.window.parent.copy_to_clipboard, copy)
|
||||
self.AppendItem(copy)
|
||||
userActions = wx.MenuItem(self, wx.NewId(), _(u"&User actions..."))
|
||||
self.Bind(wx.EVT_MENU, self.window.parent.onFollow, userActions)
|
||||
self.AppendItem(userActions)
|
||||
|
||||
class trendsPanelMenu(wx.Menu):
|
||||
def __init__(self, parent):
|
||||
super(trendsPanelMenu, self).__init__()
|
||||
self.window = parent
|
||||
tweetThisTrend = wx.MenuItem(self, wx.NewId(), _(u"&Tweet about this trend"))
|
||||
self.Bind(wx.EVT_MENU, self.window.onResponse, tweetThisTrend)
|
||||
self.AppendItem(tweetThisTrend)
|
||||
view = wx.MenuItem(self, wx.NewId(), _(u"&Show item"))
|
||||
self.Bind(wx.EVT_MENU, self.window.parent.view, view)
|
||||
self.AppendItem(view)
|
||||
copy = wx.MenuItem(self, wx.NewId(), _(u"&Copy to clipboard"))
|
||||
self.Bind(wx.EVT_MENU, self.window.parent.copy_to_clipboard, copy)
|
||||
self.AppendItem(copy)
|
@@ -20,18 +20,20 @@ import wx
|
||||
from multiplatform_widgets import widgets
|
||||
|
||||
class accountPanel(wx.Panel):
|
||||
def __init__(self, parent):
|
||||
def __init__(self, parent, name_buffer):
|
||||
super(accountPanel, self).__init__(parent=parent)
|
||||
self.type = "account"
|
||||
self.name_buffer = name_buffer
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
self.list = widgets.list(self, _(u"Announce"))
|
||||
sizer.Add(self.list.list, 0, wx.ALL, 5)
|
||||
self.SetSizer(sizer)
|
||||
|
||||
def get_more_items(self):
|
||||
output.speak(_(u"This action is not supported for this buffer"))
|
||||
|
||||
class emptyPanel(accountPanel):
|
||||
def __init__(self, parent):
|
||||
super(emptyPanel, self).__init__(parent=parent)
|
||||
super(emptyPanel, self).__init__(parent=parent, name_buffer="")
|
||||
self.type = "empty"
|
||||
|
||||
def get_more_items(self):
|
||||
output.speak(_(u"This action is not supported for this buffer"))
|
@@ -21,6 +21,7 @@ import sound
|
||||
import config
|
||||
import twitter
|
||||
import gui.dialogs
|
||||
import menus
|
||||
import logging as original_logger
|
||||
import output
|
||||
from multiplatform_widgets import widgets
|
||||
@@ -36,13 +37,15 @@ class peoplePanel(basePanel):
|
||||
self.Bind(event.MyEVT_OBJECT, self.update)
|
||||
self.Bind(event.MyEVT_DELETED, self.Remove)
|
||||
self.list.list.Bind(wx.EVT_CHAR_HOOK, self.interact)
|
||||
self.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.showMenu, self.list.list)
|
||||
self.Bind(wx.EVT_LIST_KEY_DOWN, self.showMenuByKey, self.list.list)
|
||||
|
||||
def create_list(self):
|
||||
self.list = widgets.list(self, _(u"User"), style=wx.LC_REPORT|wx.LC_SINGLE_SEL, size=(800, 800))
|
||||
|
||||
def __init__(self, parent, window, name_buffer, function, argumento=None, sound="", timeline=False):
|
||||
self.type = "people"
|
||||
super(peoplePanel, self).__init__(parent, window, name_buffer, function, argumento=argumento, sound=sound)
|
||||
self.type = "people"
|
||||
self.responseBtn.SetLabel(_(u"Mention"))
|
||||
self.retweetBtn.Disable()
|
||||
self.compose_function = twitter.compose.compose_followers_list
|
||||
@@ -140,3 +143,18 @@ class peoplePanel(basePanel):
|
||||
def remove_buffer(self):
|
||||
pos = None
|
||||
return pos
|
||||
|
||||
def get_message(self, dialog=False):
|
||||
if dialog == False: return " ".join(self.compose_function(self.db.settings[self.name_buffer][self.list.get_selected()], self.db))
|
||||
else:
|
||||
list = self.compose_function(self.db.settings[self.name_buffer][self.list.get_selected()], self.db)
|
||||
return " ".join(list)
|
||||
|
||||
def showMenu(self, ev):
|
||||
if self.list.get_count() == 0: return
|
||||
self.PopupMenu(menus.peoplePanelMenu(self), ev.GetPosition())
|
||||
|
||||
def showMenuByKey(self, ev):
|
||||
if self.list.get_count() == 0: return
|
||||
if ev.GetKeyCode() == wx.WXK_WINDOWS_MENU:
|
||||
self.PopupMenu(menus.peoplePanelMenu(self), self.list.list.GetPosition())
|
||||
|
@@ -17,35 +17,155 @@
|
||||
#
|
||||
############################################################
|
||||
import wx
|
||||
import sound
|
||||
import config
|
||||
import twitter
|
||||
import gui.dialogs
|
||||
import twitter
|
||||
import config
|
||||
import sound
|
||||
import logging as original_logger
|
||||
from base import basePanel
|
||||
import output
|
||||
import platform
|
||||
import menus
|
||||
from multiplatform_widgets import widgets
|
||||
from mysc.thread_utils import call_threaded
|
||||
log = original_logger.getLogger("buffers.base")
|
||||
|
||||
class trendPanel(basePanel):
|
||||
def __init__(self, parent, window, name_buffer, *args, **kwargs):
|
||||
super(searchPanel, self).__init__(parent, window, name_buffer, sound)
|
||||
self.type = "trend"
|
||||
self.args = kwargs
|
||||
class trendsPanel(wx.Panel):
|
||||
|
||||
def compose_function(self, trend):
|
||||
return [trend["name"]]
|
||||
|
||||
def start_streams(self):
|
||||
num = twitter.starting.search(self.db, self.twitter, self.name_buffer, **self.args)
|
||||
if num > 0: sound.player.play("search_updated.ogg")
|
||||
self.put_items(num)
|
||||
return num
|
||||
def bind_events(self):
|
||||
self.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.showMenu, self.list.list)
|
||||
self.Bind(wx.EVT_LIST_KEY_DOWN, self.showMenuByKey, self.list.list)
|
||||
self.list.list.Bind(wx.EVT_CHAR_HOOK, self.interact)
|
||||
|
||||
def get_message(self, dialog=False):
|
||||
return self.compose_function(self.trends[self.list.get_selected()])[0]
|
||||
|
||||
|
||||
def create_list(self):
|
||||
self.list = widgets.list(self, _(u"Trending topic"), style=wx.LC_REPORT|wx.LC_SINGLE_SEL|wx.LC_VRULES)
|
||||
if self.system == "Windows":
|
||||
self.list.set_windows_size(0, 30)
|
||||
self.list.set_size()
|
||||
|
||||
def __init__(self, parent, window, name_buffer, argumento=None, sound=""):
|
||||
self.type = "trends"
|
||||
self.twitter = window.twitter
|
||||
self.name_buffer = name_buffer
|
||||
self.argumento = argumento
|
||||
self.sound = sound
|
||||
self.parent = window
|
||||
self.system = platform.system()
|
||||
wx.Panel.__init__(self, parent)
|
||||
self.trends = []
|
||||
self.sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
self.create_list()
|
||||
self.btn = wx.Button(self, -1, _(u"Tweet"))
|
||||
self.btn.Bind(wx.EVT_BUTTON, self.post_status)
|
||||
self.tweetTrendBtn = wx.Button(self, -1, _(u"Tweet about this trend"))
|
||||
self.tweetTrendBtn.Bind(wx.EVT_BUTTON, self.onResponse)
|
||||
btnSizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
btnSizer.Add(self.btn, 0, wx.ALL, 5)
|
||||
btnSizer.Add(self.tweetTrendBtn, 0, wx.ALL, 5)
|
||||
self.sizer.Add(btnSizer, 0, wx.ALL, 5)
|
||||
self.sizer.Add(self.list.list, 0, wx.ALL, 5)
|
||||
self.bind_events()
|
||||
self.SetSizer(self.sizer)
|
||||
|
||||
def remove_buffer(self):
|
||||
dlg = wx.MessageDialog(self, _(u"Do you really want to delete this search term?"), _(u"Attention"), style=wx.ICON_QUESTION|wx.YES_NO)
|
||||
dlg = wx.MessageDialog(self, _(u"Do you really want to delete this buffer?"), _(u"Attention"), style=wx.ICON_QUESTION|wx.YES_NO)
|
||||
if dlg.ShowModal() == wx.ID_YES:
|
||||
names = config.main["other_buffers"]["tweet_searches"]
|
||||
user = self.name_buffer[:-7]
|
||||
log.info(u"Deleting %s's search term" % user)
|
||||
if user in names:
|
||||
names.remove(user)
|
||||
self.db.settings.pop(self.name_buffer)
|
||||
pos = self.db.settings["buffers"].index(self.name_buffer)
|
||||
self.db.settings["buffers"].remove(self.name_buffer)
|
||||
return pos
|
||||
topics = config.main["other_buffers"]["trending_topic_buffers"]
|
||||
topic = self.name_buffer[:-3]
|
||||
log.info(u"Deleting %s's trending topics buffer" % topic)
|
||||
if topic in topics:
|
||||
topics.remove(topic)
|
||||
return 0
|
||||
|
||||
def start_streams(self):
|
||||
data = self.twitter.twitter.get_place_trends(id=self.argumento)
|
||||
if not hasattr(self, "name"):
|
||||
self.name = data[0]["locations"][0]["name"]
|
||||
self.trends = data[0]["trends"]
|
||||
sound.player.play(self.sound)
|
||||
return len(self.trends)
|
||||
|
||||
def get_more_items(self):
|
||||
output.speak(_(u"This action is not supported for this buffer"))
|
||||
|
||||
def put_items(self, num):
|
||||
selected_item = self.list.get_selected()
|
||||
self.list.clear()
|
||||
for i in self.trends:
|
||||
tweet = self.compose_function(i)
|
||||
self.list.insert_item(False, *tweet)
|
||||
self.set_list_position()
|
||||
self.list.select_item(selected_item)
|
||||
|
||||
def post_status(self, ev=None):
|
||||
text = gui.dialogs.message.tweet(_(u"Write the tweet here"), _(u"Tweet"), "", self)
|
||||
if text.ShowModal() == wx.ID_OK:
|
||||
if text.image == None:
|
||||
call_threaded(self.twitter.api_call, call_name="update_status", _sound="tweet_send.ogg", status=text.text.GetValue())
|
||||
else:
|
||||
call_threaded(self.twitter.api_call, call_name="update_status_with_media", _sound="tweet_send.ogg", status=text.text.GetValue(), media=text.file)
|
||||
if ev != None: self.list.list.SetFocus()
|
||||
|
||||
def onRetweet(self, event=None): pass
|
||||
|
||||
def onResponse(self, ev):
|
||||
trend = self.trends[self.list.get_selected()]["name"]
|
||||
text = gui.dialogs.message.tweet(_(u"Write the tweet here"), _(u"Tweet"), trend+" ", self)
|
||||
if text.ShowModal() == wx.ID_OK:
|
||||
if text.image == None:
|
||||
call_threaded(self.twitter.api_call, call_name="update_status", _sound="tweet_send.ogg", status=text.text.GetValue())
|
||||
else:
|
||||
call_threaded(self.twitter.api_call, call_name="update_status_with_media", _sound="tweet_send.ogg", status=text.text.GetValue(), media=text.file)
|
||||
if ev != None: self.list.list.SetFocus()
|
||||
|
||||
def interact(self, ev):
|
||||
if type(ev) is str: event = ev
|
||||
else:
|
||||
if ev.GetKeyCode() == wx.WXK_F5: event = "volume_down"
|
||||
elif ev.GetKeyCode() == wx.WXK_F6: event = "volume_up"
|
||||
elif ev.GetKeyCode() == wx.WXK_DELETE and ev.ShiftDown(): event = "clear_list"
|
||||
else:
|
||||
ev.Skip()
|
||||
return
|
||||
if event == "volume_down":
|
||||
if config.main["sound"]["volume"] > 0.05:
|
||||
config.main["sound"]["volume"] = config.main["sound"]["volume"]-0.05
|
||||
sound.player.play("volume_changed.ogg", False)
|
||||
if hasattr(self.parent, "audioStream"):
|
||||
self.parent.audioStream.stream.volume = config.main["sound"]["volume"]
|
||||
elif event == "volume_up":
|
||||
if config.main["sound"]["volume"] < 0.95:
|
||||
config.main["sound"]["volume"] = config.main["sound"]["volume"]+0.05
|
||||
sound.player.play("volume_changed.ogg", False)
|
||||
if hasattr(self.parent, "audioStream"):
|
||||
self.parent.audioStream.stream.volume = config.main["sound"]["volume"]
|
||||
elif event == "clear_list" and self.list.get_count() > 0:
|
||||
dlg = wx.MessageDialog(self, _(u"Do you really want to empty this buffer? It's items will be removed from the list"), _(u"Empty buffer"), wx.ICON_QUESTION|wx.YES_NO)
|
||||
if dlg.ShowModal() == wx.ID_YES:
|
||||
self.trends = []
|
||||
self.list.clear()
|
||||
try:
|
||||
ev.Skip()
|
||||
except:
|
||||
pass
|
||||
|
||||
def set_list_position(self):
|
||||
if config.main["general"]["reverse_timelines"] == False:
|
||||
self.list.select_item(len(self.trends)-1)
|
||||
else:
|
||||
self.list.select_item(0)
|
||||
|
||||
def showMenu(self, ev):
|
||||
if self.list.get_count() == 0: return
|
||||
self.PopupMenu(menus.trendsPanelMenu(self), ev.GetPosition())
|
||||
|
||||
def showMenuByKey(self, ev):
|
||||
if self.list.get_count() == 0: return
|
||||
if ev.GetKeyCode() == wx.WXK_WINDOWS_MENU:
|
||||
self.PopupMenu(menus.trendsPanelMenu(self), self.list.list.GetPosition())
|
||||
|
@@ -40,7 +40,7 @@ class searchUsersPanel(peoplePanel):
|
||||
self.create_list()
|
||||
self.args = args
|
||||
self.kwargs = kwargs
|
||||
self.type = "timeline"
|
||||
self.type = "user_search"
|
||||
|
||||
def start_streams(self):
|
||||
num = twitter.starting.search_users(self.db, self.twitter, self.name_buffer, **self.kwargs)
|
||||
|
@@ -1 +1 @@
|
||||
import message, urlList, follow, utils, show_user, update_profile, configuration, lists, search
|
||||
import message, urlList, follow, utils, show_user, update_profile, configuration, lists, search, trending
|
@@ -29,6 +29,7 @@ import webbrowser
|
||||
import paths
|
||||
import platform
|
||||
from mysc import restart
|
||||
from extra.autocompletionUsers import settings
|
||||
log = original_logger.getLogger("configuration")
|
||||
|
||||
system = platform.system()
|
||||
@@ -50,9 +51,13 @@ class general(wx.Panel):
|
||||
langBox.Add(language, 0, wx.ALL, 5)
|
||||
langBox.Add(self.language, 0, wx.ALL, 5)
|
||||
sizer.Add(langBox, 0, wx.ALL, 5)
|
||||
self.au = wx.Button(self, -1, _(u"Set the autocomplete function"))
|
||||
self.ask_at_exit = wx.CheckBox(self, -1, _(U"ask before exiting TwBlue?"))
|
||||
self.ask_at_exit.SetValue(config.main["general"]["ask_at_exit"])
|
||||
sizer.Add(self.ask_at_exit, 0, wx.ALL, 5)
|
||||
self.use_invisible_shorcuts = wx.CheckBox(self, -1, _(u"Use invisible interface's keyboard shorcuts on the GUI"))
|
||||
self.use_invisible_shorcuts.SetValue(config.main["general"]["use_invisible_keyboard_shorcuts"])
|
||||
sizer.Add(self.use_invisible_shorcuts, 0, wx.ALL, 5)
|
||||
self.relative_time = wx.CheckBox(self, -1, _(U"Relative times"))
|
||||
self.relative_time.SetValue(config.main["general"]["relative_times"])
|
||||
sizer.Add(self.relative_time, 0, wx.ALL, 5)
|
||||
@@ -84,6 +89,7 @@ class general(wx.Panel):
|
||||
sizer.Add(self.reverse_timelines, 0, wx.ALL, 5)
|
||||
self.SetSizer(sizer)
|
||||
|
||||
|
||||
class other_buffers(wx.Panel):
|
||||
def __init__(self, parent):
|
||||
wx.Panel.__init__(self, parent)
|
||||
@@ -264,6 +270,7 @@ class configurationDialog(wx.Dialog):
|
||||
self.general = general(notebook)
|
||||
notebook.AddPage(self.general, _(u"General"))
|
||||
self.general.SetFocus()
|
||||
self.Bind(wx.EVT_BUTTON, self.autocompletion, self.general.au)
|
||||
self.buffers = other_buffers(notebook)
|
||||
notebook.AddPage(self.buffers, _(u"Show other buffers"))
|
||||
self.ignored_clients = ignoredClients(notebook)
|
||||
@@ -285,6 +292,9 @@ class configurationDialog(wx.Dialog):
|
||||
panel.SetSizer(sizer)
|
||||
self.SetClientSize(sizer.CalcMin())
|
||||
|
||||
def autocompletion(self, ev):
|
||||
configuration = settings.autocompletionSettings(self.parent)
|
||||
|
||||
def check_followers_change(self):
|
||||
if self.buffers.followers.GetValue() != self.buffers.followers_value:
|
||||
if self.buffers.followers.GetValue() == True:
|
||||
@@ -376,6 +386,13 @@ class configurationDialog(wx.Dialog):
|
||||
if platform.system() == "Windows":
|
||||
config.main["general"]["voice_enabled"] = self.general.disable_sapi5.GetValue()
|
||||
config.main["general"]["ask_at_exit"] = self.general.ask_at_exit.GetValue()
|
||||
if (self.general.use_invisible_shorcuts.GetValue() == True and config.main["general"]["use_invisible_keyboard_shorcuts"] != True) and self.parent.showing == True:
|
||||
km = self.parent.create_invisible_keyboard_shorcuts()
|
||||
self.parent.register_invisible_keyboard_shorcuts(km)
|
||||
elif (self.general.use_invisible_shorcuts.GetValue() == False and config.main["general"]["use_invisible_keyboard_shorcuts"] != False) and self.parent.showing == True:
|
||||
km = self.parent.create_invisible_keyboard_shorcuts()
|
||||
self.parent.unregister_invisible_keyboard_shorcuts(km)
|
||||
config.main["general"]["use_invisible_keyboard_shorcuts"] = self.general.use_invisible_shorcuts.GetValue()
|
||||
config.main["general"]["hide_gui"] = self.general.show_gui.GetValue()
|
||||
config.main["general"]["max_api_calls"] = self.general.apiCalls.GetValue()
|
||||
config.main["general"]["max_tweets_per_call"] = self.general.itemsPerApiCall.GetValue()
|
||||
|
@@ -23,6 +23,7 @@ import twitter
|
||||
from twitter import utils
|
||||
from twython import TwythonError
|
||||
import output
|
||||
import re
|
||||
|
||||
class follow(wx.Dialog):
|
||||
def __init__(self, parent, default="follow"):
|
||||
@@ -48,6 +49,7 @@ class follow(wx.Dialog):
|
||||
self.block = wx.RadioButton(panel, -1, _(u"Block"))
|
||||
self.unblock = wx.RadioButton(panel, -1, _(u"Unblock"))
|
||||
self.reportSpam = wx.RadioButton(panel, -1, _(u"Report as spam"))
|
||||
self.ignore_client = wx.RadioButton(panel, -1, _(u"Ignore tweets from this client"))
|
||||
self.setup_default(default)
|
||||
actionSizer.Add(label2)
|
||||
actionSizer.Add(self.follow)
|
||||
@@ -57,6 +59,7 @@ class follow(wx.Dialog):
|
||||
actionSizer.Add(self.block)
|
||||
actionSizer.Add(self.unblock)
|
||||
actionSizer.Add(self.reportSpam)
|
||||
actionSizer.Add(self.ignore_client)
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
ok = wx.Button(panel, wx.ID_OK, _(u"OK"))
|
||||
ok.Bind(wx.EVT_BUTTON, self.onok)
|
||||
@@ -133,6 +136,16 @@ class follow(wx.Dialog):
|
||||
self.Destroy()
|
||||
except TwythonError as err:
|
||||
output.speak("Error %s: %s" % (err.error_code, err.msg), True)
|
||||
elif self.ignore_client.GetValue() == True:
|
||||
tweet = self.parent.get_tweet()
|
||||
if tweet.has_key("sender"):
|
||||
output.speak(_(u"You can't ignore direct messages"))
|
||||
return
|
||||
else:
|
||||
client = re.sub(r"(?s)<.*?>", "", tweet["source"])
|
||||
if client not in config.main["twitter"]["ignored_clients"]:
|
||||
config.main["twitter"]["ignored_clients"].append(client)
|
||||
self.Destroy()
|
||||
|
||||
def setup_default(self, default):
|
||||
if default == "follow":
|
||||
|
@@ -127,7 +127,7 @@ class listViewer(wx.Dialog):
|
||||
output.speak(_(u"This list is arready opened."))
|
||||
return
|
||||
listUI = gui.buffers.lists.listPanel(self.nb, self.parent, list_updated["slug"]+"-list", argumento=utils.find_list(list_updated["slug"], self.db.settings["lists"]))
|
||||
self.nb.AddPage(listUI, _(u"List for %s") % (list_updated["slug"],))
|
||||
self.nb.InsertSubPage(self.db.settings["buffers"].index("lists"), listUI, _(u"List for %s") % (list_updated["slug"],))
|
||||
self.db.settings["buffers"].append(list_updated["slug"]+"-list")
|
||||
num = listUI.start_streams()
|
||||
listUI.put_items(num)
|
||||
@@ -165,6 +165,14 @@ class userListViewer(listViewer):
|
||||
self.db.settings["lists"].append(list)
|
||||
except TwythonError as e:
|
||||
output.speak("error %s: %s" % (e.status_code, e.msg))
|
||||
def onDelete(self, event=None):
|
||||
list_id = self.lists[self.lista.get_selected()]["id"]
|
||||
try:
|
||||
list = self.twitter.twitter.unsubscribe_from_list(list_id=list_id)
|
||||
item = utils.find_item(list["id"], self.db.settings["lists"])
|
||||
self.db.settings["lists"].remove(list)
|
||||
except TwythonError as e:
|
||||
output.speak("error %s: %s" % (e.msg))
|
||||
|
||||
class createListDialog(wx.Dialog):
|
||||
|
||||
|
@@ -30,6 +30,7 @@ from twython import TwythonError
|
||||
from extra import translator, AudioUploader
|
||||
import platform
|
||||
from extra.AudioUploader import transfer
|
||||
from extra.autocompletionUsers import completion
|
||||
if platform.system() != "Darwin":
|
||||
from extra.AudioUploader import dropbox_transfer
|
||||
from extra.SpellChecker import gui as spellCheckerGUI
|
||||
@@ -183,6 +184,8 @@ class tweet(textLimited):
|
||||
self.okButton = wx.Button(self.panel, wx.ID_OK, _(u"Send"), size=wx.DefaultSize)
|
||||
self.okButton.Bind(wx.EVT_BUTTON, self.onSend)
|
||||
self.okButton.SetDefault()
|
||||
autocompletionButton = wx.Button(self.panel, -1, _(u"&Autocomplete users"))
|
||||
self.Bind(wx.EVT_BUTTON, self.autocompletion, autocompletionButton)
|
||||
cancelButton = wx.Button(self.panel, wx.ID_CANCEL, _(u"Close"), size=wx.DefaultSize)
|
||||
cancelButton.Bind(wx.EVT_BUTTON, self.onCancel)
|
||||
self.buttonsBox1 = wx.BoxSizer(wx.HORIZONTAL)
|
||||
@@ -202,8 +205,11 @@ class tweet(textLimited):
|
||||
self.mainBox.Add(self.ok_cancelSizer)
|
||||
selectId = wx.NewId()
|
||||
self.Bind(wx.EVT_MENU, self.onSelect, id=selectId)
|
||||
# autocompletionId = wx.NewId()
|
||||
# self.Bind(wx.EVT_MENU, self.autocompletion, id=autocompletionId)
|
||||
self.accel_tbl = wx.AcceleratorTable([
|
||||
(wx.ACCEL_CTRL, ord('A'), selectId),
|
||||
#(wx.ACCEL_ALT, ord('A'), autocompletionId),
|
||||
])
|
||||
self.SetAcceleratorTable(self.accel_tbl)
|
||||
self.panel.SetSizer(self.mainBox)
|
||||
@@ -215,6 +221,10 @@ class tweet(textLimited):
|
||||
self.onTimer(wx.EVT_CHAR_HOOK)
|
||||
self.SetClientSize(self.mainBox.CalcMin())
|
||||
|
||||
def autocompletion(self, event=None):
|
||||
c = completion.autocompletionUsers(self)
|
||||
c.show_menu()
|
||||
|
||||
def onUpload_image(self, ev):
|
||||
if self.upload_image.GetLabel() == _(u"Discard image"):
|
||||
self.image = None
|
||||
@@ -305,7 +315,7 @@ class reply(tweet):
|
||||
super(reply, self).__init__(message, title, text, parent)
|
||||
self.in_reply_to = parent.db.settings[parent.name_buffer][parent.list.get_selected()]["id"]
|
||||
self.text.SetInsertionPoint(len(self.text.GetValue()))
|
||||
self.mentionAll = wx.Button(self, -1, _(u"Mention to all"), size=wx.DefaultSize)
|
||||
self.mentionAll = wx.Button(self, -1, _(u"Men&tion all"), size=wx.DefaultSize)
|
||||
self.mentionAll.Disable()
|
||||
self.mentionAll.Bind(wx.EVT_BUTTON, self.mentionAllUsers)
|
||||
self.buttonsBox1.Add(self.mentionAll, 0, wx.ALL, 5)
|
||||
@@ -332,10 +342,14 @@ class reply(tweet):
|
||||
class viewTweet(wx.Dialog):
|
||||
def __init__(self, tweet):
|
||||
super(viewTweet, self).__init__(None, size=(850,850))
|
||||
self.SetTitle(_(u"Tweet - %i characters ") % (len(tweet)))
|
||||
self.SetTitle(_(u"Tweet - %i characters ") % (len(tweet["text"])))
|
||||
panel = wx.Panel(self)
|
||||
label = wx.StaticText(panel, -1, _(u"Tweet"))
|
||||
self.text = wx.TextCtrl(panel, -1, tweet, style=wx.TE_READONLY|wx.TE_MULTILINE, size=(250, 180))
|
||||
if tweet.has_key("retweeted_status"):
|
||||
text = "rt @%s: %s" % (tweet["retweeted_status"]["user"]["screen_name"], tweet["retweeted_status"]["text"])
|
||||
else:
|
||||
text = tweet["text"]
|
||||
self.text = wx.TextCtrl(panel, -1, text, style=wx.TE_READONLY|wx.TE_MULTILINE, size=(250, 180))
|
||||
dc = wx.WindowDC(self.text)
|
||||
dc.SetFont(self.text.GetFont())
|
||||
(x, y, z) = dc.GetMultiLineTextExtent("0"*140)
|
||||
@@ -346,6 +360,20 @@ class viewTweet(wx.Dialog):
|
||||
textBox.Add(self.text, 1, wx.EXPAND, 5)
|
||||
mainBox = wx.BoxSizer(wx.VERTICAL)
|
||||
mainBox.Add(textBox, 0, wx.ALL, 5)
|
||||
rtCountLabel = wx.StaticText(panel, -1, _(u"Retweets: "))
|
||||
rtCount = wx.TextCtrl(panel, -1, str(tweet["retweet_count"]), size=wx.DefaultSize, style=wx.TE_READONLY|wx.TE_MULTILINE)
|
||||
rtBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
rtBox.Add(rtCountLabel, 0, wx.ALL, 5)
|
||||
rtBox.Add(rtCount, 0, wx.ALL, 5)
|
||||
favsCountLabel = wx.StaticText(panel, -1, _(u"Favourites: "))
|
||||
favsCount = wx.TextCtrl(panel, -1, str(tweet["favorite_count"]), size=wx.DefaultSize, style=wx.TE_READONLY|wx.TE_MULTILINE)
|
||||
favsBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
favsBox.Add(favsCountLabel, 0, wx.ALL, 5)
|
||||
favsBox.Add(favsCount, 0, wx.ALL, 5)
|
||||
infoBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
infoBox.Add(rtBox, 0, wx.ALL, 5)
|
||||
infoBox.Add(favsBox, 0, wx.ALL, 5)
|
||||
mainBox.Add(infoBox, 0, wx.ALL, 5)
|
||||
if platform.system() != "Darwin":
|
||||
spellcheck = wx.Button(panel, -1, _("Spelling correction"), size=wx.DefaultSize)
|
||||
spellcheck.Bind(wx.EVT_BUTTON, self.onCheck)
|
||||
@@ -417,3 +445,87 @@ class viewTweet(wx.Dialog):
|
||||
urlList.unshorten(urls, self).ShowModal()
|
||||
self.text.SetFocus()
|
||||
|
||||
class viewNonTweet(wx.Dialog):
|
||||
def __init__(self, tweet):
|
||||
super(viewNonTweet, self).__init__(None, size=(850,850))
|
||||
self.SetTitle(_(u"View"))
|
||||
panel = wx.Panel(self)
|
||||
label = wx.StaticText(panel, -1, _(u"Item"))
|
||||
self.text = wx.TextCtrl(parent=panel, id=-1, value=tweet, style=wx.TE_READONLY|wx.TE_MULTILINE, size=(250, 180))
|
||||
dc = wx.WindowDC(self.text)
|
||||
dc.SetFont(self.text.GetFont())
|
||||
(x, y, z) = dc.GetMultiLineTextExtent("0"*140)
|
||||
self.text.SetSize((x, y))
|
||||
self.text.SetFocus()
|
||||
textBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
textBox.Add(label, 0, wx.ALL, 5)
|
||||
textBox.Add(self.text, 1, wx.EXPAND, 5)
|
||||
mainBox = wx.BoxSizer(wx.VERTICAL)
|
||||
mainBox.Add(textBox, 0, wx.ALL, 5)
|
||||
spellcheck = wx.Button(panel, -1, _("Spelling correction"), size=wx.DefaultSize)
|
||||
spellcheck.Bind(wx.EVT_BUTTON, self.onCheck)
|
||||
self.unshortenButton = wx.Button(panel, -1, _(u"Expand URL"), size=wx.DefaultSize)
|
||||
self.unshortenButton.Bind(wx.EVT_BUTTON, self.onUnshorten)
|
||||
self.unshortenButton.Disable()
|
||||
translateButton = wx.Button(panel, -1, _(u"Translate message"), size=wx.DefaultSize)
|
||||
translateButton.Bind(wx.EVT_BUTTON, self.onTranslate)
|
||||
cancelButton = wx.Button(panel, wx.ID_CANCEL, _(u"Close"), size=wx.DefaultSize)
|
||||
cancelButton.SetDefault()
|
||||
buttonsBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
buttonsBox.Add(spellcheck, 0, wx.ALL, 5)
|
||||
buttonsBox.Add(self.unshortenButton, 0, wx.ALL, 5)
|
||||
buttonsBox.Add(translateButton, 0, wx.ALL, 5)
|
||||
buttonsBox.Add(cancelButton, 0, wx.ALL, 5)
|
||||
mainBox.Add(buttonsBox, 0, wx.ALL, 5)
|
||||
selectId = wx.NewId()
|
||||
self.Bind(wx.EVT_MENU, self.onSelect, id=selectId)
|
||||
self.accel_tbl = wx.AcceleratorTable([
|
||||
(wx.ACCEL_CTRL, ord('A'), selectId),
|
||||
])
|
||||
self.SetAcceleratorTable(self.accel_tbl)
|
||||
panel.SetSizer(mainBox)
|
||||
self.SetClientSize(mainBox.CalcMin())
|
||||
self.check_urls()
|
||||
|
||||
def check_urls(self):
|
||||
if len(twitter.utils.find_urls_in_text(self.text.GetValue())) > 0:
|
||||
self.unshortenButton.Enable()
|
||||
|
||||
def onCheck(self, ev):
|
||||
text = self.text.GetValue()
|
||||
dlg = spellCheckerGUI.spellCheckerDialog(text, "")
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
self.text.ChangeValue(dlg.checker.get_text())
|
||||
dlg.Destroy()
|
||||
|
||||
def onTranslate(self, ev):
|
||||
dlg = translator.gui.translateDialog()
|
||||
selection = dlg.ShowModal()
|
||||
if selection != wx.ID_CANCEL:
|
||||
text_to_translate = self.text.GetValue().encode("utf-8")
|
||||
source = [x[0] for x in translator.available_languages()][dlg.source_lang.GetSelection()]
|
||||
dest = [x[0] for x in translator.available_languages()][dlg.dest_lang.GetSelection()]
|
||||
t = translator.translator.Translator()
|
||||
t.from_lang = source
|
||||
t.to_lang = dest
|
||||
msg = t.translate(text_to_translate)
|
||||
self.text.ChangeValue(msg)
|
||||
output.speak(_(u"Translated"))
|
||||
self.text.SetFocus()
|
||||
else:
|
||||
return
|
||||
dlg.Destroy()
|
||||
|
||||
def onSelect(self, ev):
|
||||
self.text.SelectAll()
|
||||
|
||||
def onUnshorten(self, ev):
|
||||
urls = twitter.utils.find_urls_in_text(self.text.GetValue())
|
||||
if len(urls) == 0:
|
||||
output.speak(_(u"There's no URL to be expanded"))
|
||||
elif len(urls) == 1:
|
||||
self.text.SetValue(self.text.GetValue().replace(urls[0], url_shortener.unshorten(urls[0])))
|
||||
output.speak(_(u"URL expanded"))
|
||||
elif len(urls) > 1:
|
||||
urlList.unshorten(urls, self).ShowModal()
|
||||
self.text.SetFocus()
|
||||
|
@@ -19,24 +19,34 @@
|
||||
import wx
|
||||
|
||||
class trendingTopicsDialog(wx.Dialog):
|
||||
def __init__(self):
|
||||
super(searchDialog, self).__init__(None, -1)
|
||||
def __init__(self, information):
|
||||
super(trendingTopicsDialog, self).__init__(None, -1)
|
||||
self.countries = {}
|
||||
self.cities = {}
|
||||
self.information = information
|
||||
self.split_information()
|
||||
panel = wx.Panel(self)
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
self.SetTitle(_(u"Search on Twitter"))
|
||||
label = wx.StaticText(panel, -1, _(u"Search"))
|
||||
self.term = wx.TextCtrl(panel, -1,)
|
||||
dc = wx.WindowDC(self.term)
|
||||
dc.SetFont(self.term.GetFont())
|
||||
self.term.SetSize(dc.GetTextExtent("0"*40))
|
||||
self.SetTitle(_(u"View trending topics"))
|
||||
label = wx.StaticText(panel, -1, _(u"Trending topics by"))
|
||||
sizer.Add(label, 0, wx.ALL, 5)
|
||||
sizer.Add(self.term, 0, wx.ALL, 5)
|
||||
self.tweets = wx.RadioButton(panel, -1, _(u"Tweets"), style=wx.RB_GROUP)
|
||||
self.users = wx.RadioButton(panel, -1, _(u"Users"))
|
||||
self.country = wx.RadioButton(panel, -1, _(u"Country"), style=wx.RB_GROUP)
|
||||
self.city = wx.RadioButton(panel, -1, _(u"City"))
|
||||
self.Bind(wx.EVT_RADIOBUTTON, self.get_places, self.country)
|
||||
self.Bind(wx.EVT_RADIOBUTTON, self.get_places, self.city)
|
||||
|
||||
radioSizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
radioSizer.Add(self.tweets, 0, wx.ALL, 5)
|
||||
radioSizer.Add(self.users, 0, wx.ALL, 5)
|
||||
radioSizer.Add(label, 0, wx.ALL, 5)
|
||||
radioSizer.Add(self.country, 0, wx.ALL, 5)
|
||||
radioSizer.Add(self.city, 0, wx.ALL, 5)
|
||||
sizer.Add(radioSizer, 0, wx.ALL, 5)
|
||||
label = wx.StaticText(panel, -1, _(u"Location"))
|
||||
self.location = wx.ListBox(panel, -1, choices=[], style=wx.CB_READONLY)
|
||||
self.get_places()
|
||||
locationBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
locationBox.Add(label, 0, wx.ALL, 5)
|
||||
locationBox.Add(self.location, 0, wx.ALL, 5)
|
||||
sizer.Add(locationBox, 0, wx.ALL, 5)
|
||||
ok = wx.Button(panel, wx.ID_OK, _(u"OK"))
|
||||
ok.SetDefault()
|
||||
cancel = wx.Button(panel, wx.ID_CANCEL, _(u"Close"))
|
||||
@@ -46,3 +56,25 @@ class trendingTopicsDialog(wx.Dialog):
|
||||
sizer.Add(btnsizer, 0, wx.ALL, 5)
|
||||
panel.SetSizer(sizer)
|
||||
self.SetClientSize(sizer.CalcMin())
|
||||
|
||||
def split_information(self):
|
||||
# self.countries["World wide"] = 1
|
||||
# self.cities["World wide"] = 1
|
||||
for i in self.information:
|
||||
if i["placeType"]["name"] == "Country":
|
||||
self.countries[i["name"]] = i["woeid"]
|
||||
else:
|
||||
self.cities[i["name"]] = i["woeid"]
|
||||
|
||||
def get_places(self, event=None):
|
||||
values = []
|
||||
if self.country.GetValue() == True:
|
||||
for i in self.information:
|
||||
if i["placeType"]["name"] == "Country":
|
||||
values.append(i["name"])
|
||||
elif self.city.GetValue() == True:
|
||||
for i in self.information:
|
||||
if i["placeType"]["name"] != "Country":
|
||||
values.append(i["name"])
|
||||
self.location.Set(values)
|
||||
|
@@ -46,8 +46,7 @@ class urlList(wx.Dialog):
|
||||
self.SetClientSize(sizer.CalcMin())
|
||||
|
||||
def onGo(self, ev):
|
||||
webbrowser.open(self.lista.GetStringSelection())
|
||||
self.Destroy()
|
||||
self.EndModal(wx.ID_OK)
|
||||
|
||||
def populate_list(self):
|
||||
for i in self.urls:
|
||||
|
182
src/gui/main.py
182
src/gui/main.py
@@ -32,10 +32,16 @@ import output
|
||||
import platform
|
||||
import urllib2
|
||||
import sysTrayIcon
|
||||
import switchModule
|
||||
from wx.lib.pubsub import pub
|
||||
import languageHandler
|
||||
from extra.autocompletionUsers import settings as autocompletionUsersSettings
|
||||
import pygeocoder
|
||||
from pygeolib import GeocoderError
|
||||
from sessionmanager import manager
|
||||
from issueReporter import gui as issueReporterGUI
|
||||
from mysc import event
|
||||
from mysc.thread_utils import call_threaded
|
||||
from mysc.thread_utils import call_threaded, stream_threaded
|
||||
from twython import TwythonError
|
||||
from urllib2 import URLError
|
||||
from mysc.repeating_timer import RepeatingTimer
|
||||
@@ -46,6 +52,7 @@ from extra import SoundsTutorial
|
||||
from keystrokeEditor import gui as keystrokeEditorGUI
|
||||
log = original_logger.getLogger("gui.main")
|
||||
|
||||
geocoder = pygeocoder.Geocoder()
|
||||
class mainFrame(wx.Frame):
|
||||
""" Main class of the Frame. This is the Main Window."""
|
||||
|
||||
@@ -56,12 +63,16 @@ class mainFrame(wx.Frame):
|
||||
|
||||
# Application menu
|
||||
app = wx.Menu()
|
||||
switch_account = app.Append(wx.NewId(), _(u"S&witch account"))
|
||||
self.Bind(wx.EVT_MENU, self.switch_account, switch_account)
|
||||
updateProfile = app.Append(wx.NewId(), _(u"&Update profile"))
|
||||
self.Bind(wx.EVT_MENU, self.update_profile, updateProfile)
|
||||
show_hide = app.Append(wx.NewId(), _(u"&Hide window"))
|
||||
self.Bind(wx.EVT_MENU, self.show_hide, show_hide)
|
||||
search = app.Append(wx.NewId(), _(u"&Search"))
|
||||
self.Bind(wx.EVT_MENU, self.search, search)
|
||||
trends = app.Append(wx.NewId(), _(u"View &trending topics"))
|
||||
self.Bind(wx.EVT_MENU, self.get_trending_topics, trends)
|
||||
lists = app.Append(wx.NewId(), _(u"&Lists manager"))
|
||||
self.Bind(wx.EVT_MENU, self.list_manager, lists)
|
||||
sounds_tutorial = app.Append(wx.NewId(), _(u"Sounds &tutorial"))
|
||||
@@ -87,6 +98,8 @@ class mainFrame(wx.Frame):
|
||||
self.Bind(wx.EVT_MENU, self.unfav, unfav)
|
||||
view = tweet.Append(wx.NewId(), _(u"&Show tweet"))
|
||||
self.Bind(wx.EVT_MENU, self.view, view)
|
||||
view_coordinates = tweet.Append(wx.NewId(), _(u"View &address"))
|
||||
self.Bind(wx.EVT_MENU, self.reverse_geocode, view_coordinates)
|
||||
delete = tweet.Append(wx.NewId(), _(u"&Delete"))
|
||||
self.Bind(wx.EVT_MENU, self.delete, delete)
|
||||
|
||||
@@ -208,17 +221,17 @@ class mainFrame(wx.Frame):
|
||||
log.debug("Getting Twitter's Rest API...")
|
||||
self.twitter = twitter.twitter.twitter()
|
||||
super(mainFrame, self).__init__(None, -1, "TW Blue", size=(1600, 1600))
|
||||
self.Bind(wx.EVT_QUERY_END_SESSION, self.exit)
|
||||
self.Bind(wx.EVT_END_SESSION, self.exit)
|
||||
wx.GetApp().Bind(wx.EVT_QUERY_END_SESSION, self.exit)
|
||||
wx.GetApp().Bind(wx.EVT_END_SESSION, self.exit)
|
||||
log.debug(u"Creating the system tray icon... ")
|
||||
sysTray=sysTrayIcon.SysTrayIcon(self)
|
||||
self.sysTray=sysTrayIcon.SysTrayIcon(self)
|
||||
panel = wx.Panel(self)
|
||||
self.sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
self.SetTitle("TW Blue")
|
||||
try:
|
||||
updater.update_manager.check_for_update()
|
||||
except:
|
||||
pass
|
||||
wx.MessageDialog(self, _(u"An error occurred while looking for an update. It may be due to any problem either on our server or on your DNS servers. Please, try again later."), _(u"Error!"), wx.OK|wx.ICON_ERROR).ShowModal()
|
||||
self.SetMenuBar(self.makeMenus())
|
||||
self.setup_twitter(panel)
|
||||
|
||||
@@ -233,7 +246,7 @@ class mainFrame(wx.Frame):
|
||||
# Gets the tabs for home, mentions, send and direct messages.
|
||||
log.debug("Creating buffers...")
|
||||
self.db.settings["buffers"] = []
|
||||
account = buffers.accountPanel(self.nb)
|
||||
account = buffers.accountPanel(self.nb, self.db.settings["user_name"])
|
||||
self.nb.AddPage(account, self.db.settings["user_name"])
|
||||
self.db.settings["buffers"].append(self.db.settings["user_name"])
|
||||
account_index = self.db.settings["buffers"].index(self.db.settings["user_name"])
|
||||
@@ -310,11 +323,23 @@ class mainFrame(wx.Frame):
|
||||
self.db.settings["buffers"].append(i+"favs")
|
||||
self.fav_stream = RepeatingTimer(180, self.get_fav_buffers)
|
||||
self.fav_stream.start()
|
||||
for i in config.main["other_buffers"]["trending_topic_buffers"]:
|
||||
buff = buffers.trendsPanel(self.nb, self, "%s_tt" % (i,), argumento=i, sound="trends_updated.ogg")
|
||||
timer = RepeatingTimer(300, buff.start_streams)
|
||||
timer.start()
|
||||
num = buff.start_streams()
|
||||
buff.put_items(num)
|
||||
self.nb.InsertSubPage(self.db.settings["buffers"].index(self.db.settings["user_name"]), buff, _(u"Trending topics for %s") % (buff.name,))
|
||||
self.sizer.Add(self.nb, 0, wx.ALL, 5)
|
||||
if config.main["general"]["use_invisible_keyboard_shorcuts"] == True:
|
||||
km = self.create_invisible_keyboard_shorcuts()
|
||||
self.register_invisible_keyboard_shorcuts(km)
|
||||
panel.SetSizer(self.sizer)
|
||||
self.SetClientSize(self.sizer.CalcMin())
|
||||
self.Bind(event.MyEVT_STARTED, self.onInit)
|
||||
self.Bind(event.EVT_RESULT, self.onMemberAdded)
|
||||
pub.subscribe(self.listen_streamerror, "streamError")
|
||||
pub.subscribe(self.listen_for_friends, "friendsReceived")
|
||||
call_threaded(self.init, run_streams=True)
|
||||
|
||||
def init(self, run_streams=False):
|
||||
@@ -347,6 +372,7 @@ class mainFrame(wx.Frame):
|
||||
self.check_streams.start()
|
||||
# If all it's done, then play a nice sound saying that all it's OK.
|
||||
sound.player.play("ready.ogg")
|
||||
autocompletionUsersSettings.execute_at_startup(window=self)
|
||||
|
||||
def remove_list(self, id):
|
||||
for i in range(0, self.nb.GetPageCount()):
|
||||
@@ -369,21 +395,21 @@ class mainFrame(wx.Frame):
|
||||
|
||||
def setup_twitter(self, panel):
|
||||
""" Setting up the connection for twitter, or authenticate if the config file has valid credentials."""
|
||||
try:
|
||||
self.twitter.login(self.user_key, self.user_secret)
|
||||
self.logging_in_twblue(panel)
|
||||
log.info("Authorized in Twitter.")
|
||||
del self.user_key; del self.user_secret
|
||||
except:
|
||||
dlg1 = wx.MessageDialog(panel, _(u"Connection error. Try again later."), _(u"Error!"), wx.ICON_ERROR)
|
||||
dlg1.ShowModal()
|
||||
self.Close(True)
|
||||
# try:
|
||||
self.twitter.login(self.user_key, self.user_secret)
|
||||
self.logging_in_twblue(panel)
|
||||
log.info("Authorized in Twitter.")
|
||||
del self.user_key; del self.user_secret
|
||||
# except:
|
||||
# dlg1 = wx.MessageDialog(panel, _(u"Connection error. Try again later."), _(u"Error!"), wx.ICON_ERROR)
|
||||
# dlg1.ShowModal()
|
||||
# self.Close(True)
|
||||
|
||||
def get_home(self):
|
||||
""" Gets the home stream, that manages home timeline, mentions, direct messages and sent."""
|
||||
try:
|
||||
self.stream = twitter.buffers.stream.streamer(application.app_key, application.app_secret, config.main["twitter"]["user_key"], config.main["twitter"]["user_secret"], parent=self)
|
||||
call_threaded(self.stream.user)
|
||||
stream_threaded(self.stream.user)
|
||||
except:
|
||||
self.stream.disconnect()
|
||||
|
||||
@@ -406,13 +432,16 @@ class mainFrame(wx.Frame):
|
||||
ids+= str(z)+", "
|
||||
if ids != "":
|
||||
# try:
|
||||
call_threaded(self.stream2.statuses.filter, follow=ids)
|
||||
stream_threaded(self.stream2.statuses.filter, follow=ids)
|
||||
# except:
|
||||
# pass
|
||||
# except:
|
||||
# self.stream2.disconnect()
|
||||
|
||||
def check_stream_up(self):
|
||||
if not hasattr(self, "stream") and not hasattr(self, "stream2"):
|
||||
self.init(run_streams=True)
|
||||
return
|
||||
try:
|
||||
urllib2.urlopen("http://74.125.228.231", timeout=5)
|
||||
except urllib2.URLError:
|
||||
@@ -501,7 +530,7 @@ class mainFrame(wx.Frame):
|
||||
dlg = dialogs.lists.removeUserListDialog(self)
|
||||
if dlg.ShowModal() == wx.ID_OK:
|
||||
try:
|
||||
list = self.twitter.twitter.delete_list_member(list_id=self.db.settings["lists"][dlg.get_selected()]["id"], screen_name=user)
|
||||
list = self.twitter.twitter.delete_list_member(list_id=self.db.settings["lists"][dlg.lista.get_selected()]["id"], screen_name=user)
|
||||
older_list = twitter.utils.find_item(self.db.settings["lists"][dlg.get_selected()]["id"], self.db.settings["lists"])
|
||||
if list["mode"] == "private":
|
||||
self.db.settings["lists"].pop(older_list)
|
||||
@@ -546,8 +575,7 @@ class mainFrame(wx.Frame):
|
||||
webbrowser.open("http://twblue.com.mx")
|
||||
|
||||
def onReportBug(self, ev):
|
||||
webbrowser.open("https://github.com/manuelcortez/TWBlue/issues")
|
||||
# issueReporterGUI.reportBug(self.db.settings["user_name"]).ShowModal()
|
||||
issueReporterGUI.reportBug(self.db.settings["user_name"]).ShowModal()
|
||||
|
||||
def onCheckForUpdates(self, ev):
|
||||
updater.update_manager.check_for_update(msg=True)
|
||||
@@ -574,7 +602,7 @@ class mainFrame(wx.Frame):
|
||||
output.speak(self.nb.GetPageText(self.nb.GetSelection())+",", True)
|
||||
|
||||
def skip_blank_pages(self, forward=True):
|
||||
if self.nb.GetCurrentPage().type == "account" or self.nb.GetCurrentPage().type == "empty" and (self.showing == False or platform.system() == "Darwin"):
|
||||
if self.nb.GetCurrentPage().type == "account" or self.nb.GetCurrentPage().type == "empty":
|
||||
self.nb.AdvanceSelection(forward)
|
||||
|
||||
def close(self, ev=None):
|
||||
@@ -590,6 +618,8 @@ class mainFrame(wx.Frame):
|
||||
def exit(self, event=None):
|
||||
config.main.write()
|
||||
log.debug("Exiting...")
|
||||
self.sysTray.RemoveIcon()
|
||||
self.sysTray.Destroy()
|
||||
try:
|
||||
self.check_streams.cancel()
|
||||
except AttributeError:
|
||||
@@ -661,8 +691,18 @@ class mainFrame(wx.Frame):
|
||||
self.nb.GetCurrentPage().onRetweet(ev)
|
||||
|
||||
def view(self, ev=None):
|
||||
tweet = self.nb.GetCurrentPage().get_message(dialog=True)
|
||||
dialogs.message.viewTweet(tweet).ShowModal()
|
||||
tp = self.nb.GetCurrentPage().type
|
||||
if tp == "buffer" or tp == "timeline" or tp == "favourites_timeline" or tp == "list" or tp == "search":
|
||||
try:
|
||||
id = self.db.settings[self.nb.GetCurrentPage().name_buffer][self.nb.GetCurrentPage().list.get_selected()]["id"]
|
||||
tweet = self.twitter.twitter.show_status(id=id)
|
||||
dialogs.message.viewTweet(tweet).ShowModal()
|
||||
except TwythonError as e:
|
||||
non_tweet = self.nb.GetCurrentPage().get_message(dialog=True)
|
||||
dialogs.message.viewNonTweet(non_tweet).ShowModal()
|
||||
else:
|
||||
non_tweet = self.nb.GetCurrentPage().get_message(dialog=True)
|
||||
dialogs.message.viewNonTweet(non_tweet).ShowModal()
|
||||
|
||||
def fav(self, ev=None):
|
||||
if self.nb.GetCurrentPage().name_buffer != "direct_messages" and self.nb.GetCurrentPage().name_buffer != "followers" and self.nb.GetCurrentPage().name_buffer != "friends":
|
||||
@@ -778,6 +818,8 @@ class mainFrame(wx.Frame):
|
||||
except:
|
||||
msg = _(u"%s. Empty") % (self.nb.GetPageText(self.nb.GetSelection()))
|
||||
output.speak(msg, 1)
|
||||
if self.showing == True:
|
||||
self.nb.GetCurrentPage().list.list.SetFocus()
|
||||
|
||||
def right(self, event=None):
|
||||
num = self.nb.GetSelection()
|
||||
@@ -791,21 +833,37 @@ class mainFrame(wx.Frame):
|
||||
except:
|
||||
msg = _(u"%s. Empty") % (self.nb.GetPageText(self.nb.GetSelection()))
|
||||
output.speak(msg, 1)
|
||||
if self.showing == True:
|
||||
self.nb.GetCurrentPage().list.list.SetFocus()
|
||||
|
||||
def show_hide(self, ev=None):
|
||||
# if platform.system() == "Linux" or platform.system() == "Darwin": return
|
||||
def create_invisible_keyboard_shorcuts(self):
|
||||
keymap = {}
|
||||
for i in config.main["keymap"]:
|
||||
if hasattr(self, i):
|
||||
keymap[config.main["keymap"][i]] = getattr(self, i)
|
||||
return keymap
|
||||
|
||||
def register_invisible_keyboard_shorcuts(self, keymap):
|
||||
self.keyboard_handler = WXKeyboardHandler(self)
|
||||
self.keyboard_handler.register_keys(keymap)
|
||||
|
||||
def unregister_invisible_keyboard_shorcuts(self, keymap):
|
||||
try:
|
||||
self.keyboard_handler.unregister_keys(keymap)
|
||||
del self.keyboard_handler
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
def show_hide(self, ev=None):
|
||||
km = self.create_invisible_keyboard_shorcuts()
|
||||
if self.showing == True:
|
||||
self.keyboard_handler = WXKeyboardHandler(self)
|
||||
self.keyboard_handler.register_keys(keymap)
|
||||
if config.main["general"]["use_invisible_keyboard_shorcuts"] == False:
|
||||
self.register_invisible_keyboard_shorcuts(km)
|
||||
self.Hide()
|
||||
self.showing = False
|
||||
else:
|
||||
self.keyboard_handler.unregister_keys(keymap)
|
||||
del self.keyboard_handler
|
||||
if config.main["general"]["use_invisible_keyboard_shorcuts"] == False:
|
||||
self.unregister_invisible_keyboard_shorcuts(km)
|
||||
self.Show()
|
||||
self.showing = True
|
||||
|
||||
@@ -959,6 +1017,72 @@ class mainFrame(wx.Frame):
|
||||
return page
|
||||
return page
|
||||
|
||||
def switch_account(self, ev):
|
||||
switchModule.switcher(self)
|
||||
|
||||
def reverse_geocode(self, event=None):
|
||||
try:
|
||||
tweet = self.nb.GetCurrentPage().get_tweet()
|
||||
if tweet["coordinates"] != None:
|
||||
x = tweet["coordinates"]["coordinates"][0]
|
||||
y = tweet["coordinates"]["coordinates"][1]
|
||||
address = geocoder.reverse_geocode(y, x)
|
||||
if event == None: output.speak(address[0].__str__().decode("utf-8"))
|
||||
else: wx.MessageDialog(self, address[0].__str__().decode("utf-8"), _(u"Address"), wx.OK).ShowModal()
|
||||
else:
|
||||
output.speak(_(u"There are no coordinates in this tweet"))
|
||||
except GeocoderError:
|
||||
output.speak(_(u"There are no results for the coordinates in this tweet"))
|
||||
except ValueError:
|
||||
output.speak(_(u"Error decoding coordinates. Try again later."))
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
def view_reverse_geocode(self, event=None):
|
||||
try:
|
||||
tweet = self.nb.GetCurrentPage().get_tweet()
|
||||
if tweet["coordinates"] != None:
|
||||
x = tweet["coordinates"]["coordinates"][0]
|
||||
y = tweet["coordinates"]["coordinates"][1]
|
||||
address = geocoder.reverse_geocode(y, x)
|
||||
dialogs.message.viewNonTweet(address[0].__str__().decode("utf-8")).ShowModal()
|
||||
else:
|
||||
output.speak(_(u"There are no coordinates in this tweet"))
|
||||
except GeocoderError:
|
||||
output.speak(_(u"There are no results for the coordinates in this tweet"))
|
||||
except ValueError:
|
||||
output.speak(_(u"Error decoding coordinates. Try again later."))
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
def get_trending_topics(self, event=None):
|
||||
info = self.twitter.twitter.get_available_trends()
|
||||
trendingDialog = dialogs.trending.trendingTopicsDialog(info)
|
||||
if trendingDialog.ShowModal() == wx.ID_OK:
|
||||
if trendingDialog.country.GetValue() == True:
|
||||
woeid = trendingDialog.countries[trendingDialog.location.GetStringSelection()]
|
||||
elif trendingDialog.city.GetValue() == True:
|
||||
woeid = trendingDialog.cities[trendingDialog.location.GetStringSelection()]
|
||||
buff = buffers.trendsPanel(self.nb, self, "%s_tt" % (woeid,), argumento=woeid, sound="trends_updated.ogg")
|
||||
self.nb.InsertSubPage(self.db.settings["buffers"].index(self.db.settings["user_name"]), buff, _(u"Trending topics for %s") % (trendingDialog.location.GetStringSelection(),))
|
||||
timer = RepeatingTimer(300, buff.start_streams)
|
||||
timer.start()
|
||||
num = buff.start_streams()
|
||||
config.main["other_buffers"]["trending_topic_buffers"].append(woeid)
|
||||
buff.put_items(num)
|
||||
|
||||
def listen_streamerror(self):
|
||||
log.error("There is a connection error")
|
||||
if hasattr(self, "stream"):
|
||||
self.stream.disconnect()
|
||||
del self.stream
|
||||
if hasattr(self, "stream2"):
|
||||
self.stream2.disconnect()
|
||||
del self.stream2
|
||||
|
||||
def listen_for_friends(self):
|
||||
self.stream2.set_friends(self.stream.friends)
|
||||
|
||||
### Close App
|
||||
def Destroy(self):
|
||||
self.sysTray.Destroy()
|
||||
|
23
src/gui/switchModule.py
Normal file
23
src/gui/switchModule.py
Normal file
@@ -0,0 +1,23 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import wx
|
||||
import gui
|
||||
import config
|
||||
from sessionmanager import gui as sessionManagerUI
|
||||
|
||||
class switcher(object):
|
||||
def __init__(self, window):
|
||||
self.hold_window = window
|
||||
self.hold_window.Hide()
|
||||
sessionManagerWindow = sessionManagerUI.sessionManagerWindow()
|
||||
if sessionManagerWindow.ShowModal() == wx.ID_OK:
|
||||
self.hold_window.Destroy()
|
||||
self.window = gui.main.mainFrame()
|
||||
self.window.Show()
|
||||
self.window.showing = True
|
||||
if config.main != None and config.main["general"]["hide_gui"] == True:
|
||||
self.window.show_hide()
|
||||
self.window.Hide()
|
||||
wx.GetApp().SetTopWindow(self.window)
|
||||
else:
|
||||
self.hold_window.Show()
|
||||
|
@@ -55,7 +55,7 @@ class SysTrayIcon(wx.TaskBarIcon):
|
||||
if (self.frame.showing):
|
||||
self.frame.SetFocus()
|
||||
else:
|
||||
self.frame.onShow_hide()
|
||||
self.frame.show_hide()
|
||||
|
||||
def Destroy(self):
|
||||
self.menu.Destroy()
|
||||
|
0
src/issueReporter/__init__.py
Normal file
0
src/issueReporter/__init__.py
Normal file
21
src/issueReporter/constants.py
Normal file
21
src/issueReporter/constants.py
Normal file
@@ -0,0 +1,21 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
############################################################
|
||||
# Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo <manuel@manuelcortez.net>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
############################################################
|
||||
categories = ["General", "documentation", "translation"]
|
||||
reproducibilities = ["always", "sometimes", "random", "have not tried", "unable to duplicate"]
|
||||
severities = ["block", "crash", "major", "minor", "tweak", "text", "trivial", "feature"]
|
32
src/issueReporter/get_logs.py
Normal file
32
src/issueReporter/get_logs.py
Normal file
@@ -0,0 +1,32 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
############################################################
|
||||
# Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo <manuel@manuelcortez.net>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
############################################################
|
||||
import paths
|
||||
import os
|
||||
|
||||
def get_logs_files():
|
||||
files = {}
|
||||
for i in os.listdir(paths.logs_path()):
|
||||
if i == "debug.log": continue
|
||||
f = open(paths.logs_path(i), "r")
|
||||
files[i] = f.readlines()
|
||||
f.close()
|
||||
try: os.remove(paths.logs_path("tracebacks.log"))
|
||||
except: pass
|
||||
return files
|
||||
|
124
src/issueReporter/gui.py
Normal file
124
src/issueReporter/gui.py
Normal file
@@ -0,0 +1,124 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
############################################################
|
||||
# Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo <manuel@manuelcortez.net>
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
############################################################
|
||||
import wx
|
||||
import application
|
||||
from suds.client import Client
|
||||
import constants
|
||||
|
||||
class reportBug(wx.Dialog):
|
||||
def __init__(self, user_name):
|
||||
self.user = "reporter1"
|
||||
self.user_name = user_name
|
||||
self.password = "contrasena"
|
||||
self.url = application.report_bugs_url
|
||||
self.categories = [_(u"General"), _(u"Documentation"), _(u"Translation")]
|
||||
self.reproducibilities = [_(u"always"), _(u"sometimes"), _(u"random"), _(u"have not tried"), _(u"unable to duplicate")]
|
||||
self.severities = [_(u"block"), _(u"crash"), _(u"major"), _(u"minor"), _(u"tweak"), _(u"text"), _(u"trivial"), _(u"feature")]
|
||||
wx.Dialog.__init__(self, None, -1)
|
||||
self.SetTitle(_(u"Report an error"))
|
||||
panel = wx.Panel(self)
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
categoryLabel = wx.StaticText(panel, -1, _(u"Select a category"), size=wx.DefaultSize)
|
||||
self.category = wx.ComboBox(panel, -1, choices=self.categories, style=wx.CB_READONLY)
|
||||
self.category.SetSize(self.category.GetBestSize())
|
||||
self.category.SetSelection(0)
|
||||
categoryB = wx.BoxSizer(wx.HORIZONTAL)
|
||||
categoryB.Add(categoryLabel, 0, wx.ALL, 5)
|
||||
categoryB.Add(self.category, 0, wx.ALL, 5)
|
||||
self.category.SetFocus()
|
||||
sizer.Add(categoryB, 0, wx.ALL, 5)
|
||||
summaryLabel = wx.StaticText(panel, -1, _(u"Briefly describe what happened. You will be able to thoroughly explain it later"), size=wx.DefaultSize)
|
||||
self.summary = wx.TextCtrl(panel, -1)
|
||||
dc = wx.WindowDC(self.summary)
|
||||
dc.SetFont(self.summary.GetFont())
|
||||
self.summary.SetSize(dc.GetTextExtent("a"*80))
|
||||
# self.summary.SetFocus()
|
||||
summaryB = wx.BoxSizer(wx.HORIZONTAL)
|
||||
summaryB.Add(summaryLabel, 0, wx.ALL, 5)
|
||||
summaryB.Add(self.summary, 0, wx.ALL, 5)
|
||||
sizer.Add(summaryB, 0, wx.ALL, 5)
|
||||
descriptionLabel = wx.StaticText(panel, -1, _(u"Here, you can describe the bug in detail"), size=wx.DefaultSize)
|
||||
self.description = wx.TextCtrl(panel, -1, style=wx.TE_MULTILINE)
|
||||
dc = wx.WindowDC(self.description)
|
||||
dc.SetFont(self.description.GetFont())
|
||||
(x, y, z) = dc.GetMultiLineTextExtent("0"*2000)
|
||||
self.description.SetSize((x, y))
|
||||
descBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
descBox.Add(descriptionLabel, 0, wx.ALL, 5)
|
||||
descBox.Add(self.description, 0, wx.ALL, 5)
|
||||
sizer.Add(descBox, 0, wx.ALL, 5)
|
||||
reproducibilityLabel = wx.StaticText(panel, -1, _(u"how often does this bug happen?"), size=wx.DefaultSize)
|
||||
self.reproducibility = wx.ComboBox(panel, -1, choices=self.reproducibilities, style=wx.CB_READONLY)
|
||||
self.reproducibility.SetSelection(3)
|
||||
self.reproducibility.SetSize(self.reproducibility.GetBestSize())
|
||||
reprB = wx.BoxSizer(wx.HORIZONTAL)
|
||||
reprB.Add(reproducibilityLabel, 0, wx.ALL, 5)
|
||||
reprB.Add(self.reproducibility, 0, wx.ALL, 5)
|
||||
sizer.Add(reprB, 0, wx.ALL, 5)
|
||||
severityLabel = wx.StaticText(panel, -1, _(u"Select the importance that you think this bug has"))
|
||||
self.severity = wx.ComboBox(panel, -1, choices=self.severities, style=wx.CB_READONLY)
|
||||
self.severity.SetSize(self.severity.GetBestSize())
|
||||
self.severity.SetSelection(3)
|
||||
severityB = wx.BoxSizer(wx.HORIZONTAL)
|
||||
severityB.Add(severityLabel, 0, wx.ALL, 5)
|
||||
severityB.Add(self.severity, 0, wx.ALL, 5)
|
||||
sizer.Add(severityB, 0, wx.ALL, 5)
|
||||
self.agree = wx.CheckBox(panel, -1, _(u"I know that the TW Blue bug system will get my Twitter username to contact me and fix the bug quickly"))
|
||||
self.agree.SetValue(False)
|
||||
sizer.Add(self.agree, 0, wx.ALL, 5)
|
||||
ok = wx.Button(panel, wx.ID_OK, _(u"Send report"))
|
||||
ok.Bind(wx.EVT_BUTTON, self.onSend)
|
||||
ok.SetDefault()
|
||||
cancel = wx.Button(panel, wx.ID_CANCEL, _(u"Cancel"))
|
||||
btnBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||
btnBox.Add(ok, 0, wx.ALL, 5)
|
||||
btnBox.Add(cancel, 0, wx.ALL, 5)
|
||||
sizer.Add(btnBox, 0, wx.ALL, 5)
|
||||
panel.SetSizer(sizer)
|
||||
self.SetClientSize(sizer.CalcMin())
|
||||
|
||||
def onSend(self, ev):
|
||||
if self.summary.GetValue() == "" or self.description.GetValue() == "":
|
||||
wx.MessageDialog(self, _(u"You must fill out both fields"), _(u"Error"), wx.OK|wx.ICON_ERROR).ShowModal()
|
||||
return
|
||||
if self.agree.GetValue() == False:
|
||||
wx.MessageDialog(self, _(u"You need to mark the checkbox to provide us your twitter username to contact to you if is necessary."), _(u"Error"), wx.ICON_ERROR).ShowModal()
|
||||
return
|
||||
# try:
|
||||
client = Client(self.url)
|
||||
issue = client.factory.create('IssueData')
|
||||
issue.project.name = "TWBlue"
|
||||
issue.project.id = 0
|
||||
issue.summary = self.summary.GetValue(),
|
||||
issue.description = "Reported by @%s\n\n" % (self.user_name) + self.description.GetValue()
|
||||
issue.category = constants.categories[self.category.GetSelection()]
|
||||
issue.reproducibility.name = constants.reproducibilities[self.reproducibility.GetSelection()]
|
||||
issue.severity.name = constants.severities[self.severity.GetSelection()]
|
||||
issue.priority.name = "normal"
|
||||
issue.view_state.name = "public"
|
||||
issue.resolution.name = "open"
|
||||
issue.projection.name = "none"
|
||||
issue.eta.name = "eta"
|
||||
issue.status.name = "new"
|
||||
id = client.service.mc_issue_add(self.user, self.password, issue)
|
||||
wx.MessageDialog(self, _(u"Thanks for reporting this bug! In future versions, you may be able to find it in the changes list. You've reported the bug number %i") % (id), _(u"reported"), wx.OK).ShowModal()
|
||||
self.EndModal(wx.ID_OK)
|
||||
# except:
|
||||
# wx.MessageDialog(self, _(u"Something unexpected occurred while trying to report the bug. Please, try again later"), _(u"Error while reporting"), wx.ICON_ERROR|wx.OK).ShowModal()
|
||||
# self.EndModal(wx.ID_CANCEL)
|
@@ -42,4 +42,7 @@ actions = {
|
||||
"edit_keystrokes": _(u"Shows the keystroke editor"),
|
||||
"view_user_lists": _(u"Show lists for a specified user"),
|
||||
"get_more_items": _(u"loads previous items to any buffer"),
|
||||
"reverse_geocode": _(u"Get location of any tweet"),
|
||||
"view_reverse_geocode": _(u"Displays the tweet's location in a dialog"),
|
||||
"get_trending_topics": _(u"Creates a buffer for displaying trends for a desired place"),
|
||||
}
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
93
src/main.py
93
src/main.py
@@ -19,57 +19,68 @@ A twitter accessible, easy of use and cross platform application."""
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
############################################################
|
||||
import sys
|
||||
from StringIO import StringIO
|
||||
#redirect the original stdout and stderr
|
||||
stdout=sys.stdout
|
||||
stderr=sys.stderr
|
||||
# Set a StringIO object as stdout and stderr to avoid problems using the installed version.
|
||||
sys.stdout = StringIO()
|
||||
sys.stderr = StringIO()
|
||||
import wx
|
||||
|
||||
import os
|
||||
ssmg = None
|
||||
import gui
|
||||
import paths
|
||||
import config
|
||||
import commandline
|
||||
import platform
|
||||
if platform.system() == "Windows":
|
||||
from logger import logger as logging
|
||||
if platform.system() == "Darwin":
|
||||
import osx_prepare
|
||||
osx_prepare.setup()
|
||||
from logger import logger as logging
|
||||
from sessionmanager import manager
|
||||
from sessionmanager import gui as smGUI
|
||||
manager.setup()
|
||||
import sys
|
||||
|
||||
import config
|
||||
import output
|
||||
import sound
|
||||
import languageHandler
|
||||
#close the memory buffers for stdout and stderr
|
||||
sys.stdout.close()
|
||||
sys.stderr.close()
|
||||
#if it's a binary version
|
||||
if hasattr(sys, 'frozen'):
|
||||
sys.stderr = open(paths.logs_path("stderr.log"), 'w')
|
||||
sys.stdout = open(paths.logs_path("stdout.log"), 'w')
|
||||
|
||||
class app(wx.App):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(app, self).__init__(*args, **kwargs)
|
||||
if platform.system() != "Darwin":
|
||||
self.start()
|
||||
else:
|
||||
self.mac()
|
||||
|
||||
def mac(self):
|
||||
self.hold_frame = wx.Frame(title="None", parent=None)
|
||||
self.hold_frame.Show()
|
||||
wx.CallLater(10, self.start)
|
||||
|
||||
def start(self):
|
||||
ssmg = smGUI.sessionManagerWindow()
|
||||
if ssmg.ShowModal() == wx.ID_OK:
|
||||
frame = gui.main.mainFrame()
|
||||
frame.Show()
|
||||
frame.showing = True
|
||||
if config.main != None and config.main["general"]["hide_gui"] == True and platform.system() == "Windows":
|
||||
frame.show_hide()
|
||||
frame.Hide()
|
||||
self.SetTopWindow(frame)
|
||||
if hasattr(self, "frame"): self.hold_frame.Hide()
|
||||
# If the user press on cancel.
|
||||
else:
|
||||
self.Exit()
|
||||
|
||||
ap = app()
|
||||
sys.stderr = open(paths.logs_path("stderr.log"), 'w')
|
||||
sys.stdout = open(paths.logs_path("stdout.log"), 'w')
|
||||
else:
|
||||
sys.stdout=stdout
|
||||
sys.stderr=stderr
|
||||
|
||||
app = wx.App()
|
||||
#app = wx.App(redirect=True, useBestVisual=True, filename=paths.logs_path('tracebacks.log'))
|
||||
configured = False
|
||||
configs = []
|
||||
for i in os.listdir(paths.config_path()):
|
||||
if os.path.isdir(paths.config_path(i)): configs.append(i)
|
||||
if len(configs) == 1:
|
||||
manager.manager.set_current_session(configs[0])
|
||||
config.MAINFILE = "%s/session.conf" % (manager.manager.get_current_session())
|
||||
config.setup()
|
||||
lang=config.main['general']['language']
|
||||
languageHandler.setLanguage(lang)
|
||||
sound.setup()
|
||||
output.setup()
|
||||
configured = True
|
||||
else:
|
||||
ssmg = smGUI.sessionManagerWindow()
|
||||
if configured == True or ssmg.ShowModal() == wx.ID_OK:
|
||||
frame = gui.main.mainFrame()
|
||||
frame.Show()
|
||||
frame.showing = True
|
||||
if config.main != None and config.main["general"]["hide_gui"] == True and platform.system() == "Windows":
|
||||
frame.show_hide()
|
||||
frame.Hide()
|
||||
app.SetTopWindow(frame)
|
||||
else:
|
||||
app.Exit()
|
||||
### I should uncomment this
|
||||
#if platform.system() != "Windows":
|
||||
# local = wx.Locale(wx.LANGUAGE_DEFAULT)
|
||||
@@ -77,5 +88,5 @@ ap = app()
|
||||
# local.AddCatalog("twblue")
|
||||
#ap = app(redirect=True, useBestVisual=True, filename=paths.logs_path('tracebacks.log'))
|
||||
#wx.CallLater(10, start)
|
||||
ap.MainLoop()
|
||||
app.MainLoop()
|
||||
|
||||
|
@@ -3,6 +3,7 @@ import threading
|
||||
import wx
|
||||
from twython import TwythonRateLimitError
|
||||
import time
|
||||
from wx.lib.pubsub import pub
|
||||
|
||||
def call_threaded(func, *args, **kwargs):
|
||||
#Call the given function in a daemonized thread and return the thread.
|
||||
@@ -19,3 +20,14 @@ def call_threaded(func, *args, **kwargs):
|
||||
thread.daemon = True
|
||||
thread.start()
|
||||
return thread
|
||||
|
||||
def stream_threaded(func, *args, **kwargs):
|
||||
def new_func(*a, **k):
|
||||
try:
|
||||
func(*a, **k)
|
||||
except:
|
||||
pub.sendMessage("streamError")
|
||||
thread = threading.Thread(target=new_func, args=args, kwargs=kwargs)
|
||||
thread.daemon = True
|
||||
thread.start()
|
||||
return thread
|
@@ -1,4 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import shutil
|
||||
import time
|
||||
import wx
|
||||
import manager
|
||||
@@ -23,28 +24,26 @@ class sessionManagerWindow(wx.Dialog):
|
||||
label = wx.StaticText(panel, -1, _(u"Select a twitter account to start TW Blue"), size=wx.DefaultSize)
|
||||
listSizer = wx.BoxSizer(wx.HORIZONTAL)
|
||||
self.list = widgets.list(panel, _(u"Account"), style=wx.LC_SINGLE_SEL|wx.LC_REPORT)
|
||||
self.fill_list()
|
||||
listSizer.Add(label, 0, wx.ALL, 5)
|
||||
listSizer.Add(self.list.list, 0, wx.ALL, 5)
|
||||
sizer.Add(listSizer, 0, wx.ALL, 5)
|
||||
new = wx.Button(panel, -1, _(u"New account"), size=wx.DefaultSize)
|
||||
new.Bind(wx.EVT_BUTTON, self.new_account)
|
||||
self.removeSession = wx.Button(panel, -1, _(u"Remove session"))
|
||||
self.removeSession.Disable()
|
||||
self.removeSession.Bind(wx.EVT_BUTTON, self.remove)
|
||||
ok = wx.Button(panel, wx.ID_OK, size=wx.DefaultSize)
|
||||
ok.SetDefault()
|
||||
ok.Bind(wx.EVT_BUTTON, self.ok)
|
||||
cancel = wx.Button(panel, wx.ID_CANCEL, size=wx.DefaultSize)
|
||||
buttons = wx.BoxSizer(wx.HORIZONTAL)
|
||||
buttons.Add(new, 0, wx.ALL, 5)
|
||||
buttons.Add(self.removeSession, 0, wx.ALL, 5)
|
||||
buttons.Add(ok, 0, wx.ALL, 5)
|
||||
buttons.Add(cancel, 0, wx.ALL, 5)
|
||||
sizer.Add(buttons, 0, wx.ALL, 5)
|
||||
panel.SetSizer(sizer)
|
||||
# sizer.Layout()
|
||||
# self.Fit()
|
||||
# self.SetSize(panel.GetBestSize())
|
||||
# panelSizer.Add(panel)
|
||||
# self.SetSizerAndFit(sizer)
|
||||
# sizer.Layout()
|
||||
self.fill_list()
|
||||
min = sizer.CalcMin()
|
||||
self.SetClientSize(min)
|
||||
|
||||
@@ -55,12 +54,16 @@ class sessionManagerWindow(wx.Dialog):
|
||||
strconfig = "%s/session.conf" % (paths.config_path(i))
|
||||
config_test = Configuration(strconfig)
|
||||
name = config_test["twitter"]["user_name"]
|
||||
if name != "" and config_test["twitter"]["user_key"] != "" and config_test["twitter"]["user_secret"] != "":
|
||||
if name != "" or (config_test["twitter"]["user_key"] != "" and config_test["twitter"]["user_secret"] != ""):
|
||||
self.list.insert_item(False, name)
|
||||
self.sessions.append(i)
|
||||
else:
|
||||
del config_test
|
||||
shutil.rmtree(path=paths.config_path(i), ignore_errors=True)
|
||||
if self.list.get_count() > 0:
|
||||
self.list.select_item(0)
|
||||
self.list.list.SetSize(self.list.list.GetBestSize())
|
||||
self.removeSession.Enable()
|
||||
|
||||
def ok(self, ev):
|
||||
if self.list.get_count() == 0:
|
||||
@@ -74,8 +77,6 @@ class sessionManagerWindow(wx.Dialog):
|
||||
languageHandler.setLanguage(lang)
|
||||
sound.setup()
|
||||
output.setup()
|
||||
# else:
|
||||
# self.name = current_session
|
||||
self.EndModal(wx.ID_OK)
|
||||
|
||||
def new_account(self, ev):
|
||||
@@ -99,3 +100,12 @@ class sessionManagerWindow(wx.Dialog):
|
||||
if self.list.get_count() == 1:
|
||||
self.list.select_item(0)
|
||||
self.sessions.append(location)
|
||||
|
||||
def remove(self, ev):
|
||||
selected_item = self.list.get_selected()
|
||||
selected_session = self.sessions[selected_item]
|
||||
ask = wx.MessageDialog(self, _(u"Do you really want delete this account?"), _(u"Remove account"), wx.YES_NO)
|
||||
if ask.ShowModal() == wx.ID_YES:
|
||||
self.sessions.remove(selected_session)
|
||||
shutil.rmtree(path=paths.config_path(selected_session), ignore_errors=True)
|
||||
self.list.remove_item(selected_item)
|
@@ -34,7 +34,7 @@ def get_architecture_files():
|
||||
("Microsoft.VC90.MFC", glob("../windows-dependencies/x86/Microsoft.VC90.MFC/*")),]
|
||||
elif platform.architecture()[0][:2] == "64":
|
||||
return [
|
||||
("", ["../windows-dependencies/x64/oggenc2.exe", "../windows-dependencies/x86/bootstrap.exe"]),
|
||||
("", ["../windows-dependencies/x64/oggenc2.exe", "../windows-dependencies/x64/bootstrap.exe"]),
|
||||
("Microsoft.VC90.CRT", glob("../windows-dependencies/x64/Microsoft.VC90.CRT/*")),
|
||||
("Microsoft.VC90.MFC", glob("../windows-dependencies/x64/Microsoft.VC90.MFC/*")),]
|
||||
|
||||
@@ -90,7 +90,8 @@ data_files = get_data(),
|
||||
options = {
|
||||
'py2exe': {
|
||||
'optimize':2,
|
||||
'dll_excludes': ["MPR.dll", "api-ms-win-core-apiquery-l1-1-0.dll", "api-ms-win-core-console-l1-1-0.dll", "api-ms-win-core-delayload-l1-1-1.dll", "api-ms-win-core-errorhandling-l1-1-1.dll", "api-ms-win-core-file-l1-2-0.dll", "api-ms-win-core-handle-l1-1-0.dll", "api-ms-win-core-heap-obsolete-l1-1-0.dll", "api-ms-win-core-libraryloader-l1-1-1.dll", "api-ms-win-core-localization-l1-2-0.dll", "api-ms-win-core-processenvironment-l1-2-0.dll", "api-ms-win-core-processthreads-l1-1-1.dll", "api-ms-win-core-profile-l1-1-0.dll", "api-ms-win-core-registry-l1-1-0.dll", "api-ms-win-core-synch-l1-2-0.dll", "api-ms-win-core-sysinfo-l1-2-0.dll", "api-ms-win-security-base-l1-2-0.dll", "api-ms-win-core-heap-l1-2-0.dll", "api-ms-win-core-interlocked-l1-2-0.dll", "api-ms-win-core-localization-obsolete-l1-1-0.dll", "api-ms-win-core-string-l1-1-0.dll", "api-ms-win-core-string-obsolete-l1-1-0.dll", "WLDAP32.dll", "MSVCP90.dll"],
|
||||
'packages': ["wx.lib.pubsub", "wx.lib.pubsub.core", "wx.lib.pubsub.core.kwargs"],
|
||||
'dll_excludes': ["MPR.dll", "api-ms-win-core-apiquery-l1-1-0.dll", "api-ms-win-core-console-l1-1-0.dll", "api-ms-win-core-delayload-l1-1-1.dll", "api-ms-win-core-errorhandling-l1-1-1.dll", "api-ms-win-core-file-l1-2-0.dll", "api-ms-win-core-handle-l1-1-0.dll", "api-ms-win-core-heap-obsolete-l1-1-0.dll", "api-ms-win-core-libraryloader-l1-1-1.dll", "api-ms-win-core-localization-l1-2-0.dll", "api-ms-win-core-processenvironment-l1-2-0.dll", "api-ms-win-core-processthreads-l1-1-1.dll", "api-ms-win-core-profile-l1-1-0.dll", "api-ms-win-core-registry-l1-1-0.dll", "api-ms-win-core-synch-l1-2-0.dll", "api-ms-win-core-sysinfo-l1-2-0.dll", "api-ms-win-security-base-l1-2-0.dll", "api-ms-win-core-heap-l1-2-0.dll", "api-ms-win-core-interlocked-l1-2-0.dll", "api-ms-win-core-localization-obsolete-l1-1-0.dll", "api-ms-win-core-string-l1-1-0.dll", "api-ms-win-core-string-obsolete-l1-1-0.dll", "WLDAP32.dll", "MSVCP90.dll", "MFC90.dll"],
|
||||
'skip_archive': True
|
||||
},
|
||||
},
|
||||
|
BIN
src/sounds/default/geo.ogg
Normal file
BIN
src/sounds/default/geo.ogg
Normal file
Binary file not shown.
BIN
src/sounds/default/trends_updated.ogg
Normal file
BIN
src/sounds/default/trends_updated.ogg
Normal file
Binary file not shown.
@@ -1,5 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from twitter import compose
|
||||
from twitter import compose, utils
|
||||
from twython import TwythonStreamer
|
||||
import sound
|
||||
from mysc import event
|
||||
@@ -34,13 +34,20 @@ class streamer(TwythonStreamer):
|
||||
tweet_event.SetItem(data)
|
||||
announce = _(u"One tweet from %s in the list %s") % (data["user"]["name"], self.parent.nb.GetPage(i).name_buffer[:-5])
|
||||
tweet_event.SetAnnounce(announce)
|
||||
wx.PostEvent(self.parent.nb.GetPage(i), tweet_event)
|
||||
usr = data["in_reply_to_user_id"]
|
||||
if (usr != None and usr in self.friends) or data.has_key("retweeted_status"):
|
||||
wx.PostEvent(self.parent.nb.GetPage(i), tweet_event)
|
||||
elif usr == None:
|
||||
wx.PostEvent(self.parent.nb.GetPage(i), tweet_event)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
def set_friends(self, friends):
|
||||
self.friends = friends
|
||||
|
||||
def on_success(self, data):
|
||||
try:
|
||||
if data.has_key("text"):
|
||||
if data.has_key("text") and utils.is_allowed(data):
|
||||
self.check_tls(data)
|
||||
except:
|
||||
pass
|
@@ -8,6 +8,7 @@ import config
|
||||
import logging as original_logger
|
||||
log = original_logger.getLogger("MainStream")
|
||||
import output
|
||||
from wx.lib.pubsub import pub
|
||||
|
||||
class streamer(TwythonStreamer):
|
||||
def __init__(self, app_key, app_secret, oauth_token, oauth_token_secret, timeout=300, retry_count=None, retry_in=10, client_args=None, handlers=None, chunk_size=1, parent=None):
|
||||
@@ -51,7 +52,7 @@ class streamer(TwythonStreamer):
|
||||
wx.PostEvent(self.parent.search_buffer("buffer", "favs"), tweet_event)
|
||||
|
||||
def check_mentions(self, data):
|
||||
if "@%s" % (self.db.settings["user_name"]) in data["text"]:
|
||||
if "@%s" % (self.db.settings["user_name"].lower()) in data["text"].lower():
|
||||
tweet_event = event.event(event.EVT_OBJECT, 1)
|
||||
tweet_event.SetItem(data)
|
||||
text = _(u"One mention from %s ") % (data["user"]["name"])
|
||||
@@ -68,15 +69,14 @@ class streamer(TwythonStreamer):
|
||||
tweet_event.SetItem(data["direct_message"])
|
||||
text = _(u"One direct message")
|
||||
tweet_event.SetAnnounce(text)
|
||||
wx.PostEvent(self.parent.search_buffer("buffer", "direct_messages"), tweet_event)
|
||||
wx.PostEvent(self.parent.search_buffer("direct_message", "direct_messages"), tweet_event)
|
||||
|
||||
def check_follower(self, data):
|
||||
if data["target"]["screen_name"] == self.db.settings["user_name"]:
|
||||
if config.main["other_buffers"]["show_followers"] == True:
|
||||
tweet_event = event.event(event.EVT_OBJECT, 1)
|
||||
tweet_event.SetItem(data["source"])
|
||||
wx.PostEvent(self.parent.search_buffer("people", "followers"), tweet_event)
|
||||
elif data["source"]["screen_name"] == self.db.settings["user_name"] and config.main["other_buffers"]["show_friends"] == True:
|
||||
if data["target"]["screen_name"] == self.db.settings["user_name"] and config.main["other_buffers"]["show_followers"] == True:
|
||||
tweet_event = event.event(event.EVT_OBJECT, 1)
|
||||
tweet_event.SetItem(data["source"])
|
||||
wx.PostEvent(self.parent.search_buffer("people", "followers"), tweet_event)
|
||||
elif data["source"]["screen_name"] == self.db.settings["user_name"]:
|
||||
tweet_event = event.event(event.EVT_OBJECT, 1)
|
||||
tweet_event.SetItem(data["target"])
|
||||
wx.PostEvent(self.parent.search_buffer("people", "friends"), tweet_event)
|
||||
@@ -106,6 +106,7 @@ class streamer(TwythonStreamer):
|
||||
self.process_dm(data)
|
||||
elif "friends" in data:
|
||||
self.friends = data["friends"]
|
||||
pub.sendMessage("friendsReceived")
|
||||
elif "text" in data and utils.is_allowed(data) == True:
|
||||
if data["user"]["id"] in self.muted_users: return
|
||||
self.check_mentions(data)
|
||||
@@ -119,7 +120,7 @@ class streamer(TwythonStreamer):
|
||||
self.check_favs(data)
|
||||
elif "unfavorite" == data["event"] and config.main["other_buffers"]["show_favourites"] == True:
|
||||
self.remove_fav(data)
|
||||
elif "follow" == data["event"] and config.main["other_buffers"]["show_followers"] == True:
|
||||
elif "follow" == data["event"]:
|
||||
self.check_follower(data)
|
||||
elif "unfollow" == data["event"] and config.main["other_buffers"]["show_followers"] == True:
|
||||
self.remove_friend(data)
|
||||
|
@@ -13,6 +13,8 @@ else:
|
||||
languageHandler.setLanguage("system")
|
||||
import platform
|
||||
system = platform.system()
|
||||
import logging as original_logger
|
||||
log = original_logger.getLogger("events")
|
||||
|
||||
def prettydate(d):
|
||||
""" Converts a string to the relative time."""
|
||||
@@ -153,7 +155,7 @@ def compose_tweet(tweet, db):
|
||||
else: user = tweet["sender"]["name"]
|
||||
elif tweet.has_key("user"):
|
||||
user = tweet["user"]["name"]
|
||||
source = re.sub(r"(?s)<.*?>", " ", tweet["source"])
|
||||
source = re.sub(r"(?s)<.*?>", "", tweet["source"])
|
||||
try: text = "rt @%s: %s" % (tweet["retweeted_status"]["user"]["screen_name"], StripChars(tweet["retweeted_status"]["text"]))
|
||||
except KeyError: text = "%s" % (StripChars(tweet["text"]))
|
||||
if text[-1] in chars: text=text+"."
|
||||
@@ -224,7 +226,9 @@ def compose_event(data, username):
|
||||
elif data["event"] == "list_user_unsubscribed":
|
||||
if data["source"]["screen_name"] == username: event = _(u"You've unsubscribed from the list %s, which is owned by %s(@%s)") % (data["target_object"]["name"], data["target"]["name"], data["target"]["screen_name"])
|
||||
else: event = _("You've been unsubscribed from the list %s, which is owned by %s(@%s)") % (data["target_object"]["name"], data["source"]["name"], data["source"]["screen_name"])
|
||||
else: event = _("Unknown")
|
||||
else:
|
||||
log.error("event: %s\n target: %s\n source: %s\n" % (data["event"], data["target"], data["source"]))
|
||||
event = _("Unknown")
|
||||
# output.speak(event)
|
||||
return [time.strftime("%I:%M %p"), event]
|
||||
|
||||
|
@@ -75,15 +75,16 @@ def start_stream(db, twitter, name, function, param=None):
|
||||
last_id = 0
|
||||
if len(db.settings[name]) > 0:
|
||||
for i in tl:
|
||||
if int(i["id"]) > int(last_id):
|
||||
if int(i["id"]) > int(last_id) and utils.is_allowed(i) == True:
|
||||
if config.main["general"]["reverse_timelines"] == False: db.settings[name].append(i)
|
||||
else: db.settings[name].insert(0, i)
|
||||
num = num+1
|
||||
elif len(db.settings[name]) == 0:
|
||||
for i in tl:
|
||||
if config.main["general"]["reverse_timelines"] == False: db.settings[name].append(i)
|
||||
else: db.settings[name].insert(0, i)
|
||||
num = num+1
|
||||
if utils.is_allowed(i) == True:
|
||||
if config.main["general"]["reverse_timelines"] == False: db.settings[name].append(i)
|
||||
else: db.settings[name].insert(0, i)
|
||||
num = num+1
|
||||
# db.settings.update()
|
||||
return num
|
||||
|
||||
@@ -121,7 +122,7 @@ def update_stream(config, twitter, name, function, param=None, sndFile=""):
|
||||
tl = function(sinze_id=config.settings[name][-1]["id"], screen_name=param, count=config.main["general"]["max_tweets_per_call"])
|
||||
tl.reverse()
|
||||
for i in tl:
|
||||
if i["id"] > config.settings[name][-1]["id"]:
|
||||
if i["id"] > config.settings[name][-1]["id"] and utils.is_allowed(i) == True:
|
||||
config.settings[name].append(i)
|
||||
sounded = True
|
||||
num = num+1
|
||||
@@ -171,7 +172,7 @@ def start_sent(db, twitter, name, function, param=None):
|
||||
num = num+1
|
||||
return num
|
||||
|
||||
def start_list(db, twitter, name, list_id):
|
||||
def start_list(db, twitter, name, list_id, *args, **kwargs):
|
||||
num = 0
|
||||
if db.settings.has_key(name):
|
||||
try:
|
||||
@@ -181,23 +182,24 @@ def start_list(db, twitter, name, list_id):
|
||||
last_id = db.settings[name][-1]["id"]
|
||||
except IndexError:
|
||||
pass
|
||||
tl = twitter.twitter.get_list_statuses(list_id=list_id, count=200)
|
||||
tl = twitter.twitter.get_list_statuses(list_id=list_id, *args, **kwargs)
|
||||
else:
|
||||
tl = twitter.twitter.get_list_statuses(list_id=list_id, count=200)
|
||||
tl = twitter.twitter.get_list_statuses(list_id=list_id, *args, **kwargs)
|
||||
tl.reverse()
|
||||
db.settings[name] = []
|
||||
last_id = 0
|
||||
if len(db.settings[name]) > 0:
|
||||
for i in tl:
|
||||
if int(i["id"]) > int(last_id):
|
||||
if int(i["id"]) > int(last_id) and utils.is_allowed(i) == True:
|
||||
if config.main["general"]["reverse_timelines"] == False: db.settings[name].append(i)
|
||||
else: db.settings[name].insert(0, i)
|
||||
num = num+1
|
||||
elif len(db.settings[name]) == 0:
|
||||
for i in tl:
|
||||
if config.main["general"]["reverse_timelines"] == False: db.settings[name].append(i)
|
||||
else: db.settings[name].insert(0, i)
|
||||
num = num+1
|
||||
if utils.is_allowed(i) == True:
|
||||
if config.main["general"]["reverse_timelines"] == False: db.settings[name].append(i)
|
||||
else: db.settings[name].insert(0, i)
|
||||
num = num+1
|
||||
db.settings.update()
|
||||
return num
|
||||
|
||||
@@ -209,15 +211,16 @@ def search(db, twitter, name, *args, **kwargs):
|
||||
tl["statuses"].reverse()
|
||||
if len(db.settings[name]) > 0:
|
||||
for i in tl["statuses"]:
|
||||
if utils.find_item(i["id"], db.settings[name]) == None:
|
||||
if utils.find_item(i["id"], db.settings[name]) == None and utils.is_allowed(i):
|
||||
if config.main["general"]["reverse_timelines"] == False: db.settings[name].append(i)
|
||||
else: db.settings[name].insert(0, i)
|
||||
num = num+1
|
||||
elif len(db.settings[name]) == 0:
|
||||
for i in tl["statuses"]:
|
||||
if config.main["general"]["reverse_timelines"] == False: db.settings[name].append(i)
|
||||
else: db.settings[name].insert(0, i)
|
||||
num = num+1
|
||||
if utils.is_allowed(i) == True:
|
||||
if config.main["general"]["reverse_timelines"] == False: db.settings[name].append(i)
|
||||
else: db.settings[name].insert(0, i)
|
||||
num = num+1
|
||||
return num
|
||||
|
||||
def search_users(db, twitter, name, *args, **kwargs):
|
||||
@@ -247,13 +250,14 @@ def get_favourites_timeline(db, twitter, name, param, *args, **kwargs):
|
||||
tl.reverse()
|
||||
if len(db.settings[name]) > 0:
|
||||
for i in tl:
|
||||
if utils.find_item(i["id"], db.settings[name]) == None:
|
||||
if utils.find_item(i["id"], db.settings[name]) == None and utils.is_allowed(i) == True:
|
||||
if config.main["general"]["reverse_timelines"] == False: db.settings[name].append(i)
|
||||
else: db.settings[name].insert(0, i)
|
||||
num = num+1
|
||||
elif len(db.settings[name]) == 0:
|
||||
for i in tl:
|
||||
if config.main["general"]["reverse_timelines"] == False: db.settings[name].append(i)
|
||||
else: db.settings[name].insert(0, i)
|
||||
num = num+1
|
||||
if utils.is_allowed(i) == True:
|
||||
if config.main["general"]["reverse_timelines"] == False: db.settings[name].append(i)
|
||||
else: db.settings[name].insert(0, i)
|
||||
num = num+1
|
||||
return num
|
@@ -25,6 +25,7 @@ class handler(BaseHTTPServer.BaseHTTPRequestHandler):
|
||||
verifier = params.get('oauth_verifier', [None])[0]
|
||||
self.wfile.write("You have successfully logged in to Twitter with TW Blue. "
|
||||
"You can close this window now.")
|
||||
self.wfile.close()
|
||||
|
||||
class twitter(object):
|
||||
|
||||
@@ -39,7 +40,7 @@ class twitter(object):
|
||||
|
||||
def authorise(self):
|
||||
httpd = BaseHTTPServer.HTTPServer(('127.0.0.1', 8080), handler)
|
||||
twitter = Twython(application.app_key, application.app_secret)
|
||||
twitter = Twython(application.app_key, application.app_secret, auth_endpoint='authorize')
|
||||
auth = twitter.get_authentication_tokens("http://127.0.0.1:8080")
|
||||
webbrowser.open_new_tab(auth['auth_url'])
|
||||
global logged, verifier
|
||||
@@ -48,6 +49,8 @@ class twitter(object):
|
||||
self.twitter = Twython(application.app_key, application.app_secret, auth['oauth_token'], auth['oauth_token_secret'])
|
||||
final = self.twitter.get_authorized_tokens(verifier)
|
||||
self.save_configuration(final["oauth_token"], final["oauth_token_secret"])
|
||||
httpd.server_close()
|
||||
|
||||
|
||||
def save_configuration(self, user_key=None, user_secret=None):
|
||||
if user_key != None and user_secret != None:
|
||||
|
@@ -58,9 +58,12 @@ def is_audio(tweet):
|
||||
return True
|
||||
return False
|
||||
|
||||
def is_geocoded(tweet):
|
||||
if tweet.has_key("coordinates") and tweet["coordinates"] != None:
|
||||
return True
|
||||
|
||||
def get_all_mentioned(tweet, config):
|
||||
""" Gets all users that has been mentioned."""
|
||||
if tweet.has_key("retweeted_status"): tweet = tweet["retweeted_status"]
|
||||
string = []
|
||||
for i in tweet["entities"]["user_mentions"]:
|
||||
if i["screen_name"] != config.settings["user_name"] and i["screen_name"] != tweet["user"]["screen_name"]:
|
||||
@@ -106,9 +109,12 @@ def api_call(parent=None, call_name=None, preexec_message="", success="", succes
|
||||
return val
|
||||
|
||||
def is_allowed(tweet):
|
||||
allowed = True
|
||||
if tweet.has_key("retweeted_status"): tweet = tweet["retweeted_status"]
|
||||
source = re.sub(r"(?s)<.*?>", "", tweet["source"])
|
||||
for i in config.main["twitter"]["ignored_clients"]:
|
||||
if i.lower() == source.lower(): allowed = False
|
||||
return allowed
|
||||
try:
|
||||
allowed = True
|
||||
if tweet.has_key("retweeted_status"): tweet = tweet["retweeted_status"]
|
||||
source = re.sub(r"(?s)<.*?>", "", tweet["source"])
|
||||
for i in config.main["twitter"]["ignored_clients"]:
|
||||
if i.lower() == source.lower(): allowed = False
|
||||
return allowed
|
||||
except KeyError:
|
||||
return True
|
@@ -26,8 +26,9 @@ def check_for_update(msg=False):
|
||||
else:
|
||||
progress.Update(percent, _(u"Update"))
|
||||
def update_complete():
|
||||
wx.MessageDialog(None, _(u"The new TW Blue version has been downloaded and installed. Press OK to start the application."), _(u"Done!")).ShowModal()
|
||||
sys.exit()
|
||||
ms = wx.MessageDialog(None, _(u"The new TW Blue version has been downloaded and installed. Press OK to start the application."), _(u"Done!"))
|
||||
if ms.ShowModal() == wx.ID_OK:
|
||||
sys.exit()
|
||||
app_updater = updater.AutoUpdater(url, new_path, 'bootstrap.exe', app_path=paths.app_path(), postexecute=paths.app_path("TWBlue.exe"), finish_callback=update_complete, percentage_callback=update)
|
||||
app_updater.start_update()
|
||||
progress.ShowModal()
|
||||
|
3
src/widgetUtils/__init__.py
Normal file
3
src/widgetUtils/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
import platform
|
||||
if platform.system() == "Windows":
|
||||
from wxUtils import *
|
32
src/widgetUtils/wxUtils.py
Normal file
32
src/widgetUtils/wxUtils.py
Normal file
@@ -0,0 +1,32 @@
|
||||
import wx
|
||||
|
||||
# Code responses for WX dialogs.
|
||||
# this is when an user presses OK on a dialogue.
|
||||
OK = wx.ID_OK
|
||||
# This is when an user presses cancel on a dialogue.
|
||||
CANCEL = wx.ID_CANCEL
|
||||
# This is when an user closes the dialogue or an id to create the close button.
|
||||
CLOSE = wx.ID_CLOSE
|
||||
# The response for a "yes" Button pressed on a dialogue.
|
||||
YES = wx.ID_YES
|
||||
# This is when the user presses No on a default dialogue.
|
||||
NO = wx.ID_NO
|
||||
|
||||
#events
|
||||
# This is raised when the application must be closed.
|
||||
CLOSE_EVENT = wx.EVT_CLOSE
|
||||
# This is activated when a button is pressed.
|
||||
BUTTON_PRESSED = wx.EVT_BUTTON
|
||||
# This is activated when an user enter text on an edit box.
|
||||
ENTERED_TEXT = wx.EVT_TEXT
|
||||
|
||||
def exit_application():
|
||||
""" Closes the current window cleanly. """
|
||||
wx.GetApp().ExitMainLoop()
|
||||
|
||||
def connect_event(parent, event, func):
|
||||
""" Connects an event to a function.
|
||||
parent wx.window: The widget that will listen for the event.
|
||||
event widgetUtils.event: The event that will be listened for the parent. The event should be one of the widgetUtils events.
|
||||
function func: The function that will be connected to the event."""
|
||||
return getattr(parent, "Bind")(event, func)
|
57
tools/build_twblue.sh
Normal file
57
tools/build_twblue.sh
Normal file
@@ -0,0 +1,57 @@
|
||||
#!/bin/bash
|
||||
# Define paths for a regular use, if there are not paths for python32 or 64, these commands will be taken.
|
||||
pythonpath32="/C/python27x86"
|
||||
pythonpath64="/C/python27"
|
||||
nsyspath=$PROGRAMFILES/NSIS
|
||||
|
||||
help () {
|
||||
echo -e "$0 | usage:"
|
||||
echo -e "$0 | \t./generate_installer.sh [-py32path <path to python for 32 bits> | -py64path <path for python on 64 bits> | -nsyspath <path to nsys> | -h]"
|
||||
}
|
||||
|
||||
# parsing options from the command line
|
||||
while [[ $# > 1 ]]
|
||||
do
|
||||
key="$1"
|
||||
shift
|
||||
|
||||
case $key in
|
||||
-py32path)
|
||||
pythonpath32="$1"
|
||||
shift
|
||||
;;
|
||||
-py64path)
|
||||
pythonpath64="$1"
|
||||
shift
|
||||
;;
|
||||
-nsispath)
|
||||
nsispath="$1"
|
||||
shift
|
||||
;;
|
||||
-help)
|
||||
help
|
||||
;;
|
||||
*)
|
||||
help
|
||||
esac
|
||||
done
|
||||
|
||||
cd ../src
|
||||
if [ -d build/ ];
|
||||
then
|
||||
rm -rf build
|
||||
fi
|
||||
if [ -d dist/ ];
|
||||
then
|
||||
rm -rf dist
|
||||
fi
|
||||
$pythonpath32/python.exe "setup.py" "py2exe" "--quiet"
|
||||
mv -f dist ../scripts/TWBlue
|
||||
rm -rf build
|
||||
$pythonpath64/python.exe "setup.py" "py2exe" "--quiet"
|
||||
mv -f dist ../scripts/TWBlue64
|
||||
rm -rf build
|
||||
cd ../scripts
|
||||
$nsispath/Unicode/makensis.exe "twblue.nsi"
|
||||
rm -rf TWBlue
|
||||
rm -rf TWBlue64
|
@@ -1,13 +0,0 @@
|
||||
#!/bin/bash
|
||||
mkdir ../src/documentation
|
||||
for i in `ls ../documentation`
|
||||
do
|
||||
if test -d ../documentation/$i
|
||||
then
|
||||
mkdir ../src/documentation/$i
|
||||
pandoc -s ../documentation/$i/changes.md -o ../src/documentation/$i/changes.html
|
||||
pandoc -s ../documentation/$i/manual.md -o ../src/documentation/$i/manual.html
|
||||
cp ../documentation/license.txt ../src/documentation/license.txt
|
||||
fi
|
||||
done
|
||||
exit
|
File diff suppressed because it is too large
Load Diff
982
tools/twblue.pot
982
tools/twblue.pot
File diff suppressed because it is too large
Load Diff
1
windows-dependencies
Submodule
1
windows-dependencies
Submodule
Submodule windows-dependencies added at 739034e207
Reference in New Issue
Block a user