1
0
mirror of https://github.com/arsenetar/dupeguru.git synced 2026-01-22 06:37:17 +00:00

Convert hscommon, qtlib and cocoalib to submodules

... rather than subtrees. That also represents a small qtlib updates
which needed a code adjustment.
This commit is contained in:
Virgil Dupras
2016-05-25 21:07:30 -04:00
parent 4b6f8b45e2
commit bb1f0f5be6
188 changed files with 17 additions and 15586 deletions

1
qtlib Submodule

Submodule qtlib added at d4e3c4ba64

4
qtlib/.gitignore vendored
View File

@@ -1,4 +0,0 @@
__pycache__
*.pyc
*.mo
.DS_Store

View File

@@ -1,8 +0,0 @@
[main]
host = https://www.transifex.com
[hscommon.qtlib]
file_filter = locale/<lang>/LC_MESSAGES/qtlib.po
source_file = locale/qtlib.pot
source_lang = en
type = PO

View File

@@ -1,10 +0,0 @@
Copyright 2014, 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.

View File

View File

@@ -1,76 +0,0 @@
# Created By: Virgil Dupras
# Created On: 2009-05-09
# Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
#
# This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
# which should be included with this package. The terms are also available at
# http://www.gnu.org/licenses/gpl-3.0.html
from PyQt5.QtCore import Qt, QCoreApplication
from PyQt5.QtGui import QPixmap, QFont
from PyQt5.QtWidgets import (QDialog, QDialogButtonBox, QSizePolicy, QHBoxLayout, QVBoxLayout,
QLabel, QApplication)
from hscommon.trans import trget
tr = trget('qtlib')
class AboutBox(QDialog):
def __init__(self, parent, app, **kwargs):
flags = Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowSystemMenuHint | Qt.MSWindowsFixedSizeDialogHint
super().__init__(parent, flags, **kwargs)
self.app = app
self._setupUi()
self.buttonBox.accepted.connect(self.accept)
self.buttonBox.rejected.connect(self.reject)
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 2014"))
self.label = QLabel(self)
font = QFont()
font.setWeight(75)
font.setBold(True)
self.label.setFont(font)
self.verticalLayout.addWidget(self.label)
self.buttonBox = QDialogButtonBox(self)
self.buttonBox.setOrientation(Qt.Horizontal)
self.buttonBox.setStandardButtons(QDialogButtonBox.Ok)
self.verticalLayout.addWidget(self.buttonBox)
self.horizontalLayout.addLayout(self.verticalLayout)
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_())

View File

@@ -1,19 +0,0 @@
# -*- coding: utf-8 -*-
# Created By: Virgil Dupras
# Created On: 2009-10-16
# Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
#
# This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
# which should be included with this package. The terms are also available at
# http://www.gnu.org/licenses/gpl-3.0.html
from PyQt5.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()'))

View File

@@ -1,86 +0,0 @@
# Created By: Virgil Dupras
# Created On: 2009-11-25
# Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
#
# This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
# which should be included with this package. The terms are also available at
# http://www.gnu.org/licenses/gpl-3.0.html
from PyQt5.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)

View File

