def hide(self): """ Hide the control """ QWidget.hide(self)
class PreprocessorModule(gui.OWComponent, QWidget): """The base widget for the pre-processing modules.""" change_signal = pyqtSignal() # Emitted when the settings are changed. title = NotImplemented attribute = NotImplemented methods = NotImplemented single_method = True toggle_enabled = True enabled = settings.Setting(True) disabled_value = None Layout = QGridLayout def __init__(self, master): QWidget.__init__(self) gui.OWComponent.__init__(self, master) self.master = master # Title bar. title_holder = QWidget() title_holder.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed) title_holder.setStyleSheet(""" .QWidget { background: qlineargradient( x1:0 y1:0, x2:0 y2:1, stop:0 #F8F8F8, stop:1 #C8C8C8); border-bottom: 1px solid #B3B3B3; } """) self.titleArea = QHBoxLayout() self.titleArea.setContentsMargins(10, 5, 10, 5) self.titleArea.setSpacing(0) title_holder.setLayout(self.titleArea) self.title_label = QLabel(self.title) self.title_label.mouseDoubleClickEvent = self.on_toggle self.title_label.setStyleSheet('font-size: 12px; border: 2px solid red;') self.titleArea.addWidget(self.title_label) self.off_label = QLabel('[disabled]') self.off_label.setStyleSheet('color: #B0B0B0; margin-left: 5px;') self.titleArea.addWidget(self.off_label) self.off_label.hide() self.titleArea.addStretch() # Root. self.rootArea = QVBoxLayout() self.rootArea.setContentsMargins(0, 0, 0, 0) self.rootArea.setSpacing(0) self.setLayout(self.rootArea) self.rootArea.addWidget(title_holder) self.contents = QWidget() contentArea = QVBoxLayout() contentArea.setContentsMargins(15, 10, 15, 10) self.contents.setLayout(contentArea) self.rootArea.addWidget(self.contents) self.method_layout = self.Layout() self.setup_method_layout() self.contents.layout().addLayout(self.method_layout) if self.toggle_enabled: self.on_off_button = OnOffButton(enabled=self.enabled) self.on_off_button.stateChanged.connect(self.on_toggle) self.on_off_button.setContentsMargins(0, 0, 0, 0) self.titleArea.addWidget(self.on_off_button) self.display_widget() @staticmethod def get_tooltip(method): return ' '.join([l.strip() for l in method.__doc__.split('\n')]).strip('.') \ if method.__doc__ else None @staticmethod def textify(text): return text.replace('&', '&&') @property def value(self): if self.enabled: return self.get_value() return self.disabled_value def setup_method_layout(self): raise NotImplementedError def on_toggle(self, event=None): # Activated when the widget is enabled/disabled. self.enabled = not self.enabled self.display_widget() self.update_value() def display_widget(self): if self.enabled: self.off_label.hide() self.contents.show() self.title_label.setStyleSheet('color: #000000;') else: self.off_label.show() self.contents.hide() self.title_label.setStyleSheet('color: #B0B0B0;') def get_value(self): raise NotImplemented def update_value(self): self.change_signal.emit()
class PreprocessorModule(gui.OWComponent, QWidget): """The base widget for the pre-processing modules.""" change_signal = pyqtSignal() # Emitted when the settings are changed. title = NotImplemented attribute = NotImplemented methods = NotImplemented single_method = True toggle_enabled = True enabled = settings.Setting(True) disabled_value = None Layout = QGridLayout def __init__(self, master): QWidget.__init__(self) gui.OWComponent.__init__(self, master) self.master = master # Title bar. title_holder = QWidget() title_holder.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed) title_holder.setStyleSheet(""" .QWidget { background: qlineargradient( x1:0 y1:0, x2:0 y2:1, stop:0 #F8F8F8, stop:1 #C8C8C8); border-bottom: 1px solid #B3B3B3; } """) self.titleArea = QHBoxLayout() self.titleArea.setContentsMargins(10, 5, 10, 5) self.titleArea.setSpacing(0) title_holder.setLayout(self.titleArea) self.title_label = QLabel(self.title) self.title_label.mouseDoubleClickEvent = self.on_toggle self.title_label.setStyleSheet( 'font-size: 12px; border: 2px solid red;') self.titleArea.addWidget(self.title_label) self.off_label = QLabel('[disabled]') self.off_label.setStyleSheet('color: #B0B0B0; margin-left: 5px;') self.titleArea.addWidget(self.off_label) self.off_label.hide() self.titleArea.addStretch() # Root. self.rootArea = QVBoxLayout() self.rootArea.setContentsMargins(0, 0, 0, 0) self.rootArea.setSpacing(0) self.setLayout(self.rootArea) self.rootArea.addWidget(title_holder) self.contents = QWidget() contentArea = QVBoxLayout() contentArea.setContentsMargins(15, 10, 15, 10) self.contents.setLayout(contentArea) self.rootArea.addWidget(self.contents) self.method_layout = self.Layout() self.setup_method_layout() self.contents.layout().addLayout(self.method_layout) if self.toggle_enabled: self.on_off_button = OnOffButton(enabled=self.enabled) self.on_off_button.stateChanged.connect(self.on_toggle) self.on_off_button.setContentsMargins(0, 0, 0, 0) self.titleArea.addWidget(self.on_off_button) self.display_widget() @staticmethod def get_tooltip(method): return ' '.join([l.strip() for l in method.__doc__.split('\n')]).strip('.') \ if method.__doc__ else None @staticmethod def textify(text): return text.replace('&', '&&') @property def value(self): if self.enabled: return self.get_value() return self.disabled_value def setup_method_layout(self): raise NotImplementedError def on_toggle(self, event=None): # Activated when the widget is enabled/disabled. self.enabled = not self.enabled self.display_widget() self.update_value() def display_widget(self): if self.enabled: self.off_label.hide() self.contents.show() self.title_label.setStyleSheet('color: #000000;') else: self.off_label.show() self.contents.hide() self.title_label.setStyleSheet('color: #B0B0B0;') def get_value(self): raise NotImplemented def update_value(self): self.change_signal.emit()
class Screenshot(QDialog): def __init__(self, parent=None): super().__init__(parent, Qt.CustomizeWindowHint | Qt.FramelessWindowHint | Qt.Window | Qt.WindowStaysOnTopHint | Qt.X11BypassWindowManagerHint) self.setAttribute(Qt.WA_DeleteOnClose) self.installEventFilter(self) self.setMouseTracking(True) self._band = QRubberBand(QRubberBand.Rectangle, self) self._resize_origin = None self._drag_mask = 0 self._origin = None self.selected_image = None # Window background desktop = QApplication.desktop() if is_qt5(): g = desktop.geometry() self._snapshot = QPixmap(g.width(), g.height()) painter = QPainter(self._snapshot) for screen in QApplication.screens(): g = screen.geometry() painter.drawPixmap(g, screen.grabWindow(0, g.x(), g.y(), g.width(), g.height())) painter.end() else: self._snapshot = QPixmap.grabWindow(desktop.winId(), 0, 0, desktop.width(), desktop.height()) self.setGeometry(desktop.geometry()) self._darken = self._snapshot.copy() painter = QPainter(self._darken) brush = QBrush(QColor(0, 0, 0, 128)) painter.setBrush(brush) painter.drawRect(self._darken.rect()) painter.end() # Buttons self._buttons = QWidget(self) self._button_layout = QHBoxLayout(self._buttons) self._button_layout.setSpacing(0) self._button_layout.setContentsMargins(0, 0, 0, 0) self._button_layout.setContentsMargins(0, 0, 0, 0) self.save_as = QPushButton(self.tr('Save As')) self.save_as.pressed.connect(self.save_image_as) self.save_as.setCursor(Qt.ArrowCursor) self._button_layout.addWidget(self.save_as) self.copy = QPushButton(self.tr('Copy')) self.copy.pressed.connect(self.copy_to_clipboard) self.copy.setCursor(Qt.ArrowCursor) self._button_layout.addWidget(self.copy) self.share = QPushButton(self.tr('Share')) self.share.pressed.connect(self.share_selection) self.share.setCursor(Qt.ArrowCursor) self._button_layout.addWidget(self.share) self._buttons.hide() def paintEvent(self, _): painter = QPainter(self) painter.drawPixmap(0, 0, self._darken) if self._band.isVisible(): br = self._band.geometry() r = QRect(br.topLeft(), br.bottomRight()) painter.drawPixmap(r, self._snapshot.copy(r)) def get_selection(self): return self._snapshot.copy(self._band.geometry()) def save_image_as(self): img = self.get_selection().toImage() if img.isNull(): QMessageBox.critical(self, self.tr('Error'), self.tr('No image was selected!')) return self.hide() formats = { self.tr('Portable Network Graphics (*.png)'): 'png', self.tr('Joint Photographic Experts Group (*.jpg *.jpeg)'): 'jpg', self.tr('Graphics Interchange Format (*.gif)'): 'gif', self.tr('Bitmap (*.bmp)'): 'bmp', self.tr('All Images (*.png *.jpg *.gif *.bmp)'): 'all' } file_format = None destination = QFileDialog.getSaveFileName(self, 'Save image', '', ';;'.join(formats.keys())) if isinstance(destination, tuple): destination, file_format = destination file_format = formats[file_format] if file_format == 'all': file_format = None if not file_format: file_format = destination.rsplit('.', 1)[-1] if destination: if file_format not in formats.values(): file_format = 'png' if not destination.endswith('.' + file_format): destination += '.' + file_format img.save(destination, file_format, 0 if file_format == 'png' else 90) self.reject() def copy_to_clipboard(self): img = self.get_selection() if img.isNull(): QMessageBox.critical(self, self.tr('Error'), self.tr('No image was selected!')) return QApplication.clipboard().setPixmap(img) self.reject() def share_selection(self): self.selected_image = self.get_selection() self.accept() def eventFilter(self, obj, e): if e.type() == QEvent.Enter: self.activateWindow() if e.type() == QEvent.KeyPress and e.key() == Qt.Key_Escape: self.reject() return True return super().eventFilter(obj, e) def mousePressEvent(self, event): if self.update_cursor_shape(event.pos(), event.button() == Qt.LeftButton): self._resize_origin = event.pos() else: self._origin = event.pos() if not self._band.isVisible(): self._band.setGeometry(QRect(self._origin, self._origin)) self._band.show() super().mousePressEvent(event) def mouseMoveEvent(self, event): p = event.pos() mouse_down = event.buttons() & Qt.LeftButton if mouse_down: m = self._drag_mask wr = self.rect() if m: g = self._band.geometry() d = p - self._resize_origin if d.x() or d.y(): if m == RESIZE_DRAG: g.translate(d) else: if m & RESIZE_LEFT: g.translate(d.x(), 0) g.setWidth(g.width() - d.x()) elif m & RESIZE_RIGHT: g.setWidth(g.width() + d.x()) if m & RESIZE_TOP: g.translate(0, d.y()) g.setHeight(g.height() - d.y()) elif m & RESIZE_BOTTOM: g.setHeight(g.height() + d.y()) self._resize_origin = p # Contain in the screen px = min(max(g.topLeft().x(), 0), wr.width() - g.width()) py = min(max(g.topLeft().y(), 0), wr.height() - g.height()) g.moveTo(px, py) else: g = QRect(self._origin, p).normalized() self._band.setGeometry(g) br = self._band.geometry() x = (br.width() / 2 - self._buttons.width() / 2) + br.left() # buttons at center of band x = max(0, min(x, wr.width() - self._buttons.width())) # prevent going off-screen if (wr.height() - br.bottom()) > self._buttons.height(): # if at bottom y = br.bottom() else: y = max(0, br.top() - self._buttons.height()) self._buttons.move(x, y) self._buttons.show() self.repaint() else: self.update_cursor_shape(p, mouse_down) self._drag_mask = self.get_drag_mask(p) super().mouseMoveEvent(event) def mouseReleaseEvent(self, event): self.update_cursor_shape(event.pos(), False) super().mouseReleaseEvent(event) def update_cursor_shape(self, p, mouse_down): m = self.get_drag_mask(p) if m == RESIZE_DRAG: self.setCursor(Qt.ClosedHandCursor if mouse_down else Qt.OpenHandCursor) elif (m & RESIZE_LEFT and m & RESIZE_TOP) or (m & RESIZE_RIGHT and m & RESIZE_BOTTOM): self.setCursor(Qt.SizeFDiagCursor) elif (m & RESIZE_LEFT and m & RESIZE_BOTTOM) or (m & RESIZE_RIGHT and m & RESIZE_TOP): self.setCursor(Qt.SizeBDiagCursor) elif m & RESIZE_LEFT or m & RESIZE_RIGHT: self.setCursor(Qt.SizeHorCursor) elif m & RESIZE_TOP or m & RESIZE_BOTTOM: self.setCursor(Qt.SizeVerCursor) else: self.setCursor(Qt.ArrowCursor) return False return True def get_drag_mask(self, p): br = self._band.geometry() if br.contains(p): def is_hovering(x): return 0 <= x <= 10 m = 0 m |= RESIZE_LEFT if is_hovering(p.x() - br.left()) else 0 m |= RESIZE_RIGHT if is_hovering(br.right() - p.x()) else 0 m |= RESIZE_BOTTOM if is_hovering(br.bottom() - p.y()) else 0 m |= RESIZE_TOP if is_hovering(p.y() - br.top()) else 0 if m: return m return RESIZE_DRAG return 0