def __init__(self, url, color): QWidget.__init__(self) self.setStyleSheet("background-color: black") self.file_name_font = QFont() self.file_name_font.setPointSize(24) self.file_name_label = QLabel(self) self.file_name_label.setText(url) self.file_name_label.setFont(self.file_name_font) self.file_name_label.setAlignment(Qt.AlignCenter) self.file_name_label.setStyleSheet("color: #eee") self.qrcode_label = QLabel(self) self.notify_font = QFont() self.notify_font.setPointSize(12) self.notify_label = QLabel(self) self.notify_label.setText("Scan above QR to copy information") self.notify_label.setFont(self.notify_font) self.notify_label.setAlignment(Qt.AlignCenter) self.notify_label.setStyleSheet("color: #eee") layout = QVBoxLayout(self) layout.setContentsMargins(0, 0, 0, 0) layout.addStretch() layout.addWidget(self.qrcode_label, 0, Qt.AlignCenter) layout.addSpacing(20) layout.addWidget(self.file_name_label, 0, Qt.AlignCenter) layout.addSpacing(40) layout.addWidget(self.notify_label, 0, Qt.AlignCenter) layout.addStretch() self.qrcode_label.setPixmap(qrcode.make(url, image_factory=Image).pixmap())
def __init__(self, parent = None): super(ItemContent, self).__init__(parent) layout = QVBoxLayout(self) layout.setContentsMargins(0, 0, 0, 20) layout.setSpacing(0) self.content = ItemVContent(self) layout.addWidget(self.content)
def __init__(self): super(MainWindow, self).__init__() widget = QWidget() self.setCentralWidget(widget) topFiller = QWidget() topFiller.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.infoLabel = QLabel( "<i>Choose a menu option, or right-click to invoke a context menu</i>", alignment=Qt.AlignCenter) self.infoLabel.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken) bottomFiller = QWidget() bottomFiller.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) vbox = QVBoxLayout() vbox.setContentsMargins(5, 5, 5, 5) vbox.addWidget(topFiller) vbox.addWidget(self.infoLabel) vbox.addWidget(bottomFiller) widget.setLayout(vbox) self.createActions() self.createMenus() message = "A context menu is available by right-clicking" self.statusBar().showMessage(message) self.setWindowTitle("Menus") self.setMinimumSize(160,160) self.resize(480,320)
def __init__(self, parent, cli_iface, iface_name): super(ControlPanelWindow, self).__init__(parent) self.setWindowTitle('SLCAN Adapter Control Panel') self.setAttribute(Qt.WA_DeleteOnClose) # This is required to stop background timers! self._cli_iface = cli_iface self._iface_name = iface_name self._state_widget = StateWidget(self, self._cli_iface) self._config_widget = ConfigWidget(self, self._cli_iface) self._cli_widget = CLIWidget(self, self._cli_iface) self._tab_widget = QTabWidget(self) self._tab_widget.addTab(self._state_widget, get_icon('dashboard'), 'Adapter State') self._tab_widget.addTab(self._config_widget, get_icon('wrench'), 'Configuration') self._tab_widget.addTab(self._cli_widget, get_icon('terminal'), 'Command Line') self._status_bar = QStatusBar(self) self._status_bar.setSizeGripEnabled(False) iface_name_label = QLabel(iface_name.split('/')[-1], self) iface_name_label.setFont(get_monospace_font()) layout = QVBoxLayout(self) layout.addWidget(iface_name_label) layout.addWidget(self._tab_widget) layout.addWidget(self._status_bar) left, top, right, bottom = layout.getContentsMargins() bottom = 0 layout.setContentsMargins(left, top, right, bottom) self.setLayout(layout) self.resize(400, 400)
def _close_group(self, main_layout, group_name, group_layout): """Closes the the existing group, used during controls creation """ debug_print('FormContainer._close_group close group', group_name) # The widget that holds this group's controls controls_widget = QWidget() controls_widget.setLayout(group_layout) if group_name: # Group controls start out hidden controls_widget.setVisible(False) # The group box, which contains the label to toggle the controls # and the controls themselves group_box_layout = QVBoxLayout() group_box_layout.addWidget(ToggleWidgetLabel( group_name, controls_widget, initially_visible=False )) group_box_layout.addWidget(controls_widget) group_box_layout.setContentsMargins( 0, # left 0, # top 0, # right 0 # bottom ) group_box = QGroupBox() group_box.setLayout(group_box_layout) # Add the group box to the main layout main_layout.addRow(group_box) else: # current group has no name and therefore no toggle group main_layout.addRow(controls_widget)
def initMainUi(self): role_names = self.parentApplet.dataSelectionApplet.topLevelOperator.DatasetRoles.value self.list_widgets = [] # Create a tab for each role for role_index, role_name in enumerate(role_names): select_button = QPushButton("Select " + role_name + " Files...", clicked=partial(self.select_files, role_index) ) clear_button = QPushButton("Clear " + role_name + " Files", clicked=partial(self.clear_files, role_index) ) button_layout = QHBoxLayout() button_layout.addWidget(select_button) button_layout.addSpacerItem( QSpacerItem(0,0,hPolicy=QSizePolicy.Expanding) ) button_layout.addWidget(clear_button) button_layout.setContentsMargins(0, 0, 0, 0) button_layout_widget = QWidget() button_layout_widget.setLayout(button_layout) button_layout_widget.setSizePolicy( QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Maximum) ) list_widget = QListWidget(parent=self) list_widget.setSizePolicy( QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) ) self.list_widgets.append( list_widget ) tab_layout = QVBoxLayout() tab_layout.setContentsMargins(0, 0, 0, 0) tab_layout.addWidget( button_layout_widget ) tab_layout.addWidget( list_widget ) layout_widget = QWidget(parent=self) layout_widget.setLayout(tab_layout) self.addTab(layout_widget, role_name)
class LeftPanel(FFrame): def __init__(self, app, parent=None): super().__init__(parent) self._app = app self.library_panel = LP_LibraryPanel(self._app) self.playlists_panel = LP_PlaylistsPanel(self._app) self._layout = QVBoxLayout(self) self.setLayout(self._layout) self.setObjectName('c_left_panel') self.set_theme_style() self.setup_ui() def set_theme_style(self): theme = self._app.theme_manager.current_theme style_str = ''' #{0} {{ background: transparent; }} '''.format(self.objectName(), theme.color5.name()) self.setStyleSheet(style_str) def setup_ui(self): self._layout.setContentsMargins(0, 0, 0, 0) self._layout.setSpacing(0) self._layout.addWidget(self.library_panel) self._layout.addWidget(self.playlists_panel) self._layout.addStretch(1)
def initUI(self): self.setWindowTitle('Twitter Client') self.setWindowIcon(QIcon("twitter.svg")) QIcon.setThemeName("Adwaita") lay = QVBoxLayout(self) scr = QScrollArea(self) scr.setWidgetResizable(True) scr.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) lay2 = QVBoxLayout() self.setLayout(lay) placehold = QWidget() lay.addWidget(scr) scr.setWidget(placehold) placehold.setLayout(lay2) self.lay = lay2 lay2.setSpacing(0) lay.setSpacing(0) lay.setContentsMargins(0, 0, 0, 0) but = QPushButton("Refresh") lay.addWidget(but) but.pressed.connect(self.fetch_tweets) self.show()
class RightPanel_Container(FScrollArea): def __init__(self, app, parent=None): super().__init__(parent) self._app = app self.right_panel = RightPanel(self._app) self._layout = QVBoxLayout(self) self.setWidget(self.right_panel) self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.setWidgetResizable(True) self.setObjectName('c_left_panel') self.set_theme_style() self.setup_ui() def set_theme_style(self): theme = self._app.theme_manager.current_theme style_str = ''' #{0} {{ background: transparent; border: 0px; }} '''.format(self.objectName(), theme.color5.name()) self.setStyleSheet(style_str) def setup_ui(self): self._layout.setContentsMargins(0, 0, 0, 0) self._layout.setSpacing(0)
def __init__(self, parent=None): super(LocatorWidget, self).__init__( parent, Qt.Dialog | Qt.FramelessWindowHint) self._parent = parent self.setModal(True) self.setAttribute(Qt.WA_TranslucentBackground) self.setStyleSheet("background:transparent;") self.setFixedHeight(400) self.setFixedWidth(500) view = QQuickWidget() view.rootContext().setContextProperty("theme", resources.QML_COLORS) view.setResizeMode(QQuickWidget.SizeRootObjectToView) view.setSource(ui_tools.get_qml_resource("Locator.qml")) self._root = view.rootObject() vbox = QVBoxLayout(self) vbox.setContentsMargins(0, 0, 0, 0) vbox.setSpacing(0) vbox.addWidget(view) self.locate_symbols = locator.LocateSymbolsThread() self.locate_symbols.finished.connect(self._cleanup) # FIXME: invalid signal # self.locate_symbols.terminated.connect(self._cleanup) # Hide locator with Escape key shortEscMisc = QShortcut(QKeySequence(Qt.Key_Escape), self) shortEscMisc.activated.connect(self.hide) # Locator things self.filterPrefix = re.compile(r'(@|<|>|-|!|\.|/|:)') self.page_items_step = 10 self._colors = { "@": "#5dade2", "<": "#4becc9", ">": "#ff555a", "-": "#66ff99", ".": "#a591c6", "/": "#f9d170", ":": "#18ffd6", "!": "#ff884d"} self._filters_list = [ ("@", "Filename"), ("<", "Class"), (">", "Function"), ("-", "Attribute"), (".", "Current"), ("/", "Opened"), (":", "Line"), ("!", "NoPython") ] self._replace_symbol_type = {"<": "<", ">": ">"} self.reset_values() self._filter_actions = { '.': self._filter_this_file, '/': self._filter_tabs, ':': self._filter_lines } self._root.textChanged['QString'].connect(self.set_prefix) self._root.open['QString', int].connect(self._open_item) self._root.fetchMore.connect(self._fetch_more)
class NavigationBar(QWidget): itemName = ['A', 'B', 'C', 'D', 'E'] def __init__(self, parent): super().__init__(parent) self.initUI() def initUI(self): self.setObjectName("naviBar") sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(1) sizePolicy.setHeightForWidth(self.sizePolicy().hasHeightForWidth()) self.setSizePolicy(sizePolicy) self.vboxList = QVBoxLayout(self) self.vboxList.setContentsMargins(0, 0, 0, 0) self.vboxList.setSpacing(6) self.initBtnList(self.vboxList) def initBtnList(self, vBox): for name in self.itemName: btn = QPushButton(name, self) vBox.addWidget(btn)
def __init__(self, parent, name): QWidget.__init__(self, parent) self.setStyleSheet(get_stylesheet("ribbonPane")) horizontal_layout = QHBoxLayout() horizontal_layout.setSpacing(0) horizontal_layout.setContentsMargins(0, 0, 0, 0) self.setLayout(horizontal_layout) vertical_widget = QWidget(self) horizontal_layout.addWidget(vertical_widget) horizontal_layout.addWidget(RibbonSeparator(self)) vertical_layout = QVBoxLayout() vertical_layout.setSpacing(0) vertical_layout.setContentsMargins(0, 0, 0, 0) vertical_widget.setLayout(vertical_layout) label = QLabel(name) label.setAlignment(Qt.AlignCenter) label.setStyleSheet("color:#666;") content_widget = QWidget(self) vertical_layout.addWidget(content_widget) vertical_layout.addWidget(label) content_layout = QHBoxLayout() content_layout.setAlignment(Qt.AlignLeft) content_layout.setSpacing(0) content_layout.setContentsMargins(0, 0, 0, 0) self.contentLayout = content_layout content_widget.setLayout(content_layout)
class ScheduleView(BaseView): def _setup(self): self._setupUi() self.sctable = ScheduleTable(model=self.model.table, view=self.tableView) self._setupColumns() # Can only be done after the model has been connected def _setupUi(self): self.resize(400, 300) self.verticalLayout = QVBoxLayout(self) self.verticalLayout.setContentsMargins(0, 0, 0, 0) self.tableView = TableView(self) self.tableView.setEditTriggers(QAbstractItemView.NoEditTriggers) self.tableView.setSelectionBehavior(QAbstractItemView.SelectRows) self.tableView.setSortingEnabled(True) self.tableView.horizontalHeader().setHighlightSections(False) self.tableView.horizontalHeader().setMinimumSectionSize(18) self.tableView.verticalHeader().setVisible(False) self.tableView.verticalHeader().setDefaultSectionSize(18) self.verticalLayout.addWidget(self.tableView) def _setupColumns(self): h = self.tableView.horizontalHeader() h.setSectionsMovable(True) # column drag & drop reorder # --- QWidget override def setFocus(self): self.sctable.view.setFocus() # --- Public def fitViewsForPrint(self, viewPrinter): viewPrinter.fitTable(self.sctable) # --- model --> view def get_panel_view(self, model): return SchedulePanel(model, self.mainwindow)
def __init__(self, parent=None): super(MDIHistory, self).__init__(parent) self.setMinimumSize(QSize(300, 200)) self.setWindowTitle("PyQt5 editor test example") lay = QVBoxLayout() lay.setContentsMargins(0,0,0,0) self.setLayout(lay) self.list = QListView() self.list.setEditTriggers(QListView.NoEditTriggers) self.list.activated.connect(self.activated) self.list.setAlternatingRowColors(True) self.list.selectionChanged = self.selectionChanged self.model = QStandardItemModel(self.list) self.MDILine = MDILine() self.MDILine.soft_keyboard = False self.MDILine.line_up = self.line_up self.MDILine.line_down = self.line_down # add widgets lay.addWidget(self.list) lay.addWidget(self.MDILine) self.reload()
def _get_control_layout(self): """ Create static layout. """ widget = QWidget() vbox = QVBoxLayout() widget.setLayout(vbox) vbox.setContentsMargins(0, 0, 0, 0) self.template_combo_box = QComboBox() self.template_combo_box.currentIndexChanged.connect(self._item_selected) vbox.addWidget(self.template_combo_box) scrollable_vbox = utils.get_scrollable(self.controls_layout) vbox.addWidget(scrollable_vbox, stretch=80) buttons_layout = QHBoxLayout() vbox.addLayout(buttons_layout, stretch=20) b = QPushButton("Назад") b.setObjectName("controls") b.clicked.connect(self._close) buttons_layout.addWidget(b) widget.setGraphicsEffect(utils.get_shadow()) return widget
class PluginUninstallDialog(QDialog): """ Class for the dialog variant. """ def __init__(self, pluginManager, parent=None): """ Constructor @param pluginManager reference to the plugin manager object @param parent reference to the parent widget (QWidget) """ super(PluginUninstallDialog, self).__init__(parent) self.setSizeGripEnabled(True) self.__layout = QVBoxLayout(self) self.__layout.setContentsMargins(0, 0, 0, 0) self.setLayout(self.__layout) self.cw = PluginUninstallWidget(pluginManager, self) size = self.cw.size() self.__layout.addWidget(self.cw) self.resize(size) self.setWindowTitle(self.cw.windowTitle()) self.cw.buttonBox.accepted.connect(self.accept) self.cw.buttonBox.rejected.connect(self.reject)
class GeneralLedgerView(BaseTransactionView): def _setup(self): self._setupUi() self.gltable = GeneralLedgerTable(model=self.model.gltable, view=self.tableView) self._setupColumns() # Can only be done after the model has been connected def _setupUi(self): self.resize(400, 300) self.verticalLayout = QVBoxLayout(self) self.verticalLayout.setContentsMargins(0, 0, 0, 0) self.tableView = TableView(self) self.tableView.setEditTriggers(QAbstractItemView.DoubleClicked|QAbstractItemView.EditKeyPressed) self.tableView.setSelectionBehavior(QAbstractItemView.SelectRows) self.tableView.setSortingEnabled(False) self.tableView.horizontalHeader().setHighlightSections(False) self.tableView.horizontalHeader().setMinimumSectionSize(18) self.tableView.verticalHeader().setVisible(False) self.tableView.verticalHeader().setDefaultSectionSize(18) self.verticalLayout.addWidget(self.tableView) def _setupColumns(self): h = self.tableView.horizontalHeader() h.setSectionsMovable(True) # column drag & drop reorder #--- QWidget override def setFocus(self): self.gltable.view.setFocus() #--- Public def fitViewsForPrint(self, viewPrinter): viewPrinter.fitTable(self.gltable)
def nestWidget(parent, child): l = QVBoxLayout() l.setContentsMargins(0,0,0,0) l.setSpacing(0) parent.setLayout(l) parent.layout().addWidget(child) return child
def __init__(self, parent=None): super(FilesHandler, self).__init__( None, Qt.FramelessWindowHint | Qt.Popup) self.setAttribute(Qt.WA_TranslucentBackground) self._main_container = parent # Create the QML user interface. self.setFixedHeight(300) self.setFixedWidth(400) self.view = QQuickWidget() self.view.rootContext().setContextProperty( "theme", resources.QML_COLORS) self.view.setResizeMode(QQuickWidget.SizeRootObjectToView) self.view.setSource(ui_tools.get_qml_resource("FilesHandler.qml")) # self.view.setClearColor(Qt.transparent) self._root = self.view.rootObject() vbox = QVBoxLayout(self) vbox.setContentsMargins(0, 0, 0, 0) vbox.setSpacing(0) vbox.addWidget(self.view) self._model = {} self._temp_files = {} self._max_index = 0 self._root.open.connect(self._open) self._root.close.connect(self._close) self._root.fuzzySearch.connect(self._fuzzy_search) self._root.hide.connect(self.hide)
def __init__(self, parent=None): super(MDIHistory, self).__init__(parent) self.setMinimumSize(QSize(200, 150)) self.setWindowTitle("PyQt5 editor test example") lay = QVBoxLayout() lay.setContentsMargins(0,0,0,0) self.setLayout(lay) self.list = QListView() self.list.setEditTriggers(QListView.NoEditTriggers) self.list.activated.connect(self.activated) self.list.setAlternatingRowColors(True) self.list.selectionChanged = self.selectionChanged self.model = QStandardItemModel(self.list) self.MDILine = MDILine() self.MDILine.soft_keyboard = False self.MDILine.line_up = self.line_up self.MDILine.line_down = self.line_down STATUS.connect('reload-mdi-history', self.reload) # add widgets lay.addWidget(self.list) lay.addWidget(self.MDILine) self.fp = os.path.expanduser(INFO.MDI_HISTORY_PATH) try: open(self.fp, 'r') except: open(self.fp, 'a+') LOG.debug('MDI History file created: {}'.format(self.fp)) self.reload() self.select_row('last')
class QCustomQWidget (QWidget): def __init__(self, parent=None): super(QCustomQWidget, self).__init__(parent) self.textQVBoxLayout = QVBoxLayout() self.textQVBoxLayout.setContentsMargins(0, 0, 0, 0) self.textQVBoxLayout.setSpacing(0) self.textUpQLabel = QLabel() self.textDownQLabel = QLabel() self.textQVBoxLayout.addWidget(self.textUpQLabel) self.textQVBoxLayout.addWidget(self.textDownQLabel) self.allQHBoxLayout = QHBoxLayout() self.allQHBoxLayout.setContentsMargins(0, 0, 0, 0) self.allQHBoxLayout.setSpacing(3) self.iconQLabel = QLabel() self.allQHBoxLayout.addWidget(self.iconQLabel, 0) self.allQHBoxLayout.addLayout(self.textQVBoxLayout, 1) self.setLayout(self.allQHBoxLayout) # setStyleSheet self.textUpQLabel.setStyleSheet('''color: rgb(0, 0, 255);''') self.textDownQLabel.setStyleSheet('''color: rgb(0, 0, 0);''') def setTextUp(self, text): self.textUpQLabel.setText(text) def setTextDown(self, text): self.textDownQLabel.setText(text) def setIcon(self, imagePath): self.iconQLabel.setPixmap(QPixmap(imagePath))
class EditorWidget(QFrame): def __init__(self, parent=None, text=None, EditorSidebarClass=EditorSidebar, EditorViewClass=EditorView): QFrame.__init__(self, parent) self.view = EditorViewClass(self, text) self.sidebar = EditorSidebarClass(self) self.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken) self.setLineWidth(2) self.vlayout = QVBoxLayout() self.vlayout.setSpacing(0) self.setLayout(self.vlayout) self.hlayout = QHBoxLayout() self.vlayout.addLayout(self.hlayout) self.hlayout.addWidget(self.sidebar) self.hlayout.addWidget(self.view) self.vlayout.setContentsMargins(2, 2, 2, 2) def setPlainText(self, text): self.view.document().setPlainText(text) self.view.setModified(False) def isModified(self): return self.view.document().isModified() def toPlainText(self): return unicode(self.view.document().toPlainText()) def setModified(self, flag): self.view.document().setModified(flag)
def __init__(self, parent=None): super(CentralWidget, self).__init__(parent) self.parent = parent main_container = QHBoxLayout(self) main_container.setContentsMargins(0, 0, 0, 0) main_container.setSpacing(0) # This variables are used to save the spliiter sizes self.lateral_panel = LateralPanel() self._add_functions = { "central": self._insert_widget_inside, "lateral": self._insert_widget_base } self._items = {} # Toolbar self._toolbar = ntoolbar.NToolBar(self) main_container.addWidget(self._toolbar) # Create Splitters to divide the UI 3 regions self._splitter_base = dynamic_splitter.DynamicSplitter(Qt.Horizontal) self._splitter_inside = dynamic_splitter.DynamicSplitter(Qt.Vertical) self._splitter_base.addWidget(self._splitter_inside) vbox = QVBoxLayout() vbox.setContentsMargins(0, 0, 0, 0) vbox.setSpacing(0) vbox.addWidget(self._splitter_base) tools_dock = IDE.get_service("tools_dock") vbox.addWidget(tools_dock.buttons_widget) main_container.addLayout(vbox) # main_container.addWidget(self._splitter_base) IDE.register_service("central_container", self)
class Col_select(QWidget): """Drop down element to select columns after a quantity was selected""" def __init__(self, columns, parent=None): super().__init__(parent) self.columns = columns self.checkboxes = [] self.initUI() def initUI(self): self.layout = QVBoxLayout() self.layout.setContentsMargins(30, 0, 0, 0) for column in self.columns: checkbox = QCheckBox() checkbox.setText(column) self.layout.addWidget(checkbox) self.checkboxes.append(checkbox) self.setLayout(self.layout) def get_selected(self): return [col for col, checkbox in zip(self.columns, self.checkboxes) if checkbox.isChecked()]
class LP_PlaylistsPanel(FFrame): def __init__(self, app, parent=None): super().__init__(parent) self._app = app self.header = LP_GroupHeader(self._app, '歌单') self._layout = QVBoxLayout(self) self.setObjectName('lp_playlists_panel') self.set_theme_style() self.setup_ui() def set_theme_style(self): theme = self._app.theme_manager.current_theme style_str = ''' #{0} {{ background: transparent; }} '''.format(self.objectName(), theme.color5.name()) self.setStyleSheet(style_str) def add_item(self, item): self._layout.addWidget(item) def setup_ui(self): self._layout.setContentsMargins(0, 0, 0, 0) self._layout.setSpacing(0) self._layout.addWidget(self.header)
class RightWidget(QWidget): def __init__(self, parent=None): super().__init__(parent) self.layout = QVBoxLayout() self.webview = MusicWidget() self.set_me() self.set_widgets_prop() self.set_layouts_prop() def set_me(self): self.setLayout(self.layout) def paintEvent(self, event): """ self is derived from QWidget, Stylesheets don't work unless \ paintEvent is reimplemented.y at the same time, if self is derived from QFrame, this isn't needed. """ option = QStyleOption() option.initFrom(self) painter = QPainter(self) style = self.style() style.drawPrimitive(QStyle.PE_Widget, option, painter, self) def set_widgets_prop(self): self.webview.setObjectName("webview") def set_layouts_prop(self): self.layout.setContentsMargins(0, 0, 0, 0) self.layout.setSpacing(0) self.layout.addWidget(self.webview)
def __init__(self, main_window, items): super().__init__() vbox = QVBoxLayout() vbox.setSpacing(0) vbox.setContentsMargins(0, 0, 0, 0) self.setLayout(vbox) top_system_buttons = TopSystemButtons(main_window) vbox.addWidget(top_system_buttons) vbox.addStretch() hbox = QHBoxLayout() hbox.addSpacing(25) hbox.setSpacing(0) hbox.setContentsMargins(0, 0, 0, 0) vbox.addLayout(hbox) l = QLabel() hbox.addWidget(l) vbox.addStretch() vbox.addWidget(SelectMenu(main_window, items)) main_window.communication.input_changed_signal.connect(l.setText) self.resizeEvent = functools.partial(main_window.resized, self, top_system_buttons) self.setGraphicsEffect(utils.get_shadow())
def __init__( self, parent, node, target_node_id, file_server_widget, node_monitor, dynamic_node_id_allocator_widget ): super(NodePropertiesWindow, self).__init__(parent) self.setAttribute(Qt.WA_DeleteOnClose) # This is required to stop background timers! self.setWindowTitle("Node Properties [%d]" % target_node_id) self.setMinimumWidth(640) self._target_node_id = target_node_id self._node = node self._file_server_widget = file_server_widget self._info_box = InfoBox(self, target_node_id, node_monitor) self._controls = Controls(self, node, target_node_id, file_server_widget, dynamic_node_id_allocator_widget) self._config_params = ConfigParams(self, node, target_node_id) self._status_bar = QStatusBar(self) self._status_bar.setSizeGripEnabled(False) layout = QVBoxLayout(self) layout.addWidget(self._info_box) layout.addWidget(self._controls) layout.addWidget(self._config_params) layout.addWidget(self._status_bar) left, top, right, bottom = layout.getContentsMargins() bottom = 0 layout.setContentsMargins(left, top, right, bottom) self.setLayout(layout)
class DocWindow(QWidget): app = None def __init__(self, app): super(DocWindow, self).__init__() DocWindow.app = app self.vlayout = QVBoxLayout() self.view = DocView() self.backbtn = QPushButton('Back') self.closebtn = QPushButton('Close') self.vlayout.setContentsMargins(1, 1, 1, 1) self.vlayout.setSpacing(1) self.vlayout.addWidget(self.view) hlayout = QHBoxLayout() buttonbox = QWidget() buttonbox.setLayout(hlayout) self.vlayout.addWidget(buttonbox) hlayout.addWidget(self.closebtn) hlayout.addWidget(self.backbtn) self.closebtn.clicked.connect(self.hide) self.backbtn.clicked.connect(self.view.back) self.setLayout(self.vlayout) self.setWindowTitle('BlueSky documentation') def show_cmd_doc(self, cmd): if not cmd: cmd = 'Command-Reference' self.view.load(QUrl.fromLocalFile(QFileInfo('data/html/' + cmd.lower() + '.html').absoluteFilePath()))
def __init__(self, parent=None): super(QueryContainer, self).__init__(parent) self._parent = parent box = QVBoxLayout(self) self.setObjectName("query_container") box.setContentsMargins(0, 0, 0, 0) box.setSpacing(0) # Regex for validate variable name self.__validName = re.compile(r'^[a-z_]\w*$') self.__nquery = 1 # Tab self._tabs = tab_widget.TabWidget() self._tabs.tabBar().setObjectName("tab_query") self._tabs.setAutoFillBackground(True) p = self._tabs.palette() p.setColor(p.Window, Qt.white) self._tabs.setPalette(p) box.addWidget(self._tabs) self.relations = {} self.__hide() # Connections self._tabs.tabCloseRequested.connect(self.__hide) self._tabs.saveEditor['PyQt_PyObject'].connect( self.__on_save_editor)
def __init__(self, parent=None): super(GcodeEditor, self).__init__(parent) self.load_dialog_code = 'LOAD' self.save_dialog_code = 'SAVE' STATUS.connect('general', self.returnFromDialog) self.isCaseSensitive = 0 self.setMinimumSize(QSize(300, 200)) self.setWindowTitle("PyQt5 editor test example") lay = QVBoxLayout() lay.setContentsMargins(0, 0, 0, 0) self.setLayout(lay) # make editor self.editor = GcodeDisplay(self) # class patch editor's function to ours # so we get the lines percent update self.editor.emit_percent = self.emit_percent self.editor.setReadOnly(True) self.editor.setModified(False) ################################ # add menubar actions ################################ # Create new action self.newAction = QAction(QIcon.fromTheme('document-new'), 'New', self) self.newAction.setShortcut('Ctrl+N') self.newAction.setStatusTip('New document') self.newAction.triggered.connect(self.newCall) # Create open action self.openAction = QAction(QIcon.fromTheme('document-open'), '&Open', self) self.openAction.setShortcut('Ctrl+O') self.openAction.setStatusTip('Open document') self.openAction.triggered.connect(self.openCall) # Create save action self.saveAction = QAction(QIcon.fromTheme('document-save'), '&Save', self) self.saveAction.setShortcut('Ctrl+S') self.saveAction.setStatusTip('Save document') self.saveAction.triggered.connect(self.saveCall) # Create exit action self.exitAction = QAction(QIcon.fromTheme('application-exit'), '&Exit', self) self.exitAction.setShortcut('Ctrl+Q') self.exitAction.setStatusTip('Exit application') self.exitAction.triggered.connect(self.exitCall) # Create gcode lexer action self.gCodeLexerAction = QAction(QIcon.fromTheme('lexer.png'), '&Gcode\nLexer', self) self.gCodeLexerAction.setCheckable(1) self.gCodeLexerAction.setShortcut('Ctrl+G') self.gCodeLexerAction.setStatusTip('Set Gcode highlighting') self.gCodeLexerAction.triggered.connect(self.gcodeLexerCall) # Create gcode lexer action self.pythonLexerAction = QAction(QIcon.fromTheme('lexer.png'), '&Python\nLexer', self) self.pythonLexerAction.setShortcut('Ctrl+P') self.pythonLexerAction.setStatusTip('Set Python highlighting') self.pythonLexerAction.triggered.connect(self.pythonLexerCall) # Create toolbar and add action self.toolBar = QToolBar('File') self.toolBar.addAction(self.newAction) self.toolBar.addAction(self.openAction) self.toolBar.addAction(self.saveAction) self.toolBar.addAction(self.exitAction) self.toolBar.addSeparator() # add lexer actions self.toolBar.addAction(self.gCodeLexerAction) self.toolBar.addAction(self.pythonLexerAction) self.toolBar.addSeparator() self.label = QLabel( '''<html><head/><body><p><span style=" font-size:20pt; font-weight:600;">Edit Mode</span></p></body></html>''' ) self.toolBar.addWidget(self.label) # create a frame for buttons box = QHBoxLayout() box.addWidget(self.toolBar) self.topMenu = QFrame() self.topMenu.setLayout(box) # add widgets lay.addWidget(self.topMenu) lay.addWidget(self.editor) lay.addWidget(self.createGroup()) self.readOnlyMode()
class App(QWidget): def __init__(self): super().__init__() self.title = 'Card selector' self.left = 10 self.top = 10 self.width = 420 self.height = 300 self.initUI() def initUI(self): self.setWindowTitle(self.title) self.setGeometry(self.left, self.top, self.width, self.height) self.setStyleSheet('background: white') self.scroll_layout = QVBoxLayout(self) self.scroll_layout.setContentsMargins(15, 15, 15, 15) self.scroll_layout.setSpacing(0) self.setLayout(self.scroll_layout) self.card_holder = CardHolder( self, self.getNewCard, self.collectCards ) self.card_holder.setBackgroundColor(QColor(Qt.yellow)) self.card_holder.setBorderWidth(10) self.card_holder.set_max_overlapped_cards(5) self.card_holder.set_y_coordinate_by_reverse_index_method(self.get_y_coordinate_by_reverse_index) self.card_holder.set_x_offset_by_index_method(self.get_x_offset_by_index) self.scroll_layout.addWidget(self.card_holder) next_button = QPushButton("next",self) next_button.clicked.connect(self.card_holder.button_animated_move_to_next) next_button.setFocusPolicy(Qt.NoFocus) previous_button = QPushButton("prev",self) previous_button.clicked.connect(self.card_holder.button_animated_move_to_previous) previous_button.setFocusPolicy(Qt.NoFocus) fill_up_button = QPushButton("fill up",self) fill_up_button.clicked.connect(self.fill_up) fill_up_button.setFocusPolicy(Qt.NoFocus) self.scroll_layout.addStretch(1) self.scroll_layout.addWidget(previous_button) self.scroll_layout.addWidget(next_button) self.scroll_layout.addWidget(fill_up_button) self.card_holder.setFocus() self.show() def change_spinner(self): self.card_holder.set_spinner(self.spinner_file_name) def fill_up(self): self.card_holder.startCardCollection([]) def collectCards(self, paths): """ """ cdl = [] cdl.append("Elso") cdl.append("Masodik") cdl.append("Harmadik") cdl.append("Negyedik") cdl.append("Otodik") cdl.append("Hatodik") cdl.append("Hetedik") cdl.append("Nyolcadik") cdl.append("Kilencedik") cdl.append("Tizedik") return cdl def getNewCard(self, card_data, local_index, index): """ """ card = Card(self.card_holder, card_data, local_index, index) card.setBorderFocusedColor(QColor(Qt.blue)) #card.setBackgroundColor(QColor(Qt.white)) #card.set_border_radius( 15 ) #card.setBorderWidth(18) panel = card.getPanel() layout = panel.getLayout() # Construct the Card # label=QLabel(card_data + "\n\n\n\n\n\n\n\n\n\nHello") # layout.addWidget(label) #layout.addWidget(QPushButton("hello")) myPanel = MyPanel(card) layout.addWidget(myPanel) return card def get_y_coordinate_by_reverse_index(self, reverse_index): """ """ return reverse_index * reverse_index * 16 def get_x_offset_by_index(self, index): """ """ return index * 4
class View(QWidget): trigger_focus_event = QtCore.pyqtSignal(str) def __init__(self, emacs_xid, buffer, view_info): super(View, self).__init__() self.buffer = buffer self.emacs_xid = emacs_xid # Init widget attributes. self.setWindowFlags(Qt.FramelessWindowHint) self.setAttribute(Qt.WA_X11DoNotAcceptFocus, True) self.setContentsMargins(0, 0, 0, 0) self.installEventFilter(self) # Init attributes. self.view_info = view_info (self.buffer_id, self.x, self.y, self.width, self.height) = view_info.split(":") self.x = int(self.x) self.y = int(self.y) self.width = int(self.width) self.height = int(self.height) # Build QGraphicsView. self.layout = QVBoxLayout(self) self.layout.setContentsMargins(0, 0, 0, 0) self.graphics_view = QGraphicsView(buffer, self) self.graphics_view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.graphics_view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.graphics_view.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform | QPainter.TextAntialiasing) # Remove damn border from QGraphicsView. self.graphics_view.setFrameStyle(0) self.graphics_view.setStyleSheet( "QGraphicsView {background: transparent; border: 3px; outline: none;}" ) self.layout.addWidget(self.graphics_view) # NOTE: show function must start before resize to trigger *first* resizeEvent after show. self.show() # Resize after show to trigger fit view operation. self.resize(self.width, self.height) def resizeEvent(self, event): # Fit content to view rect just when buffer fit_to_view option is enable. if self.buffer.fit_to_view: if event.oldSize().isValid(): self.graphics_view.fitInView( self.graphics_view.scene().sceneRect(), Qt.KeepAspectRatio) QWidget.resizeEvent(self, event) def eventFilter(self, obj, event): # Focus emacs buffer when user click view. if event.type() in [ QEvent.MouseButtonPress, QEvent.MouseButtonRelease, QEvent.MouseMove, QEvent.MouseButtonDblClick, QEvent.Wheel ]: # Send mouse event to applicatin view. self.trigger_focus_event.emit("{0},{1}".format( event.globalX(), event.globalY())) # Stop mouse event. return True return False def showEvent(self, event): # NOTE: we must reparent after widget show, otherwise reparent operation maybe failed. self.reparent() # Make graphics view at left-top corner after show. self.graphics_view.verticalScrollBar().setValue(0) self.graphics_view.horizontalScrollBar().setValue(0) def reparent(self): xlib_display = get_xlib_display() view_xid = self.winId().__int__() view_xwindow = xlib_display.create_resource_object("window", view_xid) emacs_xwindow = xlib_display.create_resource_object( "window", self.emacs_xid) view_xwindow.reparent(emacs_xwindow, self.x, self.y) xlib_display.sync() def handle_destroy(self): self.destroy()
class MainWindow(QWidget): """The main window of qutebrowser. Adds all needed components to a vbox, initializes subwidgets and connects signals. Attributes: status: The StatusBar widget. _downloadview: The DownloadView widget. _tabbed_browser: The TabbedBrowser widget. _vbox: The main QVBoxLayout. _commandrunner: The main CommandRunner instance. """ def __init__(self, win_id, parent=None): super().__init__(parent) self.setAttribute(Qt.WA_DeleteOnClose) self._commandrunner = None self.win_id = win_id self.registry = objreg.ObjectRegistry() objreg.window_registry[win_id] = self objreg.register('main-window', self, scope='window', window=win_id) tab_registry = objreg.ObjectRegistry() objreg.register('tab-registry', tab_registry, scope='window', window=win_id) message_bridge = message.MessageBridge(self) objreg.register('message-bridge', message_bridge, scope='window', window=win_id) self.setWindowTitle('qutebrowser') if win_id == 0: self._load_geometry() else: self._set_default_geometry() log.init.debug("Initial mainwindow geometry: {}".format( self.geometry())) self._vbox = QVBoxLayout(self) self._vbox.setContentsMargins(0, 0, 0, 0) self._vbox.setSpacing(0) log.init.debug("Initializing downloads...") download_manager = downloads.DownloadManager(win_id, self) objreg.register('download-manager', download_manager, scope='window', window=win_id) self._downloadview = downloadview.DownloadView(win_id) self._vbox.addWidget(self._downloadview) self._downloadview.show() self._tabbed_browser = tabbedbrowser.TabbedBrowser(win_id) objreg.register('tabbed-browser', self._tabbed_browser, scope='window', window=win_id) self._vbox.addWidget(self._tabbed_browser) self.status = bar.StatusBar(win_id) self._vbox.addWidget(self.status) self._completion = completionwidget.CompletionView(win_id, self) self._commandrunner = runners.CommandRunner(win_id) log.init.debug("Initializing search...") search_runner = runners.SearchRunner(self) objreg.register('search-runner', search_runner, scope='window', window=win_id) log.init.debug("Initializing modes...") modeman.init(self.win_id, self) self._connect_signals() QTimer.singleShot( 0, functools.partial(modeman.enter, win_id, usertypes.KeyMode.normal, 'init')) # When we're here the statusbar might not even really exist yet, so # resizing will fail. Therefore, we use singleShot QTimers to make sure # we defer this until everything else is initialized. QTimer.singleShot(0, self._connect_resize_completion) objreg.get('config').changed.connect(self.on_config_changed) #self.retranslateUi(MainWindow) #self.tabWidget.setCurrentIndex(0) #QtCore.QMetaObject.connectSlotsByName(MainWindow) def __repr__(self): return utils.get_repr(self) @pyqtSlot(str, str) def on_config_changed(self, section, option): """Resize the completion if related config options changed.""" if section == 'completion' and option in ('height', 'shrink'): self.resize_completion() @classmethod def spawn(cls, show=True): """Create a new main window. Args: show: Show the window after creating. Return: The new window id. """ win_id = next(win_id_gen) win = MainWindow(win_id) if show: win.show() return win_id def _load_geometry(self): """Load the geometry from the state file.""" state_config = objreg.get('state-config') try: data = state_config['geometry']['mainwindow'] log.init.debug("Restoring mainwindow from {}".format(data)) geom = base64.b64decode(data, validate=True) except KeyError: # First start self._set_default_geometry() except binascii.Error: log.init.exception("Error while reading geometry") self._set_default_geometry() else: try: ok = self.restoreGeometry(geom) except KeyError: log.init.exception("Error while restoring geometry.") self._set_default_geometry() if not ok: log.init.warning("Error while restoring geometry.") self._set_default_geometry() def _connect_resize_completion(self): """Connect the resize_completion signal and resize it once.""" self._completion.resize_completion.connect(self.resize_completion) self.resize_completion() def _set_default_geometry(self): """Set some sensible default geometry.""" self.setGeometry(QRect(50, 50, 800, 600)) def _get_object(self, name): """Get an object for this window in the object registry.""" return objreg.get(name, scope='window', window=self.win_id) def _connect_signals(self): """Connect all mainwindow signals.""" # pylint: disable=too-many-locals,too-many-statements key_config = objreg.get('key-config') status = self._get_object('statusbar') keyparsers = self._get_object('keyparsers') completion_obj = self._get_object('completion') tabs = self._get_object('tabbed-browser') cmd = self._get_object('status-command') completer = self._get_object('completer') search_runner = self._get_object('search-runner') message_bridge = self._get_object('message-bridge') mode_manager = self._get_object('mode-manager') prompter = self._get_object('prompter') # misc self._tabbed_browser.close_window.connect(self.close) mode_manager.entered.connect(hints.on_mode_entered) # status bar mode_manager.entered.connect(status.on_mode_entered) mode_manager.left.connect(status.on_mode_left) mode_manager.left.connect(cmd.on_mode_left) mode_manager.left.connect(prompter.on_mode_left) # commands keyparsers[usertypes.KeyMode.normal].keystring_updated.connect( status.keystring.setText) cmd.got_cmd.connect(self._commandrunner.run_safely) cmd.got_search.connect(search_runner.search) cmd.got_search_rev.connect(search_runner.search_rev) cmd.returnPressed.connect(tabs.on_cmd_return_pressed) search_runner.do_search.connect(tabs.search) tabs.got_cmd.connect(self._commandrunner.run_safely) # config for obj in keyparsers.values(): key_config.changed.connect(obj.on_keyconfig_changed) # messages message_bridge.s_error.connect(status.disp_error) message_bridge.s_info.connect(status.disp_temp_text) message_bridge.s_set_text.connect(status.set_text) message_bridge.s_maybe_reset_text.connect(status.txt.maybe_reset_text) message_bridge.s_set_cmd_text.connect(cmd.set_cmd_text) message_bridge.s_question.connect(prompter.ask_question, Qt.DirectConnection) # statusbar # FIXME some of these probably only should be triggered on mainframe # loadStarted. # https://github.com/The-Compiler/qutebrowser/issues/112 tabs.current_tab_changed.connect(status.prog.on_tab_changed) tabs.cur_progress.connect(status.prog.setValue) tabs.cur_load_finished.connect(status.prog.hide) tabs.cur_load_started.connect(status.prog.on_load_started) tabs.current_tab_changed.connect(status.percentage.on_tab_changed) tabs.cur_scroll_perc_changed.connect(status.percentage.set_perc) tabs.current_tab_changed.connect(status.txt.on_tab_changed) tabs.cur_statusbar_message.connect(status.txt.on_statusbar_message) tabs.cur_load_started.connect(status.txt.on_load_started) tabs.current_tab_changed.connect(status.url.on_tab_changed) tabs.cur_url_text_changed.connect(status.url.set_url) tabs.cur_link_hovered.connect(status.url.set_hover_url) tabs.cur_load_status_changed.connect(status.url.on_load_status_changed) # command input / completion mode_manager.left.connect(tabs.on_mode_left) cmd.clear_completion_selection.connect( completion_obj.on_clear_completion_selection) cmd.hide_completion.connect(completion_obj.hide) # quickmark completion quickmark_manager = objreg.get('quickmark-manager') quickmark_manager.changed.connect(completer.init_quickmark_completions) @pyqtSlot() def resize_completion(self): """Adjust completion according to config.""" # Get the configured height/percentage. confheight = str(config.get('completion', 'height')) if confheight.endswith('%'): perc = int(confheight.rstrip('%')) height = self.height() * perc / 100 else: height = int(confheight) # Shrink to content size if needed and shrinking is enabled if config.get('completion', 'shrink'): contents_height = ( self._completion.viewportSizeHint().height() + self._completion.horizontalScrollBar().sizeHint().height()) if contents_height <= height: height = contents_height else: contents_height = -1 # hpoint now would be the bottom-left edge of the widget if it was on # the top of the main window. topleft_y = self.height() - self.status.height() - height topleft_y = qtutils.check_overflow(topleft_y, 'int', fatal=False) topleft = QPoint(0, topleft_y) bottomright = self.status.geometry().topRight() rect = QRect(topleft, bottomright) if rect.isValid(): self._completion.setGeometry(rect) @cmdutils.register(instance='main-window', scope='window') @pyqtSlot() def close(self): """Close the current window. // Extend close() so we can register it as a command. """ super().close() @cmdutils.register(instance='main-window', scope='window') def fullscreen(self): """Toggle fullscreen mode.""" if self.isFullScreen(): self.showNormal() else: self.showFullScreen() def resizeEvent(self, e): """Extend resizewindow's resizeEvent to adjust completion. Args: e: The QResizeEvent """ super().resizeEvent(e) self.resize_completion() self._downloadview.updateGeometry() self._tabbed_browser.tabBar().refresh() def closeEvent(self, e): """Override closeEvent to display a confirmation if needed.""" confirm_quit = config.get('ui', 'confirm-quit') tab_count = self._tabbed_browser.count() download_manager = objreg.get('download-manager', scope='window', window=self.win_id) download_count = download_manager.rowCount() quit_texts = [] # Close if set to never ask for confirmation if 'never' in confirm_quit: pass # Ask if multiple-tabs are open if 'multiple-tabs' in confirm_quit and tab_count > 1: quit_texts.append("{} {} open.".format( tab_count, "tab is" if tab_count == 1 else "tabs are")) # Ask if multiple downloads running if 'downloads' in confirm_quit and download_count > 0: quit_texts.append("{} {} running.".format( tab_count, "download is" if tab_count == 1 else "downloads are")) # Process all quit messages that user must confirm if quit_texts or 'always' in confirm_quit: text = '\n'.join(['Really quit?'] + quit_texts) confirmed = message.ask(self.win_id, text, usertypes.PromptMode.yesno, default=True) # Stop asking if the user cancels if not confirmed: log.destroy.debug("Cancelling closing of window {}".format( self.win_id)) e.ignore() return e.accept() objreg.get('app').geometry = bytes(self.saveGeometry()) log.destroy.debug("Closing window {}".format(self.win_id)) self._tabbed_browser.shutdown()
class VideoTile(QWidget): hotkey_ctrl_down = False def __init__(self, parent, video, vid_id, clipboard, status_bar): QWidget.__init__(self, parent=parent) self.clipboard = clipboard self.status_bar = status_bar self.video = video self.id = vid_id self.parent = parent self.root = parent.root # MainWindow # parent.parent.parent.bind('<KeyPress-ctrl>', self.key_press_ctrl) # parent.parent.parent.bind('<KeyRelease-ctrl>', self.key_release_ctrl) self.pref_height = read_config('Gui', 'tile_pref_height') self.pref_width = read_config('Gui', 'tile_pref_width') self.setFixedSize(self.pref_width, self.pref_height) self.layout = QVBoxLayout() self.layout.setContentsMargins(0, 0, 0, 4) self.thumbnail_widget = self.init_thumbnailtile() self.layout.addWidget(self.thumbnail_widget) self.title_widget = TitleTile(video.title, self) self.layout.addWidget(self.title_widget) self.channel_widget = ChannelTile(video.channel_title, self) self.layout.addWidget(self.channel_widget) self.date_widget = DateTile('', self) self.layout.addWidget(self.date_widget) self.setLayout(self.layout) self.set_video(video) def init_thumbnailtile(self): raise ValueError( "ThumbnailTile initialised from VideoTile, not subclass!") def set_video(self, video): self.video = video self.set_tool_tip() self.title_widget.update_font() show_grab_method = read_config('Debug', 'show_grab_method') if show_grab_method: grab_method = '' grab_methods = video.grab_methods if len(grab_methods) > 0: grab_method = grab_methods[0] for grab in grab_methods[1:]: grab_method = '{}, {}'.format(grab_method, grab) self.channel_widget.setText("{} | {}".format( video.channel_title, grab_method)) else: self.channel_widget.setText(self.video.channel_title) vid_age = datetime.datetime.utcnow() - self.video.date_published self.date_widget.setText( self.strfdelta(vid_age, "{hours}:{minutes}:{seconds}", "{days} days ")) self.old_videos(vid_age) self.thumbnail_widget.setPixmap(QPixmap(video.thumbnail_path)) self.update() @staticmethod def strfdelta(tdelta, hours, days): d = {} d["hours"], rem = divmod(tdelta.seconds, 3600) d["minutes"], d["seconds"] = divmod(rem, 60) if int(tdelta.days) > 0: return_string = "{}{}".format(days.format(days=tdelta.days), hours.format(**d)) else: return_string = "{}".format(hours.format(**d)) return return_string def old_videos(self, vid_age): if read_config('Gui', 'grey_old_videos'): if vid_age > datetime.timedelta(days=1): pal = self.palette() pal.setColor(QPalette.Background, Qt.lightGray) self.setAutoFillBackground(True) self.setPalette(pal) else: pal = self.palette() pal.setColor(QPalette.Background, Qt.white) self.setAutoFillBackground(True) self.setPalette(pal) def set_tool_tip(self): if not read_config('Debug', 'disable_tooltips'): if read_config('Gui', 'tooltip_pictures'): text_element = read_config('Gui', 'tooltip_picture_size') thumb_width = read_config('Gui', 'tooltip_picture_width') thumb_height = read_config('Gui', 'tooltip_picture_height') resized_thumb = resize_thumbnail(self.video.thumbnail_path, thumb_width, thumb_height) self.setToolTip( "<{} style='text-align:center;'><img src={} style='float:below'>{}: {}</{}>" .format(text_element, resized_thumb, self.video.channel_title, self.video.title, text_element)) # if self.root.hotkey_ctrl_down: # print(self.root.hotkey_ctrl_down) # self.showTooltip() else: self.setToolTip("{}: {}".format(self.video.channel_title, self.video.title)) def copy_url(self): """ Copy selected video URL(s) to clipboard :return: """ self.clipboard.setText(self.video.url_video) self.status_bar.showMessage( 'Copied URL to clipboard: {} ({} - {})'.format( self.video.url_video, self.video.channel_title, self.video.title)) def mark_downloaded(self): """ Mark the video as downloaded :return: """ logger.info('Mark downloaded: {:2d}: {} {} - {}'.format( self.id, self.video.url_video, self.video.channel_title, self.video.title)) update_history('Downloaded:\t{}\t{} - {} '.format( self.video.url_video, self.video.channel_title, self.video.title)) self.video.downloaded = True self.video.date_downloaded = datetime.datetime.utcnow() self.parent.main_model.grid_view_listener.tileDownloaded.emit( self.video) if read_config('Gui', 'enable_auto_copy_to_clipboard'): self.copy_url() if read_config('Youtube-dl', 'use_youtube_dl'): self.status_bar.showMessage( 'Downloading video with youtube-dl: {} ({} - {})'.format( self.video.url_video, self.video.channel_title, self.video.title)) def mark_discarded(self): """ Mark the video as discarded :return: """ logger.info('Mark dismissed: {:2d}: {} {} - {}'.format( self.id, self.video.url_video, self.video.channel_title, self.video.title)) update_history('Dismissed:\t{}\t{} - {} '.format( self.video.url_video, self.video.channel_title, self.video.title)) self.video.discarded = True self.parent.main_model.grid_view_listener.tileDiscarded.emit( self.video) self.status_bar.showMessage('Dismissed: {} ({} - {})'.format( self.video.url_video, self.video.channel_title, self.video.title)) def mark_watched(self): """ Mark the video as downloaded :return: """ logger.debug('Mark watched: {:2d}: {} {} - {}'.format( self.id, self.video.url_video, self.video.channel_title, self.video.title)) update_history('Watched:\t{}\t{} - {} '.format( self.video.url_video, self.video.channel_title, self.video.title)) self.video.watched = True self.parent.main_model.grid_view_listener.tileWatched.emit(self.video) # Get the system clipboard contents def clipboard_changed(self): text = self.clipboard().text() logger.info(text) self.b.insertPlainText(text + '\n') def decrease_prio(self): self.parent.main_model.grid_view_listener.decreaseWatchPrio.emit( self.video)
def __init__(self, persepolis_setting): super().__init__() # MainWindow self.persepolis_setting = persepolis_setting icons = ':/' + \ str(self.persepolis_setting.value('settings/icons')) + '/' self.setWindowTitle("Persepolis Download Manager") self.setWindowIcon( QIcon.fromTheme('persepolis', QIcon(':/persepolis.svg'))) self.centralwidget = QWidget(self) self.verticalLayout = QVBoxLayout(self.centralwidget) # enable drag and drop self.setAcceptDrops(True) # frame self.frame = QFrame(self.centralwidget) # download_table_horizontalLayout download_table_horizontalLayout = QHBoxLayout() tabels_splitter = QSplitter(Qt.Horizontal) # category_tree self.category_tree_qwidget = QWidget(self) category_tree_verticalLayout = QVBoxLayout() self.category_tree = CategoryTreeView(self) category_tree_verticalLayout.addWidget(self.category_tree) self.category_tree_model = QStandardItemModel() self.category_tree.setModel(self.category_tree_model) category_table_header = ['Category'] self.category_tree_model.setHorizontalHeaderLabels( category_table_header) self.category_tree.header().setStretchLastSection(True) # queue_panel self.queue_panel_widget = QWidget(self) queue_panel_verticalLayout_main = QVBoxLayout(self.queue_panel_widget) # queue_panel_show_button self.queue_panel_show_button = QPushButton(self) queue_panel_verticalLayout_main.addWidget(self.queue_panel_show_button) # queue_panel_widget_frame self.queue_panel_widget_frame = QFrame(self) self.queue_panel_widget_frame.setFrameShape(QFrame.StyledPanel) self.queue_panel_widget_frame.setFrameShadow(QFrame.Raised) queue_panel_verticalLayout_main.addWidget( self.queue_panel_widget_frame) queue_panel_verticalLayout = QVBoxLayout(self.queue_panel_widget_frame) queue_panel_verticalLayout_main.setContentsMargins(50, -1, 50, -1) # start_end_frame self.start_end_frame = QFrame(self) # start time start_verticalLayout = QVBoxLayout(self.start_end_frame) self.start_checkBox = QCheckBox(self) start_verticalLayout.addWidget(self.start_checkBox) self.start_frame = QFrame(self) self.start_frame.setFrameShape(QFrame.StyledPanel) self.start_frame.setFrameShadow(QFrame.Raised) start_frame_verticalLayout = QVBoxLayout(self.start_frame) self.start_time_qDataTimeEdit = QDateTimeEdit(self.start_frame) self.start_time_qDataTimeEdit.setDisplayFormat('H:mm') start_frame_verticalLayout.addWidget(self.start_time_qDataTimeEdit) start_verticalLayout.addWidget(self.start_frame) # end time self.end_checkBox = QCheckBox(self) start_verticalLayout.addWidget(self.end_checkBox) self.end_frame = QFrame(self) self.end_frame.setFrameShape(QFrame.StyledPanel) self.end_frame.setFrameShadow(QFrame.Raised) end_frame_verticalLayout = QVBoxLayout(self.end_frame) self.end_time_qDateTimeEdit = QDateTimeEdit(self.end_frame) self.end_time_qDateTimeEdit.setDisplayFormat('H:mm') end_frame_verticalLayout.addWidget(self.end_time_qDateTimeEdit) start_verticalLayout.addWidget(self.end_frame) self.reverse_checkBox = QCheckBox(self) start_verticalLayout.addWidget(self.reverse_checkBox) queue_panel_verticalLayout.addWidget(self.start_end_frame) # limit_after_frame self.limit_after_frame = QFrame(self) # limit_checkBox limit_verticalLayout = QVBoxLayout(self.limit_after_frame) self.limit_checkBox = QCheckBox(self) limit_verticalLayout.addWidget(self.limit_checkBox) # limit_frame self.limit_frame = QFrame(self) self.limit_frame.setFrameShape(QFrame.StyledPanel) self.limit_frame.setFrameShadow(QFrame.Raised) limit_verticalLayout.addWidget(self.limit_frame) limit_frame_verticalLayout = QVBoxLayout(self.limit_frame) # limit_spinBox limit_frame_horizontalLayout = QHBoxLayout() self.limit_spinBox = QDoubleSpinBox(self) self.limit_spinBox.setMinimum(1) self.limit_spinBox.setMaximum(1023) limit_frame_horizontalLayout.addWidget(self.limit_spinBox) # limit_comboBox self.limit_comboBox = QComboBox(self) self.limit_comboBox.addItem("") self.limit_comboBox.addItem("") limit_frame_horizontalLayout.addWidget(self.limit_comboBox) limit_frame_verticalLayout.addLayout(limit_frame_horizontalLayout) # limit_pushButton self.limit_pushButton = QPushButton(self) limit_frame_verticalLayout.addWidget(self.limit_pushButton) # after_checkBox self.after_checkBox = QtWidgets.QCheckBox(self) limit_verticalLayout.addWidget(self.after_checkBox) # after_frame self.after_frame = QtWidgets.QFrame(self) self.after_frame.setFrameShape(QtWidgets.QFrame.StyledPanel) self.after_frame.setFrameShadow(QtWidgets.QFrame.Raised) limit_verticalLayout.addWidget(self.after_frame) after_frame_verticalLayout = QVBoxLayout(self.after_frame) # after_comboBox self.after_comboBox = QComboBox(self) self.after_comboBox.addItem("") after_frame_verticalLayout.addWidget(self.after_comboBox) # after_pushButton self.after_pushButton = QPushButton(self) after_frame_verticalLayout.addWidget(self.after_pushButton) queue_panel_verticalLayout.addWidget(self.limit_after_frame) category_tree_verticalLayout.addWidget(self.queue_panel_widget) # keep_awake_checkBox self.keep_awake_checkBox = QCheckBox(self) queue_panel_verticalLayout.addWidget(self.keep_awake_checkBox) self.category_tree_qwidget.setLayout(category_tree_verticalLayout) tabels_splitter.addWidget(self.category_tree_qwidget) # download table widget self.download_table_content_widget = QWidget(self) download_table_content_widget_verticalLayout = QVBoxLayout( self.download_table_content_widget) self.download_table = DownloadTableWidget(self) download_table_content_widget_verticalLayout.addWidget( self.download_table) tabels_splitter.addWidget(self.download_table_content_widget) self.download_table.setColumnCount(13) self.download_table.setSelectionBehavior(QAbstractItemView.SelectRows) self.download_table.setEditTriggers(QAbstractItemView.NoEditTriggers) self.download_table.verticalHeader().hide() # hide gid and download dictioanry section self.download_table.setColumnHidden(8, True) self.download_table.setColumnHidden(9, True) download_table_header = [ 'File Name', 'Status', 'Size', 'Downloaded', 'Percentage', 'Connections', 'Transfer rate', 'Estimate time left', 'Gid', 'Link', 'First try date', 'Last try date', 'Category' ] self.download_table.setHorizontalHeaderLabels(download_table_header) # fixing the size of download_table when window is Maximized! self.download_table.horizontalHeader().setSectionResizeMode(0) self.download_table.horizontalHeader().setStretchLastSection(True) tabels_splitter.setStretchFactor(0, 3) # category_tree width tabels_splitter.setStretchFactor(1, 10) # ratio of tables's width download_table_horizontalLayout.addWidget(tabels_splitter) self.frame.setLayout(download_table_horizontalLayout) self.verticalLayout.addWidget(self.frame) self.setCentralWidget(self.centralwidget) # menubar self.menubar = QMenuBar(self) self.menubar.setGeometry(QRect(0, 0, 600, 24)) self.setMenuBar(self.menubar) fileMenu = self.menubar.addMenu('&File') editMenu = self.menubar.addMenu('&Edit') viewMenu = self.menubar.addMenu('&View') downloadMenu = self.menubar.addMenu('&Download') queueMenu = self.menubar.addMenu('&Queue') videoFinderMenu = self.menubar.addMenu('&Video Finder') helpMenu = self.menubar.addMenu('&Help') # viewMenu submenus sortMenu = viewMenu.addMenu('Sort by') # statusbar self.statusbar = QStatusBar(self) self.setStatusBar(self.statusbar) self.statusbar.showMessage("Persepolis Download Manager") # toolBar self.toolBar2 = QToolBar(self) self.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar2) self.toolBar2.setWindowTitle('Menu') self.toolBar2.setFloatable(False) self.toolBar2.setMovable(False) self.toolBar = QToolBar(self) self.addToolBar(QtCore.Qt.TopToolBarArea, self.toolBar) self.toolBar.setWindowTitle('Toolbar') self.toolBar.setFloatable(False) self.toolBar.setMovable(False) #toolBar and menubar and actions self.youtubeAddLinkAction = QAction( QIcon(icons + 'video_finder'), 'Find Video Links', self, statusTip='Download video or audio from youtube and ...', triggered=self.showYoutubeAddLinkWindow) videoFinderMenu.addAction(self.youtubeAddLinkAction) self.stopAllAction = QAction(QIcon(icons + 'stop_all'), 'Stop all active downloads', self, statusTip='Stop all active downloads', triggered=self.stopAllDownloads) downloadMenu.addAction(self.stopAllAction) self.sort_file_name_Action = QAction('File name', self, triggered=self.sortByName) sortMenu.addAction(self.sort_file_name_Action) self.sort_file_size_Action = QAction('File size', self, triggered=self.sortBySize) sortMenu.addAction(self.sort_file_size_Action) self.sort_first_try_date_Action = QAction( 'First try date', self, triggered=self.sortByFirstTry) sortMenu.addAction(self.sort_first_try_date_Action) self.sort_last_try_date_Action = QAction('Last try date', self, triggered=self.sortByLastTry) sortMenu.addAction(self.sort_last_try_date_Action) self.sort_download_status_Action = QAction('Download status', self, triggered=self.sortByStatus) sortMenu.addAction(self.sort_download_status_Action) self.trayAction = QAction('Show system tray icon', self, statusTip="Show/Hide system tray icon", triggered=self.showTray) self.trayAction.setCheckable(True) viewMenu.addAction(self.trayAction) self.showMenuBarAction = QAction('Show menubar', self, statusTip='Show menubar', triggered=self.showMenuBar) self.showMenuBarAction.setCheckable(True) viewMenu.addAction(self.showMenuBarAction) self.showSidePanelAction = QAction('Show side panel', self, statusTip='Show side panel', triggered=self.showSidePanel) self.showSidePanelAction.setCheckable(True) viewMenu.addAction(self.showSidePanelAction) self.minimizeAction = QAction(QIcon(icons + 'minimize'), 'Minimize to system tray', self, shortcut="Ctrl+W", statusTip="Minimize to system tray", triggered=self.minMaxTray) viewMenu.addAction(self.minimizeAction) self.addlinkAction = QAction(QIcon(icons + 'add'), 'Add New Download Link', self, shortcut="Ctrl+N", statusTip="Add New Download Link", triggered=self.addLinkButtonPressed) fileMenu.addAction(self.addlinkAction) self.addtextfileAction = QAction( QIcon(icons + 'file'), 'Import links from text file', self, statusTip='Create a Text file and put links in it.line by line!', triggered=self.importText) fileMenu.addAction(self.addtextfileAction) self.resumeAction = QAction(QIcon(icons + 'play'), 'Resume Download', self, shortcut="Ctrl+R", statusTip="Resume Download", triggered=self.resumeButtonPressed) downloadMenu.addAction(self.resumeAction) self.pauseAction = QAction(QIcon(icons + 'pause'), 'Pause Download', self, shortcut="Ctrl+C", statusTip="Pause Download", triggered=self.pauseButtonPressed) downloadMenu.addAction(self.pauseAction) self.stopAction = QAction(QIcon(icons + 'stop'), 'Stop Download', self, shortcut="Ctrl+S", statusTip="Stop/Cancel Download", triggered=self.stopButtonPressed) downloadMenu.addAction(self.stopAction) self.propertiesAction = QAction(QIcon(icons + 'setting'), 'Properties', self, shortcut="Ctrl+P", statusTip="Properties", triggered=self.propertiesButtonPressed) downloadMenu.addAction(self.propertiesAction) self.progressAction = QAction(QIcon(icons + 'window'), 'Progress', self, shortcut="Ctrl+Z", statusTip="Progress", triggered=self.progressButtonPressed) downloadMenu.addAction(self.progressAction) self.openFileAction = QAction(QIcon(icons + 'file'), 'Open file', self, statusTip='Open file', triggered=self.openFile) fileMenu.addAction(self.openFileAction) self.openDownloadFolderAction = QAction( QIcon(icons + 'folder'), 'Open download folder', self, statusTip='Open download folder', triggered=self.openDownloadFolder) fileMenu.addAction(self.openDownloadFolderAction) self.openDefaultDownloadFolderAction = QAction( QIcon(icons + 'folder'), 'Open default download folder', self, statusTip='Open default download folder', triggered=self.openDefaultDownloadFolder) fileMenu.addAction(self.openDefaultDownloadFolderAction) self.exitAction = QAction(QIcon(icons + 'exit'), 'Exit', self, shortcut="Ctrl+Q", statusTip="Exit", triggered=self.closeEvent) fileMenu.addAction(self.exitAction) self.clearAction = QAction( QIcon(icons + 'multi_remove'), 'Clear download list', self, statusTip='Clear all items in download list', triggered=self.clearDownloadList) editMenu.addAction(self.clearAction) self.removeSelectedAction = QAction( QIcon(icons + 'remove'), 'Remove selected downloads form list', self, statusTip='Remove selected downloads form list', triggered=self.removeSelected) editMenu.addAction(self.removeSelectedAction) self.removeSelectedAction.setEnabled(False) self.deleteSelectedAction = QAction( QIcon(icons + 'trash'), 'Delete selected download files', self, statusTip='Delete selected download files', triggered=self.deleteSelected) editMenu.addAction(self.deleteSelectedAction) self.deleteSelectedAction.setEnabled(False) self.createQueueAction = QAction(QIcon(icons + 'add_queue'), 'Create new queue', self, statusTip='Create new download queue', triggered=self.createQueue) queueMenu.addAction(self.createQueueAction) self.removeQueueAction = QAction(QIcon(icons + 'remove_queue'), 'Remove this queue', self, statusTip='Remove this queue', triggered=self.removeQueue) queueMenu.addAction(self.removeQueueAction) self.startQueueAction = QAction(QIcon(icons + 'start_queue'), 'Start this queue', self, statusTip='Start this queue', triggered=self.startQueue) queueMenu.addAction(self.startQueueAction) self.stopQueueAction = QAction(QIcon(icons + 'stop_queue'), 'Stop this queue', self, statusTip='Stop this queue', triggered=self.stopQueue) queueMenu.addAction(self.stopQueueAction) self.moveUpSelectedAction = QAction( QIcon(icons + 'multi_up'), 'Move up selected items', self, statusTip='Move currently selected items up by one row', triggered=self.moveUpSelected) queueMenu.addAction(self.moveUpSelectedAction) self.moveDownSelectedAction = QAction( QIcon(icons + 'multi_down'), 'Move down selected items', self, statusTip='Move currently selected items down by one row', triggered=self.moveDownSelected) queueMenu.addAction(self.moveDownSelectedAction) self.preferencesAction = QAction(QIcon(icons + 'preferences'), 'Preferences', self, statusTip='Preferences', triggered=self.openPreferences, menuRole=5) editMenu.addAction(self.preferencesAction) self.aboutAction = QAction(QIcon(icons + 'about'), 'About', self, statusTip='About', triggered=self.openAbout, menuRole=4) helpMenu.addAction(self.aboutAction) self.issueAction = QAction(QIcon(icons + 'about'), 'Report an issue', self, statusTip='Report an issue', triggered=self.reportIssue) helpMenu.addAction(self.issueAction) self.updateAction = QAction(QIcon(icons + 'about'), 'Check for newer version', self, statusTip='Check for newer release', triggered=self.newUpdate) helpMenu.addAction(self.updateAction) self.logAction = QAction(QIcon(icons + 'about'), 'Show log file', self, statusTip='Help', triggered=self.showLog) helpMenu.addAction(self.logAction) self.helpAction = QAction(QIcon(icons + 'about'), 'Help', self, statusTip='Help', triggered=self.persepolisHelp) helpMenu.addAction(self.helpAction) self.qmenu = MenuWidget(self) self.toolBar2.addWidget(self.qmenu) # labels self.queue_panel_show_button.setText("Hide options") self.start_checkBox.setText("Start Time") self.end_checkBox.setText("End Time") self.reverse_checkBox.setText("Download bottom of\n the list first") self.limit_checkBox.setText("Limit Speed") self.limit_comboBox.setItemText(0, "KB/S") self.limit_comboBox.setItemText(1, "MB/S") self.limit_pushButton.setText("Apply") self.after_checkBox.setText("After download") self.after_comboBox.setItemText(0, "Shut Down") self.keep_awake_checkBox.setText("Keep system awake!") self.keep_awake_checkBox.setToolTip( "<html><head/><body><p>This option is preventing system from going to sleep.\ This is necessary if your power manager is suspending system automatically. </p></body></html>" ) self.after_pushButton.setText("Apply")
class FilterModal(QWidget): WANT_TO_CLOSE_SIGNAL = pyqtSignal() def __init__(self, pos, width, title, sort_mode, filter_mode, name_filter, parent=None): super(FilterModal, self).__init__(parent=parent) self.setWindowFlags(Qt.SplashScreen) self.setFocusPolicy(Qt.ClickFocus) self.setFocus() self.vbox = QVBoxLayout() self.bt_sorted_asc = QPushButton("Trier A -> Z") self.bt_sorted_dsc = QPushButton("Trier Z -> A") self.title = title self.name_filter = name_filter self.sort_mode = sort_mode self.filter_mode = filter_mode self.list_fiter = filter_store.dicts_filter[self.name_filter] self.setFixedWidth(width) self.move(pos) self.init_widget() self.show() def init_widget(self): self.vbox.setSpacing(5) self.vbox.setContentsMargins(1, 5, 1, 5) if self.sort_mode: if filter_store.sort_name == self.name_filter: if filter_store.sort_asc: self.bt_sorted_asc.setStyleSheet( button_no_radius_orange_stylesheet) self.bt_sorted_dsc.setStyleSheet( button_no_radius_stylesheet) else: self.bt_sorted_asc.setStyleSheet( button_no_radius_stylesheet) self.bt_sorted_dsc.setStyleSheet( button_no_radius_orange_stylesheet) else: self.bt_sorted_asc.setStyleSheet(button_no_radius_stylesheet) self.bt_sorted_dsc.setStyleSheet(button_no_radius_stylesheet) self.bt_sorted_asc.clicked.connect(self.on_click_bt_sorted_asc) self.bt_sorted_dsc.clicked.connect(self.on_click_bt_sorted_dsc) self.vbox.addWidget(self.bt_sorted_asc) self.vbox.addWidget(self.bt_sorted_dsc) if self.sort_mode and self.filter_mode: hbar = MondonWidget() hbar.setFixedHeight(2) hbar.set_background_color(color_gris_moyen) self.vbox.addWidget(hbar) if self.filter_mode: for value in self.list_fiter.keys(): text = value if self.name_filter == "code_perfo": text = "Perfo. " + chr( 96 + value).capitalize() if value != "Tous" else value self.vbox.addWidget( LineFilter(parent=None, value=value, text=text, name_filter=self.name_filter)) bt_ok = QPushButton("OK") bt_ok.setFixedWidth(40) bt_ok.setStyleSheet(button_14_stylesheet) bt_ok.clicked.connect(self.on_click_bt_ok) hbox = QHBoxLayout() hbox.addWidget(bt_ok) self.vbox.addLayout(hbox) self.setLayout(self.vbox) def update_widget(self): items = (self.vbox.itemAt(i) for i in range(self.vbox.count())) for item in items: if item.widget() and item.widget().objectName() == "LineFilter": item.widget().update_widget() def paintEvent(self, event): p = QPainter(self) color = color_blanc.rgb_components qcolor_blanc = QColor(color[0], color[1], color[2]) color = color_gris_moyen.rgb_components qcolor_gris = QColor(color[0], color[1], color[2]) pen = QPen() pen.setColor(qcolor_gris) p.setPen(pen) p.fillRect(0, 0, self.width(), self.height(), qcolor_blanc) p.drawRect(0, 0, self.width() - 1, self.height() - 1) def on_click_bt_ok(self): self.WANT_TO_CLOSE_SIGNAL.emit() def on_click_bt_sorted_asc(self): filter_store.set_sort_param(sort_name=self.name_filter, sort_asc=True) self.WANT_TO_CLOSE_SIGNAL.emit() def on_click_bt_sorted_dsc(self): filter_store.set_sort_param(sort_name=self.name_filter, sort_asc=False) self.WANT_TO_CLOSE_SIGNAL.emit() def focusOutEvent(self, e): self.WANT_TO_CLOSE_SIGNAL.emit()
class MainWindowUI(object): title = "Synspy Launcher" def __init__(self, MainWin): super(MainWindow).__init__() # Main Window MainWin.setObjectName("MainWindow") MainWin.setWindowTitle(MainWin.tr("%s %s (synspy: %s)" % (self.title, launcher_version, synspy_version))) MainWin.resize(800, 600) self.centralWidget = QWidget(MainWin) self.centralWidget.setObjectName("centralWidget") MainWin.setCentralWidget(self.centralWidget) self.verticalLayout = QVBoxLayout(self.centralWidget) self.verticalLayout.setContentsMargins(11, 11, 11, 11) self.verticalLayout.setSpacing(6) self.verticalLayout.setObjectName("verticalLayout") # Splitter for Worklist/Log self.splitter = QSplitter(Qt.Vertical) # Table View (Work list) self.workList = TableWidget(self.centralWidget) self.workList.setObjectName("tableWidget") self.workList.setStyleSheet( """ QTableWidget { border: 2px solid grey; border-radius: 5px; } """) self.workList.setEditTriggers(QAbstractItemView.NoEditTriggers) # use NoEditTriggers to disable editing self.workList.setAlternatingRowColors(True) self.workList.setSelectionBehavior(QAbstractItemView.SelectRows) self.workList.setSelectionMode(QAbstractItemView.SingleSelection) self.workList.verticalHeader().setDefaultSectionSize(18) # tighten up the row size self.workList.horizontalHeader().setStretchLastSection(True) # self.workList.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) self.workList.setSortingEnabled(True) # allow sorting self.workList.setContextMenuPolicy(Qt.ActionsContextMenu) self.workList.doubleClicked.connect(MainWin.on_actionLaunch_triggered) self.splitter.addWidget(self.workList) # Log Widget self.logTextBrowser = QPlainTextEditLogger(self.centralWidget) self.logTextBrowser.widget.setObjectName("logTextBrowser") self.logTextBrowser.widget.setStyleSheet( """ QPlainTextEdit { border: 2px solid grey; border-radius: 5px; background-color: lightgray; } """) self.splitter.addWidget(self.logTextBrowser.widget) # add splitter self.splitter.setSizes([600, 100]) self.verticalLayout.addWidget(self.splitter) # Actions # Launch self.actionLaunch = QAction(MainWin) self.actionLaunch.setObjectName("actionLaunch") self.actionLaunch.setText(MainWin.tr("Launch Analysis")) self.actionLaunch.setToolTip(MainWin.tr("Launch the synspy-viewer process")) self.actionLaunch.setShortcut(MainWin.tr("Ctrl+L")) # Refresh self.actionRefresh = QAction(MainWin) self.actionRefresh.setObjectName("actionRefresh") self.actionRefresh.setText(MainWin.tr("Refresh Work List")) self.actionRefresh.setToolTip(MainWin.tr("Refresh the work list")) self.actionRefresh.setShortcut(MainWin.tr("Ctrl+R")) # Options self.actionOptions = QAction(MainWin) self.actionOptions.setObjectName("actionOptions") self.actionOptions.setText(MainWin.tr("Options")) self.actionOptions.setToolTip(MainWin.tr("Configuration Options")) self.actionOptions.setShortcut(MainWin.tr("Ctrl+P")) # Login self.actionLogin = QAction(MainWin) self.actionLogin.setObjectName("actionLogin") self.actionLogin.setText(MainWin.tr("Login")) self.actionLogin.setToolTip(MainWin.tr("Login to the server")) self.actionLogin.setShortcut(MainWin.tr("Ctrl+G")) # Logout self.actionLogout = QAction(MainWin) self.actionLogout.setObjectName("actionLogout") self.actionLogout.setText(MainWin.tr("Logout")) self.actionLogout.setToolTip(MainWin.tr("Logout of the server")) self.actionLogout.setShortcut(MainWin.tr("Ctrl+O")) # Exit self.actionExit = QAction(MainWin) self.actionExit.setObjectName("actionExit") self.actionExit.setText(MainWin.tr("Exit")) self.actionExit.setToolTip(MainWin.tr("Exit the application")) self.actionExit.setShortcut(MainWin.tr("Ctrl+Z")) # Help self.actionHelp = QAction(MainWin) self.actionHelp.setObjectName("actionHelp") self.actionHelp.setText(MainWin.tr("Help")) self.actionHelp.setToolTip(MainWin.tr("Help")) self.actionHelp.setShortcut(MainWin.tr("Ctrl+H")) # Mark Incomplete self.markIncompleteAction = QAction('Mark Incomplete', self.workList) self.markIncompleteAction.triggered.connect(MainWin.markIncomplete) # Tool Bar self.mainToolBar = QToolBar(MainWin) self.mainToolBar.setObjectName("mainToolBar") self.mainToolBar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) MainWin.addToolBar(Qt.TopToolBarArea, self.mainToolBar) # Launch self.mainToolBar.addAction(self.actionLaunch) self.actionLaunch.setIcon(qApp.style().standardIcon(QStyle.SP_MediaPlay)) # Reload self.mainToolBar.addAction(self.actionRefresh) self.actionRefresh.setIcon(qApp.style().standardIcon(QStyle.SP_BrowserReload)) # Options self.mainToolBar.addAction(self.actionOptions) self.actionOptions.setIcon(qApp.style().standardIcon(QStyle.SP_FileDialogDetailedView)) # this spacer right justifies everything that comes after it spacer = QWidget() spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) self.mainToolBar.addWidget(spacer) # Login self.mainToolBar.addAction(self.actionLogin) self.actionLogin.setIcon(qApp.style().standardIcon(QStyle.SP_DialogApplyButton)) # Logout self.mainToolBar.addAction(self.actionLogout) self.actionLogout.setIcon(qApp.style().standardIcon(QStyle.SP_DialogOkButton)) # Help #self.mainToolBar.addAction(self.actionHelp) self.actionHelp.setIcon(qApp.style().standardIcon(QStyle.SP_MessageBoxQuestion)) # Exit self.mainToolBar.addAction(self.actionExit) self.actionExit.setIcon(qApp.style().standardIcon(QStyle.SP_DialogCancelButton)) # Status Bar self.statusBar = QStatusBar(MainWin) self.statusBar.setToolTip("") self.statusBar.setStatusTip("") self.statusBar.setObjectName("statusBar") MainWin.setStatusBar(self.statusBar) # finalize UI setup QMetaObject.connectSlotsByName(MainWin)
class Window(QtWidgets.QMainWindow): def __init__(self): super(Window, self).__init__() self.setWindowTitle("geheim") #self.setMinimumSize(1800, 450) def workerThread(foo, bar): fetchData() # self.greeting_text.startAnimation() self.updateInformation() #define timer self.timer = QTimer(self) #set intveral self.timer.setInterval(1000) self.timerCounter = 0 #define the slot for each timer tick @QtCore.pyqtSlot() def timerTick(): if recieved_calendar_data: #set the new time each second self.today_lbl.setText(currentTime()) #incr the counter self.timerCounter += 1 #if 108.000 seconds are gone we updatet the infromation (30min) if self.timerCounter == 10: _thread.start_new_thread(workerThread, ("None", "None")) self.timerCounter = 0 #connect the new slot to the timer timeout self.timer.timeout.connect(timerTick) #start the timer self.timer.start() #Fetch data the first time fetchData() #init the UI self.initUI() self.updateInformation() newPalette = self.palette() newPalette.setColor(QtGui.QPalette.Window, Qt.black) self.setPalette(newPalette) # self.showFullScreen() self.show() #FUNCTOIN FOR UI INITIALIZATION def initUI(self): QtGui.QFontDatabase.addApplicationFont("HelveticaNeue-UltraLight.ttf") QtGui.QFontDatabase.addApplicationFont("weathericons-regular-webfont.ttf") #Central Widget self.centWid = QtWidgets.QWidget(self) self.setCentralWidget(self.centWid) #Define main Vertical Layout self.vBox = QtWidgets.QVBoxLayout() #Define Upper hBox row self.upperHbox = QtWidgets.QHBoxLayout() #Define central hBox row self.centralHbox = QHBoxLayout() self.bottomHbox = QHBoxLayout() #Upper left widget self.upperLeftWid = QtWidgets.QWidget(self) #Upper right widget self.upperRightWid = QtWidgets.QWidget(self) #Upper middle widget self.upperMidWid = QtWidgets.QWidget(self) #Central middle widget self.centralMidWid = QtWidgets.QWidget(self) #bottom middle widget self.bottomMidWid = QtWidgets.QWidget(self) #------------------------------------------------------------------------------------------------------------ #-----------------Define Time and Calendar------------------------------------------------------------------- #------------------------------------------------------------------------------------------------------------ self.cal_row_vBox = QVBoxLayout() self.time_hBox = QHBoxLayout() self.today_lbl = QtWidgets.QLabel(self) self.tempToday = datetime.datetime.now() self.today_lbl.setText(currentTime()) self.today_lbl.setStyleSheet("font : 60px; font : bold; color : rgba(220, 220, 220, 250); font-family : HelveticaNeue-UltraLight") self.time_hBox.addWidget(self.today_lbl) if recieved_calendar_data: self.time_evnt_1_hbox = QHBoxLayout() self.time_evnt_1_date = QtWidgets.QLabel(self) self.time_evnt_1_evnt = QtWidgets.QLabel(self) self.time_evnt_1_date.setStyleSheet("font : 30px; color : rgba(220, 220, 220, 250); font-family : HelveticaNeue-UltraLight") self.time_evnt_1_evnt.setStyleSheet("font : 25px; font : bold; color : rgba(220, 220, 220, 250); font-family : HelveticaNeue-UltraLight") self.time_evnt_1_hbox.addWidget(self.time_evnt_1_date) self.time_evnt_1_hbox.addWidget(self.time_evnt_1_evnt) #--------------Second Row-------------- self.time_evnt_2_hbox = QHBoxLayout() self.time_evnt_2_date = QtWidgets.QLabel(self) self.time_evnt_2_evnt = QtWidgets.QLabel(self) self.time_evnt_2_date.setStyleSheet("font : 30px; color : rgba(220, 220, 220, 200); font-family : HelveticaNeue-UltraLight") self.time_evnt_2_evnt.setStyleSheet("font : 25px; font : bold; color : rgba(220, 220, 220, 200); font-family : HelveticaNeue-UltraLight") self.time_evnt_2_hbox.addWidget(self.time_evnt_2_date) self.time_evnt_2_hbox.addWidget(self.time_evnt_2_evnt) #--------------Third Row-------------- self.time_evnt_3_hbox = QHBoxLayout() self.time_evnt_3_date = QtWidgets.QLabel(self) self.time_evnt_3_evnt = QtWidgets.QLabel(self) self.time_evnt_3_date.setStyleSheet("font : 30px; color : rgba(220, 220, 220, 150); font-family : HelveticaNeue-UltraLight") self.time_evnt_3_evnt.setStyleSheet("font : 25px; font : bold; color : rgba(220, 220, 220, 150); font-family : HelveticaNeue-UltraLight") self.time_evnt_3_hbox.addWidget(self.time_evnt_3_date) self.time_evnt_3_hbox.addWidget(self.time_evnt_3_evnt) #--------------Fourth Row-------------- self.time_evnt_4_hbox = QHBoxLayout() self.time_evnt_4_date = QtWidgets.QLabel(self) self.time_evnt_4_evnt = QtWidgets.QLabel(self) self.time_evnt_4_date.setStyleSheet("font : 30px; color : rgba(220, 220, 220, 100); font-family : HelveticaNeue-UltraLight") self.time_evnt_4_evnt.setStyleSheet("font : 25px; font : bold; color : rgba(220, 220, 220, 100); font-family : HelveticaNeue-UltraLight") self.time_evnt_4_hbox.addWidget(self.time_evnt_4_date) self.time_evnt_4_hbox.addWidget(self.time_evnt_4_evnt) #Add all the rows and events and stuff self.cal_row_vBox.addLayout(self.time_hBox) self.cal_row_vBox.addLayout(self.time_evnt_1_hbox) self.cal_row_vBox.addLayout(self.time_evnt_2_hbox) self.cal_row_vBox.addLayout(self.time_evnt_3_hbox) self.cal_row_vBox.addLayout(self.time_evnt_4_hbox) self.cal_row_vBox.addStretch() else: self.fct_error = QtWidgets.QLabel() self.fct_error.setText("A http request error occured") self.fct_error.setStyleSheet("font : 30px; font : bold; color : rgba(250, 50, 50, 200); font-family : HelveticaNeue-UltraLight") self.cal_row_vBox.addWidget(self.fct_error) #Content margins (left, top, right, bottom) self.cal_row_vBox.setContentsMargins(30, 30, 0 , 0) self.upperLeftWid.setLayout(self.cal_row_vBox) #------------------------------------------------------------------------------------------------------------ #-----------------Define Weather forecast-------------------------------------------------------------------- #------------------------------------------------------------------------------------------------------------ self.fct_row_vBox = QVBoxLayout() if recieved_weather_data: #FIRST ROW (Todays forecast) currentDay = datetime.datetime.fromtimestamp(int(weatherForecast[0]['dt'])) self.fct_0_hBox = QHBoxLayout() #define text label0 self.fct_0_text0 = QtWidgets.QLabel(self) self.fct_0_text0.setStyleSheet("font : 80px; color : rgba(220, 220, 220, 250); font-family : HelveticaNeue-UltraLight") self.fct_0_text0.setText(weekdayToGerman(currentDay.weekday())) #define text label0 self.fct_0_text1 = QtWidgets.QLabel(self) self.fct_0_text1.setStyleSheet("font : 80px; color : rgba(220, 220, 220, 250); font-family : HelveticaNeue-UltraLight") #define icon label self.fct_0_icn = QtWidgets.QLabel(self) self.fct_0_icn.setPixmap(QtGui.QPixmap(str(weatherForecast[0]['weather'][0]['icon'] + ".png"))) #add widgets to layout first icon then text self.fct_0_hBox.addWidget(self.fct_0_icn) self.fct_0_hBox.addWidget(self.fct_0_text0) self.fct_0_hBox.addStretch() self.fct_0_hBox.addWidget(self.fct_0_text1) #--------------------------------------------- #Second ROW (next forecast) currentDay = datetime.datetime.fromtimestamp(int(weatherForecast[1]['dt'])) self.fct_1_hBox = QHBoxLayout() #define text label self.fct_1_text0 = QtWidgets.QLabel(self) self.fct_1_text0.setStyleSheet("font : 70px; color : rgba(220, 220, 220, 200); font-family : HelveticaNeue-UltraLight") self.fct_1_text0.setText(weekdayToGerman(currentDay.weekday())) #define text label self.fct_1_text1 = QtWidgets.QLabel(self) self.fct_1_text1.setStyleSheet("font : 70px; color : rgba(220, 220, 220, 200); font-family : HelveticaNeue-UltraLight") #define icon label self.fct_1_icn = QtWidgets.QLabel(self) self.fct_1_img = QtGui.QPixmap(str(weatherForecast[1]['weather'][0]['icon'] + ".png")).toImage() self.fct_1_img = setAlphaOfImg(self.fct_1_img, 200) self.fct_1_icn.setPixmap(QtGui.QPixmap.fromImage(self.fct_1_img)) #add widgets to layout first icon then text self.fct_1_spacer = QtWidgets.QSpacerItem(60, 0, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) self.fct_1_hBox.addItem(self.fct_1_spacer) self.fct_1_hBox.addWidget(self.fct_1_icn) self.fct_1_hBox.addWidget(self.fct_1_text0) self.fct_1_hBox.addStretch() self.fct_1_hBox.addWidget(self.fct_1_text1) #--------------------------------------------- #Third ROW (next forecast) currentDay = datetime.datetime.fromtimestamp(int(weatherForecast[2]['dt'])) self.fct_2_hBox = QHBoxLayout() #define text label self.fct_2_text0 = QtWidgets.QLabel(self) self.fct_2_text0.setStyleSheet("font : 70px; color : rgba(220, 220, 220, 150); font-family : HelveticaNeue-UltraLight") self.fct_2_text0.setText(weekdayToGerman(currentDay.weekday())) #define text label self.fct_2_text1 = QtWidgets.QLabel(self) self.fct_2_text1.setStyleSheet("font : 70px; color : rgba(220, 220, 220, 150); font-family : HelveticaNeue-UltraLight") #define icon label self.fct_2_icn = QtWidgets.QLabel(self) self.fct_2_img = QtGui.QPixmap(str(weatherForecast[3]['weather'][0]['icon'] + ".png")).toImage() self.fct_2_img = setAlphaOfImg(self.fct_2_img, 150) self.fct_2_icn.setPixmap(QtGui.QPixmap.fromImage(self.fct_2_img)) #add widgets to layout first icon then text self.fct_2_hBox.addItem(self.fct_1_spacer) self.fct_2_hBox.addWidget(self.fct_2_icn) self.fct_2_hBox.addWidget(self.fct_2_text0) self.fct_2_hBox.addStretch() self.fct_2_hBox.addWidget(self.fct_2_text1) #--------------------------------------------- #Fourth ROW (next forecast) currentDay = datetime.datetime.fromtimestamp(int(weatherForecast[3]['dt'])) self.fct_3_hBox = QHBoxLayout() #define text label self.fct_3_text0 = QtWidgets.QLabel(self) self.fct_3_text0.setStyleSheet("font : 70px; color : rgba(220, 220, 220, 100); font-family : HelveticaNeue-UltraLight") self.fct_3_text0.setText(weekdayToGerman(currentDay.weekday())) #define text label self.fct_3_text1 = QtWidgets.QLabel(self) self.fct_3_text1.setStyleSheet("font : 70px; color : rgba(220, 220, 220, 100); font-family : HelveticaNeue-UltraLight") #define icon label self.fct_3_icn = QtWidgets.QLabel(self) self.fct_3_img = QtGui.QPixmap(str(weatherForecast[3]['weather'][0]['icon'] + ".png")).toImage() self.fct_3_img = setAlphaOfImg(self.fct_3_img, 100) self.fct_3_icn.setPixmap(QtGui.QPixmap.fromImage(self.fct_3_img)) #add widgets to layout first icon then text self.fct_3_hBox.addItem(self.fct_1_spacer) self.fct_3_hBox.addWidget(self.fct_3_icn) self.fct_3_hBox.addWidget(self.fct_3_text0) self.fct_3_hBox.addStretch() self.fct_3_hBox.addWidget(self.fct_3_text1) self.fct_row_vBox.addLayout(self.fct_0_hBox) self.fct_row_vBox.addLayout(self.fct_1_hBox) self.fct_row_vBox.addLayout(self.fct_2_hBox) self.fct_row_vBox.addLayout(self.fct_3_hBox) #Http error occured show error else: self.fct_error = QtWidgets.QLabel(self) self.fct_error.setText("A http request error occured") self.fct_error.setStyleSheet("font : 30px; font : bold; color : rgba(250, 50, 50, 200); font-family : HelveticaNeue-UltraLight") self.fct_row_vBox.addWidget(self.fct_error) #Content margins(left, top, right, bottom) self.fct_row_vBox.setContentsMargins(0, 30, 30, 0) self.upperRightWid.setLayout(self.fct_row_vBox) #------------------------------------------------------------------------------------------------------------ #-----------------End weather forecast definition------------------------------------------------------------ #------------------------------------------------------------------------------------------------------------ #------------------------------------------------------------------------------------------------------------ #-----------------Define driving time components------------------------------------------------------------- #------------------------------------------------------------------------------------------------------------ #Rows layout manager self.trvl_vBox = QVBoxLayout() self.trvl_time_hBox = QHBoxLayout() self.trvl_inf_hBox = QHBoxLayout() self.trvl_time_text0 = QtWidgets.QLabel(self) self.trvl_time_text0.setStyleSheet("font : 30px; font : bold; color : rgba(220, 220, 220, 255); font-family : HelveticaNeue-UltraLight") #Check if http error occured if recieved_driving_data: self.trvl_time_text1 = QtWidgets.QLabel(self) self.trvl_time_text1.setStyleSheet("font : 30px; color : rgba(220, 220, 220, 255); font-family : HelveticaNeue-UltraLight") #Displays Minutes (2nd row) self.trvl_time_hBox.addStretch() self.trvl_time_hBox.addWidget(self.trvl_time_text1) self.trvl_time_hBox.addStretch() #error occured show error text else: self.trvl_error = QtWidgets.QLabel(self) self.trvl_error.setText("A http error occured") self.trvl_error.setStyleSheet("font : 30px; font : bold; color : rgba(250, 50, 50, 200); font-family : HelveticaNeue-UltraLight") self.trvl_time_hBox.addStretch() self.trvl_time_hBox.addWidget(self.trvl_error) self.trvl_time_hBox.addStretch() #Display text (1st row) self.trvl_inf_hBox.addStretch() self.trvl_inf_hBox.addWidget(self.trvl_time_text0) self.trvl_inf_hBox.addStretch() #Combines rows togehter self.trvl_vBox.addLayout(self.trvl_inf_hBox) self.trvl_vBox.addLayout(self.trvl_time_hBox) self.trvl_vBox.addStretch() #Content margins (left, top, right, bottom) self.trvl_vBox.setContentsMargins(0, 60, 0 , 0) self.upperMidWid.setLayout(self.trvl_vBox) #------------------------------------------------------------------------------------------------------------ #-----------------End driving time components definition----------------------------------------------------- #------------------------------------------------------------------------------------------------------------ #------------------------------------------------------------------------------------------------------------ #-----------------Start Rss feed compontents definition------------------------------------------------------ #------------------------------------------------------------------------------------------------------------ self.rss_vBox = QVBoxLayout() self.rss_text = QtWidgets.QLabel(self) self.rss_text.setStyleSheet("font : 30px; font : bold; color : rgba(220, 220, 220, 255); font-family : HelveticaNeue-UltraLight") self.rss_vBox.addWidget(self.rss_text) #content margins (left,top, right, bottom) self.rss_vBox.setContentsMargins(0, 0, 0, 60) self.bottomMidWid.setLayout(self.rss_vBox) #------------------------------------------------------------------------------------------------------------ #-----------------End Rss feed compontents definition------------------------------------------------------ #------------------------------------------------------------------------------------------------------------ #------------------------------------------------------------------------------------------------------------ #-----------------Start greeting compontents definition------------------------------------------------------ #------------------------------------------------------------------------------------------------------------ self.greeting_vBox = QVBoxLayout() self.greeting_text = AnimationLabel(greeting()) self.greeting_text.setStyleSheet("font : 45px; font : bold; color : rgba(220, 220, 220, 255); font-family : HelveticaNeue-UltraLight") self.greeting_vBox.addWidget(self.greeting_text) self.centralMidWid.setLayout(self.greeting_vBox) #Add left upper Corner self.upperHbox.addWidget(self.upperLeftWid) # #Stretch to middle and add middle self.upperHbox.addStretch() self.upperHbox.addWidget(self.upperMidWid) #Stretch to right corner and add Right corner self.upperHbox.addStretch() self.upperHbox.addWidget(self.upperRightWid) self.centralHbox.addStretch() self.centralHbox.addWidget(self.centralMidWid) self.centralHbox.addStretch() self.bottomHbox.addStretch() self.bottomHbox.addWidget(self.bottomMidWid) self.bottomHbox.addStretch() #Add Rows and Stretch self.vBox.addLayout(self.upperHbox) self.vBox.addStretch() self.vBox.addLayout(self.centralHbox) self.vBox.addStretch() self.vBox.addLayout(self.bottomHbox) #Set Layout of the central Widget and show that shit self.centWid.setLayout(self.vBox) #FUNCTION FOR UPDATING UI def updateInformation(self): #Travel information self.trvl_time_text0.setText("Fahrtzeit von Ergenzingen nach Tübingen") self.trvl_time_text1.setText(str(drivingInformation[0]) + " Minuten mit " + str(drivingInformation[1]) + " Minuten Verzögerung") #Weather information self.fct_3_text1.setText(str(weatherForecast[3]['main']['temp']) + "°C") self.fct_2_text1.setText(str(weatherForecast[2]['main']['temp']) + "°C") self.fct_1_text1.setText(str(weatherForecast[1]['main']['temp']) + "°C") self.fct_0_text1.setText(str(weatherForecast[0]['main']['temp']) + "°C") #Calendar Infromation if len(events) > 3: current_event = events[3] self.time_evnt_4_evnt.setText(process_Summary(current_event[1])) self.time_evnt_4_date.setText(weekdayToGerman(current_event[0].weekday()) + " " + str(current_event[0].day)+ "." + str(current_event[0].month) + "." + str(current_event[0].year)[2:4] +", " + str(current_event[0].hour) + ":" + process_Minute(current_event[0].minute) + " Uhr ") if len(events) > 2: current_event = events[2] self.time_evnt_3_evnt.setText(process_Summary(current_event[1])) self.time_evnt_3_date.setText(weekdayToGerman(current_event[0].weekday()) + " " + str(current_event[0].day)+ "." + str(current_event[0].month) + "." + str(current_event[0].year)[2:4] +", " + str(current_event[0].hour) + ":" + process_Minute(current_event[0].minute) + " Uhr ") if len(events) > 1: current_event = events[1] self.time_evnt_2_evnt.setText(process_Summary(current_event[1])) self.time_evnt_2_date.setText(weekdayToGerman(current_event[0].weekday()) + " " + str(current_event[0].day)+ "." + str(current_event[0].month) + "." + str(current_event[0].year)[2:4] +", " + str(current_event[0].hour) + ":" + process_Minute(current_event[0].minute) + " Uhr ") if len(events): current_event = events[0] self.time_evnt_1_evnt.setText(process_Summary(current_event[1])) self.time_evnt_1_date.setText(weekdayToGerman(current_event[0].weekday()) + " " + str(current_event[0].day)+ "." + str(current_event[0].month) + "." + str(current_event[0].year)[2:4] +", " + str(current_event[0].hour) + ":" + process_Minute(current_event[0].minute) + " Uhr ") #News feed self.rss_text.setText(feedparser.parse("https://www.theguardian.com/world/rss")["entries"][0]["title"]) #Greeting self.greeting_text.setText(greeting()) print("Information on GUI is Updatet") print("")
class CameraViewWidget(QWidget): """A widget to show images from a frame source and display the camera controls. Parameters ---------- Returns ------- """ def __init__(self, *args, experiment=None, **kwargs): """ :param experiment: experiment to which this belongs (:class:Experiment <stytra.Experiment> object) """ super().__init__(*args, **kwargs) self.experiment = experiment if experiment is not None: self.camera = experiment.camera experiment.gui_timer.timeout.connect(self.retrieve_image) else: self.gui_timer = QTimer() self.gui_timer.setSingleShot(False) self.control_params = self.experiment.camera_state # Create the layout for the camera view: self.camera_display_widget = pg.GraphicsLayoutWidget() # Display area for showing the camera image: self.display_area = pg.ViewBox(lockAspect=1, invertY=False) self.display_area.setRange(QRectF(0, 0, 640, 480), update=True, disableAutoRange=True) self.scale = 640 self.display_area.invertY(True) # Image to which the frame will be set, initially black: self.image_item = pg.ImageItem() self.image_item.setImage(np.zeros((640, 480), dtype=np.uint8)) self.display_area.addItem(self.image_item) self.camera_display_widget.addItem(self.display_area) # Queue of frames coming from the camera if hasattr(experiment, "frame_dispatcher"): self.frame_queue = self.experiment.frame_dispatcher.gui_queue else: self.frame_queue = self.camera.frame_queue # Queue of control parameters for the camera: self.control_queue = self.camera.control_queue self.camera_rotation = self.camera.rotation self.layout = QVBoxLayout() self.layout.setContentsMargins(0, 0, 0, 0) self.layout.addWidget(self.camera_display_widget) self.layout_control = QHBoxLayout() self.layout_control.setContentsMargins(10, 0, 10, 10) self.btn_pause = ControlToggleIcon( self.experiment.camera_state, "paused", icon_on=get_icon("play"), icon_off=get_icon("pause"), action_off="Pause", action_on="Play", ) self.layout_control.addWidget(self.btn_pause) if hasattr(self.experiment.camera_state, "replay"): self.experiment.camera_state.replay = False self.btn_rewind = ControlToggleIcon( self.experiment.camera_state, "replay", icon_on=get_icon("rewind"), action_off="Resume", action_on="Replay", ) self.layout_control.addWidget(self.btn_rewind) if self.control_queue is not None: self.btn_camera_param = IconButton(icon_name="edit_camera", action_name="Configure camera") self.btn_camera_param.clicked.connect(self.show_params_gui) self.layout_control.addWidget(self.btn_camera_param) self.btn_capture = IconButton(icon_name="camera_flash", action_name="Capture frame") self.btn_capture.clicked.connect(self.save_image) self.layout_control.addWidget(self.btn_capture) self.btn_autorange = ToggleIconButton(icon_off="autoscale", icon_on="autoscaleOFF", action_on="Autoscale") self.layout_control.addWidget(self.btn_autorange) self.layout.addLayout(self.layout_control) self.current_image = None self.setLayout(self.layout) self.current_frame_time = None self.param_widget = None def retrieve_image(self): """Update displayed frame while emptying frame source queue. This is done through a while loop that takes all available frames at every update. # TODO fix this somehow? **Important!** if the input queue is too fast this will produce an infinite loop and block the interface! Parameters ---------- Returns ------- """ first = True while True: try: # In this way, the frame displayed is actually the most # recent one added to the queue, as a queue is FILO: if first: qr = self.frame_queue.get(timeout=0.0001) self.current_image = qr[-1] self.current_frame_time = qr[0] # first = False else: # Else, get to free the queue: _, _ = self.frame_queue.get(timeout=0.001) except Empty: break # Once obtained current image, display it: if self.isVisible(): if self.current_image is not None: if self.current_image.shape[0] != self.scale: self.scale = self.current_image.shape[0] self.scale_changed() self.display_area.setRange(QRectF( 0, 0, self.current_image.shape[1], self.current_image.shape[0]), update=True, disableAutoRange=True) self.image_item.setImage( self.current_image, autoLevels=self.btn_autorange.isChecked()) def scale_changed(self): self.display_area.setRange(QRectF(0, 0, self.current_image.shape[1], self.current_image.shape[0]), update=True, disableAutoRange=True) def save_image(self, name=None): """Save a frame to the current directory.""" if name is None or not name: timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S") name = self.experiment.filename_base() + timestamp + "_img.png" imsave(name, self.image_item.image) def show_params_gui(self): """ """ self.param_widget = ParameterGui(self.control_params) self.param_widget.show()
def select_storage(self, path, get_wallet_from_daemon) -> Tuple[str, Optional[WalletStorage]]: vbox = QVBoxLayout() hbox = QHBoxLayout() hbox.addWidget(QLabel(_('Wallet') + ':')) name_e = QLineEdit() hbox.addWidget(name_e) button = QPushButton(_('Choose...')) hbox.addWidget(button) vbox.addLayout(hbox) msg_label = WWLabel('') vbox.addWidget(msg_label) hbox2 = QHBoxLayout() pw_e = PasswordLineEdit('', self) pw_e.setFixedWidth(17 * char_width_in_lineedit()) pw_label = QLabel(_('Password') + ':') hbox2.addWidget(pw_label) hbox2.addWidget(pw_e) hbox2.addStretch() vbox.addLayout(hbox2) vbox.addSpacing(50) vbox_create_new = QVBoxLayout() vbox_create_new.addWidget(QLabel(_('Alternatively') + ':'), alignment=Qt.AlignLeft) button_create_new = QPushButton(_('Create New Wallet')) button_create_new.setMinimumWidth(120) vbox_create_new.addWidget(button_create_new, alignment=Qt.AlignLeft) widget_create_new = QWidget() widget_create_new.setLayout(vbox_create_new) vbox_create_new.setContentsMargins(0, 0, 0, 0) vbox.addWidget(widget_create_new) self.set_layout(vbox, title=_('Electrum wallet')) temp_storage = None # type: Optional[WalletStorage] wallet_folder = os.path.dirname(path) def on_choose(): path, __ = QFileDialog.getOpenFileName(self, "Select your wallet file", wallet_folder) if path: name_e.setText(path) def on_filename(filename): # FIXME? "filename" might contain ".." (etc) and hence sketchy path traversals are possible nonlocal temp_storage temp_storage = None msg = None path = os.path.join(wallet_folder, filename) wallet_from_memory = get_wallet_from_daemon(path) try: if wallet_from_memory: temp_storage = wallet_from_memory.storage # type: Optional[WalletStorage] else: temp_storage = WalletStorage(path) except (StorageReadWriteError, WalletFileException) as e: msg = _('Cannot read file') + f'\n{repr(e)}' except Exception as e: self.logger.exception('') msg = _('Cannot read file') + f'\n{repr(e)}' self.next_button.setEnabled(temp_storage is not None) user_needs_to_enter_password = False if temp_storage: if not temp_storage.file_exists(): msg =_("This file does not exist.") + '\n' \ + _("Press 'Next' to create this wallet, or choose another file.") elif not wallet_from_memory: if temp_storage.is_encrypted_with_user_pw(): msg = _("This file is encrypted with a password.") + '\n' \ + _('Enter your password or choose another file.') user_needs_to_enter_password = True elif temp_storage.is_encrypted_with_hw_device(): msg = _("This file is encrypted using a hardware device.") + '\n' \ + _("Press 'Next' to choose device to decrypt.") else: msg = _("Press 'Next' to open this wallet.") else: msg = _("This file is already open in memory.") + "\n" \ + _("Press 'Next' to create/focus window.") if msg is None: msg = _('Cannot read file') msg_label.setText(msg) widget_create_new.setVisible(bool(temp_storage and temp_storage.file_exists())) if user_needs_to_enter_password: pw_label.show() pw_e.show() pw_e.setFocus() else: pw_label.hide() pw_e.hide() button.clicked.connect(on_choose) button_create_new.clicked.connect( partial( name_e.setText, get_new_wallet_name(wallet_folder))) name_e.textChanged.connect(on_filename) name_e.setText(os.path.basename(path)) def run_user_interaction_loop(): while True: if self.loop.exec_() != 2: # 2 = next raise UserCancelled() assert temp_storage if temp_storage.file_exists() and not temp_storage.is_encrypted(): break if not temp_storage.file_exists(): break wallet_from_memory = get_wallet_from_daemon(temp_storage.path) if wallet_from_memory: raise WalletAlreadyOpenInMemory(wallet_from_memory) if temp_storage.file_exists() and temp_storage.is_encrypted(): if temp_storage.is_encrypted_with_user_pw(): password = pw_e.text() try: temp_storage.decrypt(password) break except InvalidPassword as e: self.show_message(title=_('Error'), msg=str(e)) continue except BaseException as e: self.logger.exception('') self.show_message(title=_('Error'), msg=repr(e)) raise UserCancelled() elif temp_storage.is_encrypted_with_hw_device(): try: self.run('choose_hw_device', HWD_SETUP_DECRYPT_WALLET, storage=temp_storage) except InvalidPassword as e: self.show_message(title=_('Error'), msg=_('Failed to decrypt using this hardware device.') + '\n' + _('If you use a passphrase, make sure it is correct.')) self.reset_stack() return self.select_storage(path, get_wallet_from_daemon) except (UserCancelled, GoBack): raise except BaseException as e: self.logger.exception('') self.show_message(title=_('Error'), msg=repr(e)) raise UserCancelled() if temp_storage.is_past_initial_decryption(): break else: raise UserCancelled() else: raise Exception('Unexpected encryption version') try: run_user_interaction_loop() finally: try: pw_e.clear() except RuntimeError: # wrapped C/C++ object has been deleted. pass # happens when decrypting with hw device return temp_storage.path, (temp_storage if temp_storage.file_exists() else None)
class Window(QWidget): play_previous_needed = pyqtSignal() play_next_needed = pyqtSignal() def __init__(self): super().__init__(parent=None) if IS_MACOS: # On macOS, Qt.Tooltip widget can't accept focus and it will hide # when the application window is actiavted. Qt.Tool widget can't # keep staying on top. Neither of them work well on macOS. flags = Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint else: # TODO: use proper flags on other platforms # see #413 for more details flags = Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint | Qt.Tool self.setWindowFlags(flags) self.setAttribute(Qt.WA_TranslucentBackground) self.c = Container(self) self._layout = QVBoxLayout(self) self._layout.setContentsMargins(0, 0, 0, 0) self._layout.setSpacing(0) self._layout.addWidget(self.c) self._old_pos = None QShortcut(QKeySequence.ZoomIn, self).activated.connect(self.zoomin) QShortcut(QKeySequence.ZoomOut, self).activated.connect(self.zoomout) QShortcut(QKeySequence('Ctrl+='), self).activated.connect(self.zoomin) QShortcut(QKeySequence.Cancel, self).activated.connect(self.hide) self.setToolTip(''' * 右键可以弹出设置菜单 * Ctrl+= 或者 Ctrl++ 可以增大字体 * Ctrl+- 可以减小字体 * 鼠标前进后退键可以播放前一首/下一首 ''') def set_sentence(self, text): if self.isVisible(): self.c.label.setText(text) def mousePressEvent(self, e): self._old_pos = e.globalPos() def mouseMoveEvent(self, e): # NOTE: e.button() == Qt.LeftButton don't work on Windows # on Windows, even I drag with LeftButton, the e.button() return 0, # which means no button if self._old_pos is not None: delta = e.globalPos() - self._old_pos self.move(self.x() + delta.x(), self.y() + delta.y()) self._old_pos = e.globalPos() def mouseReleaseEvent(self, e): if not self.rect().contains(e.pos()): return if e.button() == Qt.BackButton: self.play_previous_needed.emit() elif e.button() == Qt.ForwardButton: self.play_next_needed.emit() def zoomin(self): label = self.c.label font = label.font() resize_font(font, +1) label.setFont(font) def zoomout(self): label = self.c.label font = label.font() resize_font(font, - 1) label.setFont(font) def sizeHint(self): return QSize(500, 60)
def _setupUI(self): """ Sets up thee UI for the rearrangement Viewer. Notes: helper method for __init__ Returns: None """ self.scrollA = QScrollArea() self.listA = SourceList(self) self.listA.itemSelectionChanged.connect(self.show_relevant_tools) self.scrollA.setWidget(self.listA) self.scrollA.setWidgetResizable(True) self.scrollB = QScrollArea() self.listB = SinkList(self) self.listB.itemSelectionChanged.connect(self.show_relevant_tools) self.scrollB.setWidget(self.listB) self.scrollB.setWidgetResizable(True) self.appendB = QToolButton() # TODO: move &A here and use alt-Enter to Accept dialog? self.appendB.setText("Add &Page(s)") self.appendB.setArrowType(Qt.DownArrow) self.appendB.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.removeB = QToolButton() self.removeB.setArrowType(Qt.UpArrow) self.removeB.setText("&Remove Page(s)") self.removeB.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.sLeftB = QToolButton() self.sLeftB.setArrowType(Qt.LeftArrow) self.sLeftB.setText("Shift Left") self.sLeftB.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.sRightB = QToolButton() self.sRightB.setArrowType(Qt.RightArrow) self.sRightB.setText("Shift Right") self.sRightB.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.reverseB = QPushButton("Reverse Order") self.revertB = QPushButton("Revert to original state") self.revertB.clicked.connect(self.populateListOriginal) self.rotateB_cw = QPushButton("\N{Clockwise Open Circle Arrow} Rotate CW") self.rotateB_ccw = QPushButton("\N{Anticlockwise Open Circle Arrow} Rotate CCW") self.closeB = QPushButton("&Cancel") self.acceptB = QPushButton("&Accept") self.permute = [False] def GrippyMcGrab(): """Grippy bars to spice-up QSplitterHandles.""" width = 64 pad = 20 hb = QHBoxLayout() hb.addItem( QSpacerItem(pad, 1, QSizePolicy.MinimumExpanding, QSizePolicy.Minimum) ) vb = QVBoxLayout() hb.addLayout(vb) hb.addItem( QSpacerItem(pad, 1, QSizePolicy.MinimumExpanding, QSizePolicy.Minimum) ) vb.setContentsMargins(0, 1, 0, 1) vb.setSpacing(2) vb.addItem( QSpacerItem( width, 3, QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding ) ) for i in range(3): f = QFrame() f.setFrameShape(QFrame.HLine) f.setFrameShadow(QFrame.Sunken) vb.addWidget(f) vb.addItem( QSpacerItem( width, 3, QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding ) ) return hb hb3 = QHBoxLayout() self.tools = QFrame() hb = QHBoxLayout() self.tools.setLayout(hb) hb.setContentsMargins(0, 0, 0, 0) hb.addWidget(self.rotateB_ccw) hb.addWidget(self.rotateB_cw) hb.addItem(QSpacerItem(16, 20, QSizePolicy.Minimum, QSizePolicy.Minimum)) hb.addWidget(self.sLeftB) hb.addWidget(self.sRightB) hb.addItem(QSpacerItem(16, 20, QSizePolicy.Minimum, QSizePolicy.Minimum)) hb3.addWidget(self.tools) hb3.addWidget(self.reverseB) hb3.addItem( QSpacerItem(16, 20, QSizePolicy.MinimumExpanding, QSizePolicy.Minimum) ) hb3.addWidget(self.acceptB) hb3.addWidget(self.closeB) allPages = QLabel("Other Pages in Exam") thisQuestion = QLabel("Pages for this Question") # center add/remove buttons on label row hb1 = QHBoxLayout() hb1.addWidget(thisQuestion) hb1.addLayout(GrippyMcGrab()) hb = QHBoxLayout() hb.addWidget(self.appendB) hb.addItem(QSpacerItem(64, 20, QSizePolicy.Minimum, QSizePolicy.Minimum)) hb.addWidget(self.removeB) hb1.addLayout(hb) hb1.addLayout(GrippyMcGrab()) hb1.addWidget(self.revertB) vb0 = QVBoxLayout() s = QSplitter() s.setOrientation(Qt.Vertical) # s.setOpaqueResize(False) s.setChildrenCollapsible(False) s.setHandleWidth(50) # TODO: better not to hardcode, take from children? vb0.addWidget(s) f = QFrame() s.addWidget(f) vb = QVBoxLayout() vb.setContentsMargins(0, 0, 0, 0) f.setLayout(vb) vb.addWidget(allPages) vb.addWidget(self.scrollA) f = QFrame() s.addWidget(f) vb = QVBoxLayout() vb.setContentsMargins(0, 0, 0, 0) f.setLayout(vb) vb.addWidget(self.scrollB) vb.addLayout(hb3) handle = s.handle(1) vb = QVBoxLayout() vb.setContentsMargins(0, 0, 0, 0) vb.setSpacing(0) handle.setLayout(hb1) hb1.setContentsMargins(0, 0, 0, 0) # TODO: Buttons inside the splitter bar, disable drag and custom cursor for b in (self.removeB, self.appendB, self.revertB): b.mouseMoveEvent = lambda *args: None b.setCursor(Qt.ArrowCursor) self.setLayout(vb0) self.resize(QSize(self.parent.width() * 7 / 8, self.parent.height() * 9 / 10)) self.closeB.clicked.connect(self.close) self.sLeftB.clicked.connect(self.shuffleLeft) self.sRightB.clicked.connect(self.shuffleRight) self.reverseB.clicked.connect(self.reverseOrder) self.rotateB_cw.clicked.connect(lambda: self.rotateImages(90)) self.rotateB_ccw.clicked.connect(lambda: self.rotateImages(-90)) self.appendB.clicked.connect(self.sourceToSink) self.removeB.clicked.connect(self.sinkToSource) self.acceptB.clicked.connect(self.doShuffle) allPageWidgets = [self.listA, self.listB] self.listA.selectionModel().selectionChanged.connect( lambda sel, unsel: self.singleSelect(self.listA, allPageWidgets) ) self.listB.selectionModel().selectionChanged.connect( lambda sel, unsel: self.singleSelect(self.listB, allPageWidgets) )
class LoginDialog(FDialog): def __init__(self, app, parent=None): super().__init__(parent) self._app = app self.is_encrypted = False self.captcha_needed = False self.captcha_id = 0 self.username_input = LineInput(self) self.pw_input = LineInput(self) self.pw_input.setEchoMode(QLineEdit.Password) # self.remember_checkbox = FCheckBox(self) self.captcha_label = FLabel(self) self.captcha_label.hide() self.captcha_input = LineInput(self) self.captcha_input.hide() self.hint_label = FLabel(self) self.ok_btn = FButton('登录', self) self._layout = QVBoxLayout(self) self.username_input.setPlaceholderText('网易邮箱或者手机号') self.pw_input.setPlaceholderText('密码') self.setObjectName('login_dialog') self.set_theme_style() self.setup_ui() self.pw_input.textChanged.connect(self.dis_encrypt) def fill(self, data): self.username_input.setText(data['username']) self.pw_input.setText(data['password']) self.is_encrypted = True def set_theme_style(self): pass def setup_ui(self): self.setFixedWidth(200) self._layout.setContentsMargins(0, 0, 0, 0) self._layout.setSpacing(0) self._layout.addWidget(self.username_input) self._layout.addWidget(self.pw_input) self._layout.addWidget(self.captcha_label) self._layout.addWidget(self.captcha_input) self._layout.addWidget(self.hint_label) # self._layout.addWidget(self.remember_checkbox) self._layout.addWidget(self.ok_btn) def show_hint(self, text): self.hint_label.setText(text) @property def data(self): username = self.username_input.text() pw = self.pw_input.text() if self.is_encrypted: password = pw else: password = hashlib.md5(pw.encode('utf-8')).hexdigest() d = dict(username=username, password=password) return d def captcha_verify(self, data): self.captcha_needed = True url = data['captcha_url'] self.captcha_id = data['captcha_id'] self.captcha_input.show() self.captcha_label.show() self._app.pixmap_from_url(url, self.captcha_label.setPixmap) def dis_encrypt(self, text): self.is_encrypted = False
class MainWindow(QMainWindow): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.experiment_controller = ExperimentController() self.pen_color = ColorDialogWithKnee() self.pen_color.updateSignal.connect(self.set_pen_color) self.setupUi() self.show() self.active_canvas = 0 # 操作レイヤの制御 self.is_enabled_knee_control = False self.is_mode_switched = False self.current_drawing_mode = OperationMode.DRAWING_POINTS self.current_color_saturation = 127 self.current_knee_operation_mode = OperationMode.NONE self.current_knee_value = QPointF() self.fixed_knee_value = QPointF(0, 0) self.is_fixed_knee_value = False self.picked_color = QColor() # self.timerThread = QThread() # 実験記録関連の変数 start_experiment_action = QAction("計測開始", self) start_experiment_action.setShortcut(QKeySequence("Ctrl+P")) start_experiment_action.triggered.connect(self.start_experiment) save_records_action = QAction("計測結果を保存", self) save_records_action.setShortcut(QKeySequence("Ctrl+S")) save_records_action.triggered.connect(self.save_picture_and_experiment) operation_menu = self.menubar.addMenu("experiments") operation_menu.addAction(start_experiment_action) operation_menu.addAction(save_records_action) try: self.timer_thread = KneePosition.TimerThread() self.timer_thread.updateSignal.connect( self.control_params_with_knee) self.timer_thread.start() self.kneePosition = self.timer_thread.kneePosition self.is_enabled_knee_control = True self.experiment_controller.is_enabled_knee_control = True self.current_knee_operation_mode = OperationMode.DRAWING_POINTS except serial.serialutil.SerialException as e: self.statusbar.showMessage("膝操作が無効:シリアル通信が確保できていません。原因:" + str(e)) self.canvas[0].set_enable_knee_control(self.is_enabled_knee_control) self.displayKneeOperationModeTextLabel.setText( "Knee mode: \n {}".format(self.current_knee_operation_mode)) # self.colorPickerToolButton.setStyleSheet("background-color: black") def setupUi(self): self.setObjectName("self") self.resize(900, 650) self.centralwidget = QWidget(self) self.centralwidget.setObjectName("centralwidget") self.displayKneeOperationModeTextLabel = QLabel(self.centralwidget) self.displayKneeOperationModeTextLabel.setGeometry( QRect(610, 10, 270, 40)) self.displayKneeOperationModeTextLabel.setObjectName( "displayKneeOperationModeTextLabel") self.selectOperationModeButton = QPushButton(self.centralwidget) self.selectOperationModeButton.setGeometry(QRect(600, 50, 140, 40)) self.selectOperationModeButton.setObjectName( "selectOperationModeButton") self.selectOperationModeButton.clicked.connect( self.switch_drawing_mode) self.canvasTableView = QTableView(self.centralwidget) self.canvasTableView.setGeometry(QRect(600, 130, 290, 150)) self.canvasTableView.setObjectName("canvasTableView") self.canvasTableView.setSelectionMode( QAbstractItemView.SingleSelection) self.canvasTableView.horizontalHeader().setDefaultSectionSize(145) self.canvasTableView.clicked.connect(self.table_item_clicked) self.addCanvasButton = QPushButton(self.centralwidget) self.addCanvasButton.setGeometry(QRect(600, 300, 120, 25)) self.addCanvasButton.setObjectName("addCanvasButton") self.addCanvasButton.clicked.connect(self.add_canvas) self.deleteCanvasButton = QPushButton(self.centralwidget) self.deleteCanvasButton.setGeometry(QRect(760, 300, 120, 25)) self.deleteCanvasButton.setObjectName("deleteCanvasButton") self.deleteCanvasButton.clicked.connect(self.delete_canvas) self.readFileNametextEdit = QTextEdit(self.centralwidget) self.readFileNametextEdit.setGeometry(QRect(610, 350, 140, 30)) self.readFileNametextEdit.setLineWidth(2) self.readFileNametextEdit.setObjectName("readFileNametextEdit") self.fileReadButton = QPushButton(self.centralwidget) self.fileReadButton.setGeometry(QRect(750, 350, 140, 35)) self.fileReadButton.setObjectName("fileReadButton") self.fileReadButton.clicked.connect(self.file_read) self.colorPickerToolButton = QToolButton(self.centralwidget) self.colorPickerToolButton.setGeometry(QRect(600, 400, 280, 30)) self.colorPickerToolButton.setObjectName("colorPickerToolButton") self.colorPickerToolButton.setAutoFillBackground(True) self.verticalLayoutWidget = QWidget(self) self.verticalLayoutWidget.setGeometry(QRect(600, 440, 280, 120)) self.verticalLayoutWidget.setObjectName("verticalLayoutWidget") self.verticalLayout = QVBoxLayout(self.verticalLayoutWidget) self.verticalLayout.setContentsMargins(0, 0, 0, 0) self.verticalLayout.setObjectName("verticalLayout") self.hueLabel = QLabel(self.verticalLayoutWidget) self.hueLabel.setObjectName("hueLabel") self.verticalLayout.addWidget(self.hueLabel) self.hueSlider = QSlider(self.verticalLayoutWidget) self.hueSlider.setOrientation(Qt.Horizontal) self.hueSlider.setObjectName("hueSlider") self.hueSlider.setRange(0, 360) self.hueSlider.valueChanged.connect(self.pen_color.hue_changed) self.hueSlider.setTracking(True) self.verticalLayout.addWidget(self.hueSlider) self.saturationLabel = QLabel(self.verticalLayoutWidget) self.saturationLabel.setObjectName("saturationLabel") self.verticalLayout.addWidget(self.saturationLabel) self.saturationSlider = QSlider(self.verticalLayoutWidget) self.saturationSlider.setOrientation(Qt.Horizontal) self.saturationSlider.setObjectName("saturationSlider") self.saturationSlider.setRange(0, 255) self.saturationSlider.setValue(255) self.saturationSlider.valueChanged.connect( self.pen_color.saturation_changed) self.saturationSlider.setTracking(True) self.verticalLayout.addWidget(self.saturationSlider) self.valueLabel = QLabel(self.verticalLayoutWidget) self.valueLabel.setObjectName("valueLabel") self.verticalLayout.addWidget(self.valueLabel) self.valueSlider = QSlider(self.verticalLayoutWidget) self.valueSlider.setOrientation(Qt.Horizontal) self.valueSlider.setObjectName("valueSlider") self.valueSlider.valueChanged.connect(self.pen_color.value_changed) self.valueSlider.setRange(0, 255) self.valueSlider.setTracking(True) self.verticalLayout.addWidget(self.valueSlider) self.canvas = [] self.canvas.append(Canvas(self.centralwidget)) self.canvas[0].setGeometry(QRect(0, 0, 600, 600)) self.canvas[0].setObjectName("canvas0") palette = self.canvas[0].palette() palette.setColor(QPalette.Background, QColor(255, 255, 255, 0)) self.canvas[0].setPalette(palette) self.canvas[0].setAutoFillBackground(True) self.canvas[0].experiment_controller = self.experiment_controller self.active_canvas = 0 self.setCentralWidget(self.centralwidget) self.menubar = QMenuBar(self) self.menubar.setGeometry(QRect(0, 0, 889, 22)) self.menubar.setObjectName("menubar") self.setMenuBar(self.menubar) self.statusbar = QStatusBar(self) self.statusbar.setObjectName("statusbar") self.setStatusBar(self.statusbar) self.canvasNameTableModel = CanvasNameTableModel() self.canvasTableView.setModel(self.canvasNameTableModel) self.canvasTableView.setCurrentIndex( self.canvasNameTableModel.index(self.active_canvas, 0)) self.canvasNameTableModel.layoutChanged.emit() _translate = QCoreApplication.translate self.setWindowTitle(_translate("MainWindow", "MainWindow")) self.addCanvasButton.setText(_translate("MainWindow", "レイヤを追加")) self.deleteCanvasButton.setText(_translate("MainWindow", "レイヤを削除")) self.fileReadButton.setText(_translate("MainWindow", "ファイルを読込む")) self.selectOperationModeButton.setText( _translate("MainWindow", "DRAWING_POINTS")) self.displayKneeOperationModeTextLabel.setText( _translate("MainWindow", "Knee mode:NONE")) self.hueLabel.setText(_translate("MainWindow", "Hue: 0")) self.saturationLabel.setText( _translate("MainWindow", "Saturation: 255")) self.valueLabel.setText(_translate("MainWindow", "Brightness: 0")) # self.currentCanvasNameTextLabel.setText(_translate("MainWindow", "Now at: canvas[0]")) QMetaObject.connectSlotsByName(self) def display_statusbar(self): self.statusbar.showMessage("現在のレイヤ: {} 膝モード: {} マウスモード: {}".format( self.canvasNameTableModel.canvas_name[self.active_canvas], self.current_knee_operation_mode.name, self.current_drawing_mode.name)) # -- レイヤ(canvas)に対する操作 -- def add_canvas(self): new_canvas = Canvas(self.centralwidget) new_canvas.setGeometry(QRect(0, 0, 600, 600)) new_canvas.setObjectName("canvas") new_canvas.mainWindow = self palette = new_canvas.palette() palette.setColor(QPalette.Background, QColor(255, 255, 255, 0)) new_canvas.setPalette(palette) new_canvas.setAutoFillBackground(True) new_canvas.is_enable_knee_control = self.is_enabled_knee_control new_canvas.experiment_controller = self.experiment_controller new_canvas.operation_mode_changed(self.current_drawing_mode, self.current_knee_operation_mode) new_canvas.current_line_color = self.picked_color self.canvas.append(new_canvas) self.active_canvas = len(self.canvas) - 1 canvas_name = 'canvas[' + str(self.active_canvas) + ']' self.canvasNameTableModel.add_canvas(canvas_name) self.canvasTableView.setCurrentIndex( self.canvasNameTableModel.index(self.active_canvas, 0)) self.canvasNameTableModel.layoutChanged.emit() self.display_statusbar() # 使用するレイヤだけ使用可能にする for canvas in self.canvas: canvas.setEnabled(False) self.canvas[self.active_canvas].setEnabled(True) def delete_canvas(self): if len(self.canvas) > 1: if self.active_canvas == len(self.canvas) - 1: self.active_canvas -= 1 deleted_canvas = self.canvas.pop() self.canvasNameTableModel.delete_last_canvas() self.canvasTableView.setCurrentIndex( self.canvasNameTableModel.index(self.active_canvas, 0)) self.canvasNameTableModel.layoutChanged.emit() for i in range(len(deleted_canvas.existing_paths)): deleted_canvas.existing_paths.pop() deleted_canvas.hide() # 使用するレイヤだけ使用可能にする for canvas in self.canvas: canvas.setEnabled(False) self.canvas[self.active_canvas].setEnabled(True) def table_item_clicked(self, index_clicked: QModelIndex): col = index_clicked.column() row = index_clicked.row() if col == 0: self.switch_canvas_from_table(row) elif col == 1: # if row <= self.active_canvas: origin_state = self.canvasNameTableModel.is_visible[row] is_visible = self.canvasNameTableModel.set_canvas_visible( row, not origin_state) # self.canvas[row].switch_visible(is_visible) self.canvas[row].setVisible(is_visible) self.canvasNameTableModel.layoutChanged.emit() def switch_canvas_from_table(self, switch_to: int): self.active_canvas = switch_to self.canvasTableView.setCurrentIndex( self.canvasNameTableModel.index(self.active_canvas, 0)) # 使用するレイヤだけ使用可能にする for canvas in self.canvas: canvas.setEnabled(False) self.canvas[self.active_canvas].setEnabled(True) self.canvas[self.active_canvas].operation_mode_changed( self.current_drawing_mode, self.current_knee_operation_mode) self.canvas[self.active_canvas].current_line_color = self.picked_color # 全てのレイヤに現在の表示状況を反映する visible_states = self.canvasNameTableModel.is_visible for i in range(0, self.active_canvas + 1): self.canvas[i].setVisible(visible_states[i]) # 選択したレイヤは表示する self.canvas[i].setVisible(True) self.canvasNameTableModel.set_canvas_visible(i, True) # 選択したレイヤより上のレイヤは見えないようにする for i in range(self.active_canvas + 1, len(self.canvas)): self.canvas[i].setVisible(False) self.canvasNameTableModel.set_canvas_visible(i, False) self.canvasNameTableModel.layoutChanged.emit() self.display_statusbar() def switch_canvas_from_index(self, index: int): self.active_canvas = index self.canvasTableView.setCurrentIndex( self.canvasNameTableModel.index(self.active_canvas, 0)) # 使用するレイヤだけ使用可能にする for canvas in self.canvas: canvas.setEnabled(False) self.canvas[self.active_canvas].setEnabled(True) self.canvas[self.active_canvas].operation_mode_changed( self.current_knee_operation_mode, self.current_knee_operation_mode) self.canvas[self.active_canvas].current_line_color = self.picked_color # 選択したレイヤより下のレイヤは現在の表示状況を反映する visible_states = self.canvasNameTableModel.is_visible for i in range(0, self.active_canvas + 1): self.canvas[i].setVisible(visible_states[i]) # 選択したレイヤは表示する self.canvas[i].setVisible(True) self.canvasNameTableModel.set_canvas_visible(i, True) # 選択したレイヤより上のレイヤは見えないようにする for i in range(self.active_canvas + 1, len(self.canvas)): self.canvas[i].setVisible(False) self.canvasNameTableModel.set_canvas_visible(i, False) self.canvasNameTableModel.layoutChanged.emit() self.display_statusbar() # -- 絵のセーブとロード -- def save_all_picture(self): origin_visible_states = self.canvasNameTableModel.is_visible origin_active_canvas = self.active_canvas picture = QPixmap() for i in range(len(self.canvas)): self.switch_canvas_from_index(i) # レイヤを切り替え(上部のレイヤは見えない) for j in range(i): self.canvas[j].setVisible(False) # キャプチャするレイヤより下のレイヤを非表示にする picture = self.centralwidget.grab(QRect(0, 0, 600, 600)) picture.save("result_paint_experiment/p{}/{}/canvas{}.png".format( participant_No, ("knee" if self.is_enabled_knee_control else "mouse"), i)) # 元の状態に戻す self.switch_canvas_from_index(origin_active_canvas) for i in range(origin_active_canvas): is_visible = self.canvasNameTableModel.set_canvas_visible( i, origin_visible_states[i]) self.canvas[i].setVisible(origin_visible_states[i]) def save_all_points_and_paths(self): points_record_file = open( 'result_paint_experiment/p{}/{}/points_record.txt'.format( participant_No, ("knee" if self.is_enabled_knee_control else "mouse")), 'w') for canvas in self.canvas: # print(canvas.recorded_points) points_record_file.write("[\n") for line in canvas.recorded_points: points_string = " [" for point in line: points_string += "({}, {});".format(point.x(), point.y()) points_string = points_string[:-1] # 末尾の「;」だけ削除 points_string += "]\n" points_record_file.write(points_string) points_record_file.write("],\n") def save_picture(self): picture = QPixmap() picture = self.centralwidget.grab(QRect(0, 0, 600, 600)) picture.save("test.png") def file_read(self): file_name = "sampleImages/1.png" image = QImage(file_name) self.canvas[self.active_canvas].load_picture(image) # -*- 色変更 -*- def set_pen_color(self, color): self.picked_color = color self.canvas[self.active_canvas].set_line_color(color) self.hueLabel.setText("Hue: {}".format(self.pen_color.hue)) self.hueSlider.setSliderPosition(self.pen_color.hue) self.saturationLabel.setText("Saturation: {}".format( self.pen_color.saturation)) self.saturationSlider.setSliderPosition(self.pen_color.saturation) self.valueLabel.setText("Brightness: {}".format(self.pen_color.value)) self.valueSlider.setSliderPosition(self.pen_color.value) color_string = "background-color: rgb({},{},{})".format( self.pen_color.color.red(), self.pen_color.color.green(), self.pen_color.color.blue()) self.colorPickerToolButton.setStyleSheet(color_string) self.verticalLayoutWidget.update() # -*- 操作モードの切り替え -*- def switch_drawing_mode(self): if self.current_drawing_mode == OperationMode.DRAWING_POINTS: self.current_drawing_mode = OperationMode.MOVING_POINTS elif self.current_drawing_mode == OperationMode.MOVING_POINTS: self.current_drawing_mode = OperationMode.DRAWING_POINTS else: self.current_drawing_mode = OperationMode.NONE # 膝操作が有効の時は膝操作のモードも合わせる if self.is_enabled_knee_control: if self.current_drawing_mode == OperationMode.DRAWING_POINTS: self.current_knee_operation_mode = OperationMode.DRAWING_POINTS elif self.current_drawing_mode == OperationMode.MOVING_POINTS: self.current_knee_operation_mode = OperationMode.MOVING_POINTS else: self.current_knee_operation_mode = OperationMode.DRAWING_POINTS self.canvas[self.active_canvas].operation_mode_changed( self.current_drawing_mode, self.current_knee_operation_mode) self.selectOperationModeButton.setText("{}".format( self.current_drawing_mode.name)) self.displayKneeOperationModeTextLabel.setText( "Knee mode: \n {}".format(self.current_knee_operation_mode)) self.display_statusbar() def switch_knee_operation_mode(self): if self.current_knee_operation_mode == OperationMode.NONE: self.current_knee_operation_mode = OperationMode.DRAWING_POINTS self.current_drawing_mode = OperationMode.DRAWING_POINTS elif self.current_knee_operation_mode == OperationMode.DRAWING_POINTS: self.current_knee_operation_mode = OperationMode.MOVING_POINTS self.current_drawing_mode = OperationMode.MOVING_POINTS elif self.current_knee_operation_mode == OperationMode.MOVING_POINTS: self.current_knee_operation_mode = OperationMode.SWITCH_LAYER self.current_drawing_mode = OperationMode.DRAWING_POINTS elif self.current_knee_operation_mode == OperationMode.SWITCH_LAYER: self.current_knee_operation_mode = OperationMode.COLOR_PICKER self.current_drawing_mode = OperationMode.DRAWING_POINTS elif self.current_knee_operation_mode == OperationMode.COLOR_PICKER: self.current_knee_operation_mode = OperationMode.DRAWING_POINTS self.current_drawing_mode = OperationMode.DRAWING_POINTS else: self.current_knee_operation_mode = OperationMode.NONE self.canvas[self.active_canvas].operation_mode_changed( self.current_drawing_mode, self.current_knee_operation_mode) self.selectOperationModeButton.setText("{}".format( self.current_drawing_mode.name)) self.displayKneeOperationModeTextLabel.setText( "Knee mode: \n {}".format(self.current_knee_operation_mode)) self.display_statusbar() # -*- イベント処理(継承元のオーバーライド)-*- def keyPressEvent(self, keyEvent): # print(keyEvent.key()) if keyEvent.key() == Qt.Key_Return: self.canvas[self.active_canvas].fix_path() if keyEvent.key() == Qt.Key_Backspace: self.canvas[self.active_canvas].delete_last_path() if keyEvent.key() == Qt.Key_Shift: self.is_fixed_knee_value = True def keyReleaseEvent(self, keyEvent): if keyEvent.key() == Qt.Key_Shift: self.is_fixed_knee_value = False # -*- 実験を記録する関係 -*- def start_experiment(self): self.experiment_controller.start_experiment() self.statusbar.showMessage( "Experiment started p{}".format(participant_No)) def save_picture_and_experiment(self): if self.experiment_controller.is_started_experiment: self.experiment_controller.is_started_experiment = False self.experiment_controller.save_records( ) # save系統の処理で一番最初に来るように(保存パスが作られるため) self.save_all_points_and_paths() self.save_all_picture() # -*- 膝操作の操作振り分け -*- def control_params_with_knee(self, x, y): self.experiment_controller.current_knee_position = QPointF(x, y) self.experiment_controller.record_frame( self.current_drawing_mode, self.current_knee_operation_mode) if y == 0: if not self.is_mode_switched: self.statusbar.showMessage("switch") self.switch_knee_operation_mode() self.is_mode_switched = True else: if self.current_knee_operation_mode == OperationMode.NONE: pass elif self.current_knee_operation_mode == OperationMode.DRAWING_POINTS: pass elif self.current_knee_operation_mode == OperationMode.MOVING_POINTS: x, y = self.kneePosition.get_mapped_positions(x, y, 0, 200) if not self.is_fixed_knee_value: self.fixed_knee_value = QPointF(x, y) self.canvas[self.active_canvas].set_knee_position(x, y) elif self.current_knee_operation_mode == OperationMode.SWITCH_LAYER: x, _ = self.kneePosition.get_mapped_positions(x, y, 1, 359) _, y = self.kneePosition.get_mapped_positions(x, y, 0, 255) if not self.is_fixed_knee_value: self.fixed_knee_value = QPointF(x, y) target_number = (int)( self.fixed_knee_value.x() / (360 / self.canvasNameTableModel.rowCount())) if not self.active_canvas == target_number: self.switch_canvas_from_index(target_number) elif self.current_knee_operation_mode == OperationMode.COLOR_PICKER: x, _ = self.kneePosition.get_mapped_positions(x, y, 1, 359) _, y = self.kneePosition.get_mapped_positions(x, y, 0, 255) if not self.is_fixed_knee_value: self.fixed_knee_value = QPointF(x, y) next_color = self.pen_color.color next_color.setHsv(self.fixed_knee_value.x(), 255, self.fixed_knee_value.y(), 255) self.pen_color.color_changed(next_color) else: self.current_knee_operation_mode = OperationMode.NONE if self.is_mode_switched: self.is_mode_switched = False if not self.experiment_controller.is_started_experiment: status_str = "x: " + str(x) + "y: " + str(y) self.statusbar.showMessage(status_str)
class UpdateCheck(QWidget, PrintError): url = "https://electrum.org/version" download_url = "https://electrum.org/#download" VERSION_ANNOUNCEMENT_SIGNING_KEYS = ( "13xjmVAB1EATPP8RshTE8S8sNwwSUM9p1P", ) def __init__(self, main_window, latest_version=None): self.main_window = main_window QWidget.__init__(self) self.setWindowTitle('SmartCryptoTech Electrum Wallet - ' + _('Update Check')) self.content = QVBoxLayout() self.content.setContentsMargins(*[10]*4) self.heading_label = QLabel() self.content.addWidget(self.heading_label) self.detail_label = QLabel() self.detail_label.setTextInteractionFlags(Qt.LinksAccessibleByMouse) self.detail_label.setOpenExternalLinks(True) self.content.addWidget(self.detail_label) self.pb = QProgressBar() self.pb.setMaximum(0) self.pb.setMinimum(0) self.content.addWidget(self.pb) versions = QHBoxLayout() versions.addWidget(QLabel(_("Current version: {}".format(version.ELECTRUM_VERSION)))) self.latest_version_label = QLabel(_("Latest version: {}".format(" "))) versions.addWidget(self.latest_version_label) self.content.addLayout(versions) self.update_view(latest_version) self.update_check_thread = UpdateCheckThread(self.main_window) self.update_check_thread.checked.connect(self.on_version_retrieved) self.update_check_thread.failed.connect(self.on_retrieval_failed) self.update_check_thread.start() close_button = QPushButton(_("Close")) close_button.clicked.connect(self.close) self.content.addWidget(close_button) self.setLayout(self.content) self.show() def on_version_retrieved(self, version): self.update_view(version) def on_retrieval_failed(self): self.heading_label.setText('<h2>' + _("Update check failed") + '</h2>') self.detail_label.setText(_("Sorry, but we were unable to check for updates. Please try again later.")) self.pb.hide() @staticmethod def is_newer(latest_version): return latest_version > StrictVersion(version.ELECTRUM_VERSION) def update_view(self, latest_version=None): if latest_version: self.pb.hide() self.latest_version_label.setText(_("Latest version: {}".format(latest_version))) if self.is_newer(latest_version): self.heading_label.setText('<h2>' + _("There is a new update available") + '</h2>') url = "<a href='{u}'>{u}</a>".format(u=UpdateCheck.download_url) self.detail_label.setText(_("You can download the new version from {}.").format(url)) else: self.heading_label.setText('<h2>' + _("Already up to date") + '</h2>') self.detail_label.setText(_("You are already on the latest version of SmartCryptoTech Electrum Wallet.")) else: self.heading_label.setText('<h2>' + _("Checking for updates...") + '</h2>') self.detail_label.setText(_("Please wait while SmartCryptoTech Electrum Wallet checks for available updates."))
def create_master_numpad(self): self.overlay_widget = QWidget(self.widget) self.overlay_widget.setObjectName("OverlayNumPadWidget") sound_pbtn_widget = QWidget(self.overlay_widget) # sound_pbtn_widget.setAttribute(Qt.WA_TranslucentBackground) # NumPad widgets, layouts and items sound_name_lbl = QLabel(self.overlay_widget) sound_name_lbl.setObjectName('NumPadName') sound_name_lbl.setAlignment(Qt.AlignCenter) sound_name_lbl.setText('Name of Sound') numpad_spacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) settings_numpad_pbtn = QPushButton(self.overlay_widget) settings_numpad_pbtn.setObjectName('NumPad') settings_numpad_pbtn.setText('Settings') add_numpad_pbtn = QPushButton(self.overlay_widget) add_numpad_pbtn.setObjectName('NumPad') add_numpad_pbtn.setText('Add Sound') remove_numpad_pbtn = QPushButton(self.overlay_widget) remove_numpad_pbtn.setObjectName('NumPad') remove_numpad_pbtn.setText('Remove Sound') # Master sound buttons play_sound_pbtn = QPushButton() play_sound_pbtn.setObjectName('PlayBtns') play_sound_pbtn.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) play_sound_pbtn.setIcon( QIcon('./interface-stylesheets/interface-element/play.gif')) play_sound_pbtn.setAccessibleName('NumPadPushButton_%d' % self.nums) begin_sound_pbtn = QPushButton() begin_sound_pbtn.setObjectName('PlayBtns') begin_sound_pbtn.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) begin_sound_pbtn.setIcon( QIcon('./interface-stylesheets/interface-element/end.gif')) end_sound_pbtn = QPushButton() end_sound_pbtn.setObjectName('PlayBtns') end_sound_pbtn.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) end_sound_pbtn.setIcon( QIcon('./interface-stylesheets/interface-element/begin.gif')) overlay_pbtn_hbl = QVBoxLayout() overlay_pbtn_hbl.setContentsMargins(0, 0, 0, 0) overlay_pbtn_hbl.setSpacing(0) # Create and set layouts and add widgets play_sound_hbl = QHBoxLayout() play_sound_hbl.setContentsMargins(0, 0, 0, 0) play_sound_hbl.addWidget(begin_sound_pbtn) play_sound_hbl.addWidget(play_sound_pbtn) play_sound_hbl.addWidget(end_sound_pbtn) overlay_pbtn_hbl.addWidget(sound_name_lbl) overlay_pbtn_hbl.addItem(numpad_spacer) overlay_pbtn_hbl.addWidget(sound_pbtn_widget) overlay_pbtn_hbl.addWidget(add_numpad_pbtn) overlay_pbtn_hbl.addWidget(remove_numpad_pbtn) overlay_pbtn_hbl.addWidget(settings_numpad_pbtn) sound_pbtn_widget.setLayout(play_sound_hbl) self.overlay_widget.setLayout(overlay_pbtn_hbl) # Custom parameters self.overlay_widget.setGraphicsEffect(self.opacity_effect) # Events and signals widget self.widget.resizeEvent = lambda event: self.resize_event() play_sound_pbtn.clicked.connect( lambda: self.tile_events.switch_play_pbtn(play_sound_pbtn)) settings_numpad_pbtn.mousePressEvent = lambda event: self.tile_events.press_settings_buttonEvent( self.parent)
class BasePageWidget(QWidget): def __init__(self, parent, text, show_hash=True): super().__init__() self.layout = QVBoxLayout(self) self.layout.setContentsMargins(0, 0, 0, 0) self.layout.setSpacing(0) # Placeholder Widget self.PlaceholderWidget = QWidget() self.PlaceholderWidget.setProperty("ToolBoxWidget", True) self.PlaceholderLayout = QHBoxLayout(self.PlaceholderWidget) self.PlaceholderLayout.setContentsMargins(0, 0, 0, 0) self.InfoPixmap = QPixmap(":resources/icons/info.svg") self.InfoPixmapLabel = QLabel() self.InfoPixmapLabel.setScaledContents(True) self.InfoPixmapLabel.setFixedSize(32, 32) self.InfoPixmapLabel.setPixmap(self.InfoPixmap) self.InfoLabelLayout = QHBoxLayout() self.InfoLabelLayout.setContentsMargins(0, 0, 0, 6) self.InfoLabel = QLabel(text) self.InfoLabelLayout.addWidget(self.InfoLabel) self.list_widget = BaseListWidget(self) self.list_widget.hide() self.PlaceholderLayout.addStretch() self.PlaceholderLayout.addWidget(self.InfoPixmapLabel) self.PlaceholderLayout.addLayout(self.InfoLabelLayout) self.PlaceholderLayout.addStretch() # Header Widget self.HeaderWidget = QWidget() self.HeaderWidget.hide() self.HeaderWidget.setProperty("ToolBoxWidget", True) self.HeaderLayout = QHBoxLayout(self.HeaderWidget) self.HeaderLayout.setContentsMargins(2, 2, 2, 2) self.fakeLabel = QLabel() self.subversionLabel = QLabel("Version") self.subversionLabel.setAlignment(Qt.AlignCenter) self.branchLabel = QLabel("Branch") self.branchLabel.setAlignment(Qt.AlignCenter) self.commitTimeLabel = QLabel("Commit Time") self.commitTimeLabel.setAlignment(Qt.AlignCenter) self.buildHashLabel = QLabel("Hash") self.buildHashLabel.setAlignment(Qt.AlignCenter) self.HeaderLayout.addWidget(self.fakeLabel) self.HeaderLayout.addWidget(self.subversionLabel) self.HeaderLayout.addWidget(self.branchLabel) self.HeaderLayout.addWidget(self.commitTimeLabel) if show_hash: self.HeaderLayout.addWidget(self.buildHashLabel) self.HeaderLayout.addStretch() # Final layout self.layout.addWidget(self.HeaderWidget) self.layout.addWidget(self.PlaceholderWidget) self.layout.addWidget(self.list_widget) def set_info_label_text(self, text): self.InfoLabel.setText(text)
class DashboardMainWindow(QMainWindow): def __init__(self, gui_concentrate_handler, parent=None): super(DashboardMainWindow, self).__init__(parent) self.gui_concentrate_handler = gui_concentrate_handler self.__setup_ui__() def __setup_ui__(self): self.setObjectName(DashboardMainWindowStyles.main_page_style[0]) self.setWindowModality(Qt.ApplicationModal) self.setContextMenuPolicy(Qt.NoContextMenu) self.setAcceptDrops(False) self.setAutoFillBackground(False) self.setDocumentMode(False) self.setDockNestingEnabled(False) self.setMouseTracking(True) self.central_widget = QWidget(self) self.central_widget.setStyleSheet( DashboardMainWindowStyles.central_widget_style) # Add Central Layout self.central_vlayout = QVBoxLayout(self.central_widget) self.central_vlayout.setContentsMargins(0, 0, 0, 0) self.central_vlayout.setObjectName("central_vlayout") # Add Containers self.containers = QFrame(self.central_widget) self.containers.setObjectName( DashboardMainWindowStyles.main_window_containers_style[0]) self.containers.setStyleSheet( DashboardMainWindowStyles.main_window_containers_style[1]) self.containers.setFrameShape(QFrame.NoFrame) self.containers.setFrameShadow(QFrame.Plain) self.containers.setLineWidth(0) # Add Containers Layout self.containers_gridlayout = QGridLayout(self.containers) self.containers_gridlayout.setContentsMargins(0, 0, 0, 0) self.containers_gridlayout.setSpacing(0) self.containers_gridlayout.setObjectName("containers_gridlayout") # Add Scroll Layout self.navigation_scroll_layout = QScrollArea(self.containers) self.navigation_scroll_layout.setHorizontalScrollBarPolicy( Qt.ScrollBarAlwaysOff) self.navigation_scroll_layout.setObjectName( DashboardMainWindowStyles.navigation_scroll_layout_style[0]) self.navigation_scroll_layout.setStyleSheet( DashboardMainWindowStyles.navigation_scroll_layout_style[1]) self.navigation_scroll_layout.setWidgetResizable(True) self.navigation_scroll_layout.setMinimumSize(QSize(71, 0)) self.navigation_scroll_layout.setMaximumSize(QSize(71, 16777215)) # add contents self.navigation_scroll_layout_contents = QWidget() self.navigation_scroll_layout_contents.setGeometry( QRect(0, 0, 71, self.height())) self.navigation_scroll_layout_contents.setObjectName( "scroll_area_contents_page_containers") # َAdd navigation_layout self.navigation_grid_layout = QGridLayout( self.navigation_scroll_layout_contents) self.navigation_grid_layout.setContentsMargins(0, 0, 0, 0) self.navigation_grid_layout.setVerticalSpacing(0) self.navigation_grid_layout.setObjectName("navigation_grid_layout") # Add Navigation self.navigation_menu = QFrame(self.navigation_scroll_layout_contents) self.navigation_menu.setObjectName( DashboardMainWindowStyles.navigation_menu_style[0]) self.navigation_menu.setStyleSheet( DashboardMainWindowStyles.navigation_menu_style[1]) self.navigation_menu.setMaximumSize(QSize(71, 16777215)) self.navigation_menu.setFrameShape(QFrame.StyledPanel) self.navigation_menu.setFrameShadow(QFrame.Raised) # set Media Screen self.__media_screen__() # Add MainFrame self.main_frame = QFrame(self.containers) size_policy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) size_policy.setHorizontalStretch(0) size_policy.setVerticalStretch(0) size_policy.setHeightForWidth( self.main_frame.sizePolicy().hasHeightForWidth()) self.main_frame.setSizePolicy(size_policy) self.main_frame.setObjectName("main_frame") # Add MainFrameLayout self.main_frame_gridLayout = QGridLayout(self.main_frame) self.main_frame_gridLayout.setContentsMargins(8, 8, 8, 8) self.main_frame_gridLayout.setSpacing(0) self.main_frame_gridLayout.setObjectName("gridLayout") # Add pic_main_logo self.pic_main_logo = QLabel(self.navigation_menu) self.pic_main_logo.setGeometry(QRect(0, 35, 71, 71)) self.pic_main_logo.setAlignment(Qt.AlignCenter) self.pic_main_logo.setPixmap( QPixmap(AppPaths.GUI_ASSETS_ICONS_PATH + "/main_window/kodiak_icon.svg")) self.pic_main_logo.setObjectName("pic_main_logo") # Add LblTime self.lbl_time = QLabel(self.navigation_menu) self.lbl_time.setGeometry(QRect(0, 120, 69, 20)) self.lbl_time.setObjectName( DashboardMainWindowStyles.lbl_time_style[0]) self.lbl_time.setStyleSheet( DashboardMainWindowStyles.lbl_time_style[1]) self.lbl_time.setAlignment(Qt.AlignCenter) # Add lblDate self.lbl_date = QLabel(self.navigation_menu) self.lbl_date.setGeometry(QRect(0, 140, 71, 21)) self.lbl_date.setObjectName( DashboardMainWindowStyles.lbl_date_style[0]) self.lbl_date.setStyleSheet( DashboardMainWindowStyles.lbl_date_style[1]) self.lbl_date.setAlignment(Qt.AlignCenter) self.navigation_item_vlayout = QWidget(self.navigation_menu) self.navigation_item_vlayout.setGeometry(QRect(0, 220, 64, 431)) self.navigation_item_vlayout.setObjectName("navigation_item_vlayout") # set li_hacktor_logo self.li_hacktor = QLabel(self.navigation_menu) self.li_hacktor.setAccessibleName("hacktor_logo") is_extra_screen, extra_screen_width, extra_screen_height = MediaScreen( ).is_extra_large() if is_extra_screen: if extra_screen_height <= 800: self.li_hacktor.hide() else: self.li_hacktor.setGeometry( QRect(25, self.height() - 80, 22, 33)) else: if extra_screen_height > 800: self.li_hacktor.setGeometry( QRect(25, self.height() - 80, 22, 33)) else: if extra_screen_height <= 600: self.li_hacktor.hide() else: self.li_hacktor.setGeometry( QRect(25, self.height(), 22, 33)) self.li_hacktor.setPixmap( QPixmap(AppPaths.GUI_ASSETS_ICONS_PATH + "/main_window/hacktor_logo.svg")) self.li_hacktor.setAlignment(Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self.page_containers = QFrame(self.main_frame) self.page_containers.setFrameShape(QFrame.StyledPanel) self.page_containers.setFrameShadow(QFrame.Raised) self.page_containers.setObjectName("center_page_maker") self.page_containers.setMinimumSize(self.width() - 111, self.height() - 111) self.main_frame_gridLayout.addWidget( self.page_containers, 1, 0, 1, 4) # Qt.AlignHCenter | Qt.AlignVCenter) self.page_containers_grid_layout = QGridLayout(self.page_containers) self.page_containers_grid_layout.setObjectName( "page_containers_gridLayout") from ...components.menu_containers.menu_containers import MenuContainers self.menu = MenuContainers( self.page_containers_grid_layout, gui_concentrate_handler=self.gui_concentrate_handler) self.menu.setup_ui( navigation_item_vlayout=self.navigation_item_vlayout, containers=self.containers, page_containers=self.page_containers) from ...components.top_navigation_bar_containers.top_navigation_bar_containers import TopNavigationBarContainers TopNavigationBarContainers( gui_concentrate_handler=self.gui_concentrate_handler).setup_ui( containers=self.main_frame, main_gridLayout=self.main_frame_gridLayout) main_icon = QIcon() main_icon.addPixmap( QPixmap(AppPaths.GUI_ASSETS_ICONS_PATH + "/main_window/main_logo.ico")) self.setWindowIcon(main_icon) self.setAutoFillBackground(False) self.setStyleSheet(DashboardMainWindowStyles.main_page_style[1]) self.setDocumentMode(False) self.setDockNestingEnabled(False) self.navigation_grid_layout.addWidget(self.navigation_menu, 0, 0, 1, 1) self.containers_gridlayout.addWidget(self.navigation_scroll_layout, 2, 2, 1, 1) self.navigation_scroll_layout.setWidget( self.navigation_scroll_layout_contents) # self.central_widget = QWidget(self) # self.central_widget.setStyleSheet(DashboardMainWindowStyles.central_widget_style) self.central_vlayout.addWidget(self.containers) self.containers_gridlayout.addWidget(self.main_frame, 2, 1, 1, 1) self.setCentralWidget(self.central_widget) self.__retranslateUi__() def __retranslateUi__(self): """ this method for retranslate data in UI """ _translate = QCoreApplication.translate self.setWindowTitle(_translate("MainWindow", "Kodiak")) self.lbl_time.setText("04:20") self.lbl_date.setText("2020/15/19") def __media_screen__(self): """ this is private method for set a standard size window for Your monitor , Tablet or ... """ is_small_screen, small_screen_width, small_screen_height = MediaScreen( ).is_small() is_medium_screen, medium_screen_width, medium_screen_height = MediaScreen( ).is_medium() is_large_screen, large_screen_width, large_screen_height = MediaScreen( ).is_large() is_extra_large_screen, extra_large_screen_width, extra_large_screen_height = MediaScreen( ).is_extra_large() if is_extra_large_screen: if extra_large_screen_height <= 900: self.setMinimumSize( QSize( extra_large_screen_width - (extra_large_screen_width / 4), extra_large_screen_height - (extra_large_screen_height / 4) + 100)) else: self.setMinimumSize( QSize( extra_large_screen_width - (extra_large_screen_width / 4), extra_large_screen_height - (extra_large_screen_height / 6) + 50)) self.navigation_menu.setMinimumSize(QSize(71, 700)) elif is_large_screen: self.setMinimumSize( QSize(large_screen_width - 200, large_screen_height - 90)) self.navigation_menu.setMinimumSize(QSize(71, 550)) elif is_medium_screen: self.setMinimumSize( QSize(medium_screen_width - 100, medium_screen_height - 100)) self.navigation_menu.setMinimumSize(QSize(71, 700)) elif is_small_screen: self.setMinimumSize( QSize(small_screen_width - 150, small_screen_width - 250)) self.navigation_menu.setMinimumSize(QSize(71, 700)) else: # any thing else self.setMinimumSize(QSize(1150, 800)) self.navigation_menu.setMinimumSize(QSize(71, 700)) # Delete From Memory del is_small_screen, is_medium_screen, is_large_screen del small_screen_width, medium_screen_width, large_screen_width del small_screen_height, medium_screen_height, large_screen_height
def __init__(self, folder, default, login, extension, fixed_folder, parent=None): """ Initialise layout of the widget. Arguments: folder - Folder name to mount. default - Default user name login - True, if it is possible to test the users credentials on this machine extension - True, if a mount extension is required parent - Parent widget Returns: None """ super(PasswordDialog, self).__init__(parent) # Global content self.user_le = QLineEdit(self) self.user_le.setText(default) self.password_le = QLineEdit(self) self.password_le.setEchoMode(QLineEdit.Password) self.folder_le = QLineEdit(self) self.folder_le.setText(folder) self.folder_le.setReadOnly(True) self.add_to_folder = QLineEdit(self) self.login = login self.extension = extension self.add_to_folder.setEnabled(self.extension) self.password = None self.username = None self.folder = None # Buttons button_accept = QPushButton('OK', self) button_accept.setObjectName('start') button_reject = QPushButton('Cancel', self) button_reject.setObjectName('stop') layout_button = QHBoxLayout() layout_button.setContentsMargins(0, 0, 0, 0) layout_button.addWidget(button_accept) layout_button.addWidget(button_reject) # Layout central_raw_layout = QVBoxLayout(self) central_raw_layout.setContentsMargins(0, 0, 0, 0) central_widget_raw = QWidget(self) central_widget_raw.setObjectName('central_raw') central_raw_layout.addWidget(central_widget_raw) central_layout = QVBoxLayout(central_widget_raw) central_widget = QWidget(self) central_widget.setObjectName('central') central_layout.addWidget(central_widget) layout = QVBoxLayout(central_widget) if not fixed_folder: layout.addWidget(QLabel('Username', self)) layout.addWidget(self.user_le) layout.addWidget(QLabel('Password', self)) layout.addWidget(self.password_le) else: self.user_le.hide() self.user_le.setText('FIXED') self.password_le.hide() layout.addWidget(QLabel('Mount device', self)) layout.addWidget(self.folder_le) if self.extension: self.add_to_folder.setPlaceholderText('Subfolder of mount device') layout.addWidget(QLabel('Mount device extension', self)) layout.addWidget(self.add_to_folder) else: self.add_to_folder.hide() layout.addLayout(layout_button) # Events button_accept.clicked.connect(self._my_accept) button_reject.clicked.connect(self.reject)
def __init__(self, parent=None): # pylint: disable=too-many-statements super(HooksPanel, self).__init__(parent=parent) self._app_window = parent if self._app_window.dwarf is None: print('HooksPanel created before Dwarf exists') return # connect to dwarf self._app_window.dwarf.onAddJavaHook.connect(self._on_add_hook) self._app_window.dwarf.onAddNativeHook.connect(self._on_add_hook) self._app_window.dwarf.onAddNativeOnLoadHook.connect(self._on_add_hook) self._app_window.dwarf.onAddJavaOnLoadHook.connect(self._on_add_hook) self._app_window.dwarf.onHitNativeOnLoad.connect( self._on_hit_native_on_load) self._app_window.dwarf.onHitJavaOnLoad.connect( self._on_hit_java_on_load) self._app_window.dwarf.onDeleteHook.connect(self._on_hook_deleted) self._hooks_list = DwarfListView() self._hooks_list.doubleClicked.connect(self._on_dblclicked) self._hooks_list.setContextMenuPolicy(Qt.CustomContextMenu) self._hooks_list.customContextMenuRequested.connect( self._on_context_menu) self._hooks_model = QStandardItemModel(0, 5) self._hooks_model.setHeaderData(0, Qt.Horizontal, 'Address') self._hooks_model.setHeaderData(1, Qt.Horizontal, 'T') self._hooks_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter, Qt.TextAlignmentRole) self._hooks_model.setHeaderData(2, Qt.Horizontal, 'Input') self._hooks_model.setHeaderData(3, Qt.Horizontal, '{}') self._hooks_model.setHeaderData(3, Qt.Horizontal, Qt.AlignCenter, Qt.TextAlignmentRole) self._hooks_model.setHeaderData(4, Qt.Horizontal, '<>') self._hooks_model.setHeaderData(4, Qt.Horizontal, Qt.AlignCenter, Qt.TextAlignmentRole) self._hooks_list.setModel(self._hooks_model) self._hooks_list.header().setStretchLastSection(False) self._hooks_list.header().setSectionResizeMode( 0, QHeaderView.ResizeToContents | QHeaderView.Interactive) self._hooks_list.header().setSectionResizeMode( 1, QHeaderView.ResizeToContents) self._hooks_list.header().setSectionResizeMode(2, QHeaderView.Stretch) self._hooks_list.header().setSectionResizeMode( 3, QHeaderView.ResizeToContents) self._hooks_list.header().setSectionResizeMode( 4, QHeaderView.ResizeToContents) v_box = QVBoxLayout(self) v_box.setContentsMargins(0, 0, 0, 0) v_box.addWidget(self._hooks_list) #header = QHeaderView(Qt.Horizontal, self) h_box = QHBoxLayout() h_box.setContentsMargins(5, 2, 5, 5) self.btn1 = QPushButton( QIcon(utils.resource_path('assets/icons/plus.svg')), '') self.btn1.setFixedSize(20, 20) self.btn1.clicked.connect(self._on_additem_clicked) btn2 = QPushButton(QIcon(utils.resource_path('assets/icons/dash.svg')), '') btn2.setFixedSize(20, 20) btn2.clicked.connect(self.delete_items) btn3 = QPushButton( QIcon(utils.resource_path('assets/icons/trashcan.svg')), '') btn3.setFixedSize(20, 20) btn3.clicked.connect(self.clear_list) h_box.addWidget(self.btn1) h_box.addWidget(btn2) h_box.addSpacerItem( QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Preferred)) h_box.addWidget(btn3) # header.setLayout(h_box) # header.setFixedHeight(25) # v_box.addWidget(header) v_box.addLayout(h_box) self.setLayout(v_box) self._bold_font = QFont(self._hooks_list.font()) self._bold_font.setBold(True) shortcut_addnative = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_N), self._app_window, self._on_addnative) shortcut_addnative.setAutoRepeat(False) shortcut_addjava = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_J), self._app_window, self._on_addjava) shortcut_addjava.setAutoRepeat(False) shortcut_add_native_on_load = QShortcut( QKeySequence(Qt.CTRL + Qt.Key_O), self._app_window, self._on_add_native_on_load) shortcut_add_native_on_load.setAutoRepeat(False) # new menu self.new_menu = QMenu('New') self.new_menu.addAction('Native', self._on_addnative) self.new_menu.addAction('Java', self._on_addjava) self.new_menu.addAction('Module loading', self._on_add_native_on_load)
class PromptContainer(QWidget): """Container for prompts to be shown above the statusbar. This is a per-window object, however each window shows the same prompt. Attributes: _layout: The layout used to show prompts in. _win_id: The window ID this object is associated with. Signals: update_geometry: Emitted when the geometry should be updated. """ STYLESHEET = """ QWidget#PromptContainer { {% if conf.statusbar.position == 'top' %} border-bottom-left-radius: {{ conf.prompt.radius }}px; border-bottom-right-radius: {{ conf.prompt.radius }}px; {% else %} border-top-left-radius: {{ conf.prompt.radius }}px; border-top-right-radius: {{ conf.prompt.radius }}px; {% endif %} } QWidget { font: {{ conf.fonts.prompts }}; color: {{ conf.colors.prompts.fg }}; background-color: {{ conf.colors.prompts.bg }}; } QLineEdit { border: {{ conf.colors.prompts.border }}; } QTreeView { selection-background-color: {{ conf.colors.prompts.selected.bg }}; border: {{ conf.colors.prompts.border }}; } QTreeView::branch { background-color: {{ conf.colors.prompts.bg }}; } QTreeView::item:selected, QTreeView::item:selected:hover, QTreeView::branch:selected { background-color: {{ conf.colors.prompts.selected.bg }}; } """ update_geometry = pyqtSignal() def __init__(self, win_id, parent=None): super().__init__(parent) self._layout = QVBoxLayout(self) self._layout.setContentsMargins(10, 10, 10, 10) self._win_id = win_id self._prompt: Optional[_BasePrompt] = None self.setObjectName('PromptContainer') self.setAttribute(Qt.WA_StyledBackground, True) stylesheet.set_register(self) message.global_bridge.prompt_done.connect(self._on_prompt_done) prompt_queue.show_prompts.connect(self._on_show_prompts) message.global_bridge.mode_left.connect(self._on_global_mode_left) def __repr__(self): return utils.get_repr(self, win_id=self._win_id) @pyqtSlot(usertypes.Question) def _on_show_prompts(self, question): """Show a prompt for the given question. Args: question: A Question object or None. """ item = self._layout.takeAt(0) if item is not None: widget = item.widget() log.prompt.debug("Deleting old prompt {}".format(widget)) widget.hide() widget.deleteLater() if question is None: log.prompt.debug("No prompts left, hiding prompt container.") self._prompt = None self.hide() return classes = { usertypes.PromptMode.yesno: YesNoPrompt, usertypes.PromptMode.text: LineEditPrompt, usertypes.PromptMode.user_pwd: AuthenticationPrompt, usertypes.PromptMode.download: DownloadFilenamePrompt, usertypes.PromptMode.alert: AlertPrompt, } klass = classes[question.mode] prompt = klass(question) log.prompt.debug("Displaying prompt {}".format(prompt)) self._prompt = prompt # If this question was interrupted, we already connected the signal if not question.interrupted: question.aborted.connect( functools.partial(self._on_aborted, prompt.KEY_MODE)) modeman.enter(self._win_id, prompt.KEY_MODE, 'question asked') self.setSizePolicy(prompt.sizePolicy()) self._layout.addWidget(prompt) prompt.show() self.show() prompt.setFocus() self.update_geometry.emit() @pyqtSlot() def _on_aborted(self, key_mode): """Leave KEY_MODE whenever a prompt is aborted.""" try: modeman.leave(self._win_id, key_mode, 'aborted', maybe=True) except objreg.RegistryUnavailableError: # window was deleted: ignore pass @pyqtSlot(usertypes.KeyMode) def _on_prompt_done(self, key_mode): """Leave the prompt mode in this window if a question was answered.""" modeman.leave(self._win_id, key_mode, ':prompt-accept', maybe=True) @pyqtSlot(usertypes.KeyMode) def _on_global_mode_left(self, mode): """Leave prompt/yesno mode in this window if it was left elsewhere. This ensures no matter where a prompt was answered, we leave the prompt mode and dispose of the prompt object in every window. """ if mode not in [usertypes.KeyMode.prompt, usertypes.KeyMode.yesno]: return modeman.leave(self._win_id, mode, 'left in other window', maybe=True) item = self._layout.takeAt(0) if item is not None: widget = item.widget() log.prompt.debug("Deleting prompt {}".format(widget)) widget.hide() widget.deleteLater() @cmdutils.register( instance='prompt-container', scope='window', modes=[usertypes.KeyMode.prompt, usertypes.KeyMode.yesno]) def prompt_accept(self, value=None, *, save=False): """Accept the current prompt. // This executes the next action depending on the question mode, e.g. asks for the password or leaves the mode. Args: value: If given, uses this value instead of the entered one. For boolean prompts, "yes"/"no" are accepted as value. save: Save the value to the config. """ assert self._prompt is not None question = self._prompt.question try: done = self._prompt.accept(value, save=save) except Error as e: raise cmdutils.CommandError(str(e)) if done: message.global_bridge.prompt_done.emit(self._prompt.KEY_MODE) question.done() @cmdutils.register(instance='prompt-container', scope='window', modes=[usertypes.KeyMode.prompt], maxsplit=0) def prompt_open_download(self, cmdline: str = None, pdfjs: bool = False) -> None: """Immediately open a download. If no specific command is given, this will use the system's default application to open the file. Args: cmdline: The command which should be used to open the file. A `{}` is expanded to the temporary file name. If no `{}` is present, the filename is automatically appended to the cmdline. pdfjs: Open the download via PDF.js. """ assert self._prompt is not None try: self._prompt.download_open(cmdline, pdfjs=pdfjs) except UnsupportedOperationError: pass @cmdutils.register(instance='prompt-container', scope='window', modes=[usertypes.KeyMode.prompt]) @cmdutils.argument('which', choices=['next', 'prev']) def prompt_item_focus(self, which): """Shift the focus of the prompt file completion menu to another item. Args: which: 'next', 'prev' """ assert self._prompt is not None try: self._prompt.item_focus(which) except UnsupportedOperationError: pass @cmdutils.register( instance='prompt-container', scope='window', modes=[usertypes.KeyMode.prompt, usertypes.KeyMode.yesno]) def prompt_yank(self, sel=False): """Yank URL to clipboard or primary selection. Args: sel: Use the primary selection instead of the clipboard. """ assert self._prompt is not None question = self._prompt.question if question.url is None: message.error('No URL found.') return if sel and utils.supports_selection(): target = 'primary selection' else: sel = False target = 'clipboard' utils.set_clipboard(question.url, sel) message.info("Yanked to {}: {}".format(target, question.url))
def initUI(self): """ Cria todos os componentes referentes as transformações. """ self.setWindowTitle('Filtros Passa-Baixa') # Filtros (F). self.labels = {} # F: Passa-Baixa self.labels[low_pass.Filter.BOX] = QLabel('Box') self.labels[low_pass.Filter.MEDIAN] = QLabel('Mediana') self.labels[low_pass.Filter.GAUSSIAN] = QLabel('Gaussiano') labelsLayout = QVBoxLayout() labelsLayout.setContentsMargins(0, 0, 0, 0) for key, label in self.labels.items(): if key != low_pass.Filter.BOX: label.setEnabled(False) labelsLayout.addWidget(label) labelsWidget = QWidget() labelsWidget.setLayout(labelsLayout) # Máscaras(M). self.opts = {} # M: Passa-Baixa self.opts[low_pass.Filter.BOX] = QComboBox() self.opts[low_pass.Filter.BOX].addItems(['3x3', '5x5', '7x7', '9x9', '11x11']) self.opts[low_pass.Filter.MEDIAN] = QComboBox() self.opts[low_pass.Filter.MEDIAN].addItems(['3x3', '5x5', '7x7', '9x9', '11x11']) self.opts[low_pass.Filter.GAUSSIAN] = DoubleTextSpinBox() self.opts[low_pass.Filter.GAUSSIAN].setSingleStep(0.5) self.opts[low_pass.Filter.GAUSSIAN].setRange(1, 11) optsLayout = QVBoxLayout() optsLayout.setContentsMargins(0, 0, 0, 0) for key, opt in self.opts.items(): if key != low_pass.Filter.BOX: opt.setEnabled(False) optsLayout.addWidget(opt) optsWidget = QWidget() optsWidget.setLayout(optsLayout) # Seleção do Filtro (S). self.radioButtons = {} # S: Passa-Baixa self.radioButtons[low_pass.Filter.BOX] = QRadioButton() self.radioButtons[low_pass.Filter.BOX].setChecked(True) self.radioButtons[low_pass.Filter.BOX]. \ clicked.connect(lambda: self.selectFilter(low_pass.Filter.BOX)) self.radioButtons[low_pass.Filter.MEDIAN] = QRadioButton() self.radioButtons[low_pass.Filter.MEDIAN].setChecked(False) self.radioButtons[low_pass.Filter.MEDIAN]. \ clicked.connect(lambda: self.selectFilter(low_pass.Filter.MEDIAN)) self.radioButtons[low_pass.Filter.GAUSSIAN] = QRadioButton() self.radioButtons[low_pass.Filter.GAUSSIAN].setChecked(False) self.radioButtons[low_pass.Filter.GAUSSIAN]. \ clicked.connect(lambda: self.selectFilter(low_pass.Filter.GAUSSIAN)) radioButtonsLayout = QVBoxLayout() radioButtonsLayout.setContentsMargins(0, 0, 0, 0) for key, button in self.radioButtons.items(): radioButtonsLayout.addWidget(button) radioButtonsWidget = QWidget() radioButtonsWidget.setLayout(radioButtonsLayout) # Layout. sublayout = QHBoxLayout() sublayout.addWidget(labelsWidget) sublayout.addWidget(optsWidget) sublayout.addWidget(radioButtonsWidget) # Botões de OK e Cancel. buttons = QDialogButtonBox( QDialogButtonBox.Ok | QDialogButtonBox.Cancel, Qt.Horizontal, self) buttons.accepted.connect(self.getFilter) buttons.rejected.connect(self.reject) subwidget = QWidget() subwidget.setLayout(sublayout) # Layout principal. mainLayout = QVBoxLayout() mainLayout.addWidget(subwidget) mainLayout.addWidget(buttons) self.setLayout(mainLayout)
class SearchBox(QGroupBox): """ Groupbox widget layout for a search API client's queries """ delete = pyqtSignal() search = pyqtSignal(str, str, int) def __init__(self, maxResults: int, title: str, saveDirectory: str, parent: QWidget = None): super().__init__(title, parent) self.setContentsMargins(11, 3, 0, 11) self.deleteInProgress = False # Main vertical layout self.mainLayout = QVBoxLayout() self.mainLayout.setAlignment(Qt.AlignTop) self.mainLayout.setContentsMargins(0, 0, 0, 0) # Delete button and its layout deleteLayout = QHBoxLayout() deleteLayout.setAlignment(Qt.AlignRight) deleteLayout.setContentsMargins(0, 6, 0, 0) self.deleteButton = DeleteButton() deleteLayout.addWidget(self.deleteButton) self.mainLayout.addLayout(deleteLayout) # Search box layout searchBoxLayout = QVBoxLayout() searchBoxLayout.setAlignment(Qt.AlignTop) searchBoxLayout.setContentsMargins(0, 0, 11, 0) self.mainLayout.addLayout(searchBoxLayout) # Search query layout searchLayout = QHBoxLayout() self.searchTextBox = TextBox('Enter your search query here...') self.searchButton = SearchButton() self.searchButton.setEnabled(False) searchLayout.addWidget(self.searchTextBox) searchLayout.addWidget(self.searchButton) searchLayout.addStretch(1) searchBoxLayout.addLayout(searchLayout) # Number of images numImagesLayout = QHBoxLayout() self.numImages = QSpinBox() self.numImages.setRange(1, maxResults) self.numImages.setValue(1) numImagesLayout.addWidget(QLabel('Number of images')) numImagesLayout.addWidget(self.numImages) numImagesLayout.addStretch(1) searchBoxLayout.addLayout(numImagesLayout) # Save directory self.saveDir = DirectorySelector(saveDirectory) searchBoxLayout.addWidget(self.saveDir) searchBoxLayout.addStretch(1) self.setLayout(self.mainLayout) # Connect signals and slots self.deleteButton.clicked.connect(self.destroy) self.searchButton.clicked.connect(self.sendSearchRequest) self.searchButton.clicked.connect( self.destroy) # delete widget on search self.searchTextBox.textChanged.connect(self.updateSearchEnabledState) def numberOfImages(self): return self.numImages.value() def searchQuery(self): return self.searchTextBox.toPlainText() def saveDirectory(self): return self.saveDir.selectedDirectory() def setSaveDirectory(self, directory: str): self.saveDir.setSelectedDirectory(directory) def setProperties(self, title: str, marginLeft: int = 11, marginTop: int = 3, marginRight: int = 3, marginBottom: int = 11): self.setTitle(title) # Also set the contents margins since setting the title seems to change the values initially defined (bug?) self.setContentsMargins(marginLeft, marginTop, marginRight, marginBottom) def _clearLayout(self, layout): if layout is not None: while layout.count(): item = layout.takeAt(0) widget = item.widget() if widget is not None: widget.deleteLater() else: self._clearLayout(item.layout()) @pyqtSlot() def sendSearchRequest(self): self.search.emit(self.saveDirectory(), self.searchQuery(), self.numberOfImages()) @pyqtSlot() def updateSearchEnabledState(self): self.searchButton.setEnabled(self.searchTextBox.toPlainText() != '') @pyqtSlot() def destroy(self): self.deleteInProgress = True # Delete all items in the main layout self._clearLayout(self.mainLayout) # Delete self self.deleteLater() self.delete.emit()
class MyWindow(QMainWindow): # signal to begin running socket object startSign = pyqtSignal() def __init__(self, userType, name, host, port, parent=None): super(MyWindow, self).__init__(parent) self.setGeometry(600, 300, 400, 500) self.setWindowTitle(f'PyQT messanger - as {name}') self.setWindowIcon(QIcon('../img/message.png')) self.setStyleSheet(open('style.css').read()) self.name = name self.type = userType self.selection = '' # initialize socket object and thread object, add socket object to # thread and add neccessary signals self.soket = SocketWork(userType, name, host, port) self.threadWork = QThread() self.threadWork.start() self.soket.moveToThread(self.threadWork) self.soket.messageSignal.connect(self.addMessage) self.soket.usersChanged.connect(self.showUserList) self.startSign.connect(self.soket.startConnection) self.startSign.emit() # add current user to userlist self.soket.userList[(host, port)] = name self.initUI() def initUI(self): # main layout and central widget cenWidget = QWidget(self) self.mainVertLayout = QVBoxLayout(cenWidget) self.mainVertLayout.setSpacing(0) self.mainVertLayout.setContentsMargins(1, 1, 1, 1) self.mainVertLayout.addWidget(QLabel('Chat messages:')) # area for displaying messages self.messageScroll = QScrollArea() self.messageScroll.setWidgetResizable(True) self.messageScroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.messageScrollBar = self.messageScroll.verticalScrollBar() self.messageScrollBar.rangeChanged.connect(self.changeScrollFocus) butWidg = QWidget() self.chatLay = QVBoxLayout(butWidg) self.chatLay.setAlignment(Qt.AlignTop) self.chatLay.setSpacing(2) self.chatLay.setContentsMargins(3, 3, 3, 3) self.messageScroll.setWidget(butWidg) self.mainVertLayout.addWidget(self.messageScroll) # message input and 'send' button butWidg = QWidget() butLay = QHBoxLayout(butWidg) self.messageInput = QLineEdit(butWidg) self.messageInput.setPlaceholderText('Your message') self.messageInput.returnPressed.connect(self.queueMessage) butLay.addWidget(self.messageInput) butLay.addWidget(QPushButton('Send', clicked=self.queueMessage)) butWidg.setLayout(butLay) butLay.setSpacing(2) butLay.setContentsMargins(1, 1, 1, 1) self.mainVertLayout.addWidget(butWidg) # checkbox for displaying user list and buttons for message styling checkWidg = QWidget() checkLay = QHBoxLayout(checkWidg) self.showUsersCheckBox = QCheckBox(checkWidg) self.showUsersCheckBox.stateChanged.connect(self.showUserList) checkLay.addWidget(self.showUsersCheckBox) checkLay.addWidget(QLabel('Show user list')) styleButtons = [ ('Bold', '../img/bold.png'), ('Italic', '../img/italic.png') ] for name, ref in styleButtons: button = QPushButton(name, clicked=functools.partial( self.addStyles, name[0].lower())) button.setObjectName('styleButton') button.setIcon(QIcon(ref)) button.setFocusPolicy(Qt.NoFocus) checkLay.addWidget(button) checkLay.setAlignment(Qt.AlignLeft) checkWidg.setLayout(checkLay) butLay.setSpacing(2) butLay.setContentsMargins(1, 1, 1, 1) self.mainVertLayout.addWidget(checkWidg) self.setCentralWidget(cenWidget) # function that depending on where user was focused before message was added # scroll to last messages (if focus was on last message) or leaves window # without scrolling def changeScrollFocus(self): if self.focusOnBottom: self.messageScrollBar.setValue(self.messageScrollBar.maximum()) # add bold and italic style tags to message def addStyles(self, sign): selectedText = self.messageInput.selectedText() if selectedText: text = self.messageInput.text() start = self.messageInput.selectionStart() end = self.messageInput.selectionEnd() fullMessage = f'{text[0:start]}<{sign}>{selectedText}</{sign}>'\ f'{text[end:len(text)]}' self.messageInput.setText(fullMessage) else: self.messageInput.insert(f'<{sign}></{sign}>') # adds message to queue (list) for sending and sets input to blank def queueMessage(self): if self.messageInput.text(): message = {'name': self.name, 'time': datetime.datetime.now().strftime("%H:%M"), 'text': self.messageInput.text()} self.addMessage(message) self.soket.pendingMessages.append(message) self.messageInput.setText('') # adds message to main window message view def addMessage(self, message): messageWidget = QLabel(f'<b>{message["name"]} <i>at {message["time"]}:</b><br>' f'{message["text"]}') messageWidget.setWordWrap(True) messageWidget.setTextInteractionFlags(Qt.TextSelectableByMouse) if message["name"] == self.name: messageWidget.setStyleSheet('color: green;') if message['text'].startswith(f'@{self.name}, '): messageWidget.setStyleSheet('color: red;') # check where user is focused (for changeScrollFocus method) self.focusOnBottom = (self.messageScrollBar.value() == self.messageScrollBar.maximum()) self.chatLay.addWidget(messageWidget) # adds userlist from window depending on state of respective checkbox def showUserList(self): self.hideUserList() if self.showUsersCheckBox.isChecked(): self.userListScroll = QScrollArea() self.userListScroll.setWidgetResizable(True) self.userListScroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) butWidg = QWidget() chatLay = QVBoxLayout(butWidg) chatLay.setAlignment(Qt.AlignTop) chatLay.setSpacing(2) chatLay.setContentsMargins(2, 2, 2, 2) for userName in self.soket.userList.values(): user = QLabel(f'{userName}') user.installEventFilter(self) chatLay.addWidget(user) self.userListScroll.setWidget(butWidg) self.mainVertLayout.addWidget(self.userListScroll) # adds functionality to address user by clicking his name in userList # without the need to type his name by hand def eventFilter(self, obj, event): if event.type() == QEvent.MouseButtonPress: if event.button() == Qt.LeftButton and type(obj) == QLabel: self.messageInput.setText(f'@{obj.text()}, ' + self.messageInput.text()) return QObject.event(obj, event) # removes userlist from window depending on state of respective checkbox def hideUserList(self): if hasattr(self, 'userListScroll'): self.userListScroll.setParent(None) del self.userListScroll # operations to do when window is closed def closeEvent(self, event): self.soket.closeConnection() self.threadWork.quit()
class CollapsibleBox(QWidget): def __init__(self, title="", parent=None): super(CollapsibleBox, self).__init__(parent) self.toggle_button = QToolButton(text=title, checkable=True, checked=False) self.toggle_button.setStyleSheet("QToolButton { border: none; }") self.toggle_button.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.toggle_button.setArrowType(Qt.RightArrow) self.toggle_button.pressed.connect(self.on_pressed) self.toggle_animation = QParallelAnimationGroup(self) self.content_area = QScrollArea(maximumHeight=0, minimumHeight=0) self.content_area.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) self.content_area.setFrameShape(QFrame.NoFrame) self.content_area.setVisible(False) self.lay = QVBoxLayout(self) self.lay.setSpacing(0) self.lay.setContentsMargins(0, 0, 0, 0) self.lay.addWidget(self.toggle_button) self.lay.addWidget(self.content_area) self.toggle_animation.addAnimation( QPropertyAnimation(self, b"minimumHeight")) self.toggle_animation.addAnimation( QPropertyAnimation(self, b"maximumHeight")) self.toggle_animation.addAnimation( QPropertyAnimation(self.content_area, b"maximumHeight")) @pyqtSlot() def on_pressed(self): checked = self.toggle_button.isChecked() self.content_area.setVisible(not checked) self.toggle_button.setArrowType( Qt.DownArrow if not checked else Qt.RightArrow) self.toggle_animation.setDirection( QAbstractAnimation.Forward if not checked else QAbstractAnimation. Backward) self.toggle_animation.start() self.toggle_button.setChecked(not checked) def setContentLayout(self, layout): lay = self.content_area.layout() del lay self.content_area.setLayout(layout) self.content_area.setStyleSheet("background-color:transparent;") collapsed_height = (self.sizeHint().height() - self.content_area.maximumHeight()) content_height = layout.sizeHint().height() for i in range(self.toggle_animation.animationCount()): animation = self.toggle_animation.animationAt(i) animation.setDuration(500) animation.setStartValue(collapsed_height) animation.setEndValue(collapsed_height + content_height) content_animation = self.toggle_animation.animationAt( self.toggle_animation.animationCount() - 1) content_animation.setDuration(500) content_animation.setStartValue(0) content_animation.setEndValue(content_height)
class ViewMovieSearchUrl(QMdiSubWindow): def __init__(self, main): """ Search movie web url by title. :param main: Reference for main windows. """ super(ViewMovieSearchUrl, self).__init__() self.session = DB.get_session() self.main = main self.row_select = -1 text = texts.movie_s + ' ' + texts.search_web_url self.setWindowTitle(text) self.width = int(0.8 * main.frameSize().width()) self.height = int(0.8 * main.frameSize().height()) self.setGeometry(0, 0, self.width, self.height) self.subwindow = QWidget() p = self.palette() p.setColor(self.backgroundRole(), QColor(230, 230, 250)) self.setPalette(p) self.setWidget(self.subwindow) self.vbox_main = QVBoxLayout(self.subwindow) self.vbox_main.setContentsMargins(20, 20, 20, 20) # Title self.lb_title = QLabel(texts.title_s) self.lb_title.setMaximumSize(QSize(100, 25)) movie = db_select_all(self.session, Movie) self.cb_title = cb_create() populate_combobox(self.cb_title, movie) # Words text = texts.or_s + ' ' + texts.with_the_p + ' ' + texts.term_p self.lb_term = QLabel(text) self.le_term = le_create(30, texts.with_term_tt) self.le_term.setPlaceholderText('pressione enter') self.le_term.editingFinished.connect(self.query_term) # HBoxSearch self.hbox_search = hbox_create( [self.lb_title, self.cb_title, self.lb_term, self.le_term]) spacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.hbox_search.addItem(spacer) self.vbox_main.addLayout(self.hbox_search) # total self.lb_total = QLabel(texts.lb_total) self.le_total = le_create(255) self.le_total.setMaximumWidth(100) # Buttons self.pb_clear = pb_create(texts.pb_clear, 11, 30) self.pb_clear.setMaximumWidth(100) self.pb_clear.setShortcut('Ctrl+L') self.pb_clear.clicked.connect(self.clear) self.pb_leave = pb_create(texts.pb_leave, 11, 30) self.pb_leave.setMaximumWidth(100) self.pb_leave.setShortcut('Ctrl+Q') self.pb_leave.clicked.connect(self.close) # Hbox_result self.hbox_result = hbox_create( [self.lb_total, self.le_total, self.pb_clear, self.pb_leave]) spacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.hbox_result.addItem(spacer) self.vbox_main.addLayout(self.hbox_result) # Table self.table = QTableWidget() self.table.horizontalHeader().sectionClicked.connect( self.repaint_cells) self.rows = 0 self.clear_table() query = self.session.query(Movie).all() self.set_table(query) self.vbox_main.addWidget(self.table) self.cb_title.currentIndexChanged.connect(self.query_title) # Clear Table def clear_table(self): """ Clear all tables values. """ self.table.clear() self.table.setRowCount(0) self.table.setColumnCount(5) self.rows = 0 headers = [ texts.title_s, texts.original_title_s, texts.url, texts.last_edit, 'id' ] self.table.setHorizontalHeaderLabels(headers) col_width = self.width - 50 self.table.setColumnWidth(0, 0.30 * col_width) self.table.setColumnWidth(1, 0.30 * col_width) self.table.setColumnWidth(2, 0.30 * col_width) self.table.setColumnWidth(3, 0.10 * col_width) self.table.setColumnWidth(4, 0) self.table.verticalHeader().setVisible(False) self.table.setStyleSheet('background-color: #FFFFFF;') self.table.setSortingEnabled(True) # Repaint Cell def repaint_cells(self, event): """ When the table is self-reclassified repaint it. """ for r in range(self.rows): for i in range(5): if r % 2 == 0: self.table.item(r, i).setBackground(QColor(240, 250, 228)) else: self.table.item(r, i).setBackground(QColor(255, 230, 245)) # View Movie def view_obj(self, row, col): """ When clicked a cell table who has title show the html view of movie. :param row: The number of the row on which the cell was clicked. :param col: The number of the column on which the cell was clicked. """ if self.row_select != row and col == 0: movie_id = self.table.item(row, 4).text() obj = self.session.query(Movie).get(movie_id) self.main.view_html(obj.view, obj.name) self.row_select = row # Set Table def set_table(self, movies): """ Set table with all movies. :param query: The movies values. """ self.clear_table() for movie in movies: self.table.insertRow(self.rows) self.table.setItem(self.rows, 0, QTableWidgetItem(movie.name)) font = QFont() font.setUnderline(True) self.table.item(self.rows, 0).setForeground(QColor(55, 34, 243)) self.table.item(self.rows, 0).setFont(font) if movie.original_name: self.table.setItem(self.rows, 1, QTableWidgetItem(movie.original_name)) else: self.table.setItem(self.rows, 1, QTableWidgetItem('')) self.table.setItem(self.rows, 2, QTableWidgetItem(movie.search_url)) date = "{:%d/%m/%Y}".format(movie.new_edit) self.table.setItem(self.rows, 3, QTableWidgetItem(date)) self.table.setItem(self.rows, 4, QTableWidgetItem(str(movie.id))) for i in range(5): if self.rows % 2 == 0: self.table.item(self.rows, i).setBackground(QColor(240, 250, 228)) else: self.table.item(self.rows, i).setBackground(QColor(255, 230, 245)) self.table.item(self.rows, i).setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) self.table.cellClicked.connect(self.view_obj) self.rows += 1 self.le_total.setText(str(self.rows)) def set_query_title(self, movie): """ Set table with movies values search in database. :param movie: The movies values from a database search. """ self.clear_table() self.table.insertRow(self.rows) self.table.setItem(self.rows, 0, QTableWidgetItem(movie.name)) font = QFont() font.setUnderline(True) self.table.item(self.rows, 0).setForeground(QColor(55, 34, 243)) self.table.item(self.rows, 0).setFont(font) if movie.original_name: self.table.setItem(self.rows, 1, QTableWidgetItem(movie.original_name)) else: self.table.setItem(self.rows, 1, QTableWidgetItem('')) self.table.setItem(self.rows, 2, QTableWidgetItem(movie.search_url)) date = "{:%d/%m/%Y}".format(movie.new_edit) self.table.setItem(self.rows, 3, QTableWidgetItem(date)) self.table.setItem(self.rows, 4, QTableWidgetItem(str(movie.id))) for i in range(5): if self.rows % 2 == 0: self.table.item(self.rows, i).setBackground(QColor(249, 250, 228)) else: self.table.item(self.rows, i).setBackground(QColor(226, 255, 228)) self.table.item(self.rows, i).setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) self.table.cellClicked.connect(self.view_obj) self.rows += 1 self.le_total.setText(str(self.rows)) # Query def query_title(self): """ Search movie by selected title in QCombobox. """ id, name = get_combobox_info(self.cb_title) movie = self.session.query(Movie).get(id) self.set_query_title(movie) def query_term(self): """ Search movie by words in title. """ words = self.le_term.text().split() queries = [] for word in words: word = '%{0}%'.format(word) query = self.session.query(Movie) \ .filter(Movie.name.ilike(word)).all() queries += query self.set_table(queries) def clear(self): """ Clear all values in windows. """ self.cb_title.currentIndexChanged.disconnect() self.cb_title.setCurrentIndex(0) self.clear_table() query = self.session.query(Movie).all() self.set_table(query) self.cb_title.currentIndexChanged.connect(self.query_title) # Close Event def closeEvent(self, event): self.session.close()
def __init__(self, maxResults: int, title: str, saveDirectory: str, parent: QWidget = None): super().__init__(title, parent) self.setContentsMargins(11, 3, 0, 11) self.deleteInProgress = False # Main vertical layout self.mainLayout = QVBoxLayout() self.mainLayout.setAlignment(Qt.AlignTop) self.mainLayout.setContentsMargins(0, 0, 0, 0) # Delete button and its layout deleteLayout = QHBoxLayout() deleteLayout.setAlignment(Qt.AlignRight) deleteLayout.setContentsMargins(0, 6, 0, 0) self.deleteButton = DeleteButton() deleteLayout.addWidget(self.deleteButton) self.mainLayout.addLayout(deleteLayout) # Search box layout searchBoxLayout = QVBoxLayout() searchBoxLayout.setAlignment(Qt.AlignTop) searchBoxLayout.setContentsMargins(0, 0, 11, 0) self.mainLayout.addLayout(searchBoxLayout) # Search query layout searchLayout = QHBoxLayout() self.searchTextBox = TextBox('Enter your search query here...') self.searchButton = SearchButton() self.searchButton.setEnabled(False) searchLayout.addWidget(self.searchTextBox) searchLayout.addWidget(self.searchButton) searchLayout.addStretch(1) searchBoxLayout.addLayout(searchLayout) # Number of images numImagesLayout = QHBoxLayout() self.numImages = QSpinBox() self.numImages.setRange(1, maxResults) self.numImages.setValue(1) numImagesLayout.addWidget(QLabel('Number of images')) numImagesLayout.addWidget(self.numImages) numImagesLayout.addStretch(1) searchBoxLayout.addLayout(numImagesLayout) # Save directory self.saveDir = DirectorySelector(saveDirectory) searchBoxLayout.addWidget(self.saveDir) searchBoxLayout.addStretch(1) self.setLayout(self.mainLayout) # Connect signals and slots self.deleteButton.clicked.connect(self.destroy) self.searchButton.clicked.connect(self.sendSearchRequest) self.searchButton.clicked.connect( self.destroy) # delete widget on search self.searchTextBox.textChanged.connect(self.updateSearchEnabledState)
class TableContainer(QFrame, BgTransparentMixin): def __init__(self, app, parent=None): super().__init__(parent) self._app = app self._renderer = None self._table = None # current visible table self._tables = [] self._extra = None self.toolbar = SongsTableToolbar() self.tabbar = TableTabBarV2() self.meta_widget = TableMetaWidget(parent=self) self.songs_table = SongsTableView(parent=self) self.albums_table = AlbumListView(parent=self) self.artists_table = ArtistListView(parent=self) self.videos_table = VideoListView(parent=self) self.playlists_table = PlaylistListView(parent=self) self.comments_table = CommentListView(parent=self) self.desc_widget = DescLabel(parent=self) self._tables.append(self.songs_table) self._tables.append(self.albums_table) self._tables.append(self.artists_table) self._tables.append(self.playlists_table) self._tables.append(self.videos_table) self._tables.append(self.comments_table) self.songs_table.play_song_needed.connect( lambda song: asyncio.ensure_future(self.play_song(song))) self.videos_table.play_video_needed.connect( lambda video: aio.create_task(self.play_video(video))) def goto_model(model): self._app.browser.goto(model=model) for signal in [self.songs_table.show_artist_needed, self.songs_table.show_album_needed, self.albums_table.show_album_needed, self.artists_table.show_artist_needed, self.playlists_table.show_playlist_needed, ]: signal.connect(goto_model) self.toolbar.play_all_needed.connect(self.play_all) self.songs_table.add_to_playlist_needed.connect(self._add_songs_to_playlist) self.songs_table.about_to_show_menu.connect(self._songs_table_about_to_show_menu) self.songs_table.activated.connect( lambda index: aio.create_task(self._on_songs_table_activated(index))) self._setup_ui() def _setup_ui(self): self.current_table = None self.tabbar.hide() self.meta_widget.add_tabbar(self.tabbar) self.desc_widget.hide() self._layout = QVBoxLayout(self) self._layout.addWidget(self.meta_widget) self._layout.addWidget(self.toolbar) self._layout.addSpacing(10) self._layout.addWidget(self.desc_widget) for table in self._tables: self._layout.addWidget(table) self._layout.addStretch(0) self._layout.setContentsMargins(0, 0, 0, 0) self._layout.setSpacing(0) @property def current_extra(self): return self._extra @current_extra.setter def current_extra(self, extra): """(alpha)""" if self._extra is not None: self._layout.removeWidget(self._extra) self._extra.deleteLater() del self._extra self._extra = extra if self._extra is not None: self._layout.insertWidget(1, self._extra) @property def current_table(self): """current visible table, if no table is visible, return None""" return self._table @current_table.setter def current_table(self, table): """set table as current visible table show table and hide other tables, if table is None, hide all tables. """ for t in self._tables: if t != table: t.hide() if table is None: self.toolbar.hide() else: self.desc_widget.hide() table.show() if table is self.artists_table: self.toolbar.artists_mode() if table is self.albums_table: self.toolbar.albums_mode() if table is self.songs_table: self.toolbar.songs_mode() if isinstance(self._table, ImgListView): self._table.setModel(None) self._table = table async def set_renderer(self, renderer): """set ui renderer TODO: add lock for set_renderer """ if renderer is None: return # firstly, tear down everything # tear down last renderer if self._renderer is not None: await self._renderer.tearDown() self.meta_widget.hide() self.meta_widget.clear() self.tabbar.hide() self.tabbar.check_default() self.current_table = None self.current_extra = None # clean right_panel background image self._app.ui.right_panel.show_background_image(None) # disconnect songs_table signal signals = ( self.tabbar.show_contributed_albums_needed, self.tabbar.show_albums_needed, self.tabbar.show_songs_needed, self.tabbar.show_artists_needed, self.tabbar.show_playlists_needed, self.tabbar.show_desc_needed, ) for signal in signals: disconnect_slots_if_has(signal) # unbind some callback function self.songs_table.remove_song_func = None # secondly, prepare environment self.show() # thirdly, setup new renderer await renderer.setUp(self) self._renderer = renderer await self._renderer.render() async def play_song(self, song): self._app.player.play_song(song) async def play_video(self, video): media = await aio.run_in_executor(None, lambda: video.media) self._app.player.play(media) def play_all(self): task_name = 'play-all' task_spec = self._app.task_mgr.get_or_create(task_name) def reader_readall_cb(task): with suppress(ProviderIOError, asyncio.CancelledError): songs = task.result() self._app.player.play_songs(songs=songs) self.toolbar.enter_state_playall_end() model = self.songs_table.model() # FIXME: think about a more elegant way reader = model.sourceModel()._reader if reader is not None: if reader.count is not None: task = task_spec.bind_blocking_io(reader.readall) self.toolbar.enter_state_playall_start() task.add_done_callback(reader_readall_cb) return songs = model.sourceModel().songs self._app.player.play_songs(songs=songs) async def show_model(self, model): model = self._app.library.cast_model_to_v1(model) model_type = ModelType(model.meta.model_type) if model_type == ModelType.album: renderer = AlbumRenderer(model) elif model_type == ModelType.artist: renderer = ArtistRenderer(model) elif model_type == ModelType.playlist: renderer = PlaylistRenderer(model) else: renderer = None await self.set_renderer(renderer) def show_collection(self, coll): renderer = SongsCollectionRenderer(coll) aio.create_task(self.set_renderer(renderer)) def show_songs(self, songs=None, songs_g=None): """(DEPRECATED) provided only for backward compatibility""" warnings.warn('use readerer.show_songs please') renderer = Renderer() task = aio.create_task(self.set_renderer(renderer)) if songs is not None: reader = wrap(songs) else: reader = songs_g task.add_done_callback( lambda _: renderer.show_songs(reader=reader)) def show_albums_coll(self, albums_g): aio.create_task(self.set_renderer(AlbumsCollectionRenderer(albums_g))) def show_artists_coll(self, artists_g): aio.create_task(self.set_renderer(ArtistsCollectionRenderer(artists_g))) def search(self, text): if self.isVisible() and self.songs_table is not None: self.songs_table.filter_row(text) def _add_songs_to_playlist(self, songs): for song in songs: self._app.playlist.add(song) def _songs_table_about_to_show_menu(self, ctx): add_action = ctx['add_action'] models = ctx['models'] if not models or models[0].meta.model_type != ModelType.song: return song = models[0] goto = self._app.browser.goto if self._app.library.check_flags_by_model(song, ProviderFlags.similar): add_action('相似歌曲', lambda *args: goto(model=song, path='/similar')) if self._app.library.check_flags_by_model(song, ProviderFlags.hot_comments): add_action('歌曲评论', lambda *args: goto(model=song, path='/hot_comments')) async def _on_songs_table_activated(self, index): """ QTableView should have no IO operations. """ from feeluown.gui.widgets.songs import Column song = index.data(Qt.UserRole) if index.column() == Column.song: self.songs_table.play_song_needed.emit(song) else: try: song = await aio.run_in_executor( None, self._app.library.song_upgrade, song) except NotSupported: assert ModelFlags.v2 & song.meta.flags self._app.show_msg('资源提供放不支持该功能') logger.info(f'provider:{song.source} does not support song_get') song.state = ModelState.cant_upgrade except (ProviderIOError, RequestException) as e: # FIXME: we should only catch ProviderIOError here, # but currently, some plugins such fuo-qqmusic may raise # requests.RequestException logger.exception('upgrade song failed') self._app.show_msg(f'请求失败: {str(e)}') else: if index.column() == Column.artist: artists = song.artists if artists: if len(artists) > 1: self.songs_table.show_artists_by_index(index) else: self.songs_table.show_artist_needed.emit(artists[0]) elif index.column() == Column.album: self.songs_table.show_album_needed.emit(song.album) model = self.songs_table.model() topleft = model.index(index.row(), 0) bottomright = model.index(index.row(), 4) model.dataChanged.emit(topleft, bottomright, [])
class RightPanel(QFrame): def __init__(self, app, parent=None): super().__init__(parent) self._app = app self._pixmap = None self._layout = QVBoxLayout(self) self._stacked_layout = QStackedLayout() self.scrollarea = ScrollArea(self._app, self) self.table_container = self.scrollarea.t self.bottom_panel = BottomPanel(app, self) self._setup_ui() def _setup_ui(self): self.scrollarea.setMinimumHeight(100) self._layout.addWidget(self.bottom_panel) self._layout.addLayout(self._stacked_layout) self._stacked_layout.addWidget(self.scrollarea) self._layout.setContentsMargins(0, 0, 0, 0) self._layout.setSpacing(0) def show_songs(self, songs): self.set_body(self.scrollarea) self.table_container.show_songs(songs) def set_body(self, widget): """ .. versionadded:: 3.7.7 """ if widget is self.table_container: widget = self.scrollarea if widget is not self.scrollarea: self.show_background_image(None) # remove tmp widgets for i in range(self._stacked_layout.count()): w = self._stacked_layout.widget(i) if w not in (self.scrollarea, ): self._stacked_layout.removeWidget(w) self._stacked_layout.addWidget(widget) self._stacked_layout.setCurrentWidget(widget) def show_collection(self, coll, model_type): def _show_pure_albums_coll(coll): self.set_body(self.scrollarea) reader = wrap(coll.models) self.table_container.show_albums_coll(reader) def _show_pure_songs_coll(coll): self.set_body(self.scrollarea) self.table_container.show_collection(coll) def _show_pure_videos_coll(coll): from feeluown.gui.page_containers.table import VideosRenderer self.set_body(self.scrollarea) reader = wrap(coll.models) renderer = VideosRenderer(reader) aio.create_task(self.table_container.set_renderer(renderer)) if model_type == ModelType.song: _show_pure_songs_coll(coll) elif model_type == ModelType.album: _show_pure_albums_coll(coll) elif model_type == ModelType.video: _show_pure_videos_coll(coll) else: logger.warning("can't render this kind of collection") def show_background_image(self, pixmap): self._pixmap = pixmap self._adjust_meta_widget_height() self.update() def paintEvent(self, e): """ draw pixmap as a the background with a dark overlay HELP: currently, this cost much CPU """ painter = QPainter(self) painter.setPen(Qt.NoPen) painter.setRenderHint(QPainter.Antialiasing) painter.setRenderHint(QPainter.SmoothPixmapTransform) # calculate available size draw_width = self.width() draw_height = 10 # spacing defined in table container draw_height += self.bottom_panel.height() if self.table_container.meta_widget.isVisible(): draw_height += self.table_container.meta_widget.height() extra = self.table_container.current_extra if extra is not None and extra.isVisible(): draw_height += extra.height() if self.table_container.toolbar.isVisible(): draw_height += self.table_container.toolbar.height() scrolled = self.scrollarea.verticalScrollBar().value() max_scroll_height = draw_height - self.bottom_panel.height() # Do not draw the pixmap when it is not shown. if scrolled >= max_scroll_height: painter.save() painter.setBrush(self.palette().brush(QPalette.Window)) painter.drawRect(self.bottom_panel.rect()) painter.restore() return if self._pixmap is not None: self._draw_pixmap(painter, draw_width, draw_height, scrolled) self._draw_pixmap_overlay(painter, draw_width, draw_height, scrolled) curve = QEasingCurve(QEasingCurve.OutCubic) alpha_ratio = min(scrolled / max_scroll_height, 1) alpha = int(250 * curve.valueForProgress(alpha_ratio)) painter.save() color = self.palette().color(QPalette.Window) color.setAlpha(alpha) painter.setBrush(color) painter.drawRect(self.bottom_panel.rect()) painter.restore() else: # draw gradient for widgets(bottom panel + meta_widget + ...) above table self._draw_overlay(painter, draw_width, draw_height, scrolled) # if scrolled height > 30, draw background to seperate bottom_panel and body if scrolled >= 30: painter.save() painter.setBrush(self.palette().brush(QPalette.Window)) painter.drawRect(self.bottom_panel.rect()) painter.restore() return # since the body's background color is palette(base), we use # the color to draw background for remain empty area painter.save() painter.setBrush(self.palette().brush(QPalette.Base)) painter.drawRect(0, draw_height, draw_width, self.height() - draw_height) painter.restore() painter.end() def _draw_pixmap_overlay(self, painter, draw_width, draw_height, scrolled): painter.save() rect = QRect(0, 0, draw_width, draw_height) painter.translate(0, -scrolled) gradient = QLinearGradient(rect.topLeft(), rect.bottomLeft()) color = self.palette().color(QPalette.Base) if draw_height == self.height(): gradient.setColorAt(0, add_alpha(color, 180)) gradient.setColorAt(1, add_alpha(color, 230)) else: if self._app.theme_mgr.theme == Light: gradient.setColorAt(0, add_alpha(color, 220)) gradient.setColorAt(0.1, add_alpha(color, 180)) gradient.setColorAt(0.2, add_alpha(color, 140)) gradient.setColorAt(0.6, add_alpha(color, 140)) gradient.setColorAt(0.8, add_alpha(color, 200)) gradient.setColorAt(0.9, add_alpha(color, 240)) gradient.setColorAt(1, color) else: gradient.setColorAt(0, add_alpha(color, 50)) gradient.setColorAt(0.6, add_alpha(color, 100)) gradient.setColorAt(0.8, add_alpha(color, 200)) gradient.setColorAt(0.9, add_alpha(color, 240)) gradient.setColorAt(1, color) painter.setBrush(gradient) painter.drawRect(rect) painter.restore() def _draw_overlay(self, painter, draw_width, draw_height, scrolled): painter.save() rect = QRect(0, 0, draw_width, draw_height) painter.translate(0, -scrolled) gradient = QLinearGradient(rect.topLeft(), rect.bottomLeft()) gradient.setColorAt(0, self.palette().color(QPalette.Window)) gradient.setColorAt(1, self.palette().color(QPalette.Base)) painter.setBrush(gradient) painter.drawRect(rect) painter.restore() def _draw_pixmap(self, painter, draw_width, draw_height, scrolled): # scale pixmap scaled_pixmap = self._pixmap.scaledToWidth( draw_width, mode=Qt.SmoothTransformation) pixmap_size = scaled_pixmap.size() # draw the center part of the pixmap on available rect painter.save() brush = QBrush(scaled_pixmap) painter.setBrush(brush) # note: in practice, most of the time, we can't show the # whole artist pixmap, as a result, the artist head will be cut, # which causes bad visual effect. So we render the top-center part # of the pixmap here. y = (pixmap_size.height() - draw_height) // 3 painter.translate(0, - y - scrolled) rect = QRect(0, y, draw_width, draw_height) painter.drawRect(rect) painter.restore() def sizeHint(self): size = super().sizeHint() return QSize(660, size.height()) def resizeEvent(self, e): super().resizeEvent(e) if self._pixmap is not None and e.oldSize().width() != e.size().width(): self._adjust_meta_widget_height() def _adjust_meta_widget_height(self): # HACK: adjust height of table_container's meta_widget to # adapt to background image. if self._pixmap is None: self.table_container.meta_widget.setMinimumHeight(0) else: height = (self._background_image_height_hint() - self.bottom_panel.height() - self.table_container.toolbar.height()) self.table_container.meta_widget.setMinimumHeight(height) def _background_image_height_hint(self): return self.width() * 5 // 9