@@ -1,84 +0,0 @@
# Created By: Virgil Dupras
# Created On: 2009-05-23
# Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
#
# This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
# which should be included with this package. The terms are also available at
# http://www.gnu.org/licenses/gpl-3.0.html
import traceback
import sys
import os
from PyQt5.QtCore import Qt, QCoreApplication, QSize
from PyQt5.QtWidgets import QDialog, QVBoxLayout, QHBoxLayout, QLabel, QPlainTextEdit, QPushButton
from hscommon.trans import trget
from hscommon.desktop import open_url
from .util import horizontalSpacer
tr = trget('qtlib')
class ErrorReportDialog(QDialog):
def __init__(self, parent, github_url, error, **kwargs):
flags = Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowSystemMenuHint
super().__init__(parent, flags, **kwargs)
self._setupUi()
name = QCoreApplication.applicationName()
version = QCoreApplication.applicationVersion()
errorText = "Application Name: {}\nVersion: {}\n\n{}".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.github_url = github_url
self.sendButton.clicked.connect(self.goToGithub)
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. How about reporting the error?"))
self.label.setWordWrap(True)
self.verticalLayout.addWidget(self.label)
self.errorTextEdit = QPlainTextEdit(self)
self.errorTextEdit.setReadOnly(True)
self.verticalLayout.addWidget(self.errorTextEdit)
msg = tr(
"Error reports should be reported as Github issues. You can copy the error traceback "
"above and paste it in a new issue (bonus point if you run a search to make sure the "
"issue doesn't already exist). What usually really helps is if you add a description "
"of how you got the error. Thanks!"
"\n\n"
"Although the application should continue to run after this error, it may be in an "
"unstable 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("Close"))
self.dontSendButton.setMinimumSize(QSize(110, 0))
self.horizontalLayout.addWidget(self.dontSendButton)
self.sendButton = QPushButton(self)
self.sendButton.setText(tr("Go to Github"))
self.sendButton.setMinimumSize(QSize(110, 0))
self.sendButton.setDefault(True)
self.horizontalLayout.addWidget(self.sendButton)
self.verticalLayout.addLayout(self.horizontalLayout)
def goToGithub(self):
open_url(self.github_url)
def install_excepthook(github_url):
def my_excepthook(exctype, value, tb):
s = ''.join(traceback.format_exception(exctype, value, tb))
dialog = ErrorReportDialog(None, github_url, s)
dialog.exec_()
sys.excepthook = my_excepthook

Binary file not shown.

Before

Width:  |  Height:  |  Size: 398 B

View File

@@ -1,106 +0,0 @@
# Translators:
msgid ""
msgstr ""
"Project-Id-Version: hscommon\n"
"PO-Revision-Date: 2014-03-30 14:55+0000\n"
"Last-Translator: Virgil Dupras <hsoft@hardcoded.net>\n"
"Language-Team: Czech (http://www.transifex.com/p/hscommon/language/cs/)\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:29
msgid "About {}"
msgstr ""
#: qtlib/about_box.py:49
msgid "Version {}"
msgstr ""
#: qtlib/about_box.py:53
msgid "Copyright Hardcoded Software 2014"
msgstr ""
#: qtlib/error_report_dialog.py:39
msgid "Error Report"
msgstr ""
#: qtlib/error_report_dialog.py:43
msgid "Something went wrong. How about reporting the error?"
msgstr ""
#: qtlib/error_report_dialog.py:49
msgid ""
"Error reports should be reported as Github issues. You can copy the error traceback above and paste it in a new issue (bonus point if you run a search to make sure the issue doesn't already exist). What usually really helps is if you add a description of how you got the error. Thanks!\n"
"\n"
"Although the application should continue to run after this error, it may be in an unstable state, so it is recommended that you restart the application."
msgstr ""
#: qtlib/error_report_dialog.py:64
msgid "Close"
msgstr ""
#: qtlib/error_report_dialog.py:68
msgid "Go to Github"
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/preferences.py:29
msgid "Vietnamese"
msgstr ""
#: qtlib/recent.py:53
msgid "Clear List"
msgstr ""
#: qtlib/search_edit.py:41
msgid "Search..."
msgstr ""

View File

@@ -1,106 +0,0 @@
# Translators:
msgid ""
msgstr ""
"Project-Id-Version: hscommon\n"
"PO-Revision-Date: 2014-03-30 14:55+0000\n"
"Last-Translator: Virgil Dupras <hsoft@hardcoded.net>\n"
"Language-Team: German (http://www.transifex.com/p/hscommon/language/de/)\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:29
msgid "About {}"
msgstr ""
#: qtlib/about_box.py:49
msgid "Version {}"
msgstr ""
#: qtlib/about_box.py:53
msgid "Copyright Hardcoded Software 2014"
msgstr ""
#: qtlib/error_report_dialog.py:39
msgid "Error Report"
msgstr ""
#: qtlib/error_report_dialog.py:43
msgid "Something went wrong. How about reporting the error?"
msgstr ""
#: qtlib/error_report_dialog.py:49
msgid ""
"Error reports should be reported as Github issues. You can copy the error traceback above and paste it in a new issue (bonus point if you run a search to make sure the issue doesn't already exist). What usually really helps is if you add a description of how you got the error. Thanks!\n"
"\n"
"Although the application should continue to run after this error, it may be in an unstable state, so it is recommended that you restart the application."
msgstr ""
#: qtlib/error_report_dialog.py:64
msgid "Close"
msgstr ""
#: qtlib/error_report_dialog.py:68
msgid "Go to Github"
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/preferences.py:29
msgid "Vietnamese"
msgstr ""
#: qtlib/recent.py:53
msgid "Clear List"
msgstr ""
#: qtlib/search_edit.py:41
msgid "Search..."
msgstr ""

View File

@@ -1,106 +0,0 @@
# Translators:
msgid ""
msgstr ""
"Project-Id-Version: hscommon\n"
"PO-Revision-Date: 2014-03-30 14:55+0000\n"
"Last-Translator: Virgil Dupras <hsoft@hardcoded.net>\n"
"Language-Team: Spanish (http://www.transifex.com/p/hscommon/language/es/)\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:29
msgid "About {}"
msgstr "Acerca de {}"
#: qtlib/about_box.py:49
msgid "Version {}"
msgstr "Versión {}"
#: qtlib/about_box.py:53
msgid "Copyright Hardcoded Software 2014"
msgstr ""
#: qtlib/error_report_dialog.py:39
msgid "Error Report"
msgstr "Informe de error"
#: qtlib/error_report_dialog.py:43
msgid "Something went wrong. How about reporting the error?"
msgstr ""
#: qtlib/error_report_dialog.py:49
msgid ""
"Error reports should be reported as Github issues. You can copy the error traceback above and paste it in a new issue (bonus point if you run a search to make sure the issue doesn't already exist). What usually really helps is if you add a description of how you got the error. Thanks!\n"
"\n"
"Although the application should continue to run after this error, it may be in an unstable state, so it is recommended that you restart the application."
msgstr ""
#: qtlib/error_report_dialog.py:64
msgid "Close"
msgstr ""
#: qtlib/error_report_dialog.py:68
msgid "Go to Github"
msgstr ""
#: 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/preferences.py:29
msgid "Vietnamese"
msgstr ""
#: qtlib/recent.py:53
msgid "Clear List"
msgstr "Limpiar lista"
#: qtlib/search_edit.py:41
msgid "Search..."
msgstr "Búsqueda..."

View File

@@ -1,106 +0,0 @@
# Translators:
msgid ""
msgstr ""
"Project-Id-Version: hscommon\n"
"PO-Revision-Date: 2014-03-30 14:55+0000\n"
"Last-Translator: Virgil Dupras <hsoft@hardcoded.net>\n"
"Language-Team: French (http://www.transifex.com/p/hscommon/language/fr/)\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:29
msgid "About {}"
msgstr ""
#: qtlib/about_box.py:49
msgid "Version {}"
msgstr ""
#: qtlib/about_box.py:53
msgid "Copyright Hardcoded Software 2014"
msgstr ""
#: qtlib/error_report_dialog.py:39
msgid "Error Report"
msgstr ""
#: qtlib/error_report_dialog.py:43
msgid "Something went wrong. How about reporting the error?"
msgstr ""
#: qtlib/error_report_dialog.py:49
msgid ""
"Error reports should be reported as Github issues. You can copy the error traceback above and paste it in a new issue (bonus point if you run a search to make sure the issue doesn't already exist). What usually really helps is if you add a description of how you got the error. Thanks!\n"
"\n"
"Although the application should continue to run after this error, it may be in an unstable state, so it is recommended that you restart the application."
msgstr ""
#: qtlib/error_report_dialog.py:64
msgid "Close"
msgstr ""
#: qtlib/error_report_dialog.py:68
msgid "Go to Github"
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/preferences.py:29
msgid "Vietnamese"
msgstr ""
#: qtlib/recent.py:53
msgid "Clear List"
msgstr "Vider la liste"
#: qtlib/search_edit.py:41
msgid "Search..."
msgstr "Recherche..."

View File

@@ -1,106 +0,0 @@
# Translators:
msgid ""
msgstr ""
"Project-Id-Version: hscommon\n"
"PO-Revision-Date: 2014-03-30 14:55+0000\n"
"Last-Translator: Virgil Dupras <hsoft@hardcoded.net>\n"
"Language-Team: Armenian (http://www.transifex.com/p/hscommon/language/hy/)\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:29
msgid "About {}"
msgstr ""
#: qtlib/about_box.py:49
msgid "Version {}"
msgstr ""
#: qtlib/about_box.py:53
msgid "Copyright Hardcoded Software 2014"
msgstr ""
#: qtlib/error_report_dialog.py:39
msgid "Error Report"
msgstr "Սխալի զեկույցը"
#: qtlib/error_report_dialog.py:43
msgid "Something went wrong. How about reporting the error?"
msgstr ""
#: qtlib/error_report_dialog.py:49
msgid ""
"Error reports should be reported as Github issues. You can copy the error traceback above and paste it in a new issue (bonus point if you run a search to make sure the issue doesn't already exist). What usually really helps is if you add a description of how you got the error. Thanks!\n"
"\n"
"Although the application should continue to run after this error, it may be in an unstable state, so it is recommended that you restart the application."
msgstr ""
#: qtlib/error_report_dialog.py:64
msgid "Close"
msgstr ""
#: qtlib/error_report_dialog.py:68
msgid "Go to Github"
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/preferences.py:29
msgid "Vietnamese"
msgstr ""
#: qtlib/recent.py:53
msgid "Clear List"
msgstr "Մաքրել ցանկը"
#: qtlib/search_edit.py:41
msgid "Search..."
msgstr ""

View File

@@ -1,106 +0,0 @@
# Translators:
msgid ""
msgstr ""
"Project-Id-Version: hscommon\n"
"PO-Revision-Date: 2014-03-30 14:55+0000\n"
"Last-Translator: Virgil Dupras <hsoft@hardcoded.net>\n"
"Language-Team: Italian (http://www.transifex.com/p/hscommon/language/it/)\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:29
msgid "About {}"
msgstr ""
#: qtlib/about_box.py:49
msgid "Version {}"
msgstr ""
#: qtlib/about_box.py:53
msgid "Copyright Hardcoded Software 2014"
msgstr ""
#: qtlib/error_report_dialog.py:39
msgid "Error Report"
msgstr ""
#: qtlib/error_report_dialog.py:43
msgid "Something went wrong. How about reporting the error?"
msgstr ""
#: qtlib/error_report_dialog.py:49
msgid ""
"Error reports should be reported as Github issues. You can copy the error traceback above and paste it in a new issue (bonus point if you run a search to make sure the issue doesn't already exist). What usually really helps is if you add a description of how you got the error. Thanks!\n"
"\n"
"Although the application should continue to run after this error, it may be in an unstable state, so it is recommended that you restart the application."
msgstr ""
#: qtlib/error_report_dialog.py:64
msgid "Close"
msgstr ""
#: qtlib/error_report_dialog.py:68
msgid "Go to Github"
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/preferences.py:29
msgid "Vietnamese"
msgstr ""
#: qtlib/recent.py:53
msgid "Clear List"
msgstr ""
#: qtlib/search_edit.py:41
msgid "Search..."
msgstr ""

View File

@@ -1,106 +0,0 @@
# Translators:
msgid ""
msgstr ""
"Project-Id-Version: hscommon\n"
"PO-Revision-Date: 2015-07-20 16:42+0000\n"
"Last-Translator: Virgil Dupras <hsoft@hardcoded.net>\n"
"Language-Team: Korean (http://www.transifex.com/p/hscommon/language/ko/)\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: utf-8\n"
"Language: ko\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: qtlib/about_box.py:29
msgid "About {}"
msgstr ""
#: qtlib/about_box.py:49
msgid "Version {}"
msgstr ""
#: qtlib/about_box.py:53
msgid "Copyright Hardcoded Software 2014"
msgstr ""
#: qtlib/error_report_dialog.py:39
msgid "Error Report"
msgstr ""
#: qtlib/error_report_dialog.py:43
msgid "Something went wrong. How about reporting the error?"
msgstr ""
#: qtlib/error_report_dialog.py:49
msgid ""
"Error reports should be reported as Github issues. You can copy the error traceback above and paste it in a new issue (bonus point if you run a search to make sure the issue doesn't already exist). What usually really helps is if you add a description of how you got the error. Thanks!\n"
"\n"
"Although the application should continue to run after this error, it may be in an unstable state, so it is recommended that you restart the application."
msgstr ""
#: qtlib/error_report_dialog.py:64
msgid "Close"
msgstr ""
#: qtlib/error_report_dialog.py:68
msgid "Go to Github"
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/preferences.py:29
msgid "Vietnamese"
msgstr ""
#: qtlib/recent.py:53
msgid "Clear List"
msgstr ""
#: qtlib/search_edit.py:41
msgid "Search..."
msgstr ""

View File

@@ -1,106 +0,0 @@
# Translators:
msgid ""
msgstr ""
"Project-Id-Version: hscommon\n"
"PO-Revision-Date: 2014-03-30 14:55+0000\n"
"Last-Translator: Virgil Dupras <hsoft@hardcoded.net>\n"
"Language-Team: Dutch (http://www.transifex.com/p/hscommon/language/nl/)\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:29
msgid "About {}"
msgstr ""
#: qtlib/about_box.py:49
msgid "Version {}"
msgstr ""
#: qtlib/about_box.py:53
msgid "Copyright Hardcoded Software 2014"
msgstr ""
#: qtlib/error_report_dialog.py:39
msgid "Error Report"
msgstr ""
#: qtlib/error_report_dialog.py:43
msgid "Something went wrong. How about reporting the error?"
msgstr ""
#: qtlib/error_report_dialog.py:49
msgid ""
"Error reports should be reported as Github issues. You can copy the error traceback above and paste it in a new issue (bonus point if you run a search to make sure the issue doesn't already exist). What usually really helps is if you add a description of how you got the error. Thanks!\n"
"\n"
"Although the application should continue to run after this error, it may be in an unstable state, so it is recommended that you restart the application."
msgstr ""
#: qtlib/error_report_dialog.py:64
msgid "Close"
msgstr ""
#: qtlib/error_report_dialog.py:68
msgid "Go to Github"
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/preferences.py:29
msgid "Vietnamese"
msgstr ""
#: qtlib/recent.py:53
msgid "Clear List"
msgstr ""
#: qtlib/search_edit.py:41
msgid "Search..."
msgstr ""

View File

@@ -1,107 +0,0 @@
#
# Translators:
msgid ""
msgstr ""
"Project-Id-Version: hscommon\n"
"PO-Revision-Date: 2015-07-20 16:53+0000\n"
"Last-Translator: Virgil Dupras <hsoft@hardcoded.net>\n"
"Language-Team: Polish (Poland) (http://www.transifex.com/p/hscommon/language/pl_PL/)\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: utf-8\n"
"Language: pl_PL\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
#: qtlib/about_box.py:29
msgid "About {}"
msgstr ""
#: qtlib/about_box.py:49
msgid "Version {}"
msgstr ""
#: qtlib/about_box.py:53
msgid "Copyright Hardcoded Software 2014"
msgstr ""
#: qtlib/error_report_dialog.py:39
msgid "Error Report"
msgstr ""
#: qtlib/error_report_dialog.py:43
msgid "Something went wrong. How about reporting the error?"
msgstr ""
#: qtlib/error_report_dialog.py:49
msgid ""
"Error reports should be reported as Github issues. You can copy the error traceback above and paste it in a new issue (bonus point if you run a search to make sure the issue doesn't already exist). What usually really helps is if you add a description of how you got the error. Thanks!\n"
"\n"
"Although the application should continue to run after this error, it may be in an unstable state, so it is recommended that you restart the application."
msgstr ""
#: qtlib/error_report_dialog.py:64
msgid "Close"
msgstr ""
#: qtlib/error_report_dialog.py:68
msgid "Go to Github"
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/preferences.py:29
msgid "Vietnamese"
msgstr ""
#: qtlib/recent.py:53
msgid "Clear List"
msgstr ""
#: qtlib/search_edit.py:41
msgid "Search..."
msgstr ""

View File

@@ -1,110 +0,0 @@
# Translators:
# Vitu <contact@brlingo.com>, 2013-2014
msgid ""
msgstr ""
"Project-Id-Version: hscommon\n"
"PO-Revision-Date: 2014-04-30 18:58+0000\n"
"Last-Translator: Vitu <contact@brlingo.com>\n"
"Language-Team: Portuguese (Brazil) (http://www.transifex.com/p/hscommon/language/pt_BR/)\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:29
msgid "About {}"
msgstr "Sobre o {}"
#: qtlib/about_box.py:49
msgid "Version {}"
msgstr "Versão {}"
#: qtlib/about_box.py:53
msgid "Copyright Hardcoded Software 2014"
msgstr "Copyright Hardcoded Software 2014"
#: qtlib/error_report_dialog.py:39
msgid "Error Report"
msgstr "Relatório de Erro"
#: qtlib/error_report_dialog.py:43
msgid "Something went wrong. How about reporting the error?"
msgstr "Algo deu errado. Deseja relatar o erro?"
#: qtlib/error_report_dialog.py:49
msgid ""
"Error reports should be reported as Github issues. You can copy the error traceback above and paste it in a new issue (bonus point if you run a search to make sure the issue doesn't already exist). What usually really helps is if you add a description of how you got the error. Thanks!\n"
"\n"
"Although the application should continue to run after this error, it may be in an unstable state, so it is recommended that you restart the application."
msgstr ""
"Os erros devem ser relatados como problemas no Github. Copie o código de rastreamento acima e cole-o em um problema novo (pontos bônus caso você busque o erro, certificando-se de que ele ainda não exista). O que mais ajuda é adicionar uma descrição de como o erro ocorreu. Obrigado!\n"
"\n"
"Embora o aplicativo continue a funcionar após esse erro, ele pode estar “instável”. É recomendável reiniciá-lo."
#: qtlib/error_report_dialog.py:64
msgid "Close"
msgstr "Fechar"
#: qtlib/error_report_dialog.py:68
msgid "Go to Github"
msgstr "Ir para o Github"
#: 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 "Português Brasileiro"
#: qtlib/preferences.py:28
msgid "Spanish"
msgstr "Espanhol"
#: qtlib/preferences.py:29
msgid "Vietnamese"
msgstr "Vietnamita"
#: qtlib/recent.py:53
msgid "Clear List"
msgstr "Limpar Lista"
#: qtlib/search_edit.py:41
msgid "Search..."
msgstr "Buscar…"

View File

@@ -1,101 +0,0 @@
msgid ""
msgstr ""
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: utf-8\n"
#: qtlib/about_box.py:29
msgid "About {}"
msgstr ""
#: qtlib/about_box.py:49
msgid "Version {}"
msgstr ""
#: qtlib/about_box.py:53
msgid "Copyright Hardcoded Software 2014"
msgstr ""
#: qtlib/error_report_dialog.py:39
msgid "Error Report"
msgstr ""
#: qtlib/error_report_dialog.py:43
msgid "Something went wrong. How about reporting the error?"
msgstr ""
#: qtlib/error_report_dialog.py:49
msgid ""
"Error reports should be reported as Github issues. You can copy the error traceback above and paste it in a new issue (bonus point if you run a search to make sure the issue doesn't already exist). What usually really helps is if you add a description of how you got the error. Thanks!\n"
"\n"
"Although the application should continue to run after this error, it may be in an unstable state, so it is recommended that you restart the application."
msgstr ""
#: qtlib/error_report_dialog.py:64
msgid "Close"
msgstr ""
#: qtlib/error_report_dialog.py:68
msgid "Go to Github"
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/preferences.py:29
msgid "Vietnamese"
msgstr ""
#: qtlib/recent.py:53
msgid "Clear List"
msgstr ""
#: qtlib/search_edit.py:41
msgid "Search..."
msgstr ""

View File

@@ -1,110 +0,0 @@
# Translators:
# Igor Fokusov <igor@fokusov.com>, 2015
msgid ""
msgstr ""
"Project-Id-Version: hscommon\n"
"PO-Revision-Date: 2015-04-14 21:16+0000\n"
"Last-Translator: Igor Fokusov <igor@fokusov.com>\n"
"Language-Team: Russian (http://www.transifex.com/p/hscommon/language/ru/)\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: utf-8\n"
"Language: ru\n"
"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);\n"
#: qtlib/about_box.py:29
msgid "About {}"
msgstr "О {}"
#: qtlib/about_box.py:49
msgid "Version {}"
msgstr "Версия {}"
#: qtlib/about_box.py:53
msgid "Copyright Hardcoded Software 2014"
msgstr "Copyright Hardcoded Software 2014"
#: qtlib/error_report_dialog.py:39
msgid "Error Report"
msgstr "Сообщение об ошибке"
#: qtlib/error_report_dialog.py:43
msgid "Something went wrong. How about reporting the error?"
msgstr "Что-то пошло не так. Хотите отправить отчёт об ошибке?"
#: qtlib/error_report_dialog.py:49
msgid ""
"Error reports should be reported as Github issues. You can copy the error traceback above and paste it in a new issue (bonus point if you run a search to make sure the issue doesn't already exist). What usually really helps is if you add a description of how you got the error. Thanks!\n"
"\n"
"Although the application should continue to run after this error, it may be in an unstable state, so it is recommended that you restart the application."
msgstr ""
"Отчеты об ошибках нужно отправлять в Github issues проекта. Скопируйте текст ошибки выше и вставьте в созданную заметку о проблеме (перед этим желательно проверить - не создано ли уже такой проблемы до вас). Также нам очень поможет краткое описание как вы получили такую ошибку. Спасибо!\n"
"\n"
"В принципе, программа может продолжать работу, но стабильная работа не гарантируется. Поэтому желательно перезапустить программу."
#: qtlib/error_report_dialog.py:64
msgid "Close"
msgstr "Закрыть"
#: qtlib/error_report_dialog.py:68
msgid "Go to Github"
msgstr "Перейти на Github"
#: 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/preferences.py:29
msgid "Vietnamese"
msgstr "Вьетнамский"
#: qtlib/recent.py:53
msgid "Clear List"
msgstr "Очистить список"
#: qtlib/search_edit.py:41
msgid "Search..."
msgstr "Искать..."

View File

@@ -1,106 +0,0 @@
# Translators:
msgid ""
msgstr ""
"Project-Id-Version: hscommon\n"
"PO-Revision-Date: 2014-03-30 14:55+0000\n"
"Last-Translator: Virgil Dupras <hsoft@hardcoded.net>\n"
"Language-Team: Ukrainian (http://www.transifex.com/p/hscommon/language/uk/)\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:29
msgid "About {}"
msgstr ""
#: qtlib/about_box.py:49
msgid "Version {}"
msgstr ""
#: qtlib/about_box.py:53
msgid "Copyright Hardcoded Software 2014"
msgstr ""
#: qtlib/error_report_dialog.py:39
msgid "Error Report"
msgstr "Повідомлення про помилки"
#: qtlib/error_report_dialog.py:43
msgid "Something went wrong. How about reporting the error?"
msgstr ""
#: qtlib/error_report_dialog.py:49
msgid ""
"Error reports should be reported as Github issues. You can copy the error traceback above and paste it in a new issue (bonus point if you run a search to make sure the issue doesn't already exist). What usually really helps is if you add a description of how you got the error. Thanks!\n"
"\n"
"Although the application should continue to run after this error, it may be in an unstable state, so it is recommended that you restart the application."
msgstr ""
#: qtlib/error_report_dialog.py:64
msgid "Close"
msgstr ""
#: qtlib/error_report_dialog.py:68
msgid "Go to Github"
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/preferences.py:29
msgid "Vietnamese"
msgstr ""
#: qtlib/recent.py:53
msgid "Clear List"
msgstr "Очистити список"
#: qtlib/search_edit.py:41
msgid "Search..."
msgstr "Шукати..."

View File

@@ -1,106 +0,0 @@
# Translators:
msgid ""
msgstr ""
"Project-Id-Version: hscommon\n"
"PO-Revision-Date: 2014-03-30 14:55+0000\n"
"Last-Translator: Virgil Dupras <hsoft@hardcoded.net>\n"
"Language-Team: Vietnamese (http://www.transifex.com/p/hscommon/language/vi/)\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: utf-8\n"
"Language: vi\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: qtlib/about_box.py:29
msgid "About {}"
msgstr ""
#: qtlib/about_box.py:49
msgid "Version {}"
msgstr ""
#: qtlib/about_box.py:53
msgid "Copyright Hardcoded Software 2014"
msgstr ""
#: qtlib/error_report_dialog.py:39
msgid "Error Report"
msgstr ""
#: qtlib/error_report_dialog.py:43
msgid "Something went wrong. How about reporting the error?"
msgstr ""
#: qtlib/error_report_dialog.py:49
msgid ""
"Error reports should be reported as Github issues. You can copy the error traceback above and paste it in a new issue (bonus point if you run a search to make sure the issue doesn't already exist). What usually really helps is if you add a description of how you got the error. Thanks!\n"
"\n"
"Although the application should continue to run after this error, it may be in an unstable state, so it is recommended that you restart the application."
msgstr ""
#: qtlib/error_report_dialog.py:64
msgid "Close"
msgstr ""
#: qtlib/error_report_dialog.py:68
msgid "Go to Github"
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/preferences.py:29
msgid "Vietnamese"
msgstr ""
#: qtlib/recent.py:53
msgid "Clear List"
msgstr ""
#: qtlib/search_edit.py:41
msgid "Search..."
msgstr ""

View File

@@ -1,106 +0,0 @@
# Translators:
msgid ""
msgstr ""
"Project-Id-Version: hscommon\n"
"PO-Revision-Date: 2014-03-30 14:55+0000\n"
"Last-Translator: Virgil Dupras <hsoft@hardcoded.net>\n"
"Language-Team: Chinese (China) (http://www.transifex.com/p/hscommon/language/zh_CN/)\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:29
msgid "About {}"
msgstr ""
#: qtlib/about_box.py:49
msgid "Version {}"
msgstr ""
#: qtlib/about_box.py:53
msgid "Copyright Hardcoded Software 2014"
msgstr ""
#: qtlib/error_report_dialog.py:39
msgid "Error Report"
msgstr ""
#: qtlib/error_report_dialog.py:43
msgid "Something went wrong. How about reporting the error?"
msgstr ""
#: qtlib/error_report_dialog.py:49
msgid ""
"Error reports should be reported as Github issues. You can copy the error traceback above and paste it in a new issue (bonus point if you run a search to make sure the issue doesn't already exist). What usually really helps is if you add a description of how you got the error. Thanks!\n"
"\n"
"Although the application should continue to run after this error, it may be in an unstable state, so it is recommended that you restart the application."
msgstr ""
#: qtlib/error_report_dialog.py:64
msgid "Close"
msgstr ""
#: qtlib/error_report_dialog.py:68
msgid "Go to Github"
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/preferences.py:29
msgid "Vietnamese"
msgstr ""
#: qtlib/recent.py:53
msgid "Clear List"
msgstr "清空列表"
#: qtlib/search_edit.py:41
msgid "Search..."
msgstr ""

View File

@@ -1,129 +0,0 @@
# Created By: Virgil Dupras
# Created On: 2009-05-03
# Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
#
# This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
# which should be included with this package. The terms are also available at
# http://www.gnu.org/licenses/gpl-3.0.html
from PyQt5.QtCore import Qt, QSettings, QRect
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"),
'ko': tr("Korean"),
'ru': tr("Russian"),
'uk': tr("Ukrainian"),
'nl': tr('Dutch'),
'pl_PL': tr("Polish"),
'pt_BR': tr("Brazilian"),
'es': tr("Spanish"),
'vi': tr("Vietnamese"),
}
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)
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)

