paint, translate: Add new translate app, icons for paint.
55
README.md
@ -1,6 +1,6 @@
|
||||
# 15 Minute Apps
|
||||
|
||||
A collection of 15 small (minute) desktop applications written in Python
|
||||
A collection of 15 small — *minute* — desktop applications written in Python
|
||||
using the PyQt framework. These apps are intended as examples from
|
||||
which you can poke, hack and prod your way to writing your own tools.
|
||||
|
||||
@ -12,46 +12,29 @@ which covers everything you need to know to start building your own applications
|
||||
More articles, tutorials and projects using PyQt can be
|
||||
found [on my site](http://martinfitzpatrick.name/tag/pyqt).
|
||||
|
||||
## The apps
|
||||
|
||||
All code is **licensed under an MIT license**. This allows you to re-use the code freely,
|
||||
remixed in both commercial and non-commercial projects. The only requirement is to
|
||||
include the same license when distributing.
|
||||
|
||||
## Completed
|
||||
|
||||
1. Web Browser (untabbed) - "MooseAche"
|
||||
1. Web Browser (tabbed) - "Mozzarella Ashbadger"
|
||||
1. Minesweeper - "Moonsweeper"
|
||||
1. Notepad - "No2Pads"
|
||||
1. Calculator - "Calculon" (QtDesigner)
|
||||
1. Word Processor - "Megasolid Idiom"
|
||||
1. Webcam/Snapshot - "NSAViewer"
|
||||
1. Media Player - "Failamp"
|
||||
1. Post-it Notes - "Brown Note" (QtDesigner)
|
||||
1. Paint - "Piecasso" (QtDesigner)
|
||||
1. Unzip - "7Pez" (QtDesigner)
|
||||
1. Translator - "Translataar" (QtDesigner)
|
||||
1. Weather - "Raindar" (QtDesigner)
|
||||
1. [Web Browser (untabbed)](browser/) - "MooseAche"
|
||||
1. [Web Browser (tabbed)](browser_tabbed/) - "Mozzarella Ashbadger"
|
||||
1. [Minesweeper](minesweeper/) - "Moonsweeper"
|
||||
1. [Notepad](notepad/) - "No2Pads"
|
||||
1. [Calculator](calculator/) - "Calculon" (QtDesigner)
|
||||
1. [Word Processor](wordprocessor/) - "Megasolid Idiom"
|
||||
1. [Webcam/Snapshot](camera/) - "NSAViewer"
|
||||
1. [Media Player](mediaplayer/) - "Failamp"
|
||||
1. [Post-it Notes](notes/) - "Brown Note" (QtDesigner)
|
||||
1. [Paint](paint/) - "Piecasso" (QtDesigner)
|
||||
1. [Unzip](unzip/) - "7Pez" (QtDesigner)
|
||||
1. [Translator](translate/) - "Translataar" (QtDesigner)
|
||||
1. [Weather](weather/) - "Raindar" (QtDesigner)
|
||||
|
||||
## In progress
|
||||
|
||||
1. Currency converter (QtDesigner, PyQtGraph)
|
||||
|
||||
## Up next
|
||||
|
||||
1. Solitaire - "Ronery"
|
||||
|
||||
## Maybe oneday
|
||||
# License
|
||||
|
||||
1. Address Book - "PeepKeep" (QtDesigner)
|
||||
1. Photo Gallery - "PeepPeek"
|
||||
1. Vector Graphics - "Madcap Artist"
|
||||
1. Email - "GeeMail"
|
||||
1. IRC - "kIRC"
|
||||
1. Sound Editor
|
||||
1. (Audio) Spectrum Analyzer
|
||||
1. IM (Jabber)
|
||||
1. FTP
|
||||
1. Finance/Stocks
|
||||
1. Process Explorer
|
||||
1. Internet Radio
|
||||
All code is **licensed under an MIT license**. This allows you to re-use the code freely,
|
||||
remixed in both commercial and non-commercial projects. The only requirement is to
|
||||
include the same license when distributing.
|
||||
|
BIN
paint/images/blue-folder-open-image.png
Executable file
After Width: | Height: | Size: 758 B |
BIN
paint/images/border-weight.png
Executable file
After Width: | Height: | Size: 206 B |
BIN
paint/images/disk.png
Executable file
After Width: | Height: | Size: 507 B |
BIN
paint/images/document-image.png
Executable file
After Width: | Height: | Size: 671 B |
BIN
paint/images/edit-bold.png
Executable file
After Width: | Height: | Size: 282 B |
BIN
paint/images/edit-italic.png
Executable file
After Width: | Height: | Size: 247 B |
BIN
paint/images/edit-underline.png
Executable file
After Width: | Height: | Size: 274 B |
BIN
paint/images/paint-can-color.png
Executable file
After Width: | Height: | Size: 697 B |
60
translate/MainWindow.py
Normal file
@ -0,0 +1,60 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Form implementation generated from reading ui file 'mainwindow.ui'
|
||||
#
|
||||
# Created by: PyQt5 UI code generator 5.10
|
||||
#
|
||||
# WARNING! All changes made in this file will be lost!
|
||||
|
||||
from PyQt5 import QtCore, QtGui, QtWidgets
|
||||
|
||||
class Ui_MainWindow(object):
|
||||
def setupUi(self, MainWindow):
|
||||
MainWindow.setObjectName("MainWindow")
|
||||
MainWindow.resize(721, 333)
|
||||
self.centralwidget = QtWidgets.QWidget(MainWindow)
|
||||
self.centralwidget.setObjectName("centralwidget")
|
||||
self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralwidget)
|
||||
self.horizontalLayout.setObjectName("horizontalLayout")
|
||||
self.verticalLayout = QtWidgets.QVBoxLayout()
|
||||
self.verticalLayout.setObjectName("verticalLayout")
|
||||
self.srcLanguage = QtWidgets.QComboBox(self.centralwidget)
|
||||
self.srcLanguage.setObjectName("srcLanguage")
|
||||
self.verticalLayout.addWidget(self.srcLanguage)
|
||||
self.srcTextEdit = QtWidgets.QTextEdit(self.centralwidget)
|
||||
self.srcTextEdit.setObjectName("srcTextEdit")
|
||||
self.verticalLayout.addWidget(self.srcTextEdit)
|
||||
self.horizontalLayout.addLayout(self.verticalLayout)
|
||||
self.verticalLayout_3 = QtWidgets.QVBoxLayout()
|
||||
self.verticalLayout_3.setObjectName("verticalLayout_3")
|
||||
self.translateButton = QtWidgets.QPushButton(self.centralwidget)
|
||||
self.translateButton.setMinimumSize(QtCore.QSize(75, 50))
|
||||
self.translateButton.setMaximumSize(QtCore.QSize(75, 50))
|
||||
self.translateButton.setText("")
|
||||
icon = QtGui.QIcon()
|
||||
icon.addPixmap(QtGui.QPixmap("images/flag.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
|
||||
self.translateButton.setIcon(icon)
|
||||
self.translateButton.setIconSize(QtCore.QSize(75, 50))
|
||||
self.translateButton.setObjectName("translateButton")
|
||||
self.verticalLayout_3.addWidget(self.translateButton)
|
||||
self.horizontalLayout.addLayout(self.verticalLayout_3)
|
||||
self.verticalLayout_2 = QtWidgets.QVBoxLayout()
|
||||
self.verticalLayout_2.setObjectName("verticalLayout_2")
|
||||
self.destTextEdit = QtWidgets.QTextEdit(self.centralwidget)
|
||||
self.destTextEdit.setObjectName("destTextEdit")
|
||||
self.verticalLayout_2.addWidget(self.destTextEdit)
|
||||
self.horizontalLayout.addLayout(self.verticalLayout_2)
|
||||
MainWindow.setCentralWidget(self.centralwidget)
|
||||
self.menubar = QtWidgets.QMenuBar(MainWindow)
|
||||
self.menubar.setGeometry(QtCore.QRect(0, 0, 721, 22))
|
||||
self.menubar.setObjectName("menubar")
|
||||
MainWindow.setMenuBar(self.menubar)
|
||||
|
||||
self.retranslateUi(MainWindow)
|
||||
QtCore.QMetaObject.connectSlotsByName(MainWindow)
|
||||
|
||||
def retranslateUi(self, MainWindow):
|
||||
_translate = QtCore.QCoreApplication.translate
|
||||
MainWindow.setWindowTitle(_translate("MainWindow", "Translataaaar"))
|
||||
self.translateButton.setToolTip(_translate("MainWindow", "Translate"))
|
||||
|
BIN
translate/images/flag.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
159
translate/translate.py
Normal file
@ -0,0 +1,159 @@
|
||||
from PyQt5.QtGui import *
|
||||
from PyQt5.QtWidgets import *
|
||||
from PyQt5.QtCore import *
|
||||
|
||||
from MainWindow import Ui_MainWindow
|
||||
|
||||
try:
|
||||
from googletrans import Translator
|
||||
GOOGLE_TRANSLATE_AVAILABLE = True
|
||||
|
||||
except ImportError:
|
||||
GOOGLE_TRANSLATE_AVAILABLE = False
|
||||
|
||||
import json
|
||||
from urllib import parse
|
||||
import requests
|
||||
|
||||
LANGUAGES = {
|
||||
'<Detect language>': None,
|
||||
'Afrikaans': 'af',
|
||||
'Albanian': 'sq',
|
||||
'Arabic': 'ar',
|
||||
'Azerbaijani': 'az',
|
||||
'Basque': 'eu',
|
||||
'Bengali': 'bn',
|
||||
'Belarusian': 'be',
|
||||
'Bulgarian': 'bg',
|
||||
'Catalan': 'ca',
|
||||
'Chinese Simplified': 'zh-CN',
|
||||
'Chinese Traditional': 'zh-TW',
|
||||
'Croatian': 'hr',
|
||||
'Czech': 'cs',
|
||||
'Danish': 'da',
|
||||
'Dutch': 'nl',
|
||||
'English': 'en',
|
||||
'Esperanto': 'eo',
|
||||
'Estonian': 'et',
|
||||
'Filipino': 'tl',
|
||||
'Finnish': 'fi',
|
||||
'French': 'fr',
|
||||
'Galician': 'gl',
|
||||
'Georgian': 'ka',
|
||||
'German': 'de',
|
||||
'Greek': 'el',
|
||||
'Gujarati': 'gu',
|
||||
'Haitian Creole': 'ht',
|
||||
'Hebrew': 'iw',
|
||||
'Hindi': 'hi',
|
||||
'Hungarian': 'hu',
|
||||
'Icelandic': 'is',
|
||||
'Indonesian': 'id',
|
||||
'Irish': 'ga',
|
||||
'Italian': 'it',
|
||||
'Japanese': 'ja',
|
||||
'Kannada': 'kn',
|
||||
'Korean': 'ko',
|
||||
'Latin': 'la',
|
||||
'Latvian': 'lv',
|
||||
'Lithuanian': 'lt',
|
||||
'Macedonian': 'mk',
|
||||
'Malay': 'ms',
|
||||
'Maltese': 'mt',
|
||||
'Norwegian': 'no',
|
||||
'Persian': 'fa',
|
||||
'Polish': 'pl',
|
||||
'Portuguese': 'pt',
|
||||
'Romanian': 'ro',
|
||||
'Russian': 'ru',
|
||||
'Serbian': 'sr',
|
||||
'Slovak': 'sk',
|
||||
'Slovenian': 'sl',
|
||||
'Spanish': 'es',
|
||||
'Swahili': 'sw',
|
||||
'Swedish': 'sv',
|
||||
'Tamil': 'ta',
|
||||
'Telugu': 'te',
|
||||
'Thai': 'th',
|
||||
'Turkish': 'tr',
|
||||
'Ukrainian': 'uk',
|
||||
'Urdu': 'ur',
|
||||
'Vietnamese': 'vi',
|
||||
'Welsh': 'cy',
|
||||
'Yiddish': 'yi'
|
||||
}
|
||||
|
||||
|
||||
class MainWindow(QMainWindow, Ui_MainWindow):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(MainWindow, self).__init__(*args, **kwargs)
|
||||
self.setupUi(self)
|
||||
|
||||
self.translator = Translator()
|
||||
|
||||
self.destTextEdit.setReadOnly(True)
|
||||
|
||||
if GOOGLE_TRANSLATE_AVAILABLE:
|
||||
self.srcLanguage.addItems(LANGUAGES.keys())
|
||||
self.srcLanguage.currentTextChanged[str].connect(self.update_src_language)
|
||||
self.srcLanguage.setCurrentText('English')
|
||||
else:
|
||||
self.srcLanguage.hide()
|
||||
|
||||
self.translateButton.pressed.connect(self.translate)
|
||||
|
||||
self.show()
|
||||
|
||||
def update_src_language(self, l):
|
||||
self.language_src = LANGUAGES[l]
|
||||
|
||||
def google_translate(self, text):
|
||||
params = dict(
|
||||
dest='en',
|
||||
text=text
|
||||
)
|
||||
|
||||
if self.language_src:
|
||||
params['src'] = self.language_src
|
||||
|
||||
try:
|
||||
tr = self.translator.translate(**params)
|
||||
|
||||
except Exception:
|
||||
self.destTextEdit.setPlainText('Google translate error :(. Try translating from English')
|
||||
return False
|
||||
|
||||
else:
|
||||
return tr.text
|
||||
|
||||
def translate(self):
|
||||
# Perform pre-translation to English via Google Translate.
|
||||
if self.language_src != 'en':
|
||||
text = self.google_translate(self.srcTextEdit.toPlainText())
|
||||
if not text:
|
||||
return False
|
||||
|
||||
# Already in English.
|
||||
else:
|
||||
text = self.srcTextEdit.toPlainText()
|
||||
|
||||
# Perform translation to piraat.
|
||||
r = requests.get(
|
||||
'http://api.funtranslations.com/translate/pirate.json?%s' %
|
||||
parse.urlencode({'text': text})
|
||||
)
|
||||
|
||||
data = json.loads(r.text)
|
||||
if 'error' in data:
|
||||
self.destTextEdit.setPlainText("%s\n\n%s" % (data['error']['message'], text))
|
||||
else:
|
||||
self.destTextEdit.setPlainText(data['contents']['translated'])
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
app = QApplication([])
|
||||
window = MainWindow()
|
||||
app.exec_()
|