File indexing completed on 2024-04-14 03:59:09
0001 # -*- coding: utf-8 -*- 0002 """ 0003 Copyright (C) 2010-2016 Wolfgang Rohdewald <wolfgang@rohdewald.de> 0004 0005 partially based on C++ code from: 0006 Copyright (C) 2006 Mauricio Piacentini <mauricio@tabuleiro.com> 0007 0008 SPDX-License-Identifier: GPL-2.0 0009 0010 """ 0011 0012 import os 0013 0014 from qt import uic, QStandardPaths 0015 from qt import QComboBox, QTableView, QSizePolicy, QAbstractItemView 0016 from qt import QTransform 0017 0018 from kde import KIcon 0019 0020 from log import i18n 0021 0022 0023 def loadUi(base): 0024 """load the ui file for class base, deriving the file name from 0025 the class name""" 0026 name = base.__class__.__name__.lower() + '.ui' 0027 if os.path.exists(name): 0028 directory = os.getcwd() 0029 elif os.path.exists('share/kajongg/{}'.format(name)): 0030 directory = 'share/kajongg' 0031 else: 0032 directory = os.path.dirname(QStandardPaths.locate(QStandardPaths.AppDataLocation, name)) 0033 uic.loadUi(os.path.join(directory, name), base) 0034 0035 0036 class MJTableView(QTableView): 0037 0038 """a QTableView with app specific defaults""" 0039 0040 def __init__(self, parent=None): 0041 QTableView.__init__(self, parent) 0042 self.horizontalHeader().setStretchLastSection(True) 0043 self.setAlternatingRowColors(True) 0044 pol = QSizePolicy() 0045 pol.setHorizontalPolicy(QSizePolicy.Expanding) 0046 pol.setVerticalPolicy(QSizePolicy.Expanding) 0047 self.setSizePolicy(pol) 0048 self.verticalHeader().hide() 0049 0050 def initView(self): 0051 """set some app specific defaults""" 0052 self.selectRow(0) 0053 self.resizeColumnsToContents() 0054 self.setSelectionBehavior(QAbstractItemView.SelectRows) 0055 0056 0057 class ListComboBox(QComboBox): 0058 0059 """easy to use with a python list. The elements must have an 0060 attribute 'name'.""" 0061 0062 def __init__(self, items=None, parent=None): 0063 QComboBox.__init__(self, parent) 0064 self.items = items 0065 0066 @property 0067 def items(self): 0068 """combo box items""" 0069 return [self.itemData(idx) for idx in range(self.count())] 0070 0071 @items.setter 0072 def items(self, items): 0073 """combo box items""" 0074 self.clear() 0075 if items: 0076 for item in items: 0077 self.addItem(i18n(item.name), item) 0078 0079 def findItem(self, search): 0080 """return the index or -1 of not found """ 0081 for idx, item in enumerate(self.items): 0082 if item == search: 0083 return idx 0084 return -1 0085 0086 def names(self): 0087 """a list with all item names""" 0088 return list(x.name for x in self.items) 0089 0090 @property 0091 def current(self): 0092 """current item""" 0093 return self.itemData(self.currentIndex()) 0094 0095 @current.setter 0096 def current(self, item): 0097 """current item""" 0098 newIdx = self.findItem(item) 0099 if newIdx < 0: 0100 raise Exception('%s not found in ListComboBox' % item.name) 0101 self.setCurrentIndex(newIdx) 0102 0103 0104 class Painter: 0105 0106 """a helper class for painting: saves/restores painter""" 0107 0108 def __init__(self, painter): 0109 """painter is the painter to be saved/restored""" 0110 self.painter = painter 0111 0112 def __enter__(self): 0113 self.painter.save() 0114 return self 0115 0116 def __exit__(self, exc_type, exc_value, trback): 0117 """now check time passed""" 0118 self.painter.restore() 0119 0120 0121 class BlockSignals: 0122 0123 """a helper class for temporary blocking of Qt signals""" 0124 0125 def __init__(self, qobject): 0126 self.qobject = qobject 0127 0128 def __enter__(self): 0129 if isinstance(self.qobject, list): 0130 for obj in self.qobject: 0131 obj.blockSignals(True) 0132 else: 0133 self.qobject.blockSignals(True) 0134 0135 def __exit__(self, exc_type, exc_value, trback): 0136 if isinstance(self.qobject, list): 0137 for obj in self.qobject: 0138 obj.blockSignals(False) 0139 else: 0140 self.qobject.blockSignals(False) 0141 0142 0143 def decorateWindow(window, name=None): 0144 """standard Kajongg window title and icon""" 0145 if name: 0146 window.setWindowTitle('{} – {}'.format(name, i18n('Kajongg'))) 0147 else: 0148 window.setWindowTitle(i18n('Kajongg')) 0149 window.setWindowIcon(KIcon('kajongg')) 0150 0151 0152 def rotateCenter(item, angle): 0153 """rotates a QGraphicsItem around its center 0154 rotateCenter and sceneRotation could be a mixin class but there are so many 0155 classes needing this. If and when more QGraphicsItem* classes are changed 0156 to QGraphicsObject, those could be moved to GraphicsObject(QGraphicsObject)""" 0157 center = item.boundingRect().center() 0158 centerX, centerY = center.x() * item.scale(), center.y() * item.scale() 0159 item.setTransform(QTransform().translate( 0160 centerX, centerY).rotate(angle).translate(-centerX, -centerY)) 0161 0162 def sceneRotation(item): 0163 """the combined rotation of item and all parents in degrees: 0,90,180 or 270""" 0164 transform = item.sceneTransform() 0165 matrix = ( 0166 round(transform.m11()), 0167 round(transform.m12()), 0168 round(transform.m21()), 0169 round(transform.m22())) 0170 matrix = tuple(1 if x > 0 else -1 if x < 0 else 0 for x in matrix) 0171 rotations = {(0, 0, 0, 0): 0, (1, 0, 0, 1): 0, ( 0172 0, 1, -1, 0): 90, (-1, 0, 0, -1): 180, (0, -1, 1, 0): 270} 0173 if matrix not in rotations: 0174 raise Exception('matrix unknown:%s' % str(matrix)) 0175 return rotations[matrix]