View File

@@ -1,48 +0,0 @@
# Created By: Virgil Dupras
# Created On: 2013-07-01
# Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
#
# This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
# which should be included with this package. The terms are also available at
# http://www.gnu.org/licenses/gpl-3.0.html
from PyQt5.QtCore import Qt, QTimer
from PyQt5.QtWidgets import QProgressDialog
class ProgressWindow(QProgressDialog):
def __init__(self, parent, model, **kwargs):
flags = Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowSystemMenuHint
super().__init__('', "Cancel", 0, 100, parent, flags, **kwargs)
self.model = model
model.view = self
# We don't have access to QProgressDialog's labels directly, so we se the model label's view
# to self and we'll refresh them together.
self.model.jobdesc_textfield.view = self
self.model.progressdesc_textfield.view = self
self.setModal(True)
self.setAutoReset(False)
self.setAutoClose(False)
self._timer = QTimer(self)
self._timer.timeout.connect(self.model.pulse)
# --- Callbacks
def refresh(self): # Labels
self.setWindowTitle(self.model.jobdesc_textfield.text)
self.setLabelText(self.model.progressdesc_textfield.text)
def set_progress(self, last_progress):
self.setValue(last_progress)
def show(self):
self.reset()
super().show()
self.canceled.connect(self.model.cancel)
self._timer.start(500)
def close(self):
self._timer.stop()
# For some weird reason, canceled() signal is sent upon close, whether the user canceled
# or not. If we don't want a false cancellation, we have to disconnect it.
self.canceled.disconnect()
super().close()

