class CustomProxy(QGraphicsProxyWidget): def __init__(self, parent=None, wFlags=0): super(CustomProxy, self).__init__(parent, wFlags) self.popupShown = False self.currentPopup = None self.timeLine = QTimeLine(250, self) self.timeLine.valueChanged.connect(self.updateStep) self.timeLine.stateChanged.connect(self.stateChanged) def boundingRect(self): return QGraphicsProxyWidget.boundingRect(self).adjusted(0, 0, 10, 10) def paintWindowFrame(self, painter, option, widget): color = QColor(0, 0, 0, 64) r = self.windowFrameRect() right = QRectF(r.right(), r.top() + 10, 10, r.height() - 10) bottom = QRectF(r.left() + 10, r.bottom(), r.width(), 10) intersectsRight = right.intersects(option.exposedRect) intersectsBottom = bottom.intersects(option.exposedRect) if intersectsRight and intersectsBottom: path = QPainterPath() path.addRect(right) path.addRect(bottom) painter.setPen(Qt.NoPen) painter.setBrush(color) painter.drawPath(path) elif intersectsBottom: painter.fillRect(bottom, color) elif intersectsRight: painter.fillRect(right, color) super(CustomProxy, self).paintWindowFrame(painter, option, widget) def hoverEnterEvent(self, event): super(CustomProxy, self).hoverEnterEvent(event) self.scene().setActiveWindow(self) if self.timeLine.currentValue != 1: self.zoomIn() def hoverLeaveEvent(self, event): super(CustomProxy, self).hoverLeaveEvent(event) if not self.popupShown and ( self.timeLine.direction() != QTimeLine.Backward or self.timeLine.currentValue() != 0): self.zoomOut() def sceneEventFilter(self, watched, event): if watched.isWindow() and (event.type() == QEvent.UngrabMouse or event.type() == QEvent.GrabMouse): self.popupShown = watched.isVisible() if not self.popupShown and not self.isUnderMouse(): self.zoomOut() return super(CustomProxy, self).sceneEventFilter(watched, event) def itemChange(self, change, value): if change == self.ItemChildAddedChange or change == self.ItemChildRemovedChange: if change == self.ItemChildAddedChange: self.currentPopup = value self.currentPopup.setCacheMode(self.ItemCoordinateCache) if self.scene() is not None: self.currentPopup.installSceneEventFilter(self) elif self.scene() is not None: self.currentPopup.removeSceneEventFilter(self) self.currentPopup = None elif self.currentPopup is not None and change == self.ItemSceneHasChanged: self.currentPopup.installSceneEventFilter(self) return super(CustomProxy, self).itemChange(change, value) def updateStep(self, step): r = self.boundingRect() self.setTransform(QTransform() \ .translate(r.width() / 2, r.height() / 2)\ .rotate(step * 30, Qt.XAxis)\ .rotate(step * 10, Qt.YAxis)\ .rotate(step * 5, Qt.ZAxis)\ .scale(1 + 1.5 * step, 1 + 1.5 * step)\ .translate(-r.width() / 2, -r.height() / 2)) def stateChanged(self, state): if state == QTimeLine.Running: if self.timeLine.direction() == QTimeLine.Forward: self.setCacheMode(self.NoCache) elif state == QTimeLine.NotRunning: if self.timeLine.direction() == QTimeLine.Backward: self.setCacheMode(self.DeviceCoordinateCache) def zoomIn(self): if self.timeLine.direction() != QTimeLine.Forward: self.timeLine.setDirection(QTimeLine.Forward) if self.timeLine.state() == QTimeLine.NotRunning: self.timeLine.start() def zoomOut(self): if self.timeLine.direction() != QTimeLine.Backward: self.timeLine.setDirection(QTimeLine.Backward) if self.timeLine.state() == QTimeLine.NotRunning: self.timeLine.start()
class CustomProxy(QGraphicsProxyWidget): def __init__(self, parent=None, wFlags=0): super(CustomProxy, self).__init__(parent, wFlags) self.popupShown = False self.currentPopup = None self.timeLine = QTimeLine(250, self) self.timeLine.valueChanged.connect(self.updateStep) self.timeLine.stateChanged.connect(self.stateChanged) def boundingRect(self): return QGraphicsProxyWidget.boundingRect(self).adjusted(0, 0, 10, 10) def paintWindowFrame(self, painter, option, widget): color = QColor(0, 0, 0, 64) r = self.windowFrameRect() right = QRectF(r.right(), r.top()+10, 10, r.height()-10) bottom = QRectF(r.left()+10, r.bottom(), r.width(), 10) intersectsRight = right.intersects(option.exposedRect) intersectsBottom = bottom.intersects(option.exposedRect) if intersectsRight and intersectsBottom: path = QPainterPath() path.addRect(right) path.addRect(bottom) painter.setPen(Qt.NoPen) painter.setBrush(color) painter.drawPath(path) elif intersectsBottom: painter.fillRect(bottom, color) elif intersectsRight: painter.fillRect(right, color) super(CustomProxy, self).paintWindowFrame(painter, option, widget) def hoverEnterEvent(self, event): super(CustomProxy, self).hoverEnterEvent(event) self.scene().setActiveWindow(self) if self.timeLine.currentValue != 1: self.zoomIn() def hoverLeaveEvent(self, event): super(CustomProxy, self).hoverLeaveEvent(event) if not self.popupShown and (self.timeLine.direction() != QTimeLine.Backward or self.timeLine.currentValue() != 0): self.zoomOut() def sceneEventFilter(self, watched, event): if watched.isWindow() and (event.type() == QEvent.UngrabMouse or event.type() == QEvent.GrabMouse): self.popupShown = watched.isVisible() if not self.popupShown and not self.isUnderMouse(): self.zoomOut() return super(CustomProxy, self).sceneEventFilter(watched, event) def itemChange(self, change, value): if change == self.ItemChildAddedChange or change == self.ItemChildRemovedChange : if change == self.ItemChildAddedChange: self.currentPopup = value self.currentPopup.setCacheMode(self.ItemCoordinateCache) if self.scene() is not None: self.currentPopup.installSceneEventFilter(self) elif self.scene() is not None: self.currentPopup.removeSceneEventFilter(self) self.currentPopup = None elif self.currentPopup is not None and change == self.ItemSceneHasChanged: self.currentPopup.installSceneEventFilter(self) return super(CustomProxy, self).itemChange(change, value) def updateStep(self, step): r = self.boundingRect() self.setTransform(QTransform() \ .translate(r.width() / 2, r.height() / 2)\ .rotate(step * 30, Qt.XAxis)\ .rotate(step * 10, Qt.YAxis)\ .rotate(step * 5, Qt.ZAxis)\ .scale(1 + 1.5 * step, 1 + 1.5 * step)\ .translate(-r.width() / 2, -r.height() / 2)) def stateChanged(self, state): if state == QTimeLine.Running: if self.timeLine.direction() == QTimeLine.Forward: self.setCacheMode(self.NoCache) elif state == QTimeLine.NotRunning: if self.timeLine.direction() == QTimeLine.Backward: self.setCacheMode(self.DeviceCoordinateCache) def zoomIn(self): if self.timeLine.direction() != QTimeLine.Forward: self.timeLine.setDirection(QTimeLine.Forward) if self.timeLine.state() == QTimeLine.NotRunning: self.timeLine.start() def zoomOut(self): if self.timeLine.direction() != QTimeLine.Backward: self.timeLine.setDirection(QTimeLine.Backward) if self.timeLine.state() == QTimeLine.NotRunning: self.timeLine.start()
class SideSlideDecorator(QWidget): m_slidePos: QPoint m_slideWidgetPixmap: QPixmap m_timeline: QTimeLine m_backgroundPixmap: QPixmap m_decorationColor: QColor clicked = pyqtSignal() def __init__(self, *args, **kwargs): super(SideSlideDecorator, self).__init__(*args, **kwargs) self.resize(self.maximumSize()) self.m_backgroundPixmap = QPixmap() self.m_slidePos = QPoint() self.m_timeline = QTimeLine() self.m_timeline.setDuration(260) self.m_timeline.setUpdateInterval(40) self.m_timeline.setEasingCurve(QEasingCurve.OutQuad) self.m_timeline.setStartFrame(0) self.m_timeline.setEndFrame(10000) self.m_decorationColor = QColor(0, 0, 0, 0) def frameChanged(_value): self.m_decorationColor = QColor(0, 0, 0, _value / 100) self.update() self.m_timeline.frameChanged.connect(frameChanged) def grabSlideWidget(self, _slideWidget): self.m_slideWidgetPixmap = _slideWidget.grab() def grabParent(self): # self.m_backgroundPixmap = self.parentWidget().grab() pass def decorate(self, _dark): if self.m_timeline.state() == QTimeLine.Running: self.m_timeline.stop() self.m_timeline.setDirection( QTimeLine.Forward if _dark else QTimeLine.Backward) self.m_timeline.start() def slidePos(self): return self.m_slidePos def setSlidePos(self, _pos): if self.m_slidePos != _pos: self.m_slidePos = _pos self.update() def paintEvent(self, _event): painter = QPainter(self) painter.drawPixmap(0, 0, self.m_backgroundPixmap) painter.fillRect(self.rect(), self.m_decorationColor) painter.drawPixmap(self.m_slidePos, self.m_slideWidgetPixmap) super(SideSlideDecorator, self).paintEvent(_event) def mousePressEvent(self, _event): self.clicked.emit() super(SideSlideDecorator, self).mousePressEvent(_event) _slidePos = pyqtProperty(QPoint, fget=slidePos, fset=setSlidePos)
class E5AnimatedWidget(QWidget): """ Class implementing an animated widget. """ DirectionDown = 0 DirectionUp = 1 def __init__(self, direction=DirectionDown, duration=300, parent=None): """ Constructor @param direction direction of the animation @type int (one of DirectionDown or DirectionUp) @param duration duration of the animation @type int @param parent reference to the parent widget @type QWidget """ super(E5AnimatedWidget, self).__init__(parent) self.__direction = direction self.__stepHeight = 0.0 self.__stepY = 0.0 self.__startY = 0 self.__widget = QWidget(self) self.__timeline = QTimeLine(duration) self.__timeline.setFrameRange(0, 100) self.__timeline.frameChanged.connect(self.__animateFrame) self.setMaximumHeight(0) def widget(self): """ Public method to get a reference to the animated widget. @return reference to the animated widget @rtype QWidget """ return self.__widget @pyqtSlot() def startAnimation(self): """ Public slot to start the animation. """ if self.__timeline.state() == QTimeLine.Running: return shown = 0 hidden = 0 if self.__direction == self.DirectionDown: shown = 0 hidden = -self.__widget.height() self.__widget.move(QPoint(self.__widget.pos().x(), hidden)) self.__stepY = (hidden - shown) / 100.0 self.__startY = hidden self.__stepHeight = self.__widget.height() / 100.0 self.__timeline.setDirection(QTimeLine.Forward) self.__timeline.start() @pyqtSlot(int) def __animateFrame(self, frame): """ Private slot to animate the next frame. @param frame frame number @type int """ self.setFixedHeight(frame * self.__stepHeight) self.__widget.move(self.pos().x(), self.__startY - frame * self.__stepY) @pyqtSlot() def hide(self): """ Public slot to hide the animated widget. """ if self.__timeline.state() == QTimeLine.Running: return self.__timeline.setDirection(QTimeLine.Backward) self.__timeline.finished.connect(self.close) self.__timeline.start() p = self.parentWidget() if p is not None: p.setFocus() def resizeEvent(self, evt): """ Protected method to handle a resize event. @param evt reference to the event object @type QResizeEvent """ if evt.size().width() != self.__widget.width(): self.__widget.resize(evt.size().width(), self.__widget.height()) super(E5AnimatedWidget, self).resizeEvent(evt)
class Widget(QWidget, ScreenWidget): name = "accounts" def __init__(self): super(Widget, self).__init__() self.ui = Ui_SetupUsersWidget() self.ui.setupUi(self) self.edititemindex = None self.time_line = QTimeLine(400, self) self.time_line.setFrameRange(0, 220) self.time_line.frameChanged[int].connect(self.animate) self.ui.scrollArea.setFixedHeight(0) # User Icons self.normal_user_icon = QPixmap(":/gui/pics/users.png") self.super_user_icon = QPixmap(":/gui/pics/users.png") # Set disabled the create Button self.ui.createButton.setEnabled(False) # Connections self.ui.pass1.textChanged[str].connect(self.slotTextChanged) self.ui.pass2.textChanged[str].connect(self.slotTextChanged) self.ui.username.textChanged[str].connect(self.slotTextChanged) self.ui.realname.textChanged[str].connect(self.slotTextChanged) self.ui.username.textEdited[str].connect(self.slotUserNameChanged) self.ui.realname.textEdited[str].connect(self.slotRealNameChanged) self.ui.userID.valueChanged[int].connect(self.slotTextChanged) self.ui.userIDCheck.stateChanged[int].connect(self.slotuserIDCheck) self.ui.createButton.clicked.connect(self.slotCreateUser) self.ui.cancelButton.clicked.connect(self.resetWidgets) self.ui.deleteButton.clicked.connect(self.slotDeleteUser) self.ui.editButton.clicked.connect(self.slotEditUser) self.ui.addMoreUsers.clicked.connect(self.slotAdvanced) self.ui.userList.itemDoubleClicked[QListWidgetItem].connect(self.slotEditUser) self.ui.pass2.returnPressed.connect(self.slotReturnPressed) # focusInEvent is not a signal # self.ui.pass1.focusInEvent[QFocusEvent].connect(self.checkCapsLock) # self.ui.pass2.focusInEvent[QFocusEvent].connect(self.checkCapsLock) # self.ui.username.focusInEvent[QFocusEvent].connect(self.checkCapsLock) # self.ui.realname.focusInEvent[QFocusEvent].connect(self.checkCapsLock) ctx.installData.users = [] ctx.installData.autoLoginUser = None self.user_name_changed = False self.used_ids = [] def eventFilter(self, obj, event): if event.type() == QEvent.FocusIn: # even.type() ==... if obj == self.ui.pass1 or obj == self.ui.pass2 or \ obj == self.ui.username or obj == self.ui.realname: self.checkCapsLock() def shown(self): self.ui.cancelButton.hide() self.ui.realname.setFocus() if len(yali.users.PENDING_USERS) > 0 and self.ui.userList.count() == 0: for u in yali.users.PENDING_USERS: pix = self.normal_user_icon if "wheel" in u.groups: pix = self.super_user_icon UserItem(self.ui.userList, pix, user=u) self.ui.autoLogin.addItem(u.username) if len(yali.users.PENDING_USERS) == 1: self.slotEditUser(self.ui.userList.item(0)) elif len(yali.users.PENDING_USERS) > 1: self.ui.addMoreUsers.setChecked(True) self.checkUsers() self.checkCapsLock() def backCheck(self): self.refill() self.ui.cancelButton.hide() return True def refill(self): # reset and fill PENDING_USERS yali.users.reset_pending_users() for index in range(self.ui.userList.count()): user = self.ui.userList.item(index).getUser() ctx.installData.users.append(user) yali.users.PENDING_USERS.append(user) def execute(self): if self.checkUsers(): ctx.installData.autoLoginUser = str(self.ui.autoLogin.currentText()) if self.ui.createButton.text() == _("General", "Update"): return self.slotCreateUser() return True if not self.slotCreateUser(): ctx.mainScreen.step_increment = 0 return True self.refill() ctx.interface.informationWindow.hide() ctx.installData.autoLoginUser = str(self.ui.autoLogin.currentText()) return True def setCapsLockIcon(self, child): if type(child) == QLineEdit: if pardus.xorg.capslock.isOn(): child.setStyleSheet("""QLineEdit { background-image: url(:/gui/pics/caps.png); background-repeat: no-repeat; background-position: right; padding-right: 35px; }""") else: child.setStyleSheet("""QLineEdit { background-image: none; padding-right: 0px; }""") def checkCapsLock(self): for child in self.ui.groupBox.children(): self.setCapsLockIcon(child) for child in self.ui.groupBox_2.children(): self.setCapsLockIcon(child) def keyReleaseEvent(self, e): self.checkCapsLock() def showError(self, message): ctx.interface.informationWindow.update(message, type="error") ctx.mainScreen.disableNext() def animate(self, value): self.ui.scrollArea.setFixedHeight(int(value)) self.ui.frame.setMinimumHeight(250) if self.ui.scrollArea.height() == 0: self.ui.scrollArea.hide() else: self.ui.scrollArea.show() if self.ui.scrollArea.height() == 220: self.time_line.setDirection(1) self.ui.frame.setMinimumHeight(420) if self.ui.scrollArea.height() == 0: self.time_line.setDirection(0) def slotuserIDCheck(self, state): if state: self.ui.userID.setEnabled(True) else: self.ui.userID.setEnabled(False) def slotAdvanced(self): icon_path = None if self.ui.scrollArea.isVisible(): icon_path = ":/gui/pics/expand.png" self.time_line.start() else: self.ui.scrollArea.show() icon_path = ":/gui/pics/collapse.png" self.time_line.start() icon = QIcon() icon.addPixmap(QPixmap(icon_path), QIcon.Normal, QIcon.Off) self.ui.addMoreUsers.setIcon(icon) self.checkUsers() def slotTextChanged(self): username = str(self.ui.username.text()) realname = unicode(self.ui.realname.text()) password = unicode(self.ui.pass1.text()) password_confirm = unicode(self.ui.pass2.text()) if not password == '' and (password.lower() == username.lower() or password.lower() == realname.lower()): self.showError(_("General", 'Don\'t use your user name or name as a password')) return elif password_confirm != password and password_confirm: self.showError(_("General", 'Passwords do not match')) return elif len(password) == len(password_confirm) and len(password_confirm) < 4 and not password =='': self.showError(_("General", 'Password is too short')) return else: ctx.interface.informationWindow.hide() if self.ui.username.text() and password and password_confirm: self.ui.createButton.setEnabled(True) if not self.ui.addMoreUsers.isChecked(): ctx.mainScreen.enableNext() ctx.mainScreen.enableBack() else: self.ui.createButton.setEnabled(False) if not self.ui.addMoreUsers.isChecked(): ctx.mainScreen.disableNext() def currentUsers(self): users = [] for index in range(self.ui.userList.count()): users.append(self.ui.userList.item(index).getUser().username) return users def slotUserNameChanged(self): self.user_name_changed = True def slotRealNameChanged(self): if not self.user_name_changed: used_users = yali.users.get_users() used_users.extend(self.currentUsers()) self.ui.username.setText(yali.users.nick_guess(self.ui.realname.text(), used_users)) def slotCreateUser(self): user = yali.users.User() user.username = str(self.ui.username.text()) # ignore last character. see bug #887 user.realname = unicode(self.ui.realname.text()) user.passwd = unicode(self.ui.pass1.text()) user.groups = ["users", "pnp", "disk", "audio", "video", "power", "dialout", "lp", "lpadmin", "cdrom", "floppy"] pix = self.normal_user_icon if self.ui.admin.isChecked(): user.groups.append("wheel") pix = self.super_user_icon user.no_password = self.ui.noPass.isChecked() # check user validity if user.exists() or (user.username in self.currentUsers() and self.edititemindex == None): self.showError(_("General", "This user name is already taken, please choose another one.")) return False elif not user.usernameIsValid(): # FIXME: Mention about what are the invalid characters! self.showError(_("General", "The user name contains invalid characters.")) return False elif not user.realnameIsValid(): self.showError(_("General", "The real name contains invalid characters.")) return False # Dont check in edit mode if self.ui.addMoreUsers.isChecked() and self.ui.userIDCheck.isChecked(): uid = self.ui.userID.value() if self.edititemindex == None: if uid in self.used_ids: self.showError(_("General", 'User ID used before, choose another one!')) return False self.used_ids.append(uid) user.uid = uid self.ui.createButton.setText(_("General", "Add")) self.ui.cancelButton.hide() update_item = None try: self.ui.userList.takeItem(self.edititemindex) self.ui.autoLogin.removeItem(self.edititemindex + 1) except: update_item = self.edititemindex # nothing wrong. just adding a new user... pass item = UserItem(self.ui.userList, pix, user=user) # add user to auto-login list. self.ui.autoLogin.addItem(user.username) if update_item: self.ui.autoLogin.setCurrentIndex(self.ui.autoLogin.count()) # clear form self.resetWidgets() ctx.logger.debug("slotCreateUser :: user (%s) '%s (%s)' added/updated" % (user.uid, user.realname, user.username)) ctx.logger.debug("slotCreateUser :: user groups are %s" % str(','.join(user.groups))) # give focus to realname widget for a new user. #3280 #self.ui.realname.setFocus() self.checkUsers() self.user_name_changed = False self.refill() return True def slotDeleteUser(self): if self.ui.userList.currentRow() == self.edititemindex: self.resetWidgets() self.ui.autoLogin.setCurrentIndex(0) _cur = self.ui.userList.currentRow() item = self.ui.userList.item(_cur).getUser() if item.uid in self.used_ids: self.used_ids.remove(item.uid) self.ui.userList.takeItem(_cur) self.ui.autoLogin.removeItem(_cur + 1) self.ui.createButton.setText(_("General", "Add")) icon = QIcon() icon.addPixmap(QPixmap(":/gui/pics/user-group-new.png"), QIcon.Normal, QIcon.Off) self.ui.createButton.setIcon(icon) self.ui.cancelButton.hide() self.checkUsers() def slotEditUser(self, item=None): if not item: item = self.ui.userList.currentItem() self.ui.userList.setCurrentItem(item) user = item.getUser() if user.uid > -1: self.ui.userIDCheck.setChecked(True) self.ui.userID.setValue(user.uid) self.ui.username.setText(user.username) self.ui.realname.setText(user.realname) self.ui.pass1.setText(user.passwd) self.ui.pass2.setText(user.passwd) if "wheel" in user.groups: self.ui.admin.setChecked(True) else: self.ui.admin.setChecked(False) self.ui.noPass.setChecked(user.no_password) self.edititemindex = self.ui.userList.currentRow() self.ui.createButton.setText(_("General", "Update")) icon = QIcon() icon.addPixmap(QPixmap(":/gui/pics/tick.png"), QIcon.Normal, QIcon.Off) self.ui.createButton.setIcon(icon) self.ui.cancelButton.setVisible(self.ui.createButton.isVisible()) def checkUserFields(self): username = unicode(self.ui.username.text()) realname = unicode(self.ui.realname.text()) password = unicode(self.ui.pass1.text()) password_confirm = unicode(self.ui.pass2.text()) if username and realname and password and password_confirm and \ (password == password_confirm) and \ (password.lower() != username.lower() and password.lower() != realname.lower()): return True else: return False def checkUsers(self): if self.ui.userList.count() > 0: self.ui.userList.setCurrentRow(0) self.ui.deleteButton.setEnabled(True) self.ui.editButton.setEnabled(True) self.ui.autoLogin.setEnabled(True) ctx.mainScreen.enableNext() ctx.mainScreen.enableBack() return True else: if self.checkUserFields(): ctx.mainScreen.enableNext() else: ctx.mainScreen.disableNext() # there is no user in list so noting to delete self.ui.deleteButton.setEnabled(False) self.ui.editButton.setEnabled(False) self.ui.autoLogin.setEnabled(False) return False def resetWidgets(self): # clear all self.edititemindex = None self.ui.username.clear() self.ui.realname.clear() self.ui.pass1.clear() self.ui.pass2.clear() self.ui.admin.setChecked(False) self.ui.noPass.setChecked(False) self.ui.userIDCheck.setChecked(False) self.ui.createButton.setEnabled(False) if self.ui.cancelButton.isVisible(): self.ui.cancelButton.setHidden(self.sender() == self.ui.cancelButton) self.checkUsers() self.ui.createButton.setText(_("General", "Add")) icon = QIcon() icon.addPixmap(QPixmap(":/gui/pics/user-group-new.png"), QIcon.Normal, QIcon.Off) self.ui.createButton.setIcon(icon) def slotReturnPressed(self): if self.ui.createButton.isEnabled() and self.ui.addMoreUsers.isChecked(): self.slotCreateUser()