From af4e74a130243ebfce393bd76af10ec73fa55a4d Mon Sep 17 00:00:00 2001 From: Virgil Dupras Date: Sat, 22 Jun 2013 21:34:41 -0400 Subject: [PATCH] Added qtlib repo as a subtree --- qtlib/.gitignore | 4 + qtlib/.tx/config | 8 ++ qtlib/LICENSE | 10 ++ qtlib/__init__.py | 0 qtlib/about_box.py | 89 ++++++++++++ qtlib/app.py | 19 +++ qtlib/column.py | 86 ++++++++++++ qtlib/error_report_dialog.py | 88 ++++++++++++ qtlib/images/search_clear_13.png | Bin 0 -> 3084 bytes qtlib/locale/cs/LC_MESSAGES/qtlib.po | 161 ++++++++++++++++++++++ qtlib/locale/de/LC_MESSAGES/qtlib.po | 161 ++++++++++++++++++++++ qtlib/locale/es/LC_MESSAGES/qtlib.po | 161 ++++++++++++++++++++++ qtlib/locale/fr/LC_MESSAGES/qtlib.po | 161 ++++++++++++++++++++++ qtlib/locale/hy/LC_MESSAGES/qtlib.po | 161 ++++++++++++++++++++++ qtlib/locale/it/LC_MESSAGES/qtlib.po | 161 ++++++++++++++++++++++ qtlib/locale/nl/LC_MESSAGES/qtlib.po | 161 ++++++++++++++++++++++ qtlib/locale/pt_BR/LC_MESSAGES/qtlib.po | 161 ++++++++++++++++++++++ qtlib/locale/qtlib.pot | 150 ++++++++++++++++++++ qtlib/locale/ru/LC_MESSAGES/qtlib.po | 161 ++++++++++++++++++++++ qtlib/locale/uk/LC_MESSAGES/qtlib.po | 161 ++++++++++++++++++++++ qtlib/locale/zh_CN/LC_MESSAGES/qtlib.po | 161 ++++++++++++++++++++++ qtlib/preferences.py | 128 ++++++++++++++++++ qtlib/radio_box.py | 88 ++++++++++++ qtlib/recent.py | 95 +++++++++++++ qtlib/reg.py | 25 ++++ qtlib/reg_demo_dialog.py | 80 +++++++++++ qtlib/reg_submit_dialog.py | 102 ++++++++++++++ qtlib/search_edit.py | 98 ++++++++++++++ qtlib/selectable_list.py | 98 ++++++++++++++ qtlib/table.py | 152 +++++++++++++++++++++ qtlib/text_field.py | 23 ++++ qtlib/tree_model.py | 173 ++++++++++++++++++++++++ qtlib/util.py | 103 ++++++++++++++ 33 files changed, 3390 insertions(+) create mode 100644 qtlib/.gitignore create mode 100644 qtlib/.tx/config create mode 100644 qtlib/LICENSE create mode 100644 qtlib/__init__.py create mode 100644 qtlib/about_box.py create mode 100644 qtlib/app.py create mode 100644 qtlib/column.py create mode 100644 qtlib/error_report_dialog.py create mode 100644 qtlib/images/search_clear_13.png create mode 100644 qtlib/locale/cs/LC_MESSAGES/qtlib.po create mode 100644 qtlib/locale/de/LC_MESSAGES/qtlib.po create mode 100644 qtlib/locale/es/LC_MESSAGES/qtlib.po create mode 100644 qtlib/locale/fr/LC_MESSAGES/qtlib.po create mode 100755 qtlib/locale/hy/LC_MESSAGES/qtlib.po create mode 100644 qtlib/locale/it/LC_MESSAGES/qtlib.po create mode 100644 qtlib/locale/nl/LC_MESSAGES/qtlib.po create mode 100644 qtlib/locale/pt_BR/LC_MESSAGES/qtlib.po create mode 100644 qtlib/locale/qtlib.pot create mode 100644 qtlib/locale/ru/LC_MESSAGES/qtlib.po create mode 100755 qtlib/locale/uk/LC_MESSAGES/qtlib.po create mode 100644 qtlib/locale/zh_CN/LC_MESSAGES/qtlib.po create mode 100644 qtlib/preferences.py create mode 100644 qtlib/radio_box.py create mode 100644 qtlib/recent.py create mode 100644 qtlib/reg.py create mode 100644 qtlib/reg_demo_dialog.py create mode 100644 qtlib/reg_submit_dialog.py create mode 100644 qtlib/search_edit.py create mode 100644 qtlib/selectable_list.py create mode 100644 qtlib/table.py create mode 100644 qtlib/text_field.py create mode 100644 qtlib/tree_model.py create mode 100644 qtlib/util.py diff --git a/qtlib/.gitignore b/qtlib/.gitignore new file mode 100644 index 00000000..7f1e166c --- /dev/null +++ b/qtlib/.gitignore @@ -0,0 +1,4 @@ +__pycache__ +*.pyc +*.mo +.DS_Store \ No newline at end of file diff --git a/qtlib/.tx/config b/qtlib/.tx/config new file mode 100644 index 00000000..9964490d --- /dev/null +++ b/qtlib/.tx/config @@ -0,0 +1,8 @@ +[main] +host = https://www.transifex.net + +[hscommon.qtlib] +file_filter = locale//LC_MESSAGES/qtlib.po +source_file = locale/qtlib.pot +source_lang = en +type = PO diff --git a/qtlib/LICENSE b/qtlib/LICENSE new file mode 100644 index 00000000..791cf728 --- /dev/null +++ b/qtlib/LICENSE @@ -0,0 +1,10 @@ +Copyright 2013, Hardcoded Software Inc., http://www.hardcoded.net +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * Neither the name of Hardcoded Software Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/qtlib/__init__.py b/qtlib/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/qtlib/about_box.py b/qtlib/about_box.py new file mode 100644 index 00000000..00632aad --- /dev/null +++ b/qtlib/about_box.py @@ -0,0 +1,89 @@ +# Created By: Virgil Dupras +# Created On: 2009-05-09 +# Copyright 2013 Hardcoded Software (http://www.hardcoded.net) +# +# This software is licensed under the "BSD" License as described in the "LICENSE" file, +# which should be included with this package. The terms are also available at +# http://www.hardcoded.net/licenses/bsd_license + +from PyQt4.QtCore import Qt, QCoreApplication +from PyQt4.QtGui import (QDialog, QDialogButtonBox, QPixmap, QSizePolicy, QHBoxLayout, QVBoxLayout, + QLabel, QFont, QApplication) + +from hscommon.trans import trget + +tr = trget('qtlib') + +class AboutBox(QDialog): + def __init__(self, parent, app, withreg=True): + flags = Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowSystemMenuHint | Qt.MSWindowsFixedSizeDialogHint + QDialog.__init__(self, parent, flags) + self.app = app + self.withreg = withreg + self._setupUi() + + self.buttonBox.accepted.connect(self.accept) + self.buttonBox.rejected.connect(self.reject) + if self.withreg: + self.buttonBox.clicked.connect(self.buttonClicked) + + def _setupUi(self): + self.setWindowTitle(tr("About {}").format(QCoreApplication.instance().applicationName())) + self.resize(400, 190) + sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.sizePolicy().hasHeightForWidth()) + self.setSizePolicy(sizePolicy) + self.horizontalLayout = QHBoxLayout(self) + self.logoLabel = QLabel(self) + self.logoLabel.setPixmap(QPixmap(':/%s_big' % self.app.LOGO_NAME)) + self.horizontalLayout.addWidget(self.logoLabel) + self.verticalLayout = QVBoxLayout() + self.nameLabel = QLabel(self) + font = QFont() + font.setWeight(75) + font.setBold(True) + self.nameLabel.setFont(font) + self.nameLabel.setText(QCoreApplication.instance().applicationName()) + self.verticalLayout.addWidget(self.nameLabel) + self.versionLabel = QLabel(self) + self.versionLabel.setText(tr("Version {}").format(QCoreApplication.instance().applicationVersion())) + self.verticalLayout.addWidget(self.versionLabel) + self.label_3 = QLabel(self) + self.verticalLayout.addWidget(self.label_3) + self.label_3.setText(tr("Copyright Hardcoded Software 2013")) + self.label = QLabel(self) + font = QFont() + font.setWeight(75) + font.setBold(True) + self.label.setFont(font) + self.verticalLayout.addWidget(self.label) + self.registeredEmailLabel = QLabel(self) + if self.withreg: + self.registeredEmailLabel.setText(tr("UNREGISTERED")) + self.verticalLayout.addWidget(self.registeredEmailLabel) + self.buttonBox = QDialogButtonBox(self) + self.buttonBox.setOrientation(Qt.Horizontal) + self.buttonBox.setStandardButtons(QDialogButtonBox.Ok) + if self.withreg: + self.registerButton = self.buttonBox.addButton(tr("Register"), QDialogButtonBox.ActionRole) + self.verticalLayout.addWidget(self.buttonBox) + self.horizontalLayout.addLayout(self.verticalLayout) + + #--- Events + def buttonClicked(self, button): + if button is self.registerButton: + self.app.askForRegCode() + + +if __name__ == '__main__': + import sys + app = QApplication([]) + QCoreApplication.setOrganizationName('Hardcoded Software') + QCoreApplication.setApplicationName('FooApp') + QCoreApplication.setApplicationVersion('1.2.3') + app.LOGO_NAME = '' + dialog = AboutBox(None, app) + dialog.show() + sys.exit(app.exec_()) diff --git a/qtlib/app.py b/qtlib/app.py new file mode 100644 index 00000000..1fafafce --- /dev/null +++ b/qtlib/app.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# Created By: Virgil Dupras +# Created On: 2009-10-16 +# Copyright 2013 Hardcoded Software (http://www.hardcoded.net) +# +# This software is licensed under the "BSD" License as described in the "LICENSE" file, +# which should be included with this package. The terms are also available at +# http://www.hardcoded.net/licenses/bsd_license + +from PyQt4.QtCore import SIGNAL, QTimer, QObject + +class Application(QObject): + def __init__(self): + QObject.__init__(self) + QTimer.singleShot(0, self.__launchTimerTimedOut) + + def __launchTimerTimedOut(self): + self.emit(SIGNAL('applicationFinishedLaunching()')) + diff --git a/qtlib/column.py b/qtlib/column.py new file mode 100644 index 00000000..7b1ff129 --- /dev/null +++ b/qtlib/column.py @@ -0,0 +1,86 @@ +# Created By: Virgil Dupras +# Created On: 2009-11-25 +# Copyright 2013 Hardcoded Software (http://www.hardcoded.net) +# +# This software is licensed under the "BSD" License as described in the "LICENSE" file, +# which should be included with this package. The terms are also available at +# http://www.hardcoded.net/licenses/bsd_license + +from PyQt4.QtCore import Qt + +class Column: + def __init__(self, attrname, defaultWidth, editor=None, alignment=Qt.AlignLeft, cantTruncate=False): + self.attrname = attrname + self.defaultWidth = defaultWidth + self.editor = editor + self.alignment = alignment + # This is to indicate, during printing, that a column can't have its data truncated. + self.cantTruncate = cantTruncate + + +class Columns: + def __init__(self, model, columns, headerView): + self.model = model + self._headerView = headerView + self._headerView.setDefaultAlignment(Qt.AlignLeft) + def setspecs(col, modelcol): + modelcol.default_width = col.defaultWidth + modelcol.editor = col.editor + modelcol.alignment = col.alignment + modelcol.cantTruncate = col.cantTruncate + if columns: + for col in columns: + modelcol = self.model.column_by_name(col.attrname) + setspecs(col, modelcol) + else: + col = Column('', 100) + for modelcol in self.model.column_list: + setspecs(col, modelcol) + self.model.view = self + self._headerView.sectionMoved.connect(self.headerSectionMoved) + self._headerView.sectionResized.connect(self.headerSectionResized) + + #--- Public + def setColumnsWidth(self, widths): + #`widths` can be None. If it is, then default widths are set. + columns = self.model.column_list + if not widths: + widths = [column.default_width for column in columns] + for column, width in zip(columns, widths): + if width == 0: # column was hidden before. + width = column.default_width + self._headerView.resizeSection(column.logical_index, width) + + def setColumnsOrder(self, columnIndexes): + if not columnIndexes: + return + for destIndex, columnIndex in enumerate(columnIndexes): + # moveSection takes 2 visual index arguments, so we have to get our visual index first + visualIndex = self._headerView.visualIndex(columnIndex) + self._headerView.moveSection(visualIndex, destIndex) + + #--- Events + def headerSectionMoved(self, logicalIndex, oldVisualIndex, newVisualIndex): + attrname = self.model.column_by_index(logicalIndex).name + self.model.move_column(attrname, newVisualIndex) + + def headerSectionResized(self, logicalIndex, oldSize, newSize): + attrname = self.model.column_by_index(logicalIndex).name + self.model.resize_column(attrname, newSize) + + #--- model --> view + def restore_columns(self): + columns = self.model.ordered_columns + indexes = [col.logical_index for col in columns] + self.setColumnsOrder(indexes) + widths = [col.width for col in self.model.column_list] + if not any(widths): + widths = None + self.setColumnsWidth(widths) + for column in self.model.column_list: + visible = self.model.column_is_visible(column.name) + self._headerView.setSectionHidden(column.logical_index, not visible) + + def set_column_visible(self, colname, visible): + column = self.model.column_by_name(colname) + self._headerView.setSectionHidden(column.logical_index, not visible) diff --git a/qtlib/error_report_dialog.py b/qtlib/error_report_dialog.py new file mode 100644 index 00000000..baa9ea74 --- /dev/null +++ b/qtlib/error_report_dialog.py @@ -0,0 +1,88 @@ +# Created By: Virgil Dupras +# Created On: 2009-05-23 +# Copyright 2013 Hardcoded Software (http://www.hardcoded.net) +# +# This software is licensed under the "BSD" License as described in the "LICENSE" file, +# which should be included with this package. The terms are also available at +# http://www.hardcoded.net/licenses/bsd_license + +import traceback +import sys +import os + +from PyQt4.QtCore import Qt, QUrl, QCoreApplication, QSize +from PyQt4.QtGui import (QDialog, QDesktopServices, QVBoxLayout, QHBoxLayout, QLabel, + QPlainTextEdit, QPushButton, QApplication) + +from hscommon.trans import trget +from .util import horizontalSpacer + +tr = trget('qtlib') + +class ErrorReportDialog(QDialog): + def __init__(self, parent, error): + flags = Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowSystemMenuHint + QDialog.__init__(self, parent, flags) + self._setupUi() + name = QCoreApplication.applicationName() + version = QCoreApplication.applicationVersion() + errorText = "Application Name: {0}\nVersion: {1}\n\n{2}".format(name, version, error) + # Under windows, we end up with an error report without linesep if we don't mangle it + errorText = errorText.replace('\n', os.linesep) + self.errorTextEdit.setPlainText(errorText) + + self.sendButton.clicked.connect(self.accept) + self.dontSendButton.clicked.connect(self.reject) + + def _setupUi(self): + self.setWindowTitle(tr("Error Report")) + self.resize(553, 349) + self.verticalLayout = QVBoxLayout(self) + self.label = QLabel(self) + self.label.setText(tr("Something went wrong. Would you like to send the error report to Hardcoded Software?")) + self.label.setWordWrap(True) + self.verticalLayout.addWidget(self.label) + self.errorTextEdit = QPlainTextEdit(self) + self.errorTextEdit.setReadOnly(True) + self.verticalLayout.addWidget(self.errorTextEdit) + msg = tr("Although the application should continue to run after this error, it may be in an " + "instable state, so it is recommended that you restart the application.") + self.label2 = QLabel(msg) + self.label2.setWordWrap(True) + self.verticalLayout.addWidget(self.label2) + self.horizontalLayout = QHBoxLayout() + self.horizontalLayout.addItem(horizontalSpacer()) + self.dontSendButton = QPushButton(self) + self.dontSendButton.setText(tr("Don\'t Send")) + self.dontSendButton.setMinimumSize(QSize(110, 0)) + self.horizontalLayout.addWidget(self.dontSendButton) + self.sendButton = QPushButton(self) + self.sendButton.setText(tr("Send")) + self.sendButton.setMinimumSize(QSize(110, 0)) + self.sendButton.setDefault(True) + self.horizontalLayout.addWidget(self.sendButton) + self.verticalLayout.addLayout(self.horizontalLayout) + + def accept(self): + text = self.errorTextEdit.toPlainText() + url = QUrl("mailto:support@hardcoded.net?SUBJECT=Error Report&BODY=%s" % text) + QDesktopServices.openUrl(url) + QDialog.accept(self) + + +def install_excepthook(): + def my_excepthook(exctype, value, tb): + s = ''.join(traceback.format_exception(exctype, value, tb)) + dialog = ErrorReportDialog(None, s) + dialog.exec_() + + sys.excepthook = my_excepthook + +if __name__ == '__main__': + app = QApplication([]) + QCoreApplication.setOrganizationName('Hardcoded Software') + QCoreApplication.setApplicationName('FooApp') + QCoreApplication.setApplicationVersion('1.2.3') + dialog = ErrorReportDialog(None, 'some traceback') + dialog.show() + sys.exit(app.exec_()) \ No newline at end of file diff --git a/qtlib/images/search_clear_13.png b/qtlib/images/search_clear_13.png new file mode 100644 index 0000000000000000000000000000000000000000..1f1494140626accbacc670594229bf1471f6e222 GIT binary patch literal 3084 zcmV+n4D<7eP)4Tx0C)kNmUmQBSrfqTdoR7v5<-y@dJRoV0Fe@UkzPe5BmqJR7!t5oLbpCc6HqI?@={d8%D5al;0(=!Cz zYydD6nO!2_rJ!tuGDRE_#zA==00c_%EKZ!o62USwPXIWXSj`sE}8w<4jU*%sHzk2;U z$a?$5<7MdQoaVsz{O95^ejS$UX;36cb2fe1Y+3Y{{cC>d?Hh%b}~Geu0H=$|_LAH!zl zAj2Q0Uf9TEuaUC0Snjw2jC3cfEVxw!5{*}g2jLb zQa}a}gIur*tOxm^5bOYZKsl%aHJ}bOfD@nvoCX)bWpEwb1byH>7z88W8JGmG!3+dJ zc!&zoAT>xEGJwn=8;A|fhrFObC=7~)5};&A1WBP)&_<{bDu&9TgHRpxBXkP709}Q8 zpu5lzG!Fdvqf1r2MCzX|yZIz>xmnl~$ zpHUuUAPhr>A0wSn#5lp|XS`F#WweHcflJworSw_BrjROl77!Go4w=>|jpnXz2LrNOcbC zbnDFM8tF#rZqRMieW*v$W9ud9?bd78o7C6V57J+yU$1}9fM~!rNHN%J&}lGjXk-{| zxY@A9aLh>6$j@knQN7UvW2&*M@lxYz|7l}t!?UTdxjmOU*L&{Txvg_w*qYf2Z1>yVv7^}q*=@FKxBFo4U@x|B zupf8OcSvxkbQoaM*&*z0>?@8~M-Rufj;9^pI@vo(oK86X;mmSQb3W=kHqU6DU|!9< zVHaH&uFFA}!THSj3G)xkA9U4m<+@h8K6cY{%Av^?0i=GocG202Kesu9q`liwb@Yi zqU=@)9sQZ=k{U}lNr!Ug=Tzjp$&JcAxlD1HXj#{C)8$*2kFM}u@%>87O5V!$RXVHI zuNqqIzWU%AXiegp_O*Iz^VW{6^I3OfJ!yT~`d>C!Z7AOGYGd@qwmi+eb$P>^d^XkR z%jJvn2R1uzuG)gxBHYrwb?(-(tse{c1=k9#3QG##Z{uyd_MP>2rQdzpp0vHY$i8U* z4%`mWj{cplJC77A7OyBC-W9Z~c{g)+!R}Xkmh8D&Vp~$Rm$X;9cd#_Dw6#pXY)9Gq z@|5zv3Xh7$N{z~`mDBt9`+E1g?Qf{ktSYQ}cR+aH&Ox7p&DDn0C5Lc_at=MIiK^-R zp8b7Yt$J-??T5pn!-Ge{j&#&H)YTo;I9gN>*GucikHsIm`Ge;VtqrV(gN=;F!sFn$ z^!U>s6MpPJ5pbgYB>QB;PX<3#Hqn|2nxW?9&66!DErYGGtv#pwPqnu>w>AB2@$=!+ zI;ShnD4!`hOFEl(_S3l)=cdkQou9and||kKN&EeaF&A%lgm!da3b=ITviIeSo$j6I zuDDz|ebwpescYO08?84TZ?^T!>p9!&+I!)a=dH`P z{cd0HThQ0jAK8CrAbw!*4*$;B-SoRJ?&aK@xxelK_Cdizg@+}NG#*v|YVvF2p#9*P zAK5^Wa`oDjMp>M1#i^e9C^!r+xaf~-RMm2 zd;I&-4<;YlJ_dYz@G0Zdr@sILoAdna&gY5%000SaNLh0L01FcU01FcV0GgZ_0004R zNkl4#8y-UMT6vfjRzrc^8Pzptg1QNutT_lBC2kRsvPF?Hf|KlGZp@Sw8{2IG- zFi;9vB$!UE=uoK?2SE&}=hQrDCq3}vzH{HbFYo2OgfuA?_5f^xIq(48wgfLg&5=2w+%rW8~5R1g=-@t`7zyk1u*@lq}!&vq_Z%0*CZcWN$GBd4K zt5hzRSLmT#pmT5nYQ%Nj=ONVXb_ZDCw%u;`>3!dS6*a8qc1}SONU2n6y3uHqG)-Hj zr#hX^pja%{5kG%2(i^uoYG9(*>wQ%!mHRLZBl;+chSh4-9cy5EiA@8JsBAVnYuk1~ zQ55DSS(X!~X&Sn&&(p_x=j5YsmSt_BG083E^ZA<~2>R)CdeL#5f~Z0CIbH`QsO56G z>t?h0f<~JjXT0Fg!I|#p!5LT+_i_Zo%l%8|C~(B(1~6PeizC8>_#*g}_$r3tOQPam aZ|@rh&V5rl>R9st0000\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: utf-8\n" +"Language: cs\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" + +#: qtlib/about_box.py:31 +msgid "About {}" +msgstr "" + +#: qtlib/about_box.py:51 +msgid "Version {}" +msgstr "" + +#: qtlib/about_box.py:55 +msgid "Copyright Hardcoded Software 2013" +msgstr "" + +#: qtlib/about_box.py:64 +msgid "UNREGISTERED" +msgstr "" + +#: qtlib/about_box.py:70 +msgid "Register" +msgstr "" + +#: qtlib/error_report_dialog.py:38 +msgid "Error Report" +msgstr "" + +#: qtlib/error_report_dialog.py:42 +msgid "" +"Something went wrong. Would you like to send the error report to Hardcoded " +"Software?" +msgstr "" + +#: qtlib/error_report_dialog.py:48 +msgid "" +"Although the application should continue to run after this error, it may be " +"in an instable state, so it is recommended that you restart the application." +msgstr "" + +#: qtlib/error_report_dialog.py:56 +msgid "Don't Send" +msgstr "" + +#: qtlib/error_report_dialog.py:60 +msgid "Send" +msgstr "" + +#: qtlib/preferences.py:17 +msgid "English" +msgstr "" + +#: qtlib/preferences.py:18 +msgid "French" +msgstr "" + +#: qtlib/preferences.py:19 +msgid "German" +msgstr "" + +#: qtlib/preferences.py:20 +msgid "Chinese (Simplified)" +msgstr "" + +#: qtlib/preferences.py:21 +msgid "Czech" +msgstr "" + +#: qtlib/preferences.py:22 +msgid "Italian" +msgstr "" + +#: qtlib/preferences.py:23 +msgid "Armenian" +msgstr "" + +#: qtlib/preferences.py:24 +msgid "Russian" +msgstr "" + +#: qtlib/preferences.py:25 +msgid "Ukrainian" +msgstr "" + +#: qtlib/preferences.py:26 +msgid "Dutch" +msgstr "" + +#: qtlib/preferences.py:27 +msgid "Brazilian" +msgstr "" + +#: qtlib/preferences.py:28 +msgid "Spanish" +msgstr "" + +#: qtlib/recent.py:53 +msgid "Clear List" +msgstr "" + +#: qtlib/reg_demo_dialog.py:35 +msgid "$appname is Fairware" +msgstr "" + +#: qtlib/reg_demo_dialog.py:49 +msgid "Try" +msgstr "" + +#: qtlib/reg_demo_dialog.py:52 +msgid "Enter Key" +msgstr "" + +#: qtlib/reg_demo_dialog.py:55 +msgid "Buy" +msgstr "" + +#: qtlib/reg_demo_dialog.py:57 +msgid "Fairware?" +msgstr "" + +#: qtlib/reg_submit_dialog.py:31 +msgid "Enter your registration key" +msgstr "" + +#: qtlib/reg_submit_dialog.py:36 +msgid "" +"Type the key you received when you contributed to $appname, as well as the " +"e-mail used as a reference for the purchase." +msgstr "Type the key you received when you contributed to $appname, as well as the e-mail used as a reference for the purchase." + +#: qtlib/reg_submit_dialog.py:48 +msgid "Registration key:" +msgstr "" + +#: qtlib/reg_submit_dialog.py:51 +msgid "Registered e-mail:" +msgstr "" + +#: qtlib/reg_submit_dialog.py:60 +msgid "Contribute" +msgstr "Přispět" + +#: qtlib/reg_submit_dialog.py:71 +msgid "Cancel" +msgstr "Zrušit" + +#: qtlib/reg_submit_dialog.py:80 +msgid "Submit" +msgstr "" + +#: qtlib/search_edit.py:41 +msgid "Search..." +msgstr "" diff --git a/qtlib/locale/de/LC_MESSAGES/qtlib.po b/qtlib/locale/de/LC_MESSAGES/qtlib.po new file mode 100644 index 00000000..c6ba98a4 --- /dev/null +++ b/qtlib/locale/de/LC_MESSAGES/qtlib.po @@ -0,0 +1,161 @@ +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: hscommon\n" +"PO-Revision-Date: 2013-04-28 18:31+0000\n" +"Last-Translator: hsoft \n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: utf-8\n" +"Language: de\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: qtlib/about_box.py:31 +msgid "About {}" +msgstr "" + +#: qtlib/about_box.py:51 +msgid "Version {}" +msgstr "" + +#: qtlib/about_box.py:55 +msgid "Copyright Hardcoded Software 2013" +msgstr "" + +#: qtlib/about_box.py:64 +msgid "UNREGISTERED" +msgstr "" + +#: qtlib/about_box.py:70 +msgid "Register" +msgstr "" + +#: qtlib/error_report_dialog.py:38 +msgid "Error Report" +msgstr "" + +#: qtlib/error_report_dialog.py:42 +msgid "" +"Something went wrong. Would you like to send the error report to Hardcoded " +"Software?" +msgstr "" + +#: qtlib/error_report_dialog.py:48 +msgid "" +"Although the application should continue to run after this error, it may be " +"in an instable state, so it is recommended that you restart the application." +msgstr "" + +#: qtlib/error_report_dialog.py:56 +msgid "Don't Send" +msgstr "" + +#: qtlib/error_report_dialog.py:60 +msgid "Send" +msgstr "" + +#: qtlib/preferences.py:17 +msgid "English" +msgstr "Englisch" + +#: qtlib/preferences.py:18 +msgid "French" +msgstr "Französisch" + +#: qtlib/preferences.py:19 +msgid "German" +msgstr "Deutsch" + +#: qtlib/preferences.py:20 +msgid "Chinese (Simplified)" +msgstr "" + +#: qtlib/preferences.py:21 +msgid "Czech" +msgstr "" + +#: qtlib/preferences.py:22 +msgid "Italian" +msgstr "" + +#: qtlib/preferences.py:23 +msgid "Armenian" +msgstr "" + +#: qtlib/preferences.py:24 +msgid "Russian" +msgstr "" + +#: qtlib/preferences.py:25 +msgid "Ukrainian" +msgstr "" + +#: qtlib/preferences.py:26 +msgid "Dutch" +msgstr "" + +#: qtlib/preferences.py:27 +msgid "Brazilian" +msgstr "" + +#: qtlib/preferences.py:28 +msgid "Spanish" +msgstr "" + +#: qtlib/recent.py:53 +msgid "Clear List" +msgstr "" + +#: qtlib/reg_demo_dialog.py:35 +msgid "$appname is Fairware" +msgstr "$appname ist Fairware" + +#: qtlib/reg_demo_dialog.py:49 +msgid "Try" +msgstr "Spenden" + +#: qtlib/reg_demo_dialog.py:52 +msgid "Enter Key" +msgstr "Registrieren" + +#: qtlib/reg_demo_dialog.py:55 +msgid "Buy" +msgstr "" + +#: qtlib/reg_demo_dialog.py:57 +msgid "Fairware?" +msgstr "" + +#: qtlib/reg_submit_dialog.py:31 +msgid "Enter your registration key" +msgstr "Geben Sie ihren Schlüssel ein" + +#: qtlib/reg_submit_dialog.py:36 +msgid "" +"Type the key you received when you contributed to $appname, as well as the " +"e-mail used as a reference for the purchase." +msgstr "Geben Sie den empfangenen Schlüssel und die E-Mail-Adresse als Referenz für den Kauf an, wenn Sie für $appname gespendet haben." + +#: qtlib/reg_submit_dialog.py:48 +msgid "Registration key:" +msgstr "Registrierungsschlüssel:" + +#: qtlib/reg_submit_dialog.py:51 +msgid "Registered e-mail:" +msgstr "Registrierte E-Mail:" + +#: qtlib/reg_submit_dialog.py:60 +msgid "Contribute" +msgstr "Spenden" + +#: qtlib/reg_submit_dialog.py:71 +msgid "Cancel" +msgstr "Abbrechen" + +#: qtlib/reg_submit_dialog.py:80 +msgid "Submit" +msgstr "Abschicken" + +#: qtlib/search_edit.py:41 +msgid "Search..." +msgstr "" diff --git a/qtlib/locale/es/LC_MESSAGES/qtlib.po b/qtlib/locale/es/LC_MESSAGES/qtlib.po new file mode 100644 index 00000000..66a8c18f --- /dev/null +++ b/qtlib/locale/es/LC_MESSAGES/qtlib.po @@ -0,0 +1,161 @@ +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: hscommon\n" +"PO-Revision-Date: 2013-04-28 18:31+0000\n" +"Last-Translator: hsoft \n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: utf-8\n" +"Language: es\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: qtlib/about_box.py:31 +msgid "About {}" +msgstr "Acerca de {}" + +#: qtlib/about_box.py:51 +msgid "Version {}" +msgstr "Versión {}" + +#: qtlib/about_box.py:55 +msgid "Copyright Hardcoded Software 2013" +msgstr "Copyright Hardcoded Software 2013" + +#: qtlib/about_box.py:64 +msgid "UNREGISTERED" +msgstr "SIN REGISTRAR" + +#: qtlib/about_box.py:70 +msgid "Register" +msgstr "Registrar" + +#: qtlib/error_report_dialog.py:38 +msgid "Error Report" +msgstr "Informe de error" + +#: qtlib/error_report_dialog.py:42 +msgid "" +"Something went wrong. Would you like to send the error report to Hardcoded " +"Software?" +msgstr "Se ha producido un error. ¿Desea enviar un informe de error a Harcoded Software?" + +#: qtlib/error_report_dialog.py:48 +msgid "" +"Although the application should continue to run after this error, it may be " +"in an instable state, so it is recommended that you restart the application." +msgstr "Aunque la aplicación debería continuar funcionado tras el fallo, sin embargo podría volverse inestable. Se recomienda reiniciar la aplicación." + +#: qtlib/error_report_dialog.py:56 +msgid "Don't Send" +msgstr "No envíar" + +#: qtlib/error_report_dialog.py:60 +msgid "Send" +msgstr "Enviar" + +#: qtlib/preferences.py:17 +msgid "English" +msgstr "Inglés" + +#: qtlib/preferences.py:18 +msgid "French" +msgstr "Francés" + +#: qtlib/preferences.py:19 +msgid "German" +msgstr "Alemán" + +#: qtlib/preferences.py:20 +msgid "Chinese (Simplified)" +msgstr "Chino (simplificado)" + +#: qtlib/preferences.py:21 +msgid "Czech" +msgstr "Checo" + +#: qtlib/preferences.py:22 +msgid "Italian" +msgstr "Italiano" + +#: qtlib/preferences.py:23 +msgid "Armenian" +msgstr "Armenio" + +#: qtlib/preferences.py:24 +msgid "Russian" +msgstr "Ruso" + +#: qtlib/preferences.py:25 +msgid "Ukrainian" +msgstr "Ucraniano" + +#: qtlib/preferences.py:26 +msgid "Dutch" +msgstr "Holandés" + +#: qtlib/preferences.py:27 +msgid "Brazilian" +msgstr "Brasileño" + +#: qtlib/preferences.py:28 +msgid "Spanish" +msgstr "Español" + +#: qtlib/recent.py:53 +msgid "Clear List" +msgstr "Limpiar lista" + +#: qtlib/reg_demo_dialog.py:35 +msgid "$appname is Fairware" +msgstr "$appname es Fairware" + +#: qtlib/reg_demo_dialog.py:49 +msgid "Try" +msgstr "Probar" + +#: qtlib/reg_demo_dialog.py:52 +msgid "Enter Key" +msgstr "Introducir clave" + +#: qtlib/reg_demo_dialog.py:55 +msgid "Buy" +msgstr "Comprar" + +#: qtlib/reg_demo_dialog.py:57 +msgid "Fairware?" +msgstr "¿Fairware?" + +#: qtlib/reg_submit_dialog.py:31 +msgid "Enter your registration key" +msgstr "Introduzca su clave de registro" + +#: qtlib/reg_submit_dialog.py:36 +msgid "" +"Type the key you received when you contributed to $appname, as well as the " +"e-mail used as a reference for the purchase." +msgstr "Escriba la clave que recibió al donar a $appname, así como el correo electrónico que usó durante la compra." + +#: qtlib/reg_submit_dialog.py:48 +msgid "Registration key:" +msgstr "Clave de registro" + +#: qtlib/reg_submit_dialog.py:51 +msgid "Registered e-mail:" +msgstr "Correo electrónico de registro:" + +#: qtlib/reg_submit_dialog.py:60 +msgid "Contribute" +msgstr "Donar" + +#: qtlib/reg_submit_dialog.py:71 +msgid "Cancel" +msgstr "Cancelar" + +#: qtlib/reg_submit_dialog.py:80 +msgid "Submit" +msgstr "Enviar" + +#: qtlib/search_edit.py:41 +msgid "Search..." +msgstr "Búsqueda..." diff --git a/qtlib/locale/fr/LC_MESSAGES/qtlib.po b/qtlib/locale/fr/LC_MESSAGES/qtlib.po new file mode 100644 index 00000000..bb632497 --- /dev/null +++ b/qtlib/locale/fr/LC_MESSAGES/qtlib.po @@ -0,0 +1,161 @@ +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: hscommon\n" +"PO-Revision-Date: 2013-04-28 18:31+0000\n" +"Last-Translator: hsoft \n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: utf-8\n" +"Language: fr\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: qtlib/about_box.py:31 +msgid "About {}" +msgstr "" + +#: qtlib/about_box.py:51 +msgid "Version {}" +msgstr "" + +#: qtlib/about_box.py:55 +msgid "Copyright Hardcoded Software 2013" +msgstr "" + +#: qtlib/about_box.py:64 +msgid "UNREGISTERED" +msgstr "" + +#: qtlib/about_box.py:70 +msgid "Register" +msgstr "" + +#: qtlib/error_report_dialog.py:38 +msgid "Error Report" +msgstr "" + +#: qtlib/error_report_dialog.py:42 +msgid "" +"Something went wrong. Would you like to send the error report to Hardcoded " +"Software?" +msgstr "" + +#: qtlib/error_report_dialog.py:48 +msgid "" +"Although the application should continue to run after this error, it may be " +"in an instable state, so it is recommended that you restart the application." +msgstr "" + +#: qtlib/error_report_dialog.py:56 +msgid "Don't Send" +msgstr "" + +#: qtlib/error_report_dialog.py:60 +msgid "Send" +msgstr "" + +#: qtlib/preferences.py:17 +msgid "English" +msgstr "Anglais" + +#: qtlib/preferences.py:18 +msgid "French" +msgstr "Français" + +#: qtlib/preferences.py:19 +msgid "German" +msgstr "Allemand" + +#: qtlib/preferences.py:20 +msgid "Chinese (Simplified)" +msgstr "Chinois (Simplifié)" + +#: qtlib/preferences.py:21 +msgid "Czech" +msgstr "Tchèque" + +#: qtlib/preferences.py:22 +msgid "Italian" +msgstr "Italien" + +#: qtlib/preferences.py:23 +msgid "Armenian" +msgstr "Arménien" + +#: qtlib/preferences.py:24 +msgid "Russian" +msgstr "Russe" + +#: qtlib/preferences.py:25 +msgid "Ukrainian" +msgstr "Ukrainien" + +#: qtlib/preferences.py:26 +msgid "Dutch" +msgstr "Néerlandais" + +#: qtlib/preferences.py:27 +msgid "Brazilian" +msgstr "" + +#: qtlib/preferences.py:28 +msgid "Spanish" +msgstr "" + +#: qtlib/recent.py:53 +msgid "Clear List" +msgstr "Vider la liste" + +#: qtlib/reg_demo_dialog.py:35 +msgid "$appname is Fairware" +msgstr "$appname est Fairware" + +#: qtlib/reg_demo_dialog.py:49 +msgid "Try" +msgstr "Essayer" + +#: qtlib/reg_demo_dialog.py:52 +msgid "Enter Key" +msgstr "Enregistrer" + +#: qtlib/reg_demo_dialog.py:55 +msgid "Buy" +msgstr "Acheter" + +#: qtlib/reg_demo_dialog.py:57 +msgid "Fairware?" +msgstr "" + +#: qtlib/reg_submit_dialog.py:31 +msgid "Enter your registration key" +msgstr "Entrez votre clé" + +#: qtlib/reg_submit_dialog.py:36 +msgid "" +"Type the key you received when you contributed to $appname, as well as the " +"e-mail used as a reference for the purchase." +msgstr "Entrez la clé que vous avez reçue en contribuant à $appname, ainsi que le courriel utilisé pour la contribution." + +#: qtlib/reg_submit_dialog.py:48 +msgid "Registration key:" +msgstr "Clé d'enregistrement:" + +#: qtlib/reg_submit_dialog.py:51 +msgid "Registered e-mail:" +msgstr "Courriel référence:" + +#: qtlib/reg_submit_dialog.py:60 +msgid "Contribute" +msgstr "Contribuer" + +#: qtlib/reg_submit_dialog.py:71 +msgid "Cancel" +msgstr "Annuler" + +#: qtlib/reg_submit_dialog.py:80 +msgid "Submit" +msgstr "Soumettre" + +#: qtlib/search_edit.py:41 +msgid "Search..." +msgstr "Recherche..." diff --git a/qtlib/locale/hy/LC_MESSAGES/qtlib.po b/qtlib/locale/hy/LC_MESSAGES/qtlib.po new file mode 100755 index 00000000..909c074e --- /dev/null +++ b/qtlib/locale/hy/LC_MESSAGES/qtlib.po @@ -0,0 +1,161 @@ +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: hscommon\n" +"PO-Revision-Date: 2013-04-28 18:31+0000\n" +"Last-Translator: hsoft \n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: utf-8\n" +"Language: hy\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: qtlib/about_box.py:31 +msgid "About {}" +msgstr "" + +#: qtlib/about_box.py:51 +msgid "Version {}" +msgstr "" + +#: qtlib/about_box.py:55 +msgid "Copyright Hardcoded Software 2013" +msgstr "Հեղ. իրավունքը Hardcoded Software 2013" + +#: qtlib/about_box.py:64 +msgid "UNREGISTERED" +msgstr "ՉԳՐԱՆՑՎԱԾ" + +#: qtlib/about_box.py:70 +msgid "Register" +msgstr "" + +#: qtlib/error_report_dialog.py:38 +msgid "Error Report" +msgstr "Սխալի զեկույցը" + +#: qtlib/error_report_dialog.py:42 +msgid "" +"Something went wrong. Would you like to send the error report to Hardcoded " +"Software?" +msgstr "Ինչ-որ բան սխալ էր: Ուղարկե՞լ սխալի մասին զեկույց Hardcoded Software-ին:" + +#: qtlib/error_report_dialog.py:48 +msgid "" +"Although the application should continue to run after this error, it may be " +"in an instable state, so it is recommended that you restart the application." +msgstr "" + +#: qtlib/error_report_dialog.py:56 +msgid "Don't Send" +msgstr "Չուղարկել" + +#: qtlib/error_report_dialog.py:60 +msgid "Send" +msgstr "Ուղարկել" + +#: qtlib/preferences.py:17 +msgid "English" +msgstr "Անգլերեն" + +#: qtlib/preferences.py:18 +msgid "French" +msgstr "Ֆրանսերեն" + +#: qtlib/preferences.py:19 +msgid "German" +msgstr "Գերմաներեն" + +#: qtlib/preferences.py:20 +msgid "Chinese (Simplified)" +msgstr "Չինարեն (Պարզեցված)" + +#: qtlib/preferences.py:21 +msgid "Czech" +msgstr "Չեխերեն" + +#: qtlib/preferences.py:22 +msgid "Italian" +msgstr "Իտալերեն" + +#: qtlib/preferences.py:23 +msgid "Armenian" +msgstr "" + +#: qtlib/preferences.py:24 +msgid "Russian" +msgstr "" + +#: qtlib/preferences.py:25 +msgid "Ukrainian" +msgstr "" + +#: qtlib/preferences.py:26 +msgid "Dutch" +msgstr "" + +#: qtlib/preferences.py:27 +msgid "Brazilian" +msgstr "" + +#: qtlib/preferences.py:28 +msgid "Spanish" +msgstr "" + +#: qtlib/recent.py:53 +msgid "Clear List" +msgstr "Մաքրել ցանկը" + +#: qtlib/reg_demo_dialog.py:35 +msgid "$appname is Fairware" +msgstr "$appname-ը Fairware է" + +#: qtlib/reg_demo_dialog.py:49 +msgid "Try" +msgstr "Փորձել" + +#: qtlib/reg_demo_dialog.py:52 +msgid "Enter Key" +msgstr "Գրել բանալին" + +#: qtlib/reg_demo_dialog.py:55 +msgid "Buy" +msgstr "Գնել" + +#: qtlib/reg_demo_dialog.py:57 +msgid "Fairware?" +msgstr "Fairware է՞" + +#: qtlib/reg_submit_dialog.py:31 +msgid "Enter your registration key" +msgstr "Գրեք գրանցման բանալին" + +#: qtlib/reg_submit_dialog.py:36 +msgid "" +"Type the key you received when you contributed to $appname, as well as the " +"e-mail used as a reference for the purchase." +msgstr "Մուտքագրեք այն բանալին, որը ստացել եք $appname-ին աջակցելիս, քանզի Ձեր էլ. հասցեն օգտագործվել է գնման ժամանակ:" + +#: qtlib/reg_submit_dialog.py:48 +msgid "Registration key:" +msgstr "Գրանցման բանալին." + +#: qtlib/reg_submit_dialog.py:51 +msgid "Registered e-mail:" +msgstr "Գրանցված էլ. հասցեն." + +#: qtlib/reg_submit_dialog.py:60 +msgid "Contribute" +msgstr "Մասնակցել" + +#: qtlib/reg_submit_dialog.py:71 +msgid "Cancel" +msgstr "Չեղարկել" + +#: qtlib/reg_submit_dialog.py:80 +msgid "Submit" +msgstr "Հաստատել" + +#: qtlib/search_edit.py:41 +msgid "Search..." +msgstr "" diff --git a/qtlib/locale/it/LC_MESSAGES/qtlib.po b/qtlib/locale/it/LC_MESSAGES/qtlib.po new file mode 100644 index 00000000..b94a3399 --- /dev/null +++ b/qtlib/locale/it/LC_MESSAGES/qtlib.po @@ -0,0 +1,161 @@ +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: hscommon\n" +"PO-Revision-Date: 2013-04-28 18:31+0000\n" +"Last-Translator: hsoft \n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: utf-8\n" +"Language: it\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: qtlib/about_box.py:31 +msgid "About {}" +msgstr "" + +#: qtlib/about_box.py:51 +msgid "Version {}" +msgstr "" + +#: qtlib/about_box.py:55 +msgid "Copyright Hardcoded Software 2013" +msgstr "" + +#: qtlib/about_box.py:64 +msgid "UNREGISTERED" +msgstr "" + +#: qtlib/about_box.py:70 +msgid "Register" +msgstr "" + +#: qtlib/error_report_dialog.py:38 +msgid "Error Report" +msgstr "" + +#: qtlib/error_report_dialog.py:42 +msgid "" +"Something went wrong. Would you like to send the error report to Hardcoded " +"Software?" +msgstr "" + +#: qtlib/error_report_dialog.py:48 +msgid "" +"Although the application should continue to run after this error, it may be " +"in an instable state, so it is recommended that you restart the application." +msgstr "" + +#: qtlib/error_report_dialog.py:56 +msgid "Don't Send" +msgstr "" + +#: qtlib/error_report_dialog.py:60 +msgid "Send" +msgstr "" + +#: qtlib/preferences.py:17 +msgid "English" +msgstr "" + +#: qtlib/preferences.py:18 +msgid "French" +msgstr "" + +#: qtlib/preferences.py:19 +msgid "German" +msgstr "" + +#: qtlib/preferences.py:20 +msgid "Chinese (Simplified)" +msgstr "" + +#: qtlib/preferences.py:21 +msgid "Czech" +msgstr "" + +#: qtlib/preferences.py:22 +msgid "Italian" +msgstr "" + +#: qtlib/preferences.py:23 +msgid "Armenian" +msgstr "" + +#: qtlib/preferences.py:24 +msgid "Russian" +msgstr "" + +#: qtlib/preferences.py:25 +msgid "Ukrainian" +msgstr "" + +#: qtlib/preferences.py:26 +msgid "Dutch" +msgstr "" + +#: qtlib/preferences.py:27 +msgid "Brazilian" +msgstr "" + +#: qtlib/preferences.py:28 +msgid "Spanish" +msgstr "" + +#: qtlib/recent.py:53 +msgid "Clear List" +msgstr "" + +#: qtlib/reg_demo_dialog.py:35 +msgid "$appname is Fairware" +msgstr "" + +#: qtlib/reg_demo_dialog.py:49 +msgid "Try" +msgstr "" + +#: qtlib/reg_demo_dialog.py:52 +msgid "Enter Key" +msgstr "" + +#: qtlib/reg_demo_dialog.py:55 +msgid "Buy" +msgstr "" + +#: qtlib/reg_demo_dialog.py:57 +msgid "Fairware?" +msgstr "" + +#: qtlib/reg_submit_dialog.py:31 +msgid "Enter your registration key" +msgstr "" + +#: qtlib/reg_submit_dialog.py:36 +msgid "" +"Type the key you received when you contributed to $appname, as well as the " +"e-mail used as a reference for the purchase." +msgstr "Type the key you received when you contributed to $appname, as well as the e-mail used as a reference for the purchase." + +#: qtlib/reg_submit_dialog.py:48 +msgid "Registration key:" +msgstr "" + +#: qtlib/reg_submit_dialog.py:51 +msgid "Registered e-mail:" +msgstr "" + +#: qtlib/reg_submit_dialog.py:60 +msgid "Contribute" +msgstr "" + +#: qtlib/reg_submit_dialog.py:71 +msgid "Cancel" +msgstr "" + +#: qtlib/reg_submit_dialog.py:80 +msgid "Submit" +msgstr "" + +#: qtlib/search_edit.py:41 +msgid "Search..." +msgstr "" diff --git a/qtlib/locale/nl/LC_MESSAGES/qtlib.po b/qtlib/locale/nl/LC_MESSAGES/qtlib.po new file mode 100644 index 00000000..312f04a9 --- /dev/null +++ b/qtlib/locale/nl/LC_MESSAGES/qtlib.po @@ -0,0 +1,161 @@ +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: hscommon\n" +"PO-Revision-Date: 2013-04-28 18:31+0000\n" +"Last-Translator: hsoft \n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: utf-8\n" +"Language: nl\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: qtlib/about_box.py:31 +msgid "About {}" +msgstr "" + +#: qtlib/about_box.py:51 +msgid "Version {}" +msgstr "" + +#: qtlib/about_box.py:55 +msgid "Copyright Hardcoded Software 2013" +msgstr "" + +#: qtlib/about_box.py:64 +msgid "UNREGISTERED" +msgstr "" + +#: qtlib/about_box.py:70 +msgid "Register" +msgstr "" + +#: qtlib/error_report_dialog.py:38 +msgid "Error Report" +msgstr "" + +#: qtlib/error_report_dialog.py:42 +msgid "" +"Something went wrong. Would you like to send the error report to Hardcoded " +"Software?" +msgstr "" + +#: qtlib/error_report_dialog.py:48 +msgid "" +"Although the application should continue to run after this error, it may be " +"in an instable state, so it is recommended that you restart the application." +msgstr "" + +#: qtlib/error_report_dialog.py:56 +msgid "Don't Send" +msgstr "" + +#: qtlib/error_report_dialog.py:60 +msgid "Send" +msgstr "" + +#: qtlib/preferences.py:17 +msgid "English" +msgstr "Engels" + +#: qtlib/preferences.py:18 +msgid "French" +msgstr "Frans" + +#: qtlib/preferences.py:19 +msgid "German" +msgstr "Duits" + +#: qtlib/preferences.py:20 +msgid "Chinese (Simplified)" +msgstr "" + +#: qtlib/preferences.py:21 +msgid "Czech" +msgstr "Tsjechisch" + +#: qtlib/preferences.py:22 +msgid "Italian" +msgstr "Italiaans" + +#: qtlib/preferences.py:23 +msgid "Armenian" +msgstr "" + +#: qtlib/preferences.py:24 +msgid "Russian" +msgstr "" + +#: qtlib/preferences.py:25 +msgid "Ukrainian" +msgstr "" + +#: qtlib/preferences.py:26 +msgid "Dutch" +msgstr "" + +#: qtlib/preferences.py:27 +msgid "Brazilian" +msgstr "" + +#: qtlib/preferences.py:28 +msgid "Spanish" +msgstr "" + +#: qtlib/recent.py:53 +msgid "Clear List" +msgstr "" + +#: qtlib/reg_demo_dialog.py:35 +msgid "$appname is Fairware" +msgstr "$appname is Fairware" + +#: qtlib/reg_demo_dialog.py:49 +msgid "Try" +msgstr "Probeer" + +#: qtlib/reg_demo_dialog.py:52 +msgid "Enter Key" +msgstr "Registreren" + +#: qtlib/reg_demo_dialog.py:55 +msgid "Buy" +msgstr "Koop" + +#: qtlib/reg_demo_dialog.py:57 +msgid "Fairware?" +msgstr "" + +#: qtlib/reg_submit_dialog.py:31 +msgid "Enter your registration key" +msgstr "Voer uw registratiesleutel in" + +#: qtlib/reg_submit_dialog.py:36 +msgid "" +"Type the key you received when you contributed to $appname, as well as the " +"e-mail used as a reference for the purchase." +msgstr "" + +#: qtlib/reg_submit_dialog.py:48 +msgid "Registration key:" +msgstr "Registratiesleutel:" + +#: qtlib/reg_submit_dialog.py:51 +msgid "Registered e-mail:" +msgstr "Geregistreerde E-Mail:" + +#: qtlib/reg_submit_dialog.py:60 +msgid "Contribute" +msgstr "Bijdragen" + +#: qtlib/reg_submit_dialog.py:71 +msgid "Cancel" +msgstr "Annuleren" + +#: qtlib/reg_submit_dialog.py:80 +msgid "Submit" +msgstr "Doorgeven" + +#: qtlib/search_edit.py:41 +msgid "Search..." +msgstr "" diff --git a/qtlib/locale/pt_BR/LC_MESSAGES/qtlib.po b/qtlib/locale/pt_BR/LC_MESSAGES/qtlib.po new file mode 100644 index 00000000..790a7b4e --- /dev/null +++ b/qtlib/locale/pt_BR/LC_MESSAGES/qtlib.po @@ -0,0 +1,161 @@ +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: hscommon\n" +"PO-Revision-Date: 2013-04-28 18:31+0000\n" +"Last-Translator: hsoft \n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: utf-8\n" +"Language: pt_BR\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: qtlib/about_box.py:31 +msgid "About {}" +msgstr "" + +#: qtlib/about_box.py:51 +msgid "Version {}" +msgstr "" + +#: qtlib/about_box.py:55 +msgid "Copyright Hardcoded Software 2013" +msgstr "Direitos Autorais Hardcoded Software 2013" + +#: qtlib/about_box.py:64 +msgid "UNREGISTERED" +msgstr "NÃO REGISTRADO" + +#: qtlib/about_box.py:70 +msgid "Register" +msgstr "" + +#: qtlib/error_report_dialog.py:38 +msgid "Error Report" +msgstr "Relatório de Erro" + +#: qtlib/error_report_dialog.py:42 +msgid "" +"Something went wrong. Would you like to send the error report to Hardcoded " +"Software?" +msgstr "Algo deu errado. Deseja enviar o relatório de erro à Hardcoded Software?" + +#: qtlib/error_report_dialog.py:48 +msgid "" +"Although the application should continue to run after this error, it may be " +"in an instable state, so it is recommended that you restart the application." +msgstr "Embora o aplicativo continue a funcionar após este erro, ele pode estar instável. É recomendável reiniciá-lo." + +#: qtlib/error_report_dialog.py:56 +msgid "Don't Send" +msgstr "Não Enviar" + +#: qtlib/error_report_dialog.py:60 +msgid "Send" +msgstr "Enviar" + +#: qtlib/preferences.py:17 +msgid "English" +msgstr "Inglês" + +#: qtlib/preferences.py:18 +msgid "French" +msgstr "Francês" + +#: qtlib/preferences.py:19 +msgid "German" +msgstr "Alemão" + +#: qtlib/preferences.py:20 +msgid "Chinese (Simplified)" +msgstr "Chinês (Simplificado)" + +#: qtlib/preferences.py:21 +msgid "Czech" +msgstr "Tcheco" + +#: qtlib/preferences.py:22 +msgid "Italian" +msgstr "Italiano" + +#: qtlib/preferences.py:23 +msgid "Armenian" +msgstr "Armênio" + +#: qtlib/preferences.py:24 +msgid "Russian" +msgstr "Russo" + +#: qtlib/preferences.py:25 +msgid "Ukrainian" +msgstr "Ucraniano" + +#: qtlib/preferences.py:26 +msgid "Dutch" +msgstr "Holandês" + +#: qtlib/preferences.py:27 +msgid "Brazilian" +msgstr "" + +#: qtlib/preferences.py:28 +msgid "Spanish" +msgstr "" + +#: qtlib/recent.py:53 +msgid "Clear List" +msgstr "Limpar Lista" + +#: qtlib/reg_demo_dialog.py:35 +msgid "$appname is Fairware" +msgstr "$appname é Fairware" + +#: qtlib/reg_demo_dialog.py:49 +msgid "Try" +msgstr "Testar" + +#: qtlib/reg_demo_dialog.py:52 +msgid "Enter Key" +msgstr "Entrar Chave" + +#: qtlib/reg_demo_dialog.py:55 +msgid "Buy" +msgstr "Comprar" + +#: qtlib/reg_demo_dialog.py:57 +msgid "Fairware?" +msgstr "Fairware?" + +#: qtlib/reg_submit_dialog.py:31 +msgid "Enter your registration key" +msgstr "Entre sua chave de registro" + +#: qtlib/reg_submit_dialog.py:36 +msgid "" +"Type the key you received when you contributed to $appname, as well as the " +"e-mail used as a reference for the purchase." +msgstr "Digite a chave que você recebeu ao contribuir com o $appname, assim como o e-mail usado para a compra." + +#: qtlib/reg_submit_dialog.py:48 +msgid "Registration key:" +msgstr "Chave de registro:" + +#: qtlib/reg_submit_dialog.py:51 +msgid "Registered e-mail:" +msgstr "e-mail registrado:" + +#: qtlib/reg_submit_dialog.py:60 +msgid "Contribute" +msgstr "Contribuir" + +#: qtlib/reg_submit_dialog.py:71 +msgid "Cancel" +msgstr "Cancelar" + +#: qtlib/reg_submit_dialog.py:80 +msgid "Submit" +msgstr "Enviar" + +#: qtlib/search_edit.py:41 +msgid "Search..." +msgstr "Buscar…" diff --git a/qtlib/locale/qtlib.pot b/qtlib/locale/qtlib.pot new file mode 100644 index 00000000..4b455fbf --- /dev/null +++ b/qtlib/locale/qtlib.pot @@ -0,0 +1,150 @@ + +msgid "" +msgstr "" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: utf-8\n" + +#: qtlib/about_box.py:31 +msgid "About {}" +msgstr "" + +#: qtlib/about_box.py:51 +msgid "Version {}" +msgstr "" + +#: qtlib/about_box.py:55 +msgid "Copyright Hardcoded Software 2013" +msgstr "" + +#: qtlib/about_box.py:64 +msgid "UNREGISTERED" +msgstr "" + +#: qtlib/about_box.py:70 +msgid "Register" +msgstr "" + +#: qtlib/error_report_dialog.py:38 +msgid "Error Report" +msgstr "" + +#: qtlib/error_report_dialog.py:42 +msgid "Something went wrong. Would you like to send the error report to Hardcoded Software?" +msgstr "" + +#: qtlib/error_report_dialog.py:48 +msgid "Although the application should continue to run after this error, it may be in an instable state, so it is recommended that you restart the application." +msgstr "" + +#: qtlib/error_report_dialog.py:56 +msgid "Don't Send" +msgstr "" + +#: qtlib/error_report_dialog.py:60 +msgid "Send" +msgstr "" + +#: qtlib/preferences.py:17 +msgid "English" +msgstr "" + +#: qtlib/preferences.py:18 +msgid "French" +msgstr "" + +#: qtlib/preferences.py:19 +msgid "German" +msgstr "" + +#: qtlib/preferences.py:20 +msgid "Chinese (Simplified)" +msgstr "" + +#: qtlib/preferences.py:21 +msgid "Czech" +msgstr "" + +#: qtlib/preferences.py:22 +msgid "Italian" +msgstr "" + +#: qtlib/preferences.py:23 +msgid "Armenian" +msgstr "" + +#: qtlib/preferences.py:24 +msgid "Russian" +msgstr "" + +#: qtlib/preferences.py:25 +msgid "Ukrainian" +msgstr "" + +#: qtlib/preferences.py:26 +msgid "Dutch" +msgstr "" + +#: qtlib/preferences.py:27 +msgid "Brazilian" +msgstr "" + +#: qtlib/preferences.py:28 +msgid "Spanish" +msgstr "" + +#: qtlib/recent.py:53 +msgid "Clear List" +msgstr "" + +#: qtlib/reg_demo_dialog.py:35 +msgid "$appname is Fairware" +msgstr "" + +#: qtlib/reg_demo_dialog.py:49 +msgid "Try" +msgstr "" + +#: qtlib/reg_demo_dialog.py:52 +msgid "Enter Key" +msgstr "" + +#: qtlib/reg_demo_dialog.py:55 +msgid "Buy" +msgstr "" + +#: qtlib/reg_demo_dialog.py:57 +msgid "Fairware?" +msgstr "" + +#: qtlib/reg_submit_dialog.py:31 +msgid "Enter your registration key" +msgstr "" + +#: qtlib/reg_submit_dialog.py:36 +msgid "Type the key you received when you contributed to $appname, as well as the e-mail used as a reference for the purchase." +msgstr "" + +#: qtlib/reg_submit_dialog.py:48 +msgid "Registration key:" +msgstr "" + +#: qtlib/reg_submit_dialog.py:51 +msgid "Registered e-mail:" +msgstr "" + +#: qtlib/reg_submit_dialog.py:60 +msgid "Contribute" +msgstr "" + +#: qtlib/reg_submit_dialog.py:71 +msgid "Cancel" +msgstr "" + +#: qtlib/reg_submit_dialog.py:80 +msgid "Submit" +msgstr "" + +#: qtlib/search_edit.py:41 +msgid "Search..." +msgstr "" + diff --git a/qtlib/locale/ru/LC_MESSAGES/qtlib.po b/qtlib/locale/ru/LC_MESSAGES/qtlib.po new file mode 100644 index 00000000..f0348bf9 --- /dev/null +++ b/qtlib/locale/ru/LC_MESSAGES/qtlib.po @@ -0,0 +1,161 @@ +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: hscommon\n" +"PO-Revision-Date: 2013-04-28 18:31+0000\n" +"Last-Translator: hsoft \n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: utf-8\n" +"Language: ru\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#: qtlib/about_box.py:31 +msgid "About {}" +msgstr "" + +#: qtlib/about_box.py:51 +msgid "Version {}" +msgstr "" + +#: qtlib/about_box.py:55 +msgid "Copyright Hardcoded Software 2013" +msgstr "Copyright Hardcoded Software 2013" + +#: qtlib/about_box.py:64 +msgid "UNREGISTERED" +msgstr "НЕЗАРЕГИСТРИРОВАННАЯ" + +#: qtlib/about_box.py:70 +msgid "Register" +msgstr "" + +#: qtlib/error_report_dialog.py:38 +msgid "Error Report" +msgstr "Сообщение об ошибке" + +#: qtlib/error_report_dialog.py:42 +msgid "" +"Something went wrong. Would you like to send the error report to Hardcoded " +"Software?" +msgstr "Что-то пошло не так. Хотите отправить отчёт об ошибке в Hardcoded Software?" + +#: qtlib/error_report_dialog.py:48 +msgid "" +"Although the application should continue to run after this error, it may be " +"in an instable state, so it is recommended that you restart the application." +msgstr "" + +#: qtlib/error_report_dialog.py:56 +msgid "Don't Send" +msgstr "Не отправлять" + +#: qtlib/error_report_dialog.py:60 +msgid "Send" +msgstr "Отправить" + +#: qtlib/preferences.py:17 +msgid "English" +msgstr "" + +#: qtlib/preferences.py:18 +msgid "French" +msgstr "" + +#: qtlib/preferences.py:19 +msgid "German" +msgstr "" + +#: qtlib/preferences.py:20 +msgid "Chinese (Simplified)" +msgstr "" + +#: qtlib/preferences.py:21 +msgid "Czech" +msgstr "" + +#: qtlib/preferences.py:22 +msgid "Italian" +msgstr "" + +#: qtlib/preferences.py:23 +msgid "Armenian" +msgstr "" + +#: qtlib/preferences.py:24 +msgid "Russian" +msgstr "" + +#: qtlib/preferences.py:25 +msgid "Ukrainian" +msgstr "" + +#: qtlib/preferences.py:26 +msgid "Dutch" +msgstr "" + +#: qtlib/preferences.py:27 +msgid "Brazilian" +msgstr "" + +#: qtlib/preferences.py:28 +msgid "Spanish" +msgstr "" + +#: qtlib/recent.py:53 +msgid "Clear List" +msgstr "Очистить список" + +#: qtlib/reg_demo_dialog.py:35 +msgid "$appname is Fairware" +msgstr "$appname является Fairware" + +#: qtlib/reg_demo_dialog.py:49 +msgid "Try" +msgstr "Попробовать" + +#: qtlib/reg_demo_dialog.py:52 +msgid "Enter Key" +msgstr "Ввод ключа" + +#: qtlib/reg_demo_dialog.py:55 +msgid "Buy" +msgstr "Купить" + +#: qtlib/reg_demo_dialog.py:57 +msgid "Fairware?" +msgstr "Fairware?" + +#: qtlib/reg_submit_dialog.py:31 +msgid "Enter your registration key" +msgstr "Введите ваш регистрационный ключ" + +#: qtlib/reg_submit_dialog.py:36 +msgid "" +"Type the key you received when you contributed to $appname, as well as the " +"e-mail used as a reference for the purchase." +msgstr "Введите ключ, который вы получили при вкладе в $appname, а также адрес электронной почты использованный для покупки." + +#: qtlib/reg_submit_dialog.py:48 +msgid "Registration key:" +msgstr "Регистрационный ключ:" + +#: qtlib/reg_submit_dialog.py:51 +msgid "Registered e-mail:" +msgstr "Зарегистрированный e-mail:" + +#: qtlib/reg_submit_dialog.py:60 +msgid "Contribute" +msgstr "Поддержите" + +#: qtlib/reg_submit_dialog.py:71 +msgid "Cancel" +msgstr "Отменить" + +#: qtlib/reg_submit_dialog.py:80 +msgid "Submit" +msgstr "Подтвердить" + +#: qtlib/search_edit.py:41 +msgid "Search..." +msgstr "" diff --git a/qtlib/locale/uk/LC_MESSAGES/qtlib.po b/qtlib/locale/uk/LC_MESSAGES/qtlib.po new file mode 100755 index 00000000..96ce8a12 --- /dev/null +++ b/qtlib/locale/uk/LC_MESSAGES/qtlib.po @@ -0,0 +1,161 @@ +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: hscommon\n" +"PO-Revision-Date: 2013-04-28 18:31+0000\n" +"Last-Translator: hsoft \n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: utf-8\n" +"Language: uk\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#: qtlib/about_box.py:31 +msgid "About {}" +msgstr "" + +#: qtlib/about_box.py:51 +msgid "Version {}" +msgstr "" + +#: qtlib/about_box.py:55 +msgid "Copyright Hardcoded Software 2013" +msgstr "Авторське право Hardcoded Software 2013" + +#: qtlib/about_box.py:64 +msgid "UNREGISTERED" +msgstr "НЕЗАРЕЄСТРОВАНИЙ" + +#: qtlib/about_box.py:70 +msgid "Register" +msgstr "" + +#: qtlib/error_report_dialog.py:38 +msgid "Error Report" +msgstr "Повідомлення про помилки" + +#: qtlib/error_report_dialog.py:42 +msgid "" +"Something went wrong. Would you like to send the error report to Hardcoded " +"Software?" +msgstr "Щось пішло не так. Хочете відправити звіт про помилку до Hardcoded Software?" + +#: qtlib/error_report_dialog.py:48 +msgid "" +"Although the application should continue to run after this error, it may be " +"in an instable state, so it is recommended that you restart the application." +msgstr "Хоча програма має продовжувати роботу після цієї помилки, вона може перебувати у нестабільному стані, тож рекомендується перезапустити програму." + +#: qtlib/error_report_dialog.py:56 +msgid "Don't Send" +msgstr "Не відправляти" + +#: qtlib/error_report_dialog.py:60 +msgid "Send" +msgstr "Надіслати" + +#: qtlib/preferences.py:17 +msgid "English" +msgstr "" + +#: qtlib/preferences.py:18 +msgid "French" +msgstr "" + +#: qtlib/preferences.py:19 +msgid "German" +msgstr "" + +#: qtlib/preferences.py:20 +msgid "Chinese (Simplified)" +msgstr "" + +#: qtlib/preferences.py:21 +msgid "Czech" +msgstr "" + +#: qtlib/preferences.py:22 +msgid "Italian" +msgstr "" + +#: qtlib/preferences.py:23 +msgid "Armenian" +msgstr "" + +#: qtlib/preferences.py:24 +msgid "Russian" +msgstr "" + +#: qtlib/preferences.py:25 +msgid "Ukrainian" +msgstr "" + +#: qtlib/preferences.py:26 +msgid "Dutch" +msgstr "" + +#: qtlib/preferences.py:27 +msgid "Brazilian" +msgstr "" + +#: qtlib/preferences.py:28 +msgid "Spanish" +msgstr "" + +#: qtlib/recent.py:53 +msgid "Clear List" +msgstr "Очистити список" + +#: qtlib/reg_demo_dialog.py:35 +msgid "$appname is Fairware" +msgstr "$appname є Fairware" + +#: qtlib/reg_demo_dialog.py:49 +msgid "Try" +msgstr "Спробувати" + +#: qtlib/reg_demo_dialog.py:52 +msgid "Enter Key" +msgstr "Введіть Ваш ключ" + +#: qtlib/reg_demo_dialog.py:55 +msgid "Buy" +msgstr "Купити" + +#: qtlib/reg_demo_dialog.py:57 +msgid "Fairware?" +msgstr "Fairware?" + +#: qtlib/reg_submit_dialog.py:31 +msgid "Enter your registration key" +msgstr "Введіть Ваш реєстраційний ключ" + +#: qtlib/reg_submit_dialog.py:36 +msgid "" +"Type the key you received when you contributed to $appname, as well as the " +"e-mail used as a reference for the purchase." +msgstr "Введіть ключ, який Ви отримали зробивши внесок за $appname, а також адресу електронної пошти, яка була вказана під час покупки." + +#: qtlib/reg_submit_dialog.py:48 +msgid "Registration key:" +msgstr "Реєстраційний ключ:" + +#: qtlib/reg_submit_dialog.py:51 +msgid "Registered e-mail:" +msgstr "Адреса електронної пошти:" + +#: qtlib/reg_submit_dialog.py:60 +msgid "Contribute" +msgstr "Зробити внесок" + +#: qtlib/reg_submit_dialog.py:71 +msgid "Cancel" +msgstr "Скасувати" + +#: qtlib/reg_submit_dialog.py:80 +msgid "Submit" +msgstr "Надіслати" + +#: qtlib/search_edit.py:41 +msgid "Search..." +msgstr "Шукати..." diff --git a/qtlib/locale/zh_CN/LC_MESSAGES/qtlib.po b/qtlib/locale/zh_CN/LC_MESSAGES/qtlib.po new file mode 100644 index 00000000..b4ec4471 --- /dev/null +++ b/qtlib/locale/zh_CN/LC_MESSAGES/qtlib.po @@ -0,0 +1,161 @@ +# +# Translators: +msgid "" +msgstr "" +"Project-Id-Version: hscommon\n" +"PO-Revision-Date: 2013-04-28 18:31+0000\n" +"Last-Translator: hsoft \n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: utf-8\n" +"Language: zh_CN\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +#: qtlib/about_box.py:31 +msgid "About {}" +msgstr "" + +#: qtlib/about_box.py:51 +msgid "Version {}" +msgstr "" + +#: qtlib/about_box.py:55 +msgid "Copyright Hardcoded Software 2013" +msgstr "" + +#: qtlib/about_box.py:64 +msgid "UNREGISTERED" +msgstr "" + +#: qtlib/about_box.py:70 +msgid "Register" +msgstr "" + +#: qtlib/error_report_dialog.py:38 +msgid "Error Report" +msgstr "" + +#: qtlib/error_report_dialog.py:42 +msgid "" +"Something went wrong. Would you like to send the error report to Hardcoded " +"Software?" +msgstr "" + +#: qtlib/error_report_dialog.py:48 +msgid "" +"Although the application should continue to run after this error, it may be " +"in an instable state, so it is recommended that you restart the application." +msgstr "" + +#: qtlib/error_report_dialog.py:56 +msgid "Don't Send" +msgstr "" + +#: qtlib/error_report_dialog.py:60 +msgid "Send" +msgstr "" + +#: qtlib/preferences.py:17 +msgid "English" +msgstr "英语" + +#: qtlib/preferences.py:18 +msgid "French" +msgstr "法语" + +#: qtlib/preferences.py:19 +msgid "German" +msgstr "德语" + +#: qtlib/preferences.py:20 +msgid "Chinese (Simplified)" +msgstr "简体中文" + +#: qtlib/preferences.py:21 +msgid "Czech" +msgstr "" + +#: qtlib/preferences.py:22 +msgid "Italian" +msgstr "" + +#: qtlib/preferences.py:23 +msgid "Armenian" +msgstr "" + +#: qtlib/preferences.py:24 +msgid "Russian" +msgstr "" + +#: qtlib/preferences.py:25 +msgid "Ukrainian" +msgstr "" + +#: qtlib/preferences.py:26 +msgid "Dutch" +msgstr "" + +#: qtlib/preferences.py:27 +msgid "Brazilian" +msgstr "" + +#: qtlib/preferences.py:28 +msgid "Spanish" +msgstr "" + +#: qtlib/recent.py:53 +msgid "Clear List" +msgstr "清空列表" + +#: qtlib/reg_demo_dialog.py:35 +msgid "$appname is Fairware" +msgstr "$appname 是一款捐助型软件" + +#: qtlib/reg_demo_dialog.py:49 +msgid "Try" +msgstr "捐助" + +#: qtlib/reg_demo_dialog.py:52 +msgid "Enter Key" +msgstr "输入密钥" + +#: qtlib/reg_demo_dialog.py:55 +msgid "Buy" +msgstr "" + +#: qtlib/reg_demo_dialog.py:57 +msgid "Fairware?" +msgstr "" + +#: qtlib/reg_submit_dialog.py:31 +msgid "Enter your registration key" +msgstr "输入密钥" + +#: qtlib/reg_submit_dialog.py:36 +msgid "" +"Type the key you received when you contributed to $appname, as well as the " +"e-mail used as a reference for the purchase." +msgstr "当您捐助 $appname 后,请输入收到的注册密钥以及电子邮件,这将作为购买凭证。" + +#: qtlib/reg_submit_dialog.py:48 +msgid "Registration key:" +msgstr "密钥:" + +#: qtlib/reg_submit_dialog.py:51 +msgid "Registered e-mail:" +msgstr "电子邮箱:" + +#: qtlib/reg_submit_dialog.py:60 +msgid "Contribute" +msgstr "捐助" + +#: qtlib/reg_submit_dialog.py:71 +msgid "Cancel" +msgstr "取消" + +#: qtlib/reg_submit_dialog.py:80 +msgid "Submit" +msgstr "提交" + +#: qtlib/search_edit.py:41 +msgid "Search..." +msgstr "" diff --git a/qtlib/preferences.py b/qtlib/preferences.py new file mode 100644 index 00000000..1daf34ae --- /dev/null +++ b/qtlib/preferences.py @@ -0,0 +1,128 @@ +# Created By: Virgil Dupras +# Created On: 2009-05-03 +# Copyright 2013 Hardcoded Software (http://www.hardcoded.net) +# +# This software is licensed under the "BSD" License as described in the "LICENSE" file, +# which should be included with this package. The terms are also available at +# http://www.hardcoded.net/licenses/bsd_license + +from PyQt4.QtCore import Qt, QSettings, QRect, QPyNullVariant + +from hscommon.trans import trget +from hscommon.util import tryint + +tr = trget('qtlib') + +LANGNAMES = { + 'en': tr("English"), + 'fr': tr("French"), + 'de': tr("German"), + 'zh_CN': tr("Chinese (Simplified)"), + 'cs': tr("Czech"), + 'it': tr("Italian"), + 'hy': tr("Armenian"), + 'ru': tr("Russian"), + 'uk': tr("Ukrainian"), + 'nl': tr('Dutch'), + 'pt_BR': tr("Brazilian"), + 'es': tr("Spanish"), +} + +def normalize_for_serialization(v): + # QSettings doesn't consider set/tuple as "native" typs for serialization, so if we don't + # change them into a list, we get a weird serialized QVariant value which isn't a very + # "portable" value. + if isinstance(v, (set, tuple)): + v = list(v) + if isinstance(v, list): + v = [normalize_for_serialization(item) for item in v] + return v + +def adjust_after_deserialization(v): + # In some cases, when reading from prefs, we end up with strings that are supposed to be + # bool or int. Convert these. + if isinstance(v, list): + return [adjust_after_deserialization(sub) for sub in v] + if isinstance(v, str): + # might be bool or int, try them + if v == 'true': + return True + elif v == 'false': + return False + else: + return tryint(v, v) + if isinstance(v, QPyNullVariant): + return None + return v + +# About QRect conversion: +# I think Qt supports putting basic structures like QRect directly in QSettings, but I prefer not +# to rely on it and stay with generic structures. + +class Preferences: + def __init__(self): + self.reset() + self._settings = QSettings() + + def _load_values(self, settings, get): + pass + + def get_rect(self, name, default=None): + r = self.get_value(name, default) + if r is not None: + return QRect(*r) + else: + return None + + def get_value(self, name, default=None): + if self._settings.contains(name): + result = adjust_after_deserialization(self._settings.value(name)) + if result is not None: + return result + else: + # If result is None, but still present in self._settings, it usually means a value + # like "@Invalid". + return default + else: + return default + + def load(self): + self.reset() + self._load_values(self._settings) + + def reset(self): + pass + + def _save_values(self, settings, set_): + pass + + def save(self): + self._save_values(self._settings) + self._settings.sync() + + def set_rect(self, name, r): + if isinstance(r, QRect): + rectAsList = [r.x(), r.y(), r.width(), r.height()] + self.set_value(name, rectAsList) + + def set_value(self, name, value): + self._settings.setValue(name, normalize_for_serialization(value)) + + def saveGeometry(self, name, widget): + # We save geometry under a 5-sized int array: first item is a flag for whether the widget + # is maximized and the other 4 are (x, y, w, h). + m = 1 if widget.isMaximized() else 0 + r = widget.geometry() + rectAsList = [r.x(), r.y(), r.width(), r.height()] + self.set_value(name, [m] + rectAsList) + + def restoreGeometry(self, name, widget): + l = self.get_value(name) + if l and len(l) == 5: + m, x, y, w, h = l + if m: + widget.setWindowState(Qt.WindowMaximized) + else: + r = QRect(x, y, w, h) + widget.setGeometry(r) + diff --git a/qtlib/radio_box.py b/qtlib/radio_box.py new file mode 100644 index 00000000..d786c881 --- /dev/null +++ b/qtlib/radio_box.py @@ -0,0 +1,88 @@ +# Created On: 2010-06-02 +# Copyright 2013 Hardcoded Software (http://www.hardcoded.net) +# +# This software is licensed under the "BSD" License as described in the "LICENSE" file, +# which should be included with this package. The terms are also available at +# http://www.hardcoded.net/licenses/bsd_license + +from PyQt4.QtCore import pyqtSignal +from PyQt4.QtGui import QWidget, QHBoxLayout, QRadioButton + +from .util import horizontalSpacer + +class RadioBox(QWidget): + def __init__(self, parent=None, items=None, spread=True): + # If spread is False, insert a spacer in the layout so that the items don't use all the + # space they're given but rather align left. + if items is None: + items = [] + QWidget.__init__(self, parent) + self._buttons = [] + self._labels = items + self._selected_index = 0 + self._spacer = horizontalSpacer() if not spread else None + self._layout = QHBoxLayout(self) + self._update_buttons() + + #--- Private + def _update_buttons(self): + if self._spacer is not None: + self._layout.removeItem(self._spacer) + to_remove = self._buttons[len(self._labels):] + for button in to_remove: + self._layout.removeWidget(button) + button.setParent(None) + del self._buttons[len(self._labels):] + to_add = self._labels[len(self._buttons):] + for _ in to_add: + button = QRadioButton(self) + self._buttons.append(button) + self._layout.addWidget(button) + button.toggled.connect(self.buttonToggled) + if self._spacer is not None: + self._layout.addItem(self._spacer) + if not self._buttons: + return + for button, label in zip(self._buttons, self._labels): + button.setText(label) + self._update_selection() + + def _update_selection(self): + self._selected_index = max(0, min(self._selected_index, len(self._buttons)-1)) + selected = self._buttons[self._selected_index] + selected.setChecked(True) + + #--- Event Handlers + def buttonToggled(self): + for i, button in enumerate(self._buttons): + if button.isChecked(): + self._selected_index = i + self.itemSelected.emit(i) + break + + #--- Signals + itemSelected = pyqtSignal(int) + + #--- Properties + @property + def buttons(self): + return self._buttons[:] + + @property + def items(self): + return self._labels[:] + + @items.setter + def items(self, value): + self._labels = value + self._update_buttons() + + @property + def selected_index(self): + return self._selected_index + + @selected_index.setter + def selected_index(self, value): + self._selected_index = value + self._update_selection() + diff --git a/qtlib/recent.py b/qtlib/recent.py new file mode 100644 index 00000000..a75b529e --- /dev/null +++ b/qtlib/recent.py @@ -0,0 +1,95 @@ +# Created By: Virgil Dupras +# Created On: 2009-11-12 +# Copyright 2013 Hardcoded Software (http://www.hardcoded.net) +# +# This software is licensed under the "BSD" License as described in the "LICENSE" file, +# which should be included with this package. The terms are also available at +# http://www.hardcoded.net/licenses/bsd_license + +from collections import namedtuple + +from PyQt4.QtCore import pyqtSignal, QObject +from PyQt4.QtGui import QAction + +from hscommon.trans import trget +from hscommon.util import dedupe + +tr = trget('qtlib') + +MenuEntry = namedtuple('MenuEntry', 'menu fixedItemCount') + +class Recent(QObject): + def __init__(self, app, prefName, maxItemCount=10): + QObject.__init__(self) + self._app = app + self._menuEntries = [] + self._prefName = prefName + self._maxItemCount = maxItemCount + self._items = [] + self._loadFromPrefs() + + self._app.willSavePrefs.connect(self._saveToPrefs) + + #--- Private + def _loadFromPrefs(self): + items = getattr(self._app.prefs, self._prefName) + if not isinstance(items, list): + items = [] + self._items = items + + def _insertItem(self, item): + self._items = dedupe([item] + self._items)[:self._maxItemCount] + + def _refreshMenu(self, menuEntry): + menu, fixedItemCount = menuEntry + for action in menu.actions()[fixedItemCount:]: + menu.removeAction(action) + for item in self._items: + action = QAction(item, menu) + action.setData(item) + action.triggered.connect(self.menuItemWasClicked) + menu.addAction(action) + menu.addSeparator() + action = QAction(tr("Clear List"), menu) + action.triggered.connect(self.clear) + menu.addAction(action) + + def _refreshAllMenus(self): + for menuEntry in self._menuEntries: + self._refreshMenu(menuEntry) + + def _saveToPrefs(self): + setattr(self._app.prefs, self._prefName, self._items) + + #--- Public + def addMenu(self, menu): + menuEntry = MenuEntry(menu, len(menu.actions())) + self._menuEntries.append(menuEntry) + self._refreshMenu(menuEntry) + + def clear(self): + self._items = [] + self._refreshAllMenus() + self.itemsChanged.emit() + + def insertItem(self, item): + self._insertItem(str(item)) + self._refreshAllMenus() + self.itemsChanged.emit() + + def isEmpty(self): + return not bool(self._items) + + #--- Event Handlers + def menuItemWasClicked(self): + action = self.sender() + if action is not None: + item = action.data() + self.mustOpenItem.emit(item) + self._refreshAllMenus() + + #--- Signals + mustOpenItem = pyqtSignal(str) + itemsChanged = pyqtSignal() + + diff --git a/qtlib/reg.py b/qtlib/reg.py new file mode 100644 index 00000000..c66c578d --- /dev/null +++ b/qtlib/reg.py @@ -0,0 +1,25 @@ +# Created By: Virgil Dupras +# Created On: 2009-05-09 +# Copyright 2013 Hardcoded Software (http://www.hardcoded.net) +# +# This software is licensed under the "BSD" License as described in the "LICENSE" file, +# which should be included with this package. The terms are also available at +# http://www.hardcoded.net/licenses/bsd_license + +from PyQt4.QtGui import QDialog + +from .reg_submit_dialog import RegSubmitDialog +from .reg_demo_dialog import RegDemoDialog + +class Registration: + def __init__(self, app): + self.app = app + + def ask_for_code(self): + dialog = RegSubmitDialog(None, self) + return dialog.exec_() == QDialog.Accepted + + def show_demo_nag(self, prompt): + dialog = RegDemoDialog(None, self, prompt) + dialog.exec_() + diff --git a/qtlib/reg_demo_dialog.py b/qtlib/reg_demo_dialog.py new file mode 100644 index 00000000..e6675d6a --- /dev/null +++ b/qtlib/reg_demo_dialog.py @@ -0,0 +1,80 @@ +# Created By: Virgil Dupras +# Created On: 2009-05-10 +# Copyright 2013 Hardcoded Software (http://www.hardcoded.net) +# +# This software is licensed under the "BSD" License as described in the "LICENSE" file, +# which should be included with this package. The terms are also available at +# http://www.hardcoded.net/licenses/bsd_license + +import sys + +from PyQt4.QtCore import Qt, QCoreApplication +from PyQt4.QtGui import (QDialog, QApplication, QVBoxLayout, QHBoxLayout, QLabel, + QFont, QSpacerItem, QSizePolicy, QPushButton) + +from hscommon.plat import ISLINUX +from hscommon.trans import trget + +tr = trget('qtlib') + +class RegDemoDialog(QDialog): + def __init__(self, parent, reg, prompt): + flags = Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowSystemMenuHint + QDialog.__init__(self, parent, flags) + self.reg = reg + self._setupUi() + self.descLabel.setText(prompt) + + self.enterCodeButton.clicked.connect(self.enterCodeClicked) + self.buyButton.clicked.connect(self.buyClicked) + self.tryButton.clicked.connect(self.accept) + self.moreInfoButton.clicked.connect(self.moreInfoClicked) + + def _setupUi(self): + appname = QCoreApplication.instance().applicationName() + title = tr("$appname is Fairware") + title = title.replace('$appname', appname) + self.setWindowTitle(title) + # Workaround for bug at http://bugreports.qt.nokia.com/browse/QTBUG-8212 + dlg_height = 370 if ISLINUX else 240 + self.resize(400, dlg_height) + self.verticalLayout = QVBoxLayout(self) + self.descLabel = QLabel(self) + self.descLabel.setWordWrap(True) + self.verticalLayout.addWidget(self.descLabel) + spacerItem = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) + self.verticalLayout.addItem(spacerItem) + self.horizontalLayout = QHBoxLayout() + self.tryButton = QPushButton(self) + self.tryButton.setText(tr("Try")) + self.horizontalLayout.addWidget(self.tryButton) + self.enterCodeButton = QPushButton(self) + self.enterCodeButton.setText(tr("Enter Key")) + self.horizontalLayout.addWidget(self.enterCodeButton) + self.buyButton = QPushButton(self) + self.buyButton.setText(tr("Buy")) + self.horizontalLayout.addWidget(self.buyButton) + self.moreInfoButton = QPushButton(tr("Fairware?")) + self.horizontalLayout.addWidget(self.moreInfoButton) + self.verticalLayout.addLayout(self.horizontalLayout) + + #--- Events + def enterCodeClicked(self): + if self.reg.ask_for_code(): + self.accept() + + def buyClicked(self): + self.reg.app.buy() + + def moreInfoClicked(self): + self.reg.app.about_fairware() + + +if __name__ == '__main__': + app = QApplication([]) + app.unpaid_hours = 42.4 + class FakeReg: + app = app + dialog = RegDemoDialog(None, FakeReg(), "foo bar baz") + dialog.show() + sys.exit(app.exec_()) diff --git a/qtlib/reg_submit_dialog.py b/qtlib/reg_submit_dialog.py new file mode 100644 index 00000000..9a55a108 --- /dev/null +++ b/qtlib/reg_submit_dialog.py @@ -0,0 +1,102 @@ +# Created By: Virgil Dupras +# Created On: 2009-05-09 +# Copyright 2013 Hardcoded Software (http://www.hardcoded.net) +# +# This software is licensed under the "BSD" License as described in the "LICENSE" file, +# which should be included with this package. The terms are also available at +# http://www.hardcoded.net/licenses/bsd_license + +import sys + +from PyQt4.QtCore import Qt, QCoreApplication +from PyQt4.QtGui import (QDialog, QApplication, QVBoxLayout, QHBoxLayout, QLabel, QFormLayout, + QLayout, QLineEdit, QPushButton, QSpacerItem, QSizePolicy) + +from hscommon.trans import trget + +tr = trget('qtlib') + +class RegSubmitDialog(QDialog): + def __init__(self, parent, reg): + flags = Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowSystemMenuHint + QDialog.__init__(self, parent, flags) + self._setupUi() + self.reg = reg + + self.submitButton.clicked.connect(self.submitClicked) + self.contributeButton.clicked.connect(self.contributeClicked) + self.cancelButton.clicked.connect(self.reject) + + def _setupUi(self): + self.setWindowTitle(tr("Enter your registration key")) + self.resize(365, 126) + self.verticalLayout = QVBoxLayout(self) + self.promptLabel = QLabel(self) + appname = str(QCoreApplication.instance().applicationName()) + prompt = tr("Type the key you received when you contributed to $appname, as well as the " + "e-mail used as a reference for the purchase.").replace('$appname', appname) + self.promptLabel.setText(prompt) + self.promptLabel.setAlignment(Qt.AlignLeading|Qt.AlignLeft|Qt.AlignTop) + self.promptLabel.setWordWrap(True) + self.verticalLayout.addWidget(self.promptLabel) + self.formLayout = QFormLayout() + self.formLayout.setSizeConstraint(QLayout.SetNoConstraint) + self.formLayout.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow) + self.formLayout.setLabelAlignment(Qt.AlignRight|Qt.AlignTrailing|Qt.AlignVCenter) + self.formLayout.setFormAlignment(Qt.AlignLeading|Qt.AlignLeft|Qt.AlignTop) + self.label2 = QLabel(self) + self.label2.setText(tr("Registration key:")) + self.formLayout.setWidget(0, QFormLayout.LabelRole, self.label2) + self.label3 = QLabel(self) + self.label3.setText(tr("Registered e-mail:")) + self.formLayout.setWidget(1, QFormLayout.LabelRole, self.label3) + self.codeEdit = QLineEdit(self) + self.formLayout.setWidget(0, QFormLayout.FieldRole, self.codeEdit) + self.emailEdit = QLineEdit(self) + self.formLayout.setWidget(1, QFormLayout.FieldRole, self.emailEdit) + self.verticalLayout.addLayout(self.formLayout) + self.horizontalLayout = QHBoxLayout() + self.contributeButton = QPushButton(self) + self.contributeButton.setText(tr("Contribute")) + self.contributeButton.setAutoDefault(False) + self.horizontalLayout.addWidget(self.contributeButton) + spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) + self.horizontalLayout.addItem(spacerItem) + self.cancelButton = QPushButton(self) + sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.cancelButton.sizePolicy().hasHeightForWidth()) + self.cancelButton.setSizePolicy(sizePolicy) + self.cancelButton.setText(tr("Cancel")) + self.cancelButton.setAutoDefault(False) + self.horizontalLayout.addWidget(self.cancelButton) + self.submitButton = QPushButton(self) + sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.submitButton.sizePolicy().hasHeightForWidth()) + self.submitButton.setSizePolicy(sizePolicy) + self.submitButton.setText(tr("Submit")) + self.submitButton.setAutoDefault(False) + self.submitButton.setDefault(True) + self.horizontalLayout.addWidget(self.submitButton) + self.verticalLayout.addLayout(self.horizontalLayout) + + #--- Events + def contributeClicked(self): + self.reg.app.contribute() + + def submitClicked(self): + code = self.codeEdit.text() + email = self.emailEdit.text() + if self.reg.app.set_registration(code, email, False): + self.accept() + + +if __name__ == '__main__': + app = QApplication([]) + validate = lambda *args: True + dialog = RegSubmitDialog(None, validate) + dialog.show() + sys.exit(app.exec_()) diff --git a/qtlib/search_edit.py b/qtlib/search_edit.py new file mode 100644 index 00000000..e5cd9bc4 --- /dev/null +++ b/qtlib/search_edit.py @@ -0,0 +1,98 @@ +# Created By: Virgil Dupras +# Created On: 2009-12-10 +# Copyright 2013 Hardcoded Software (http://www.hardcoded.net) +# +# This software is licensed under the "BSD" License as described in the "LICENSE" file, +# which should be included with this package. The terms are also available at +# http://www.hardcoded.net/licenses/bsd_license + +from PyQt4.QtCore import pyqtSignal, Qt +from PyQt4.QtGui import (QToolButton, QLineEdit, QIcon, QPixmap, QStyle, QStyleOptionFrameV2, + QPainter, QPalette) + +from hscommon.trans import trget + +tr = trget('qtlib') + +# IMPORTANT: For this widget to work propertly, you have to add "search_clear_13" from the +# "images" folder in your resources. + +class LineEditButton(QToolButton): + def __init__(self, parent): + QToolButton.__init__(self, parent) + pixmap = QPixmap(':/search_clear_13') + self.setIcon(QIcon(pixmap)) + self.setIconSize(pixmap.size()) + self.setCursor(Qt.ArrowCursor) + self.setPopupMode(QToolButton.InstantPopup) + stylesheet = "QToolButton { border: none; padding: 0px; }" + self.setStyleSheet(stylesheet) + + +class SearchEdit(QLineEdit): + def __init__(self, parent=None, immediate=False): + # immediate: send searchChanged signals at each keystroke. + QLineEdit.__init__(self, parent) + self._clearButton = LineEditButton(self) + frameWidth = self.style().pixelMetric(QStyle.PM_DefaultFrameWidth) + paddingRight = self._clearButton.sizeHint().width() + frameWidth + 1 + stylesheet = "QLineEdit {{ padding-right:{0}px; }}".format(paddingRight) + self.setStyleSheet(stylesheet) + self.inactiveText = tr("Search...") + self.immediate = immediate + self._updateClearButton(self.text()) + + self._clearButton.clicked.connect(self._clearSearch) + self.returnPressed.connect(self._returnPressed) + self.textChanged.connect(self._textChanged) + + #--- Private + def _clearSearch(self): + self.clear() + self.searchChanged.emit() + + def _updateClearButton(self, text): + self._clearButton.setVisible(bool(text)) + + #--- QLineEdit overrides + def resizeEvent(self, event): + frameWidth = self.style().pixelMetric(QStyle.PM_DefaultFrameWidth) + rect = self.rect() + rightHint = self._clearButton.sizeHint() + rightX = rect.right() - frameWidth - rightHint.width() + rightY = (rect.bottom() - rightHint.height()) // 2 + self._clearButton.move(rightX, rightY) + + def paintEvent(self, event): + QLineEdit.paintEvent(self, event) + if not bool(self.text()) and self.inactiveText and not self.hasFocus(): + panel = QStyleOptionFrameV2() + self.initStyleOption(panel) + textRect = self.style().subElementRect(QStyle.SE_LineEditContents, panel, self) + leftMargin = 2 + rightMargin = self._clearButton.iconSize().width() + textRect.adjust(leftMargin, 0, -rightMargin, 0) + painter = QPainter(self) + disabledColor = self.palette().brush(QPalette.Disabled, QPalette.Text).color() + painter.setPen(disabledColor) + painter.drawText(textRect, Qt.AlignLeft|Qt.AlignVCenter, self.inactiveText) + + def keyPressEvent(self, event): + key = event.key() + if key == Qt.Key_Escape: + self._clearSearch() + else: + QLineEdit.keyPressEvent(self, event) + + #--- Event Handlers + def _returnPressed(self): + if not self.immediate: + self.searchChanged.emit() + + def _textChanged(self, text): + self._updateClearButton(text) + if self.immediate: + self.searchChanged.emit() + + #--- Signals + searchChanged = pyqtSignal() # Emitted when return is pressed or when the test is cleared diff --git a/qtlib/selectable_list.py b/qtlib/selectable_list.py new file mode 100644 index 00000000..48e96f53 --- /dev/null +++ b/qtlib/selectable_list.py @@ -0,0 +1,98 @@ +# Created By: Virgil Dupras +# Created On: 2011-09-06 +# Copyright 2013 Hardcoded Software (http://www.hardcoded.net) +# +# This software is licensed under the "BSD" License as described in the "LICENSE" file, +# which should be included with this package. The terms are also available at +# http://www.hardcoded.net/licenses/bsd_license + +from PyQt4.QtCore import Qt, QAbstractListModel +from PyQt4.QtGui import QItemSelection, QItemSelectionModel + +class SelectableList(QAbstractListModel): + def __init__(self, model, view): + QAbstractListModel.__init__(self) + self._updating = False + self.view = view + self.model = model + self.view.setModel(self) + self.model.view = self + + #--- Override + def data(self, index, role): + if not index.isValid(): + return None + # We need EditRole for QComboBoxes with setEditable(True) + if role in {Qt.DisplayRole, Qt.EditRole}: + return self.model[index.row()] + return None + + def rowCount(self, index): + if index.isValid(): + return 0 + return len(self.model) + + #--- Virtual + def _updateSelection(self): + raise NotImplementedError() + + def _restoreSelection(self): + raise NotImplementedError() + + #--- model --> view + def refresh(self): + self._updating = True + self.reset() + self._updating = False + self._restoreSelection() + + def update_selection(self): + self._restoreSelection() + +class ComboboxModel(SelectableList): + def __init__(self, model, view): + SelectableList.__init__(self, model, view) + self.view.currentIndexChanged[int].connect(self.selectionChanged) + + #--- Override + def _updateSelection(self): + index = self.view.currentIndex() + if index != self.model.selected_index: + self.model.select(index) + + def _restoreSelection(self): + index = self.model.selected_index + if index is not None: + self.view.setCurrentIndex(index) + + #--- Events + def selectionChanged(self, index): + if not self._updating: + self._updateSelection() + +class ListviewModel(SelectableList): + def __init__(self, model, view): + SelectableList.__init__(self, model, view) + self.view.selectionModel().selectionChanged[(QItemSelection, QItemSelection)].connect( + self.selectionChanged) + + #--- Override + def _updateSelection(self): + newIndexes = [modelIndex.row() for modelIndex in self.view.selectionModel().selectedRows()] + if newIndexes != self.model.selected_indexes: + self.model.select(newIndexes) + + def _restoreSelection(self): + newSelection = QItemSelection() + for index in self.model.selected_indexes: + newSelection.select(self.createIndex(index, 0), self.createIndex(index, 0)) + self.view.selectionModel().select(newSelection, QItemSelectionModel.ClearAndSelect) + if len(newSelection.indexes()): + currentIndex = newSelection.indexes()[0] + self.view.selectionModel().setCurrentIndex(currentIndex, QItemSelectionModel.Current) + self.view.scrollTo(currentIndex) + #--- Events + def selectionChanged(self, index): + if not self._updating: + self._updateSelection() + diff --git a/qtlib/table.py b/qtlib/table.py new file mode 100644 index 00000000..3e4fea86 --- /dev/null +++ b/qtlib/table.py @@ -0,0 +1,152 @@ +# Created By: Virgil Dupras +# Created On: 2009-11-01 +# Copyright 2013 Hardcoded Software (http://www.hardcoded.net) +# +# This software is licensed under the "BSD" License as described in the "LICENSE" file, +# which should be included with this package. The terms are also available at +# http://www.hardcoded.net/licenses/bsd_license + +from PyQt4.QtCore import Qt, QAbstractTableModel, QModelIndex +from PyQt4.QtGui import QItemSelectionModel, QItemSelection + +from .column import Columns + +class Table(QAbstractTableModel): + # Flags you want when index.isValid() is False. In those cases, _getFlags() is never called. + INVALID_INDEX_FLAGS = Qt.ItemIsEnabled + COLUMNS = [] + + def __init__(self, model, view): + QAbstractTableModel.__init__(self) + self.model = model + self.view = view + self.view.setModel(self) + self.model.view = self + if hasattr(self.model, 'columns'): + self.columns = Columns(self.model.columns, self.COLUMNS, view.horizontalHeader()) + + self.view.selectionModel().selectionChanged[(QItemSelection, QItemSelection)].connect(self.selectionChanged) + + def _updateModelSelection(self): + # Takes the selection on the view's side and update the model with it. + # an _updateViewSelection() call will normally result in an _updateModelSelection() call. + # to avoid infinite loops, we check that the selection will actually change before calling + # model.select() + newIndexes = [modelIndex.row() for modelIndex in self.view.selectionModel().selectedRows()] + if newIndexes != self.model.selected_indexes: + self.model.select(newIndexes) + + def _updateViewSelection(self): + # Takes the selection on the model's side and update the view with it. + newSelection = QItemSelection() + columnCount = self.columnCount(QModelIndex()) + for index in self.model.selected_indexes: + newSelection.select(self.createIndex(index, 0), self.createIndex(index, columnCount-1)) + self.view.selectionModel().select(newSelection, QItemSelectionModel.ClearAndSelect) + if len(newSelection.indexes()): + currentIndex = newSelection.indexes()[0] + self.view.selectionModel().setCurrentIndex(currentIndex, QItemSelectionModel.Current) + self.view.scrollTo(currentIndex) + + #--- Data Model methods + # Virtual + def _getData(self, row, column, role): + if role in (Qt.DisplayRole, Qt.EditRole): + attrname = column.name + return row.get_cell_value(attrname) + elif role == Qt.TextAlignmentRole: + return column.alignment + return None + + # Virtual + def _getFlags(self, row, column): + flags = Qt.ItemIsEnabled | Qt.ItemIsSelectable + if row.can_edit_cell(column.name): + flags |= Qt.ItemIsEditable + return flags + + # Virtual + def _setData(self, row, column, value, role): + if role == Qt.EditRole: + attrname = column.name + if attrname == 'from': + attrname = 'from_' + setattr(row, attrname, value) + return True + return False + + def columnCount(self, index): + return self.model.columns.columns_count() + + def data(self, index, role): + if not index.isValid(): + return None + row = self.model[index.row()] + column = self.model.columns.column_by_index(index.column()) + return self._getData(row, column, role) + + def flags(self, index): + if not index.isValid(): + return self.INVALID_INDEX_FLAGS + row = self.model[index.row()] + column = self.model.columns.column_by_index(index.column()) + return self._getFlags(row, column) + + def headerData(self, section, orientation, role): + if orientation != Qt.Horizontal: + return None + if section >= self.model.columns.columns_count(): + return None + column = self.model.columns.column_by_index(section) + if role == Qt.DisplayRole: + return column.display + elif role == Qt.TextAlignmentRole: + return column.alignment + else: + return None + + def revert(self): + self.model.cancel_edits() + + def rowCount(self, index): + if index.isValid(): + return 0 + return len(self.model) + + def setData(self, index, value, role): + if not index.isValid(): + return False + row = self.model[index.row()] + column = self.model.columns.column_by_index(index.column()) + return self._setData(row, column, value, role) + + def sort(self, section, order): + column = self.model.columns.column_by_index(section) + attrname = column.name + self.model.sort_by(attrname, desc=order==Qt.DescendingOrder) + + def submit(self): + self.model.save_edits() + return True + + #--- Events + def selectionChanged(self, selected, deselected): + self._updateModelSelection() + + #--- model --> view + def refresh(self): + self.reset() + self._updateViewSelection() + + def show_selected_row(self): + if self.model.selected_index is not None: + self.view.showRow(self.model.selected_index) + + def start_editing(self): + self.view.editSelected() + + def stop_editing(self): + self.view.setFocus() # enough to stop editing + + def update_selection(self): + self._updateViewSelection() diff --git a/qtlib/text_field.py b/qtlib/text_field.py new file mode 100644 index 00000000..9cf89ccb --- /dev/null +++ b/qtlib/text_field.py @@ -0,0 +1,23 @@ +# Created On: 2012/01/23 +# Copyright 2013 Hardcoded Software (http://www.hardcoded.net) +# +# This software is licensed under the "BSD" License as described in the "LICENSE" file, +# which should be included with this package. The terms are also available at +# http://www.hardcoded.net/licenses/bsd_license + +class TextField: + def __init__(self, model, view): + self.model = model + self.view = view + self.model.view = self + # Make TextField also work for QLabel, which doesn't allow editing + if hasattr(self.view, 'editingFinished'): + self.view.editingFinished.connect(self.editingFinished) + + def editingFinished(self): + self.model.text = self.view.text() + + # model --> view + def refresh(self): + self.view.setText(self.model.text) + diff --git a/qtlib/tree_model.py b/qtlib/tree_model.py new file mode 100644 index 00000000..99eb3045 --- /dev/null +++ b/qtlib/tree_model.py @@ -0,0 +1,173 @@ +# Created By: Virgil Dupras +# Created On: 2009-09-14 +# Copyright 2013 Hardcoded Software (http://www.hardcoded.net) +# +# This software is licensed under the "BSD" License as described in the "LICENSE" file, +# which should be included with this package. The terms are also available at +# http://www.hardcoded.net/licenses/bsd_license + +import logging + +from PyQt4.QtCore import QAbstractItemModel, QModelIndex + +class NodeContainer: + def __init__(self): + self._subnodes = None + self._ref2node = {} + + #--- Protected + def _createNode(self, ref, row): + # This returns a TreeNode instance from ref + raise NotImplementedError() + + def _getChildren(self): + # This returns a list of ref instances, not TreeNode instances + raise NotImplementedError() + + #--- Public + def invalidate(self): + # Invalidates cached data and list of subnodes without resetting ref2node. + self._subnodes = None + + #--- Properties + @property + def subnodes(self): + if self._subnodes is None: + children = self._getChildren() + self._subnodes = [] + for index, child in enumerate(children): + if child in self._ref2node: + node = self._ref2node[child] + node.row = index + else: + node = self._createNode(child, index) + self._ref2node[child] = node + self._subnodes.append(node) + return self._subnodes + + +class TreeNode(NodeContainer): + def __init__(self, model, parent, row): + NodeContainer.__init__(self) + self.model = model + self.parent = parent + self.row = row + + @property + def index(self): + return self.model.createIndex(self.row, 0, self) + + +class RefNode(TreeNode): + """Node pointing to a reference node. + + Use this if your Qt model wraps around a tree model that has iterable nodes. + """ + def __init__(self, model, parent, ref, row): + TreeNode.__init__(self, model, parent, row) + self.ref = ref + + def _createNode(self, ref, row): + return RefNode(self.model, self, ref, row) + + def _getChildren(self): + return list(self.ref) + + +# We use a specific TreeNode subclass to easily spot dummy nodes, especially in exception tracebacks. +class DummyNode(TreeNode): + pass + +class TreeModel(QAbstractItemModel, NodeContainer): + def __init__(self): + QAbstractItemModel.__init__(self) + NodeContainer.__init__(self) + self._dummyNodes = set() # dummy nodes' reference have to be kept to avoid segfault + + #--- Private + def _createDummyNode(self, parent, row): + # In some cases (drag & drop row removal, to be precise), there's a temporary discrepancy + # between a node's subnodes and what the model think it has. This leads to invalid indexes + # being queried. Rather than going through complicated row removal crap, it's simpler to + # just have rows with empty data replacing removed rows for the millisecond that the drag & + # drop lasts. Override this to return a node of the correct type. + return DummyNode(self, parent, row) + + def _lastIndex(self): + """Index of the very last item in the tree. + """ + currentIndex = QModelIndex() + rowCount = self.rowCount(currentIndex) + while rowCount > 0: + currentIndex = self.index(rowCount-1, 0, currentIndex) + rowCount = self.rowCount(currentIndex) + return currentIndex + + #--- Overrides + def index(self, row, column, parent): + if not self.subnodes: + return QModelIndex() + node = parent.internalPointer() if parent.isValid() else self + try: + return self.createIndex(row, column, node.subnodes[row]) + except IndexError: + logging.debug("Wrong tree index called (%r, %r, %r). Returning DummyNode", + row, column, node) + parentNode = parent.internalPointer() if parent.isValid() else None + dummy = self._createDummyNode(parentNode, row) + self._dummyNodes.add(dummy) + return self.createIndex(row, column, dummy) + + def parent(self, index): + if not index.isValid(): + return QModelIndex() + node = index.internalPointer() + if node.parent is None: + return QModelIndex() + else: + return self.createIndex(node.parent.row, 0, node.parent) + + def reset(self): + self.invalidate() + self._ref2node = {} + self._dummyNodes = set() + QAbstractItemModel.reset(self) + + def rowCount(self, parent=QModelIndex()): + node = parent.internalPointer() if parent.isValid() else self + return len(node.subnodes) + + #--- Public + def findIndex(self, rowPath): + """Returns the QModelIndex at `rowPath` + + `rowPath` is a sequence of node rows. For example, [1, 2, 1] is the 2nd child of the + 3rd child of the 2nd child of the root. + """ + result = QModelIndex() + for row in rowPath: + result = self.index(row, 0, result) + return result + + @staticmethod + def pathForIndex(index): + reversedPath = [] + while index.isValid(): + reversedPath.append(index.row()) + index = index.parent() + return list(reversed(reversedPath)) + + def refreshData(self): + """Updates the data on all nodes, but without having to perform a full reset. + + A full reset on a tree makes us lose selection and expansion states. When all we ant to do + is to refresh the data on the nodes without adding or removing a node, a call on + dataChanged() is better. But of course, Qt makes our life complicated by asking us topLeft + and bottomRight indexes. This is a convenience method refreshing the whole tree. + """ + columnCount = self.columnCount() + topLeft = self.index(0, 0, QModelIndex()) + bottomLeft = self._lastIndex() + bottomRight = self.sibling(bottomLeft.row(), columnCount-1, bottomLeft) + self.dataChanged.emit(topLeft, bottomRight) + diff --git a/qtlib/util.py b/qtlib/util.py new file mode 100644 index 00000000..4f36350f --- /dev/null +++ b/qtlib/util.py @@ -0,0 +1,103 @@ +# Created By: Virgil Dupras +# Created On: 2011-02-01 +# Copyright 2013 Hardcoded Software (http://www.hardcoded.net) +# +# This software is licensed under the "BSD" License as described in the "LICENSE" file, +# which should be included with this package. The terms are also available at +# http://www.hardcoded.net/licenses/bsd_license + +import sys +import io +import os.path as op +import os +import logging + +from hscommon.util import first + +from PyQt4.QtGui import (QDesktopWidget, QSpacerItem, QSizePolicy, QPixmap, QIcon, QAction, + QHBoxLayout, QDesktopServices) + +def moveToScreenCenter(widget): + frame = widget.frameGeometry() + frame.moveCenter(QDesktopWidget().availableGeometry().center()) + widget.move(frame.topLeft()) + +def verticalSpacer(size=None): + if size: + return QSpacerItem(1, size, QSizePolicy.Fixed, QSizePolicy.Fixed) + else: + return QSpacerItem(1, 1, QSizePolicy.Fixed, QSizePolicy.MinimumExpanding) + +def horizontalSpacer(size=None): + if size: + return QSpacerItem(size, 1, QSizePolicy.Fixed, QSizePolicy.Fixed) + else: + return QSpacerItem(1, 1, QSizePolicy.MinimumExpanding, QSizePolicy.Fixed) + +def horizontalWrap(widgets): + """Wrap all widgets in `widgets` in a horizontal layout. + + If, instead of placing a widget in your list, you place an int or None, an horizontal spacer + with the width corresponding to the int will be placed (0 or None means an expanding spacer). + """ + layout = QHBoxLayout() + for widget in widgets: + if widget is None or isinstance(widget, int): + layout.addItem(horizontalSpacer(size=widget)) + else: + layout.addWidget(widget) + return layout + +def createActions(actions, target): + # actions = [(name, shortcut, icon, desc, func)] + for name, shortcut, icon, desc, func in actions: + action = QAction(target) + if icon: + action.setIcon(QIcon(QPixmap(':/' + icon))) + if shortcut: + action.setShortcut(shortcut) + action.setText(desc) + action.triggered.connect(func) + setattr(target, name, action) + +def setAccelKeys(menu): + actions = menu.actions() + titles = [a.text() for a in actions] + available_characters = {c.lower() for s in titles for c in s if c.isalpha()} + for action in actions: + text = action.text() + c = first(c for c in text if c.lower() in available_characters) + if c is None: + continue + i = text.index(c) + newtext = text[:i] + '&' + text[i:] + available_characters.remove(c.lower()) + action.setText(newtext) + +def getAppData(): + return str(QDesktopServices.storageLocation(QDesktopServices.DataLocation)) + +class SysWrapper(io.IOBase): + def write(self, s): + if s.strip(): # don't log empty stuff + logging.warning(s) + +def setupQtLogging(level=logging.WARNING): + # Under Qt, we log in "debug.log" in appdata. Moreover, when under cx_freeze, we have a + # problem because sys.stdout and sys.stderr are None, so we need to replace them with a + # wrapper that logs with the logging module. + appdata = getAppData() + if not op.exists(appdata): + os.makedirs(appdata) + # For basicConfig() to work, we have to be sure that no logging has taken place before this call. + logging.basicConfig(filename=op.join(appdata, 'debug.log'), level=level, + format='%(asctime)s - %(levelname)s - %(message)s') + if sys.stderr is None: # happens under a cx_freeze environment + sys.stderr = SysWrapper() + if sys.stdout is None: + sys.stdout = SysWrapper() + +def escapeamp(s): + # Returns `s` with escaped ampersand (& --> &&). QAction text needs to have & escaped because + # that character is used to define "accel keys". + return s.replace('&', '&&')