View File

@@ -1,88 +0,0 @@
# Created On: 2010-06-02
# Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
#
# This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
# which should be included with this package. The terms are also available at
# http://www.gnu.org/licenses/gpl-3.0.html
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtWidgets import QWidget, QHBoxLayout, QRadioButton
from .util import horizontalSpacer
class RadioBox(QWidget):
def __init__(self, parent=None, items=None, spread=True, **kwargs):
# 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 = []
super().__init__(parent, **kwargs)
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()

View File

@@ -1,95 +0,0 @@
# Created By: Virgil Dupras
# Created On: 2009-11-12
# Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
#
# This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
# which should be included with this package. The terms are also available at
# http://www.gnu.org/licenses/gpl-3.0.html
from collections import namedtuple
from PyQt5.QtCore import pyqtSignal, QObject
from PyQt5.QtWidgets 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, **kwargs):
super().__init__(**kwargs)
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()

View File

@@ -1,98 +0,0 @@
# Created By: Virgil Dupras
# Created On: 2009-12-10
# Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
#
# This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
# which should be included with this package. The terms are also available at
# http://www.gnu.org/licenses/gpl-3.0.html
from PyQt5.QtCore import pyqtSignal, Qt
from PyQt5.QtGui import QIcon, QPixmap, QPainter, QPalette
from PyQt5.QtWidgets import QToolButton, QLineEdit, QStyle, QStyleOptionFrame
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, **kwargs):
super().__init__(parent, **kwargs)
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, **kwargs):
# immediate: send searchChanged signals at each keystroke.
super().__init__(parent, **kwargs)
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 = QStyleOptionFrame()
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

View File

@@ -1,98 +0,0 @@
# Created By: Virgil Dupras
# Created On: 2011-09-06
# Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
#
# This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
# which should be included with this package. The terms are also available at
# http://www.gnu.org/licenses/gpl-3.0.html
from PyQt5.QtCore import Qt, QAbstractListModel, QItemSelection, QItemSelectionModel
class SelectableList(QAbstractListModel):
def __init__(self, model, view, **kwargs):
super().__init__(**kwargs)
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.beginResetModel()
self.endResetModel()
self._updating = False
self._restoreSelection()
def update_selection(self):
self._restoreSelection()
class ComboboxModel(SelectableList):
def __init__(self, model, view, **kwargs):
super().__init__(model, view, **kwargs)
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, **kwargs):
super().__init__(model, view, **kwargs)
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()

View File

@@ -1,152 +0,0 @@
# Created By: Virgil Dupras
# Created On: 2009-11-01
# Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
#
# This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
# which should be included with this package. The terms are also available at
# http://www.gnu.org/licenses/gpl-3.0.html
from PyQt5.QtCore import Qt, QAbstractTableModel, QModelIndex, 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, **kwargs):
super().__init__(**kwargs)
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.beginResetModel()
self.endResetModel()
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()

View File

@@ -1,23 +0,0 @@
# Created On: 2012/01/23
# Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
#
# This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
# which should be included with this package. The terms are also available at
# http://www.gnu.org/licenses/gpl-3.0.html
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)

View File

@@ -1,173 +0,0 @@
# Created By: Virgil Dupras
# Created On: 2009-09-14
# Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
#
# This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
# which should be included with this package. The terms are also available at
# http://www.gnu.org/licenses/gpl-3.0.html
import logging
from PyQt5.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, **kwargs):
super().__init__(**kwargs)
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):
super().beginResetModel()
self.invalidate()
self._ref2node = {}
self._dummyNodes = set()
super().endResetModel()
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)

View File

@@ -1,104 +0,0 @@
# Created By: Virgil Dupras
# Created On: 2011-02-01
# Copyright 2015 Hardcoded Software (http://www.hardcoded.net)
#
# This software is licensed under the "GPLv3" License as described in the "LICENSE" file,
# which should be included with this package. The terms are also available at
# http://www.gnu.org/licenses/gpl-3.0.html
import sys
import io
import os.path as op
import os
import logging
from hscommon.util import first
from PyQt5.QtCore import QStandardPaths
from PyQt5.QtGui import QPixmap, QIcon
from PyQt5.QtWidgets import QDesktopWidget, QSpacerItem, QSizePolicy, QAction, QHBoxLayout
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 QStandardPaths.standardLocations(QStandardPaths.DataLocation)[0]
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('&', '&&')