def __init_ui(self): title_layout = QHBoxLayout() label_title = QLabel() label_title.setText('Title: ') title_layout.addWidget(label_title) title_layout.addWidget(self.te_title) content_layout = QHBoxLayout() label_content = QLabel() label_content.setText('From : ') content_layout.addWidget(label_content) content_layout.addWidget(self.te_content) space = QSpacerItem(0, 48) send_layout = QHBoxLayout() space2 = QSpacerItem(0, 0) self.btn_send.setText("Send") self.btn_send.setMinimumHeight(48) send_layout.addItem(space2) send_layout.addWidget(self.btn_send) father_layout = QVBoxLayout() father_layout.addLayout(title_layout, 1) father_layout.addLayout(content_layout, 5) father_layout.addItem(space) father_layout.addLayout(send_layout) self.setLayout(father_layout)
class ScheduleScopeDialog(QDialog): def __init__(self, parent=None): # The flags we pass are that so we don't get the "What's this" button in the title bar QDialog.__init__(self, None, Qt.WindowTitleHint | Qt.WindowSystemMenuHint) self._setupUi() self._result = ScheduleScope.Local self.cancelButton.clicked.connect(self.cancelClicked) self.globalScopeButton.clicked.connect(self.globalScopeClicked) self.localScopeButton.clicked.connect(self.localScopeClicked) def _setupUi(self): self.setWindowTitle(tr("Schedule Modification Scope")) self.resize(333, 133) self.verticalLayout = QVBoxLayout(self) self.label = QLabel(tr("Do you want this change to affect all future occurrences of this schedule?")) font = QFont() font.setWeight(75) font.setBold(True) self.label.setFont(font) self.label.setWordWrap(True) self.verticalLayout.addWidget(self.label) self.label_2 = QLabel(tr( "You can force global scope (in other words, changing all future occurrences) by " "holding Shift when you perform the change." )) self.label_2.setWordWrap(True) self.verticalLayout.addWidget(self.label_2) self.horizontalLayout = QHBoxLayout() self.cancelButton = QPushButton(tr("Cancel")) self.cancelButton.setShortcut("Esc") self.horizontalLayout.addWidget(self.cancelButton) spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout.addItem(spacerItem) self.globalScopeButton = QPushButton(tr("All future occurrences")) self.globalScopeButton.setAutoDefault(False) self.horizontalLayout.addWidget(self.globalScopeButton) self.localScopeButton = QPushButton(tr("Just this one")) self.localScopeButton.setAutoDefault(False) self.localScopeButton.setDefault(True) self.horizontalLayout.addWidget(self.localScopeButton) self.verticalLayout.addLayout(self.horizontalLayout) def cancelClicked(self): self._result = ScheduleScope.Cancel self.accept() def globalScopeClicked(self): self._result = ScheduleScope.Global self.accept() def localScopeClicked(self): self._result = ScheduleScope.Local self.accept() def queryForScope(self): self.exec_() return self._result
class ErrorReportDialog(QDialog): def __init__(self, parent, github_url, error, **kwargs): flags = Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowSystemMenuHint super().__init__(parent, flags, **kwargs) self._setupUi() name = QCoreApplication.applicationName() version = QCoreApplication.applicationVersion() errorText = "Application Name: {}\nVersion: {}\n\n{}".format(name, version, error) # Under windows, we end up with an error report without linesep if we don't mangle it errorText = errorText.replace('\n', os.linesep) self.errorTextEdit.setPlainText(errorText) self.github_url = github_url self.sendButton.clicked.connect(self.goToGithub) self.dontSendButton.clicked.connect(self.reject) def _setupUi(self): self.setWindowTitle(tr("Error Report")) self.resize(553, 349) self.verticalLayout = QVBoxLayout(self) self.label = QLabel(self) self.label.setText(tr("Something went wrong. How about reporting the error?")) self.label.setWordWrap(True) self.verticalLayout.addWidget(self.label) self.errorTextEdit = QPlainTextEdit(self) self.errorTextEdit.setReadOnly(True) self.verticalLayout.addWidget(self.errorTextEdit) msg = tr( "Error reports should be reported as Github issues. You can copy the error traceback " "above and paste it in a new issue (bonus point if you run a search to make sure the " "issue doesn't already exist). What usually really helps is if you add a description " "of how you got the error. Thanks!" "\n\n" "Although the application should continue to run after this error, it may be in an " "unstable state, so it is recommended that you restart the application." ) self.label2 = QLabel(msg) self.label2.setWordWrap(True) self.verticalLayout.addWidget(self.label2) self.horizontalLayout = QHBoxLayout() self.horizontalLayout.addItem(horizontalSpacer()) self.dontSendButton = QPushButton(self) self.dontSendButton.setText(tr("Close")) self.dontSendButton.setMinimumSize(QSize(110, 0)) self.horizontalLayout.addWidget(self.dontSendButton) self.sendButton = QPushButton(self) self.sendButton.setText(tr("Go to Github")) self.sendButton.setMinimumSize(QSize(110, 0)) self.sendButton.setDefault(True) self.horizontalLayout.addWidget(self.sendButton) self.verticalLayout.addLayout(self.horizontalLayout) def goToGithub(self): open_url(self.github_url)
def __init__(self, parent=None): super().__init__(parent) self.setSubTitle(self.tr("<h2>Choose Wallpaper</h2>")) vlayout = QVBoxLayout(self) labelLayout = QHBoxLayout() labelImage = QLabel() labelImage.setMaximumSize(64,64) labelImage.setPixmap(QIcon.fromTheme("preferences-desktop-wallpaper").pixmap(64, 64)) labelLayout.addWidget(labelImage) label = QLabel(self) label.setText(self.tr("<p>Choose your favorite wallpaper for KaOS. Don't forget to check out \ <strong>Desktop Settings</strong> for downloading new and cool wallpapers.</p>")) label.setWordWrap(True) labelLayout.addWidget(label) vlayout.addLayout(labelLayout) vlayout.addItem(QSpacerItem(20, 40, QSizePolicy.Preferred, QSizePolicy.Preferred)) groupBox = QGroupBox(self) groupBox.setTitle(self.tr("Wallpapers")) groupBox.setMinimumHeight(350) grLayout = QVBoxLayout(groupBox) self.listWidget = QListWidget() self.listWidget.setViewMode(QListView.IconMode) self.listWidget.setIconSize(QSize(250, 150)) grLayout.addWidget(self.listWidget) vlayout.addWidget(groupBox) vlayout.addItem(QSpacerItem(20, 40, QSizePolicy.Preferred, QSizePolicy.Preferred)) hlayout = QHBoxLayout() self.button = QPushButton() self.button.setText(self.tr("Choose wallpaper from file")) hlayout.addWidget(self.button) hlayout.addItem(QSpacerItem(400, 20, QSizePolicy.Preferred, QSizePolicy.Preferred)) self.checkbox = QCheckBox() self.checkbox.setText(self.tr("Don't change wallpaper")) hlayout.addWidget(self.checkbox) vlayout.addLayout(hlayout) self.checkbox.clicked.connect(self.wallpaperChecked) self.button.clicked.connect(self.wallpaperSelectDialog) self.listWidget.itemClicked.connect(self.wallpaperSelect) self.selectWallpaper = None self.wallpapersParser()
def __init__(self, parent=None): QDialog.__init__(self, parent) self.setWindowTitle(self.tr("Relation Editor")) # Data self.data = None self.resize(700, 500) box = QVBoxLayout(self) # Relation name self.relation_name = QLineEdit() self.relation_name.setVisible(False) box.addWidget(self.relation_name) # Buttons box_btns = QHBoxLayout() add_tuple_btn = QPushButton(self.tr("Add Tuple")) box_btns.addWidget(add_tuple_btn) delete_tuple_btn = QPushButton(self.tr("Delete Tuple")) box_btns.addWidget(delete_tuple_btn) add_column_btn = QPushButton(self.tr("Add Column")) box_btns.addWidget(add_column_btn) delete_column_btn = QPushButton(self.tr("Delete Column")) box_btns.addWidget(delete_column_btn) box.addLayout(box_btns) # La tabla es la vista self.view = view.View() box.addWidget(self.view) # Custom header que puede ser editado header = view.Header() self.view.setHorizontalHeader(header) # self.table = QTableView() # self.table.setSelectionBehavior(QAbstractItemView.SelectRows) # self.table.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel) # self.table.setHorizontalScrollMode(QAbstractItemView.ScrollPerPixel) # Editable header # header = custom_table.Header() # self.table.setHorizontalHeader(header) # box.addWidget(self.table) # Save and cancel button hbox = QHBoxLayout() hbox.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding)) save_btn = QPushButton(self.tr("Ok")) hbox.addWidget(save_btn) cancel_btn = QPushButton(self.tr("Cancel")) hbox.addWidget(cancel_btn) box.addLayout(hbox) # Connections save_btn.clicked.connect(self.save) cancel_btn.clicked.connect(self.close) add_tuple_btn.clicked.connect(self.__add_tuple) delete_tuple_btn.clicked.connect(self.__delete_tuple) add_column_btn.clicked.connect(self.__add_column) delete_column_btn.clicked.connect(self.__delete_column)
def horizontalWrap(widgets): """Wrap all widgets in `widgets` in a horizontal layout. If, instead of placing a widget in your list, you place an int or None, an horizontal spacer with the width corresponding to the int will be placed (0 or None means an expanding spacer). """ layout = QHBoxLayout() for widget in widgets: if widget is None or isinstance(widget, int): layout.addItem(horizontalSpacer(size=widget)) else: layout.addWidget(widget) return layout
def __init__(self): super(self.__class__, self).__init__() #self.label = QLabel('Storage provider:') #self.label.setSizePolicy(QSizePolicy(QSizePolicy.Maximum, 0)) self.combo_box = QComboBox(self) hbox = QHBoxLayout(self) hbox.addItem(QSpacerItem(100, 0, QSizePolicy.Preferred, 0)) #hbox.addWidget(self.label) hbox.addWidget(self.combo_box) hbox.addItem(QSpacerItem(100, 0, QSizePolicy.Preferred, 0))
def set_up_status_layout(self): status_label = QLabel("Status: ") self.status_condition = QLabel() font = QFont() font.setPointSize(10) font.setBold(True) self.status_condition.setFont(font) self.set_status("Down", "red") info_spacer = QSpacerItem(50, 10, QSizePolicy.Expanding, QSizePolicy.Minimum) self.settings = QPushButton("Settings") self.settings.clicked.connect(self.parent.switch_layout_settings) self.settings.setMaximumHeight(20) info_container = QHBoxLayout() info_container.setContentsMargins(20, 0, 0, 0) info_container.addWidget(status_label) info_container.addWidget(self.status_condition) info_container.addItem(info_spacer) info_container.addWidget(self.settings) requests = self.parent.settings_widget.request_table.requests self.log = LogViewer() self.parent.log = self.log self.log.introduction() self.log.entries(len(requests)) log_container = QVBoxLayout() log_container.addWidget(self.log) self.status_disable_checkbox = QCheckBox("Disable") self.status_disable_checkbox.stateChanged.connect(self.toggle_status) link = "https://github.com/kevin-lam/Posttid" help_link = QLabel('<a href="{}">Help</a>'.format(link)) help_link.setAlignment(Qt.AlignRight) help_link.linkActivated.connect(lambda: self.parent.link(link)) status_bottom_container = QHBoxLayout() status_bottom_container.setContentsMargins(10, 0, 20, 0) status_bottom_container.addWidget(self.status_disable_checkbox) status_bottom_container.addWidget(help_link) status_layout = QVBoxLayout() status_layout.addLayout(info_container) status_layout.addLayout(log_container) status_layout.addLayout(status_bottom_container) self.setLayout(status_layout)
def __init__(self, parent = None, pages = 0): super(PageWidget, self).__init__(parent) self.setObjectName("_page_widget") self.pages = pages # 页数 self.cpage = 0 # 左边按钮 self._previous_btn = BothSidesItem(self, which = "left") self._previous_btn.clicked.connect(self._previous) self._previous_btn.setToolTip("上一页") # 右边按钮 self._next_btn = BothSidesItem(self, which = "right") self._next_btn.clicked.connect(self._next) self._next_btn.setToolTip("下一页") self._page_list_widget = QListWidget(self) self._page_list_widget.setObjectName("_page_list_widget") # 无边框 self._page_list_widget.setFrameShape(QFrame.NoFrame) # 无滑动条 self._page_list_widget.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self._page_list_widget.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) # 禁止自动滚动 self._page_list_widget.setAutoScroll(False) # tab切换 self._page_list_widget.setTabKeyNavigation(True) # 设置为横向 self._page_list_widget.setFlow(QListView.LeftToRight) # 设置字体 font = QFont() font.setPointSize(14) self._page_list_widget.setFont(font) # item点击事件 self._page_list_widget.itemClicked.connect(self.ITEMCLICKED.emit) # 布局 hLayout = QHBoxLayout(self) hLayout.setSpacing(0) hLayout.setContentsMargins(0, 0, 0, 0) spacerItem = QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Minimum) hLayout.addItem(spacerItem) hLayout.addWidget(self._previous_btn) hLayout.addWidget(self._page_list_widget) hLayout.addWidget(self._next_btn) hLayout.addItem(spacerItem) self._refresh(pages) self.updateStyle() # 设置样式
def create_send_quantities_layout(self, col): hLayout = QHBoxLayout() for i in range(1, col + 1): spin = QSpinBox() spin.setMinimum(-1000) spin.setMaximum(1000) spin.setObjectName('spin_{}'.format(i)) self.send_quantities.append(spin) hLayout.addWidget(spin) hLayout.addItem(QSpacerItem(20, 20)) return hLayout
class windowTitle(QFrame): def __init__(self, parent, closeButton=True): QFrame.__init__(self, parent) self.setMaximumSize(QSize(9999999, 22)) self.setObjectName("windowTitle") self.hboxlayout = QHBoxLayout(self) self.hboxlayout.setSpacing(0) self.hboxlayout.setContentsMargins(0, 0, 4, 0) self.label = QLabel(self) self.label.setObjectName("label") self.label.setStyleSheet( "padding-left:4px; font:bold 11px; color: #FFFFFF;") self.hboxlayout.addWidget(self.label) spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.hboxlayout.addItem(spacerItem) if closeButton: self.pushButton = QPushButton(self) self.pushButton.setFocusPolicy(Qt.NoFocus) self.pushButton.setObjectName("pushButton") self.pushButton.setStyleSheet("font:bold;") self.pushButton.setText("X") self.hboxlayout.addWidget(self.pushButton) self.dragPosition = None self.mainwidget = self.parent() self.setStyleSheet(""" QFrame#windowTitle {background-color:#222222;color:#FFF;} """) # Initial position to top left self.dragPosition = self.mainwidget.frameGeometry().topLeft() def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.dragPosition = event.globalPos( ) - self.mainwidget.frameGeometry().topLeft() event.accept() def mouseMoveEvent(self, event): if event.buttons() & Qt.LeftButton: self.mainwidget.move(event.globalPos() - self.dragPosition) event.accept()
def __init__(self, servizio, parent=None): super(VistaServizio, self).__init__() self.controller = ControlloreServizio(servizio) h_layout = QHBoxLayout() v_layout = QVBoxLayout() label_nome = QLabel(self.controller.get_nome_servizio()) font_nome = label_nome.font() font_nome.setPointSize(30) label_nome.setFont(font_nome) v_layout.addWidget(label_nome) label_tipo = QLabel("Tipo: {}".format(self.controller.get_tipo_servizio())) font_tipo = label_tipo.font() font_tipo.setPointSize(17) label_tipo.setFont(font_tipo) v_layout.addWidget(label_tipo) v_layout.addItem(QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding)) label_posizione = QLabel("Posizione: {}".format(self.controller.get_posizione_servizio())) font_posizione = label_posizione.font() font_posizione.setPointSize(17) label_posizione.setFont(font_posizione) v_layout.addWidget(label_posizione) h_layout.addLayout(v_layout) h_layout.addItem(QSpacerItem(60, 20, QSizePolicy.Minimum, QSizePolicy.Expanding)) v_layout2 = QVBoxLayout() label_prezzo = QLabel("Prezzo: {}€".format(self.controller.get_prezzo_servizio())) font_prezzo = label_prezzo.font() font_prezzo.setPointSize(25) label_prezzo.setFont(font_prezzo) v_layout2.addWidget(label_prezzo) v_layout2.addStretch() label_disponibile = QLabel(self.controller.get_servizio_disponibile()) font_disponibile = label_disponibile.font() font_disponibile.setPointSize(25) label_prezzo.setFont(font_disponibile) v_layout2.addWidget(label_disponibile) h_layout.addLayout(v_layout2) self.setLayout(h_layout) self.setWindowTitle(servizio.nome)
def group_settings(self): """Settings group.""" gb_settings = QGroupBox(self.central_widget) gb_settings.setTitle(self.tr('Conversion Presets')) size_policy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred) size_policy.setHorizontalStretch(0) size_policy.setVerticalStretch(0) size_policy.setHeightForWidth( gb_settings.sizePolicy().hasHeightForWidth()) gb_settings.setSizePolicy(size_policy) hl = QHBoxLayout(gb_settings) vl = QVBoxLayout() hl1 = QHBoxLayout() label = QLabel(self.tr('Convert to:')) hl1.addWidget(label) spacer_item = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) hl1.addItem(spacer_item) vl.addLayout(hl1) self.cb_profiles = QComboBox( gb_settings, statusTip=self.tr('Select the desired video format')) self.cb_profiles.setMinimumSize(QSize(200, 0)) vl.addWidget(self.cb_profiles) hl2 = QHBoxLayout() label = QLabel(self.tr('Target Quality:')) hl2.addWidget(label) spacerItem1 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) hl2.addItem(spacerItem1) vl.addLayout(hl2) self.cb_presets = QComboBox( gb_settings, statusTip=self.tr('Select the desired video quality')) self.cb_presets.setMinimumSize(QSize(200, 0)) self.cb_profiles.currentIndexChanged.connect(partial( self.populate_presets, self.cb_presets)) self.cb_presets.activated.connect(self.update_media_files_status) vl.addWidget(self.cb_presets) hl.addLayout(vl) self.vl1.addWidget(gb_settings)
class AccountReassignPanel(Panel): PERSISTENT_NAME = 'accountReassignPanel' def __init__(self, model, mainwindow): Panel.__init__(self, mainwindow) self._setupUi() self.model = model self.accountComboBox = ComboboxModel(model=self.model.account_list, view=self.accountComboBoxView) self.continueButton.clicked.connect(self.accept) self.cancelButton.clicked.connect(self.reject) def _setupUi(self): if ISWINDOWS: self.resize(250, 140) else: self.resize(340, 165) self.setWindowTitle(tr("Re-assign Account")) self.verticalLayout = QVBoxLayout(self) self.label = QLabel(self) self.label.setWordWrap(True) self.label.setText(tr( "You\'re about to delete a non-empty account. Select an account to re-assign its " "transactions to." )) self.verticalLayout.addWidget(self.label) self.accountComboBoxView = QComboBox(self) sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.accountComboBoxView.sizePolicy().hasHeightForWidth()) self.accountComboBoxView.setSizePolicy(sizePolicy) self.accountComboBoxView.setMinimumSize(QSize(200, 0)) self.verticalLayout.addWidget(self.accountComboBoxView) spacerItem = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) self.verticalLayout.addItem(spacerItem) self.horizontalLayout = QHBoxLayout() spacerItem1 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout.addItem(spacerItem1) self.cancelButton = QPushButton(self) self.cancelButton.setText(tr("Cancel")) self.cancelButton.setShortcut("Esc") self.horizontalLayout.addWidget(self.cancelButton) self.continueButton = QPushButton(self) self.continueButton.setDefault(True) self.continueButton.setText(tr("Continue")) self.horizontalLayout.addWidget(self.continueButton) self.verticalLayout.addLayout(self.horizontalLayout)
def __init__(self): QMainWindow.__init__(self) self.title = 'test' self.left = 10 self.top = 10 self.width = 1920 self.height = 1080 self.setWindowTitle(self.title) self.setGeometry(self.left, self.top, self.width, self.height) self.statusBar().showMessage('Ready') mainMenu = self.menuBar() mainMenu.setNativeMenuBar(False) fileMenu = mainMenu.addMenu('File') helpMenu = mainMenu.addMenu('Help') exitButton = QAction(QIcon('exit24.png'), 'Exit', self) exitButton.setShortcut('Ctrl+Q') exitButton.setStatusTip('Exit application') exitButton.triggered.connect(self.close) fileMenu.addAction(exitButton) widget = QWidget(self) self.setCentralWidget(widget) vlay = QVBoxLayout(widget) hlay = QHBoxLayout() vlay.addLayout(hlay) self.nameLabel = QLabel('Name:', self) self.line = QLineEdit(self) self.nameLabel2 = QLabel('Result', self) hlay.addWidget(self.nameLabel) hlay.addWidget(self.line) hlay.addWidget(self.nameLabel2) hlay.addItem(QSpacerItem(1000, 10, QSizePolicy.Expanding)) pybutton = QPushButton('Click me', self) pybutton.clicked.connect(self.clickMethod) hlay2 = QHBoxLayout() hlay2.addWidget(pybutton) hlay2.addItem(QSpacerItem(1000, 10, QSizePolicy.Expanding)) vlay.addLayout(hlay2) m = MatplotlibWidget(self) vlay.addWidget(m)
def __init__(self): QWidget.__init__(self) from widgets.content import ContentType from widgets.flatbutton import FlatButton from widgets.hyperlink import HyperLink from widgets.section import Section self.editButton = FlatButton(":/images/edit_normal.png", ":/images/edit_hover.png") self.copyButton = FlatButton(":/images/copy_normal.png", ":/images/copy_hover.png") self.deleteButton = FlatButton(":/images/trash_normal.png", ":/images/trash_hover.png") self.addColumns = HyperLink("(+) Add Columns") self.editButton.setToolTip("Edit Row") self.deleteButton.setToolTip("Delete Row") self.copyButton.setToolTip("Copy Row") self.editButton.setMaximumWidth(24) self.copyButton.setMaximumWidth(24) self.deleteButton.setMaximumWidth(24) vbox = QVBoxLayout() vbox.setAlignment(Qt.AlignTop) vbox.setSpacing(5) vbox.addWidget(self.editButton) vbox.addWidget(self.copyButton) vbox.addWidget(self.deleteButton, 0, Qt.AlignBottom) layout = QHBoxLayout() pal = self.palette() pal.setColor(QPalette.Background, QColor(self.palette().alternateBase().color())) self.setPalette(pal) self.setAutoFillBackground(True) self.highlightedRect = QRect() self.layout = QGridLayout() self.layout.addWidget(self.addColumns, 0, 0, 1, 1, Qt.AlignCenter) self.layout.setColumnStretch(0, 1) layout.addItem(vbox) layout.addLayout(self.layout) self.setLayout(layout) self.deleteButton.clicked.connect(self.delete) self.copyButton.clicked.connect(self.copy) self.editButton.clicked.connect(self.edit) self.addColumns.clicked.connect(self.insertColumns)
class AccountReassignPanel(Panel): PERSISTENT_NAME = 'accountReassignPanel' def __init__(self, model, mainwindow): Panel.__init__(self, mainwindow) self._setupUi() self.model = model self.accountComboBox = ComboboxModel(model=self.model.account_list, view=self.accountComboBoxView) self.continueButton.clicked.connect(self.accept) self.cancelButton.clicked.connect(self.reject) def _setupUi(self): self.resize(340, 165) self.setWindowTitle(tr("Re-assign Account")) self.verticalLayout = QVBoxLayout(self) self.label = QLabel(self) self.label.setWordWrap(True) self.label.setText( tr("You\'re about to delete a non-empty account. Select an account to re-assign its " "transactions to.")) self.verticalLayout.addWidget(self.label) self.accountComboBoxView = QComboBox(self) sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.accountComboBoxView.sizePolicy().hasHeightForWidth()) self.accountComboBoxView.setSizePolicy(sizePolicy) self.accountComboBoxView.setMinimumSize(QSize(200, 0)) self.verticalLayout.addWidget(self.accountComboBoxView) spacerItem = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) self.verticalLayout.addItem(spacerItem) self.horizontalLayout = QHBoxLayout() spacerItem1 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout.addItem(spacerItem1) self.cancelButton = QPushButton(self) self.cancelButton.setText(tr("Cancel")) self.cancelButton.setShortcut("Esc") self.horizontalLayout.addWidget(self.cancelButton) self.continueButton = QPushButton(self) self.continueButton.setDefault(True) self.continueButton.setText(tr("Continue")) self.horizontalLayout.addWidget(self.continueButton) self.verticalLayout.addLayout(self.horizontalLayout)
def __init__(self, mainW): super().__init__(mainW) self.pinButton = QToolButton(self) self.pinButton.setIcon(getIcon('pin.png')) self.pinButton.setEnabled(True) self.zoomIn = QToolButton(self) self.zoomIn.setIcon(getIcon('zoom-in.png')) self.zoomIn.setShortcut(QKeySequence('Ctrl++')) self.zoomIn.setToolTip(iZoomIn()) self.zoomOut = QToolButton(self) self.zoomOut.setIcon(getIcon('zoom-out.png')) self.zoomOut.setShortcut(QKeySequence('Ctrl+-')) self.zoomOut.setToolTip(iZoomOut()) self.fitWindow = QToolButton(self) self.fitWindow.setCheckable(True) self.fitWindow.setToolTip('Fit to window') self.fitWindow.setIcon(getIcon('expand.png')) self.pathLabel = IPFSUrlLabel(None) self.pathClipB = IPFSPathClipboardButton(None) layout = QHBoxLayout() layout.addWidget(self.pathLabel, 0, Qt.AlignLeft) layout.addWidget(self.pathClipB, 0, Qt.AlignLeft) layout.addItem( QSpacerItem(10, 10, QSizePolicy.Expanding, QSizePolicy.Minimum)) layout.addWidget(self.pinButton, 0, Qt.AlignLeft) layout.addItem( QSpacerItem(10, 10, QSizePolicy.Minimum, QSizePolicy.Minimum)) layout.addWidget(self.zoomOut, 0, Qt.AlignLeft) layout.addWidget(self.zoomIn, 0, Qt.AlignLeft) layout.addWidget(self.fitWindow, 0, Qt.AlignLeft) self.vLayout.addLayout(layout) self.view = ImageView(self) self.view.imageLoaded.connect(self.onImageLoaded) self.view.qrCodesPresent.connect(self.onQrCodesListed) self.vLayout.addWidget(self.view) self.zoomIn.clicked.connect(self.view.zoomInClicked) self.zoomOut.clicked.connect(self.view.zoomOutClicked) self.fitWindow.clicked.connect( lambda: self.view.fitWindow(self.fitWindow.isChecked())) self.pinButton.clicked.connect(self.view.pinImage)
def initUI(self): self.setWindowTitle('RGB控制示例') self.setWindowIcon(QIcon('./res/apaki.ico')) self.setGeometry(400, 300, 400, 300) self.color = QColor(0, 0, 0) self.frame = QFrame(self) self.frame.setStyleSheet("QWidget { background-color: %s }" % self.color.name()) self.frame.setFrameShape(QFrame.StyledPanel) # --------------------------------------------------------------- # 虽然代码简介了,但是是不是理解不太方便呀? # exec可以直接将字符串当作代码来运行 # cmd_name: redSlider,greenSlider,blueSlider cmd_names = ['red', 'green', 'blue'] for cmd_name in cmd_names: cmd = 'self.' + cmd_name + 'Slider' + ' = QSlider(Qt.Horizontal, self)' exec(cmd) cmd = 'self.' + cmd_name + 'Slider.setMaximum(255)' exec(cmd) cmd = 'self.'+cmd_name + \ 'Slider.valueChanged[int].connect(self.changeValue)' exec(cmd) """ self.redSlider = QSlider(Qt.Horizontal, self) self.greenSlider = QSlider(Qt.Horizontal, self) # 默认纵向 self.blueSlider = QSlider(Qt.Horizontal, self) # 配置范围 self.redSlider.setMaximum(255) self.greenSlider.setMaximum(255) self.blueSlider.setMaximum(255) # 信号 self.redSlider.valueChanged[int].connect(self.changeValue) self.greenSlider.valueChanged[int].connect(self.changeValue) self.blueSlider.valueChanged[int].connect(self.changeValue) """ splitter = QSplitter(self) splitter.addWidget(self.frame) vbox = QVBoxLayout() vbox.addWidget(self.redSlider) vbox.addWidget(self.greenSlider) vbox.addWidget(self.blueSlider) hbox = QHBoxLayout() hbox.addWidget(splitter) hbox.addItem(vbox) self.setLayout(hbox)
def __init__(self, parent=None): super(LogWidget, self).__init__(parent) # Base vars self.logLength = 0 self.logger = logging.getLogger(__name__) # Palette logPalette = QPalette() logPalette.setColor(QPalette.Base, Qt.black) logPalette.setColor(QPalette.Text, Qt.yellow) # Text Panel self.logText = QPlainTextEdit(self) self.logText.setPalette(logPalette) self.logText.setReadOnly(True) # Buttons self.sendButton = QPushButton(QIcon('img/email.png'), 'Send Logs') self.sendButton.click.connect(self.sendLogs) self.forceButton = QPushButton(QIcon('img/refresh.png'), 'Force Refresh') self.forceButton.click.connect(self.forceRefresh) self.clearButton = QPushButton(QIcon('img/eraser.png'), 'Clear Logs') self.clearButton.click.connect(self.clearLogs) # Layouts layout = QVBoxLayout(self) layout.setContentsMargins(1, 1, 1, 1) layout.addWidget(self.logText) buttonLayout = QHBoxLayout() buttonLayout.setContentsMargins(1, 0, 1, 2) buttonLayout.addWidget(self.sendButton) buttonLayout.addItem( QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Minimum)) buttonLayout.addWidget(self.forceButton) buttonLayout.addWidget(self.clearButton) layout.addLayout(buttonLayout) self.setLayout(layout) # Timer self.logTimer = QTimer() self.logTimer.setInterval(5000) self.logTimer.timeout.connect(self.updateLog) self.logTimer.start()
def set_up_settings_layout(self): email_label = QLabel("Email: ") self.email_edit = QLineEdit() self.email_edit.setMaximumHeight(20) self.email_edit.setText(self.email) email_spacer = QSpacerItem(10, 10, QSizePolicy.Expanding, QSizePolicy.Minimum) self.request_table = RequestTable(self.email, self.requests, parent=self.parent) self.email_edit.setText(self.request_table.email) done = QPushButton("Done") done.setMaximumHeight(20) done.clicked.connect(self.parent.switch_layout_status) done.clicked.connect(lambda: self.finished(self.email_edit.text(), self.request_table.requests, self.request_table.inserted, self.request_table.removed, self.request_table)) email_container = QHBoxLayout() email_container.addWidget(email_label) email_container.addWidget(self.email_edit) email_container.addItem(email_spacer) email_container.addWidget(done) table_container = QVBoxLayout() table_container.addWidget(self.request_table) self.settings_disable_checkbox = QCheckBox("Disable") link = "https://github.com/kevin-lam/Posttid" help_link = QLabel('<a href="{}">Help</a>'.format(link)) help_link.setAlignment(Qt.AlignRight) help_link.linkActivated.connect(lambda: self.parent.link(link)) settings_bottom_container = QHBoxLayout() settings_bottom_container.addWidget(self.settings_disable_checkbox) settings_bottom_container.addWidget(help_link) settings_bottom_container.setContentsMargins(10, 0, 20, 0) settings_layout = QVBoxLayout() settings_layout.addLayout(email_container) settings_layout.addLayout(table_container) settings_layout.addLayout(settings_bottom_container) self.setLayout(settings_layout)
def __init__(self, parent=None): QDialog.__init__(self, parent) self.setWindowTitle(self.tr("Relation Creator")) # self.setModal(True) self.resize(700, 500) self.data = None box = QVBoxLayout(self) # Campo para el nombre de la relación self._line_relation_name = QLineEdit() self._line_relation_name.setPlaceholderText(self.tr("Relation Name")) box.addWidget(self._line_relation_name) hbox = QHBoxLayout() # Botones para agregar y eliminar tuplas/columnas btn_add_tuple = QPushButton(self.tr("Add Tuple")) hbox.addWidget(btn_add_tuple) btn_delete_tuple = QPushButton(self.tr("Delete Tuple")) hbox.addWidget(btn_delete_tuple) btn_add_column = QPushButton(self.tr("Add Column")) hbox.addWidget(btn_add_column) btn_delete_column = QPushButton(self.tr("Delete Column")) hbox.addWidget(btn_delete_column) box.addLayout(hbox) # Vista (tabla) self._view = view.View() box.addWidget(self._view) # Header personalizado para permitir ser editado header = view.Header() self._view.setHorizontalHeader(header) self._view.setModel(QStandardItemModel(0, 2)) header.model().setHeaderData(0, Qt.Horizontal, self.tr("Field 1")) header.model().setHeaderData(1, Qt.Horizontal, self.tr("Field 2")) # Botones para crear/cancelar hhbox = QHBoxLayout() hhbox.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding)) btn_create = QPushButton(self.tr("Create")) hhbox.addWidget(btn_create) btn_cancel = QPushButton(self.tr("Cancel")) hhbox.addWidget(btn_cancel) box.addLayout(hhbox) # Conexiones btn_add_tuple.clicked.connect(self.__add_tuple) btn_delete_tuple.clicked.connect(self.__delete_tuple) btn_add_column.clicked.connect(self.__add_column) btn_delete_column.clicked.connect(self.__delete_column) btn_cancel.clicked.connect(self.close) btn_create.clicked.connect(self._create)
class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(800, 602) self.centralwidget = QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.verticalLayoutWidget = QWidget(self.centralwidget) self.verticalLayoutWidget.setGeometry(QRect(0, 0, 801, 581)) self.verticalLayoutWidget.setObjectName("verticalLayoutWidget") self.verticalLayout = QVBoxLayout(self.verticalLayoutWidget) self.verticalLayout.setContentsMargins(0, 0, 0, 0) self.verticalLayout.setObjectName("verticalLayout") self.horizontalLayout = QHBoxLayout() self.horizontalLayout.setObjectName("horizontalLayout") # open file button self.openButton = QPushButton(self.verticalLayoutWidget) self.openButton.setObjectName("openButton") self.horizontalLayout.addWidget(self.openButton) # save file button self.saveButton = QPushButton(self.verticalLayoutWidget) self.saveButton.setObjectName("saveButton") self.horizontalLayout.addWidget(self.saveButton) spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout.addItem(spacerItem) self.verticalLayout.addLayout(self.horizontalLayout) # tab view self.tableView = QTableView(self.verticalLayoutWidget) self.tableView.setObjectName("tableView") self.verticalLayout.addWidget(self.tableView) MainWindow.setCentralWidget(self.centralwidget) self.statusbar = QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.retranslateUi(MainWindow) QMetaObject.connectSlotsByName(MainWindow) def retranslateUi(self, MainWindow): _translate = QCoreApplication.translate MainWindow.setWindowTitle(_translate("GeoDataHelper", "GeoDataHelper")) MainWindow.setWindowIcon(QIcon('./resources/images/icon.ico')) self.openButton.setText(_translate("open", "open")) self.saveButton.setText(_translate("save", "save"))
def initUI(self): self.resize(850, 600) self.teamConfig = TeamConfigWidget( parent=self, eventManager=self.eventConfigManager, hide=True) self.dirConfig = DirConfigWidget(parent=self, eventManager=self.eventConfigManager, hide=True) self.eventConfig = EventConfigWidget( parent=self, eventManager=self.eventConfigManager, hide=True) self.vectorConfig = VectorConfigWidget( parent=self, eventManager=self.eventConfigManager) self.stack = QStackedWidget(self) self.stack.addWidget(self.teamConfig) self.stack.addWidget(self.dirConfig) self.stack.addWidget(self.eventConfig) self.stack.addWidget(self.vectorConfig) self.viewList = QListWidget() self.viewList.insertItem(0, "Team Configuration") self.viewList.insertItem(1, "Directory Configuration") self.viewList.insertItem(2, "Event Configuration") self.viewList.insertItem(3, "Vector Configuration") self.viewList.currentRowChanged.connect( lambda i: self.stack.setCurrentIndex(i)) startNewProject = QPushButton("Start New Project") startNewProject.clicked.connect(self.start) cancel = QPushButton("Cancel") cancel.clicked.connect(self.cancel) hSpacer = QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Fixed) newProjectControlContainer = QHBoxLayout() newProjectControlContainer.addItem(hSpacer) newProjectControlContainer.addWidget(cancel) newProjectControlContainer.addWidget(startNewProject) viewContainer = QHBoxLayout() viewContainer.addWidget(self.viewList, 30) viewContainer.addWidget(self.stack, 60) mainContainer = QVBoxLayout(self) mainContainer.addLayout(viewContainer) mainContainer.addLayout(newProjectControlContainer) self.setLayout(mainContainer)
def __init__(self, parent=None): super().__init__(parent) self.setupUi(self) self.setWindowTitle('Text frequency analysis') self.changeWidgets = {} # Fill grid with widgets for i in range(LETTERS_IN_ALPHABET): letter = chr(ord('a') + i) new_layout = QHBoxLayout() # Create label with the only one letter label = QLabel(letter) label.setMinimumSize(20, 15) label.setFont(QtGui.QFont("Times", 15, QtGui.QFont.Normal)) new_layout.addWidget(label) # Create input place line_edit = QLineEdit() new_layout.addWidget(line_edit) # Create checkbox with need of change checkbox = QCheckBox('Change') new_layout.addWidget(checkbox) # Make little margin on the right vertical_spacer = QtWidgets.QSpacerItem( 20, 0, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) new_layout.addItem(vertical_spacer) # Add layout to grid self.changeWidgets[letter] = (line_edit, checkbox) x, y = i % ROWS_IN_GRID, i / ROWS_IN_GRID self.gridWithLetters.addLayout(new_layout, x, y) # Create two buttons in the right corner self.analyzeButton = QPushButton('Analyze') self.commitChangesButton = QPushButton('Commit changes') self.gridWithLetters.addWidget(self.analyzeButton, ROWS_IN_GRID - 2, COLUMNS_IN_GRID - 1) self.gridWithLetters.addWidget(self.commitChangesButton, ROWS_IN_GRID - 1, COLUMNS_IN_GRID - 1) # Connect buttons with necessary methods self.analyzeButton.clicked.connect(self.process_analyze) self.commitChangesButton.clicked.connect(self.process_commit)
class MyWin(QWidget): def __init__(self, parent=None): super(MyWin, self).__init__(parent) self.initUI() def initUI(self): #layout manager self.mainLayout = QHBoxLayout() self.leftLayout = QVBoxLayout() self.rightLayout = QVBoxLayout() #pulsanti carini self.topBtn = QPushButton('Top', self) self.topBtn.setFixedSize(32, 16) self.topBtn.move(0,0) self.bottomBtn = QPushButton('Bottom', self) self.bottomBtn.setFixedSize(48, 16) #binding callback per pulsante cliccato self.topBtn.clicked.connect(self.topButtonClick) self.bottomBtn.clicked.connect(self.bottomButtonClick) #aggiunta pulsante al layout self.leftLayout.addWidget(self.topBtn) self.leftLayout.addWidget(self.bottomBtn) #creazione label e aggiunta al layout self.label = QLabel() self.rightLayout.addWidget(self.label) self.mainLayout.addItem(self.leftLayout) self.mainLayout.addItem(self.rightLayout) #binding layout alla finestra self.setLayout(self.mainLayout) self.setFixedSize(640, 480) #mostrare la finestra self.show() def bottomButtonClick(self): self.label.setText("TESTAMENTO DI SOTTO") def topButtonClick(self): self.label.setText("TESTAMENTO DI SOPRA")
class DeckSelector(QWidget): deck_selected = pyqtSignal(int) MAX_FLEET_NUM = 4 # FIXME def __init__(self, con, parent): super(DeckSelector, self).__init__(parent) self.con = con self.decks = [] self.deck_layout = QHBoxLayout() self.setLayout(self.deck_layout) for i in range(self.MAX_FLEET_NUM): button = DeckButton(i+1,self) self.decks.append(button) self.deck_layout.addWidget(button) self.deck_layout.addItem(QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)) self.update() self.show() def on_deck_selected(self, deck_no): for deck in self.decks: if deck.deck_no != deck_no: deck.button.setChecked(False) self.deck_selected.emit(deck_no) def update(self): port = model.Port(self.con) decks_no = len(port.decks()) for (i,deck) in enumerate(self.decks): if i < decks_no: deck.show() deck.update() else: deck.hide() # for apply stylesheet def paintEvent(self, pe): opt = QStyleOption() opt.initFrom(self) p = QPainter(self) s = self.style() s.drawPrimitive(QStyle.PE_Widget, opt, p, self)
def ax(self, parent=None): #super().__init__(parent) parent.setGeometry(50, 70, 320, 250) parent.setWindowTitle("Modify settings") self.model_name = 'default' self.monte_carlo = 5 parent.setAutoFillBackground(1) layout = QGridLayout() oriz = QHBoxLayout() combo = QComboBox() combo.addItem("5") combo.addItem("10") combo.addItem("15") combo.addItem("20") combo.addItem("50") combo.move(150, 20) self.qlabel1 = QLabel('Monte Carlo sample:') self.l_model = QLabel('Select another model:') self.button_sel = QPushButton('Select model .h5') self.button_sel.clicked.connect(self.newModel) self.button_close = QPushButton('Ok') self.button_close.clicked.connect(self.ok) self.button_close.setToolTip('Press ok to continue!') self.qlabel = QLabel('Default value: 5') combo.activated[str].connect(self.onChanged) oriz.addItem(QSpacerItem(50, 10, QSizePolicy.Expanding)) oriz.addWidget(self.button_close) layout.addWidget(self.qlabel1) layout.addWidget(combo) layout.addWidget(self.qlabel) layout.addWidget(QHLine()) layout.addWidget(self.l_model) layout.addWidget(self.button_sel) layout.addWidget(QHLine()) layout.addItem(oriz) parent.setLayout(layout) self.show()
def _setLayout(self): mainLayout = QVBoxLayout() mainLayout.addItem(QSpacerItem(10, 10)) mainLayout.setSpacing(15) mainLayout.addLayout(self.input_layout) mainLayout.addItem(QSpacerItem(10, 20)) hlayout = QHBoxLayout() hlayout.addItem(QSpacerItem(30, 1)) hlayout.addWidget(self.btnOpenPolygon) hlayout.addWidget(self.polygonNameBox) mainLayout.addLayout(hlayout) mainLayout.addItem(QSpacerItem(10, 10)) mainLayout.addStretch() glayout = QGridLayout() glayout.addWidget(QLabel(' Select the principal variable'), 1, 1) glayout.addWidget(self.firstVarBox, 1, 2) glayout.addWidget( QLabel(' Select a variable to subtract (optional)'), 2, 1) glayout.addWidget(self.secondVarBox, 2, 2) glayout.addWidget(QLabel(' More options'), 3, 1) glayout.addWidget(self.supVolumeBox, 3, 2) hlayout = QHBoxLayout() hlayout.addWidget(QLabel('Time sampling frequency')) hlayout.addWidget(self.timeSampling) hlayout.setAlignment(self.timeSampling, Qt.AlignLeft) hlayout.addStretch() glayout.addLayout(hlayout, 4, 2) glayout.setAlignment(Qt.AlignLeft) glayout.setSpacing(10) mainLayout.addLayout(glayout) mainLayout.addItem(QSpacerItem(10, 20)) hlayout = QHBoxLayout() hlayout.addItem(QSpacerItem(30, 1)) hlayout.addWidget(self.btnSubmit) hlayout.addWidget(self.csvNameBox) mainLayout.addLayout(hlayout) mainLayout.addStretch() mainLayout.addItem(QSpacerItem(10, 15)) mainLayout.addWidget(QLabel(' Message logs')) mainLayout.addWidget(self.logTextBox.widget) self.setLayout(mainLayout)
def __init__(self): super(self.__class__, self).__init__() self.image = QLabel() self.description = QLabel('', self) self.description.setWordWrap(True) self.description.setOpenExternalLinks(True) form = QFormLayout() form.setWidget(0, QFormLayout.LabelRole, self.image) form.setWidget(0, QFormLayout.FieldRole, self.description) hbox = QHBoxLayout(self) hbox.addItem(QSpacerItem(30, 0, QSizePolicy.Preferred, 0)) hbox.addLayout(form) hbox.addItem(QSpacerItem(30, 0, QSizePolicy.Preferred, 0))
class ProblemDialog(QDialog): def __init__(self, parent, model, **kwargs): flags = Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowSystemMenuHint super().__init__(parent, flags, **kwargs) self._setupUi() self.model = model self.model.view = self self.table = ProblemTable(self.model.problem_table, view=self.tableView) self.revealButton.clicked.connect(self.model.reveal_selected_dupe) self.closeButton.clicked.connect(self.accept) def _setupUi(self): self.setWindowTitle(tr("Problems!")) self.resize(413, 323) self.verticalLayout = QVBoxLayout(self) self.label = QLabel(self) msg = tr( "There were problems processing some (or all) of the files. The cause of " "these problems are described in the table below. Those files were not " "removed from your results.") self.label.setText(msg) self.label.setWordWrap(True) self.verticalLayout.addWidget(self.label) self.tableView = QTableView(self) self.tableView.setEditTriggers(QAbstractItemView.NoEditTriggers) self.tableView.setSelectionMode(QAbstractItemView.SingleSelection) self.tableView.setSelectionBehavior(QAbstractItemView.SelectRows) self.tableView.setShowGrid(False) self.tableView.horizontalHeader().setStretchLastSection(True) self.tableView.verticalHeader().setDefaultSectionSize(18) self.tableView.verticalHeader().setHighlightSections(False) self.verticalLayout.addWidget(self.tableView) self.horizontalLayout = QHBoxLayout() self.revealButton = QPushButton(self) self.revealButton.setText(tr("Reveal Selected")) self.horizontalLayout.addWidget(self.revealButton) spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout.addItem(spacerItem) self.closeButton = QPushButton(self) self.closeButton.setText(tr("Close")) self.closeButton.setDefault(True) self.horizontalLayout.addWidget(self.closeButton) self.verticalLayout.addLayout(self.horizontalLayout)
class ProblemDialog(QDialog): def __init__(self, parent, model, **kwargs): flags = Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowSystemMenuHint super().__init__(parent, flags, **kwargs) self._setupUi() self.model = model self.model.view = self self.table = ProblemTable(self.model.problem_table, view=self.tableView) self.revealButton.clicked.connect(self.model.reveal_selected_dupe) self.closeButton.clicked.connect(self.accept) def _setupUi(self): self.setWindowTitle(tr("Problems!")) self.resize(413, 323) self.verticalLayout = QVBoxLayout(self) self.label = QLabel(self) msg = tr( "There were problems processing some (or all) of the files. The cause of " "these problems are described in the table below. Those files were not " "removed from your results." ) self.label.setText(msg) self.label.setWordWrap(True) self.verticalLayout.addWidget(self.label) self.tableView = QTableView(self) self.tableView.setEditTriggers(QAbstractItemView.NoEditTriggers) self.tableView.setSelectionMode(QAbstractItemView.SingleSelection) self.tableView.setSelectionBehavior(QAbstractItemView.SelectRows) self.tableView.setShowGrid(False) self.tableView.horizontalHeader().setStretchLastSection(True) self.tableView.verticalHeader().setDefaultSectionSize(18) self.tableView.verticalHeader().setHighlightSections(False) self.verticalLayout.addWidget(self.tableView) self.horizontalLayout = QHBoxLayout() self.revealButton = QPushButton(self) self.revealButton.setText(tr("Reveal Selected")) self.horizontalLayout.addWidget(self.revealButton) spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout.addItem(spacerItem) self.closeButton = QPushButton(self) self.closeButton.setText(tr("Close")) self.closeButton.setDefault(True) self.horizontalLayout.addWidget(self.closeButton) self.verticalLayout.addLayout(self.horizontalLayout)
class ViewRunResultWidget(QDialog): def __init__(self, parent, result, output): super(ViewRunResultWidget, self).__init__(parent) self.setWindowTitle("Result") self.resize(859, 704) self.m_mainLayout = QVBoxLayout(self) self.m_resultEdit = QPlainTextEdit(self) self.m_resultEdit.setReadOnly(True) self.m_resultEdit.setPlainText((result)) self.m_mainLayout.addWidget(self.m_resultEdit) self.m_outputEdit = QPlainTextEdit(self) self.m_outputEdit.setReadOnly(True) self.m_outputEdit.setPlainText(output) self.m_mainLayout.addWidget(self.m_outputEdit) self.m_buttonsLayout = QHBoxLayout() spacerItem1 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.m_buttonsLayout.addItem(spacerItem1) self.m_saveBtn = QPushButton(self) self.m_buttonsLayout.addWidget(self.m_saveBtn) self.m_cancelBtn = QPushButton(self) self.m_buttonsLayout.addWidget(self.m_cancelBtn) self.m_mainLayout.addLayout(self.m_buttonsLayout) self.m_saveBtn.setText("Save") self.m_cancelBtn.setText("Cancel") self.m_saveBtn.pressed.connect(self.saveAndAccept) self.m_cancelBtn.pressed.connect(self.reject) def saveAndAccept(self): try: filePath = QFileDialog.getSaveFileName(self, "File path to save") file = open(filePath[0], "w") file.write(self.m_resultEdit.toPlainText()) file.close() except Exception as e: QMessageBox.warning(self, "Error", "Failed to save result\n\t%s" % e) return self.accept()
def __init__(self): super().__init__() self.maze = Maze(CentralWidget.MAX_TURN_DELAY) vertical_layout = QVBoxLayout() vertical_layout.addWidget(self.maze) horizontal_layout = QHBoxLayout() delay_label = QLabel() delay_label.setText('Turn Delay') horizontal_layout.addWidget(delay_label) self.delay_slider = QSlider() self.delay_slider.setOrientation(Qt.Horizontal) self.delay_slider.setMaximum(CentralWidget.MAX_TURN_DELAY) self.delay_slider.setMinimum(CentralWidget.MIN_TURN_DELAY) self.delay_slider.setValue(CentralWidget.MAX_TURN_DELAY) self.delay_slider.valueChanged.connect(self.change_speed) horizontal_layout.addWidget(self.delay_slider) epsilon_label = QLabel() epsilon_label.setText('Epsilon') horizontal_layout.addWidget(epsilon_label) epsilon_slider = QSlider() epsilon_slider.setOrientation(Qt.Horizontal) epsilon_slider.setMaximum(CentralWidget.EPSILON_MAX) epsilon_slider.setMinimum(CentralWidget.EPSILON_MIN) epsilon_slider.setValue(CentralWidget.EPSILON_DEFAULT) epsilon_slider.valueChanged.connect(self.change_epsilon) horizontal_layout.addWidget(epsilon_slider) self.start_button = QPushButton() self.start_button.setText('Start') self.start_button.clicked.connect(self.toggle_run) horizontal_layout.addWidget(self.start_button) spacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) horizontal_layout.addItem(spacer) vertical_layout.addLayout(horizontal_layout) self.setLayout(vertical_layout)
class windowTitle(QFrame): def __init__(self, parent, closeButton=True): QFrame.__init__(self, parent) self.setMaximumSize(QSize(9999999,22)) self.setObjectName("windowTitle") self.hboxlayout = QHBoxLayout(self) self.hboxlayout.setSpacing(0) self.hboxlayout.setContentsMargins(0,0,4,0) self.label = QLabel(self) self.label.setObjectName("label") self.label.setStyleSheet("padding-left:4px; font:bold 11px; color: #FFFFFF;") self.hboxlayout.addWidget(self.label) spacerItem = QSpacerItem(40,20,QSizePolicy.Expanding,QSizePolicy.Minimum) self.hboxlayout.addItem(spacerItem) if closeButton: self.pushButton = QPushButton(self) self.pushButton.setFocusPolicy(Qt.NoFocus) self.pushButton.setObjectName("pushButton") self.pushButton.setStyleSheet("font:bold;") self.pushButton.setText("X") self.hboxlayout.addWidget(self.pushButton) self.dragPosition = None self.mainwidget = self.parent() self.setStyleSheet(""" QFrame#windowTitle {background-color:#222222;color:#FFF;} """) # Initial position to top left self.dragPosition = self.mainwidget.frameGeometry().topLeft() def mousePressEvent(self, event): if event.button() == Qt.LeftButton: self.dragPosition = event.globalPos() - self.mainwidget.frameGeometry().topLeft() event.accept() def mouseMoveEvent(self, event): if event.buttons() & Qt.LeftButton: self.mainwidget.move(event.globalPos() - self.dragPosition) event.accept()
def __init__(self, parent, remove_text, remove_method, add_text, add_method): QWidget.__init__(self, parent) layout = QHBoxLayout() remove_button = QPushButton(remove_text, self) remove_button.setIcon(QApplication.style().standardIcon(QStyle.SP_TrashIcon)) remove_button.clicked.connect(remove_method) layout.addWidget(remove_button) layout.setContentsMargins(8, 0, 8, 0) horizontal_spacer = QSpacerItem(50, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) layout.addItem(horizontal_spacer) add_button = QPushButton(add_text, self) add_button.clicked.connect(add_method) layout.addWidget(add_button) self.setLayout(layout)
def _setLayout(self): mainLayout = QVBoxLayout() mainLayout.addItem(QSpacerItem(10, 10)) mainLayout.setSpacing(15) glayout = QGridLayout() hlayout = QHBoxLayout() hlayout.addItem(QSpacerItem(30, 1)) vlayout = QVBoxLayout() lb = QLabel('Available variables') vlayout.addWidget(lb) vlayout.setAlignment(lb, Qt.AlignHCenter) vlayout.addWidget(self.firstTable) hlayout2 = QHBoxLayout() hlayout2.addItem(QSpacerItem(30, 1)) hlayout2.addWidget(self.intersect) hlayout2.setAlignment(self.intersect, Qt.AlignLeft) hlayout2.addStretch() vlayout.addLayout(hlayout2) hlayout.addLayout(vlayout) hlayout.addItem(QSpacerItem(15, 1)) vlayout = QVBoxLayout() lb = QLabel('Output variables') vlayout.addWidget(lb) vlayout.setAlignment(lb, Qt.AlignHCenter) vlayout.addWidget(self.secondTable) hlayout.addLayout(vlayout) hlayout.addItem(QSpacerItem(30, 1)) glayout.addLayout(hlayout, 1, 1) glayout.setAlignment(Qt.AlignLeft) glayout.setSpacing(10) mainLayout.addLayout(glayout) mainLayout.addItem(QSpacerItem(30, 10)) hlayout = QHBoxLayout() hlayout.addItem(QSpacerItem(30, 1)) hlayout.addWidget(self.btnSubmit) hlayout.addWidget(self.csvNameBox) mainLayout.addLayout(hlayout) mainLayout.addItem(QSpacerItem(30, 15)) mainLayout.addWidget(QLabel(' Message logs')) mainLayout.addWidget(self.logTextBox.widget) self.setLayout(mainLayout)
class ObjectActionsWidget(QWidget): def __init__(self, treeItem, obj, parent=None): super().__init__(parent) self.sDownload = AsyncSignal() self.treeItem = treeItem self.obj = obj self.ipfsPath = IPFSPath(self.obj.get('path')) self.hlayout = QHBoxLayout(self) self.setLayout(self.hlayout) self.btnOpen = QPushButton(iOpen()) self.btnOpen.setText(iOpen()) self.btnOpen.setIcon(getIcon('open.png')) self.btnOpen.clicked.connect(partialEnsure(self.onOpen)) self.btnHashmark = HashmarkThisButton(self.ipfsPath) self.btnClipboard = IPFSPathClipboardButton(self.ipfsPath) self.btnDownload = QToolButton(self) self.btnDownload.setText('Download') self.btnDownload.clicked.connect(self.onDl) self.btnDownload.hide() self.hlayout.addWidget(self.btnClipboard) self.hlayout.addWidget(self.btnHashmark) self.hlayout.addWidget(self.btnOpen) self.hlayout.addWidget(self.btnDownload) def fLayout(self): self.hlayout.addItem( QSpacerItem(10, 10, QSizePolicy.Expanding, QSizePolicy.Minimum)) def onDl(self): ensure(self.sDownload.emit()) def showControls(self, download=False): self.btnDownload.setVisible(download) async def onOpen(self, *a): app = QApplication.instance() ensure(app.resourceOpener.open(self.obj['path']))
def __init__(self, account, edit_function, *args, **kwargs): """ Виджет, который сделан в качестве элемента списка :param account: database.Account, счёт, к которому привязан элемент списка :param edit_function: функция, которая будет вызываться при нажатии на кпопку 'Ред.' напротив названия счёта """ super(AccountItem, self).__init__(*args, **kwargs) layout = QHBoxLayout(self) # Название счёта layout.addWidget(Tag(account.name, account.color, parent=self)) layout.addItem(QSpacerItem(0, 0, QSizePolicy.Expanding, QSizePolicy.Maximum)) # Кнопка, при нажатии которой будет открыто окно с редактирование счёта button = QPushButton("Ред.", self) button.clicked.connect(partial(edit_function, account)) layout.addWidget(button) self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
def __init__(self, login): super(admin_customer, self).__init__() self.setWindowTitle("Admin-Customer Functionality") self.message = QLabel('Admin-Customer Functionality') self.login = login manage_user_button = QPushButton('Manage User') manage_company_button = QPushButton('Manage Company') create_movie_button = QPushButton('Create Movie') back_button = QPushButton('Back') explore_movie_button = QPushButton('Explore Movie') explore_theater = QPushButton('Explore Theater') view_history = QPushButton('View History') visit_history = QPushButton('Visit History') manage_user_button.clicked.connect(self.man_user_clicked) manage_company_button.clicked.connect(self.man_comp_clicked) create_movie_button.clicked.connect(self.create_movie_clicked) back_button.clicked.connect(self.back_clicked) explore_movie_button.clicked.connect(self.explore_clicked) visit_history.clicked.connect(self.view_history_clicked) explore_theater.clicked.connect(self.explore_theater_clicked) view_history.clicked.connect(self.view_history_clicked) vbox = QVBoxLayout() vbox.addWidget(self.message) hbox = QHBoxLayout() vbox2 = QVBoxLayout() vbox2.addWidget(manage_user_button) vbox2.addWidget(manage_company_button) vbox2.addWidget(create_movie_button) vbox2.addWidget(visit_history) vbox3 = QVBoxLayout() vbox3.addWidget(explore_movie_button) vbox3.addWidget(explore_theater) vbox3.addWidget(view_history) vbox3.addWidget(back_button) hbox.addItem(vbox2) hbox.addItem(vbox3) vbox.addItem(hbox) self.setLayout(vbox)
def __init__(self, parent, remove_text, remove_method, add_text, add_method): QWidget.__init__(self, parent) layout = QHBoxLayout() remove_button = QPushButton(remove_text, self) remove_button.setIcon(QApplication.style().standardIcon( QStyle.SP_TrashIcon)) remove_button.clicked.connect(remove_method) layout.addWidget(remove_button) layout.setContentsMargins(8, 0, 8, 0) horizontal_spacer = QSpacerItem(50, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) layout.addItem(horizontal_spacer) add_button = QPushButton(add_text, self) add_button.clicked.connect(add_method) layout.addWidget(add_button) self.setLayout(layout)
def __init__(self): QWidget.__init__(self, flags=Qt.Widget) self.setWindowTitle("Various Layout Widgets") self.setFixedWidth(640) self.setFixedHeight(480) layout_base = QBoxLayout(QBoxLayout.TopToBottom, self) self.setLayout(layout_base) # 첫 번째 그룹 QBoxLayout grp_1 = QGroupBox("QBoxLayout") layout_base.addWidget(grp_1) layout = QHBoxLayout() layout.addWidget(QPushButton("Butoon 1")) layout.addWidget(QPushButton("Butoon 1")) layout.addWidget(QPushButton("Butoon 1")) grp_1.setLayout(layout) # 두 번째 그룹 QGridLayout grp_2 = QGroupBox("QGridLayout") layout_base.addWidget(grp_2) grp_2_layout = QBoxLayout(QBoxLayout.LeftToRight) grp_2.setLayout(grp_2_layout) layout = QGridLayout() layout.addItem(QSpacerItem(10, 100)) layout.addWidget(QLabel("Line Edit 1:"), 1, 0) layout.addWidget(QLabel("Line Edit 2:"), 2, 0) layout.addWidget(QLabel("Line Edit 2:"), 3, 0) layout.addWidget(QLineEdit(), 1, 1) layout.addWidget(QLineEdit(), 2, 1) layout.addWidget(QLineEdit(), 3, 1) grp_2_layout.addLayout(layout) grp_2_layout.addWidget(QTextEdit()) # 세 번째 그룹 QFormLaytout grp_3 = QGroupBox("QFormLaytout") layout_base.addWidget(grp_3) layout = QFormLayout() grp_3.setLayout(layout) layout.addRow(QLabel("Line Edit 1:"), QLineEdit()) layout.addRow(QLabel("Line Edit 2:"), QLineEdit()) layout.addRow(QLabel("Line Edit 3:"), QLineEdit())
def __init__(self, tab_name: str): super().__init__() self.tab_name = tab_name self.grid_layout = QGridLayout() self.grid_layout.setContentsMargins(0, 0, 0, 0) self.grid_layout.setAlignment(Qt.AlignTop | Qt.AlignBottom) self.grid_layout.setSpacing(0) layout = QHBoxLayout() layout.addLayout(self.grid_layout) layout.addItem( QSpacerItem( 20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)) layout.setContentsMargins(0, 0, 0, 0) self.setLayout(layout) self.setContentsMargins(0, 0, 0, 0)
def __createLine(self, name, score, widget): lineLayout = QHBoxLayout() self.__font.setPixelSize(16) labelName = QLabel(self) labelName.setText(name) labelName.setFont(self.__font) labelScore = QLabel(self) labelScore.setText(str(score)) labelScore.setFont(self.__font) horizontalSpacer = QSpacerItem(20, 40, QSizePolicy.Expanding, QSizePolicy.Minimum) lineLayout.addWidget(labelName) lineLayout.addItem(horizontalSpacer) lineLayout.addWidget(labelScore) widget.layout().insertLayout(widget.layout().count() - 1, lineLayout)
def __init__(self, *args, **kwargs): super(Widget, self).__init__(*args, **kwargs) layout = QHBoxLayout(self) self.province_box = QComboBox(self, minimumWidth=200) # 市级以上 self.city_box = QComboBox(self, minimumWidth=200) # 市 self.county_box = QComboBox(self, minimumWidth=200) # 市级以下 layout.addWidget(QLabel("省/直辖市/特别行政区", self)) layout.addWidget(self.province_box) layout.addItem(QSpacerItem( 20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)) layout.addWidget(QLabel("市", self)) layout.addWidget(self.city_box) layout.addItem(QSpacerItem( 20, 20, QSizePolicy.Expanding, QSizePolicy.Minimum)) layout.addWidget(QLabel("区/县", self)) layout.addWidget(self.county_box) self.initModel() self.initSignal() self.initData()
def createUnlinkedSummary(self): groupbox = QGroupBox("Unlinked Details") hlayout = QVBoxLayout() groupbox.setLayout(hlayout) slipping_layout = QHBoxLayout() hlayout.addLayout(slipping_layout) slipping_label = QLabel('Slipping Bins: ') self.slipping_text = QLabel('0') slipping_layout.addWidget(slipping_label) slipping_layout.addWidget(self.slipping_text) slipping_percentage_label = QLabel('Percentage: ') self.slipping_percentage_text = QLabel('0 %') slipping_layout.addWidget(slipping_percentage_label) slipping_layout.addWidget(self.slipping_percentage_text) spacerItem = QtWidgets.QSpacerItem(10, 10, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) slipping_layout.addItem(spacerItem) pushed_layout = QHBoxLayout() hlayout.addLayout(pushed_layout) pushed_label = QLabel('Pushed Bins: ') self.pushed_text = QLabel('0') pushed_layout.addWidget(pushed_label) pushed_layout.addWidget(self.pushed_text) pushed_percentage_label = QLabel('Percentage: ') self.pushed_percentage_text = QLabel('0 %') pushed_layout.addWidget(pushed_percentage_label) pushed_layout.addWidget(self.pushed_percentage_text) spacerItem = QtWidgets.QSpacerItem(10, 10, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) pushed_layout.addItem(spacerItem) exit_read_unlinked_layout = QHBoxLayout() hlayout.addLayout(exit_read_unlinked_layout) exit_read_unlinked_label = QLabel('Unlinked Bin Read at Exit: ') self.exit_read_unlinked_text = QLabel('0') exit_read_unlinked_layout.addWidget(exit_read_unlinked_label) exit_read_unlinked_layout.addWidget(self.exit_read_unlinked_text) spacerItem = QtWidgets.QSpacerItem(10, 10, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) exit_read_unlinked_layout.addItem(spacerItem) unlinked_lost_track_layout = QHBoxLayout() hlayout.addLayout(unlinked_lost_track_layout) unlinked_lost_track_label = QLabel("Unlinked Bin Lost Track before Exit: ") self.unlinked_lost_track_text = QLabel('0') unlinked_lost_track_layout.addWidget(unlinked_lost_track_label) unlinked_lost_track_layout.addWidget(self.unlinked_lost_track_text) spacerItem = QtWidgets.QSpacerItem(10, 10, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) unlinked_lost_track_layout.addItem(spacerItem) return groupbox
def __init__(self): super(self.__class__, self).__init__() self.folder = None self.line_edit = QLineEdit() self.button = QPushButton() self.button.setText("Browse...") self.button.clicked.connect(self.on_clicked) gbox = QGroupBox(self) gbox.setTitle("Select a folder to sync:") gbox_layout = QHBoxLayout(gbox) gbox_layout.addItem(QSpacerItem(100, 0, QSizePolicy.Preferred, 0)) gbox_layout.addWidget(self.line_edit) gbox_layout.addWidget(self.button) gbox_layout.addItem(QSpacerItem(100, 0, QSizePolicy.Preferred, 0)) hbox = QHBoxLayout(self) hbox.addWidget(gbox)
def __init__(self): super(StatusBar, self).__init__() self.setStyleSheet("border: none;") container = QWidget() box = QHBoxLayout(container) box.setSpacing(20) # File Path self.label_file = QLabel("") self.label_file.setObjectName("status-path") box.addWidget(self.label_file) # Cursor Position self._line_col = "%s / %s" self.label = QLabel(self._line_col % (0, 0)) self.label.setObjectName("status-cursor") box.addWidget(self.label) # File type self._file_type = QToolButton() self._file_type.setPopupMode(2) self._file_type.setObjectName("status-type") box.addWidget(self._file_type) # Tabs self._tabs_button = QToolButton() self._tabs_button.setObjectName("status-tabs") self._tabs_button.setPopupMode(2) menu = QMenu(self) self._load_menu_for_button(menu) self._tabs_button.setMenu(menu) self._change_text_tool_button() box.addItem(QSpacerItem(container.width() + self.width(), 0, QSizePolicy.Expanding)) box.addWidget(self._tabs_button) self.addWidget(container) Amaru.load_component("status_bar", self)
def __init__(self,winParent): super(timeWidget, self).__init__() self.winParent=winParent self.seconds = 0 hLayout = QHBoxLayout() timeLabel = QLabel("Time") self.lcd = QLCDNumber(self) self.lcd.setMaximumSize(100,50) hLayout.addWidget(timeLabel,0) hLayout.addWidget(self.lcd, 1) hSpacer = QSpacerItem(300, 30, QSizePolicy.Ignored, QSizePolicy.Ignored) hLayout.addItem(hSpacer) self.setLayout(hLayout) timer = QTimer(self) timer.start(1000) timer.timeout.connect(self.printTime) # get the palette palette = self.lcd.palette() # foreground color palette.setColor(palette.WindowText, QColor(85, 85, 255)) # background color palette.setColor(palette.Background, QColor(0, 170, 255)) # "light" border palette.setColor(palette.Light, QColor(255, 0, 0)) # "dark" border palette.setColor(palette.Dark, QColor(0, 255, 0)) # set the palette self.lcd.setPalette(palette)
class E5LineEdit(QLineEdit): """ Class implementing a line edit widget showing some inactive text. """ LeftSide = 0 RightSide = 1 def __init__(self, parent=None, inactiveText=""): """ Constructor @param parent reference to the parent widget (QWidget) @param inactiveText text to be shown on inactivity (string) """ super(E5LineEdit, self).__init__(parent) self.setMinimumHeight(22) if qVersion() < "4.7.0": self.__inactiveText = inactiveText else: self.setPlaceholderText(inactiveText) self.__mainLayout = QHBoxLayout(self) self.__mainLayout.setContentsMargins(0, 0, 0, 0) self.__mainLayout.setSpacing(0) self.__leftMargin = 0 self.__leftWidget = E5LineEditSideWidget(self) self.__leftWidget.resize(0, 0) self.__leftLayout = QHBoxLayout(self.__leftWidget) self.__leftLayout.setContentsMargins(0, 0, 2, 0) if QApplication.isRightToLeft(): self.__leftLayout.setDirection(QBoxLayout.RightToLeft) else: self.__leftLayout.setDirection(QBoxLayout.LeftToRight) self.__leftLayout.setSizeConstraint(QLayout.SetFixedSize) self.__rightWidget = E5LineEditSideWidget(self) self.__rightWidget.resize(0, 0) self.__rightLayout = QHBoxLayout(self.__rightWidget) self.__rightLayout.setContentsMargins(0, 0, 2, 0) if self.isRightToLeft(): self.__rightLayout.setDirection(QBoxLayout.RightToLeft) else: self.__rightLayout.setDirection(QBoxLayout.LeftToRight) horizontalSpacer = QSpacerItem( 0, 0, QSizePolicy.Expanding, QSizePolicy.Minimum) self.__mainLayout.addWidget( self.__leftWidget, 0, Qt.AlignVCenter | Qt.AlignLeft) self.__mainLayout.addItem(horizontalSpacer) self.__mainLayout.addWidget( self.__rightWidget, 0, Qt.AlignVCenter | Qt.AlignRight) if self.isRightToLeft(): self.__mainLayout.setDirection(QBoxLayout.RightToLeft) else: self.__mainLayout.setDirection(QBoxLayout.LeftToRight) self.setWidgetSpacing(3) self.__leftWidget.sizeHintChanged.connect(self._updateTextMargins) self.__rightWidget.sizeHintChanged.connect(self._updateTextMargins) def setLeftMargin(self, margin): """ Public method to set the left margin. @param margin left margin in pixel (integer) """ self.__leftMargin = margin def leftMargin(self): """ Public method to get the size of the left margin. @return left margin in pixel (integer) """ return self.__leftMargin def event(self, evt): """ Public method to handle events. @param evt reference to the event (QEvent) @return flag indicating, whether the event was recognized (boolean) """ if evt.type() == QEvent.LayoutDirectionChange: if self.isRightToLeft(): self.__mainLayout.setDirection(QBoxLayout.RightToLeft) self.__leftLayout.setDirection(QBoxLayout.RightToLeft) self.__rightLayout.setDirection(QBoxLayout.RightToLeft) else: self.__mainLayout.setDirection(QBoxLayout.LeftToRight) self.__leftLayout.setDirection(QBoxLayout.LeftToRight) self.__rightLayout.setDirection(QBoxLayout.LeftToRight) return QLineEdit.event(self, evt) def paintEvent(self, evt): """ Protected method handling a paint event. @param evt reference to the paint event (QPaintEvent) """ super(E5LineEdit, self).paintEvent(evt) if qVersion() < "4.7.0": if not self.text() and \ self.__inactiveText and \ not self.hasFocus(): panel = QStyleOptionFrame() self.initStyleOption(panel) textRect = self.style().subElementRect( QStyle.SE_LineEditContents, panel, self) textRect.adjust(2, 0, 0, 0) left = self.textMargin(self.LeftSide) right = self.textMargin(self.RightSide) textRect.adjust(left, 0, -right, 0) painter = QPainter(self) painter.setPen(self.palette().brush( QPalette.Disabled, QPalette.Text).color()) painter.drawText( textRect, Qt.AlignLeft | Qt.AlignVCenter, self.__inactiveText) def _updateTextMargins(self): """ Protected slot to update the text margins. """ if self.__leftMargin == 0: left = self.__leftWidget.sizeHint().width() else: left = self.__leftMargin right = self.__rightWidget.sizeHint().width() top = 0 bottom = 0 self.setTextMargins(left, top, right, bottom) def addWidget(self, widget, position): """ Public method to add a widget to a side. @param widget reference to the widget to add (QWidget) @param position position to add to (E5LineEdit.LeftSide, E5LineEdit.RightSide) """ if widget is None: return if self.isRightToLeft(): if position == self.LeftSide: position = self.RightSide else: position = self.LeftSide if position == self.LeftSide: self.__leftLayout.addWidget(widget) else: self.__rightLayout.insertWidget(1, widget) def removeWidget(self, widget): """ Public method to remove a widget from a side. @param widget reference to the widget to remove (QWidget) """ if widget is None: return self.__leftLayout.removeWidget(widget) self.__rightLayout.removeWidget(widget) widget.hide() def widgetSpacing(self): """ Public method to get the side widget spacing. @return side widget spacing (integer) """ return self.__leftLayout.spacing() def setWidgetSpacing(self, spacing): """ Public method to set the side widget spacing. @param spacing side widget spacing (integer) """ self.__leftLayout.setSpacing(spacing) self.__rightLayout.setSpacing(spacing) self._updateTextMargins() def textMargin(self, position): """ Public method to get the text margin for a side. @param position side to get margin for (E5LineEdit.LeftSide, E5LineEdit.RightSide) @return text margin (integer) """ spacing = self.__rightLayout.spacing() w = 0 if position == self.LeftSide: w = self.__leftWidget.sizeHint().width() else: w = self.__rightWidget.sizeHint().width() if w == 0: return 0 return w + spacing * 2 def inactiveText(self): """ Public method to get the inactive text. @return inactive text (string) """ if qVersion() < "4.7.0": return self.__inactiveText else: return self.placeholderText() def setInactiveText(self, inactiveText): """ Public method to set the inactive text. @param inactiveText text to be shown on inactivity (string) """ if qVersion() < "4.7.0": self.__inactiveText = inactiveText self.update() else: self.setPlaceholderText(inactiveText)
class RadioBox(QWidget): def __init__(self, parent=None, items=None, spread=True, **kwargs): # If spread is False, insert a spacer in the layout so that the items don't use all the # space they're given but rather align left. if items is None: items = [] super().__init__(parent, **kwargs) self._buttons = [] self._labels = items self._selected_index = 0 self._spacer = horizontalSpacer() if not spread else None self._layout = QHBoxLayout(self) self._update_buttons() #--- Private def _update_buttons(self): if self._spacer is not None: self._layout.removeItem(self._spacer) to_remove = self._buttons[len(self._labels):] for button in to_remove: self._layout.removeWidget(button) button.setParent(None) del self._buttons[len(self._labels):] to_add = self._labels[len(self._buttons):] for _ in to_add: button = QRadioButton(self) self._buttons.append(button) self._layout.addWidget(button) button.toggled.connect(self.buttonToggled) if self._spacer is not None: self._layout.addItem(self._spacer) if not self._buttons: return for button, label in zip(self._buttons, self._labels): button.setText(label) self._update_selection() def _update_selection(self): self._selected_index = max(0, min(self._selected_index, len(self._buttons)-1)) selected = self._buttons[self._selected_index] selected.setChecked(True) #--- Event Handlers def buttonToggled(self): for i, button in enumerate(self._buttons): if button.isChecked(): self._selected_index = i self.itemSelected.emit(i) break #--- Signals itemSelected = pyqtSignal(int) #--- Properties @property def buttons(self): return self._buttons[:] @property def items(self): return self._labels[:] @items.setter def items(self, value): self._labels = value self._update_buttons() @property def selected_index(self): return self._selected_index @selected_index.setter def selected_index(self, value): self._selected_index = value self._update_selection()
class EditorMainWindow(QMainWindow): def __init__(self): super().__init__() self.setupUi(self) self.retranslateUi(self) self.level = None path = get_default_path() if path is None: self.default_path = "" else: self.default_path = path self.dragging = False self.last_x = None self.last_y = None self.dragged_time = None self.deleting_item = False # Hack for preventing focusing on next item after deleting the previous one self.moving = False self.resetting = False self.entity_list_widget.currentItemChanged.connect(self.action_listwidget_change_selection) self.button_zoom_in.pressed.connect(self.zoom_in) self.button_zoom_out.pressed.connect(self.zoom_out) self.button_remove_entity.pressed.connect(self.remove_position) self.button_move_entity.pressed.connect(self.move_entity) self.button_clone_entity.pressed.connect(self.action_clone_entity) self.button_show_passengers.pressed.connect(self.action_passenger_window) self.button_edit_xml.pressed.connect(self.action_open_xml_editor) self.button_edit_base_xml.pressed.connect(self.action_open_basexml_editor) self.lineedit_angle.editingFinished.connect(self.action_lineedit_changeangle) self.bw_map_screen.mouse_clicked.connect(self.get_position) self.bw_map_screen.entity_clicked.connect(self.entity_position) self.bw_map_screen.mouse_dragged.connect(self.mouse_move) self.bw_map_screen.mouse_released.connect(self.mouse_release) self.bw_map_screen.mouse_wheel.connect(self.mouse_wheel_scroll_zoom) status = self.statusbar self.bw_map_screen.setMouseTracking(True) self.passenger_window = BWPassengerWindow() self.passenger_window.passengerlist.currentItemChanged.connect(self.passengerwindow_action_choose_entity) self.xmlobject_textbox = BWEntityXMLEditor() self.xmlobject_textbox.button_xml_savetext.pressed.connect(self.xmleditor_action_save_object_xml) self.xmlobject_textbox.triggered.connect(self.action_open_xml_editor_unlimited) self.basexmlobject_textbox = BWEntityXMLEditor(windowtype="XML Base Object") self.basexmlobject_textbox.button_xml_savetext.pressed.connect(self.xmleditor_action_save_base_object_xml) self.basexmlobject_textbox.triggered.connect(self.action_open_xml_editor_unlimited) self.types_visible = {} self.terrain_image = None status.showMessage("Ready") self.xml_windows = {} print("We are now ready!") def reset(self): self.resetting = True self.statusbar.clearMessage() self.dragged_time = None self.moving = False self.dragging = False self.last_x = None self.last_y = None self.dragged_time = None self.moving = False self.entity_list_widget.clearSelection() self.entity_list_widget.clear() self.bw_map_screen.reset() self.clear_visibility_toggles() for window in (self.passenger_window, self.xmlobject_textbox, self.basexmlobject_textbox): window.close() window.reset() for id in self.xml_windows: self.destroy_xml_editor(id) self.resetting = False print("reset done") def destroy_xml_editor(self, id): pass @catch_exception def open_xml_editor(self, objectid, offsetx=0, offsety=0): selected = objectid if self.level is not None and selected in self.level.obj_map: delete = [] for objid, window in self.xml_windows.items(): if not window.isVisible() and objid != selected: window.destroy() delete.append(objid) for objid in delete: del self.xml_windows[objid] if selected == self.basexmlobject_textbox.entity or selected == self.xmlobject_textbox.entity: pass # No need to make a new window elif selected in self.xml_windows and self.xml_windows[selected].isVisible(): self.xml_windows[selected].activateWindow() self.xml_windows[selected].update() else: xml_window = BWEntityXMLEditor() def xmleditor_save_object_unlimited(): self.statusbar.showMessage("Saving object changes...") try: xmlnode = xml_window.get_content() #assert self.bw_map_screen.current_entity == self.basexmlobject_textbox.entity assert xml_window.entity == xmlnode.get("id") # Disallow changing the id of the base object self.level.remove_object(xmlnode.get("id")) self.level.add_object(xmlnode) self.statusbar.showMessage("Saved base object {0} as {1}".format( xml_window.entity, self.level.obj_map[xmlnode.get("id")].name)) except: self.statusbar.showMessage("Saving object failed") traceback.print_exc() xml_window.button_xml_savetext.pressed.connect(xmleditor_save_object_unlimited) xml_window.triggered.connect(self.action_open_xml_editor_unlimited) obj = self.level.obj_map[selected] xml_window.set_title(obj.name) xml_window.set_content(obj._xml_node) #xml_window.move(QPoint(xml_editor_owner.pos().x()+20, xml_editor_owner.pos().y()+20)) xml_window.move(QPoint(offsetx, offsety)) xml_window.show() xml_window.update() self.xml_windows[selected] = xml_window @catch_exception def action_open_xml_editor_unlimited(self, xml_editor_owner): selected = xml_editor_owner.textbox_xml.textCursor().selectedText() self.open_xml_editor(selected, offsetx=xml_editor_owner.pos().x()+20, offsety=xml_editor_owner.pos().y()+20) @catch_exception def action_open_basexml_editor(self): """ if not self.basexmlobject_textbox.isVisible(): self.basexmlobject_textbox.destroy() self.basexmlobject_textbox = BWEntityXMLEditor(windowtype="XML Base Object") self.basexmlobject_textbox.button_xml_savetext.pressed.connect(self.xmleditor_action_save_base_object_xml) self.basexmlobject_textbox.triggered.connect(self.action_open_xml_editor_unlimited) self.basexmlobject_textbox.show() self.basexmlobject_textbox.activateWindow()""" if self.level is not None and self.bw_map_screen.current_entity is not None: obj = self.level.obj_map[self.bw_map_screen.current_entity] if not obj.has_attr("mBase"): pass else: baseobj = self.level.obj_map[obj.get_attr_value("mBase")] #self.basexmlobject_textbox.set_title(baseobj.id) self.open_xml_editor(baseobj.id) def xmleditor_action_save_base_object_xml(self): self.statusbar.showMessage("Saving base object changes...") try: xmlnode = self.basexmlobject_textbox.get_content() #assert self.bw_map_screen.current_entity == self.basexmlobject_textbox.entity assert self.basexmlobject_textbox.entity == xmlnode.get("id") # Disallow changing the id of the base object self.level.remove_object(xmlnode.get("id")) self.level.add_object(xmlnode) self.statusbar.showMessage("Saved base object {0} as {1}".format( self.basexmlobject_textbox.entity, self.level.obj_map[xmlnode.get("id")].name)) except: self.statusbar.showMessage("Saving base object failed") traceback.print_exc() def action_open_xml_editor(self): """ if not self.xmlobject_textbox.isVisible(): self.xmlobject_textbox.destroy() self.xmlobject_textbox = BWEntityXMLEditor() self.xmlobject_textbox.button_xml_savetext.pressed.connect(self.xmleditor_action_save_object_xml) self.xmlobject_textbox.triggered.connect(self.action_open_xml_editor_unlimited) self.xmlobject_textbox.show() self.xmlobject_textbox.activateWindow()""" if self.level is not None and self.bw_map_screen.current_entity is not None: entityobj = self.level.obj_map[self.bw_map_screen.current_entity] self.open_xml_editor(objectid=entityobj.id) update_mapscreen(self.bw_map_screen, self.level.obj_map[entityobj.id]) self.bw_map_screen.update() """self.xmlobject_textbox.set_title(entityobj.id) self.xmlobject_textbox.set_content(entityobj._xml_node) self.xmlobject_textbox.update()""" def xmleditor_action_save_object_xml(self): self.statusbar.showMessage("Saving object changes...") try: xmlnode = self.xmlobject_textbox.get_content() #assert self.bw_map_screen.current_entity == self.xmlobject_textbox.entity assert self.xmlobject_textbox.entity == xmlnode.get("id") or xmlnode.get("id") not in self.level.obj_map if self.passenger_window.isVisible(): self.passenger_window.close() if self.xmlobject_textbox.entity != xmlnode.get("id"): #obj = self.level.obj_map[xmlnode.get("id")] self.level.remove_object(self.xmlobject_textbox.entity) print("adding", xmlnode.get("id"), xmlnode.get("id") in self.level.obj_map ) self.level.add_object(xmlnode) pos = self.get_entity_item_pos(self.xmlobject_textbox.entity) item = self.entity_list_widget.takeItem(pos) self.entity_list_widget.removeItemWidget(item) self.add_item_sorted(xmlnode.get("id")) self.bw_map_screen.rename_entity(self.xmlobject_textbox.entity, xmlnode.get("id")) assert xmlnode.get("id") in self.level.obj_map self.xmlobject_textbox.entity = xmlnode.get("id") self.xmlobject_textbox.set_title(xmlnode.get("id")) else: self.level.remove_object(xmlnode.get("id")) self.level.add_object(xmlnode) update_mapscreen(self.bw_map_screen, self.level.obj_map[xmlnode.get("id")]) self.statusbar.showMessage("Saved object {0} as {1}".format( self.xmlobject_textbox.entity, self.level.obj_map[xmlnode.get("id")].name)) self.bw_map_screen.update() except: self.statusbar.showMessage("Saving object failed") traceback.print_exc() def action_clone_entity(self): entities = [] if self.bw_map_screen.current_entity is not None: entities.append(self.bw_map_screen.current_entity) elif len(self.bw_map_screen.selected_entities) > 0: entities.extend(self.bw_map_screen.selected_entities.keys()) if len(entities) > 0: dont_clone = {} for entity in entities: obj = self.level.obj_map[entity] if obj.has_attr("mPassenger"): passengers = obj.get_attr_elements("mPassenger") for passenger in passengers: if passenger != "0": dont_clone[passenger] = True select = [] for entity in entities: if entity in dont_clone: continue obj = self.level.obj_map[entity] xml_node = deepcopy(obj._xml_node) try: cloned_id = self.level.generate_unique_id(entity) xml_node.set("id", cloned_id) self.level.add_object(xml_node) bw_x, bw_y, angle = object_get_position(self.level, cloned_id) x, y = bw_coords_to_image_coords(bw_x, bw_y) self.add_item_sorted(cloned_id) self.bw_map_screen.add_entity(x, y, cloned_id, obj.type) clonedobj = self.level.obj_map[cloned_id] select.append(cloned_id) update_mapscreen(self.bw_map_screen, clonedobj) if clonedobj.has_attr("mPassenger"): orig_x = bw_x orig_y = bw_y passengers = clonedobj.get_attr_elements("mPassenger") passengers_added = [] for i, passenger in enumerate(passengers): if passenger != "0": obj = self.level.obj_map[passenger] xml_node = deepcopy(obj._xml_node) clonedpassenger_id = self.level.generate_unique_id(passenger) xml_node.set("id", clonedpassenger_id) #print("orig passenger: {0}, new passenger: {1}, alreadyexists: {2}".format( # passenger, clonedpassenger_id, clonedpassenger_id in self.level.obj_map #)) #print(type(passenger), type(clonedpassenger_id)) self.level.add_object(xml_node) #x, y = object_get_position(self.level, newid) x = orig_x + (i+1)*8 y = orig_y + (i+1)*8 #print(orig_x, orig_y, x, y) object_set_position(self.level, clonedpassenger_id, x, y) x, y = bw_coords_to_image_coords(x, y) self.add_item_sorted(clonedpassenger_id) self.bw_map_screen.add_entity(x, y, clonedpassenger_id, obj.type) update_mapscreen(self.bw_map_screen, self.level.obj_map[clonedpassenger_id]) passengers_added.append(passenger) clonedobj.set_attr_value("mPassenger", clonedpassenger_id, i) select.append(clonedpassenger_id) #print("passengers added:", passengers_added) self.bw_map_screen.selected_entities = {} if len(select) == 1: ent = select[0] self.set_entity_text(ent) self.bw_map_screen.choose_entity(ent) else: for ent in select: self.bw_map_screen.selected_entities[ent] = True self.set_entity_text_multiple(self.bw_map_screen.selected_entities) self.bw_map_screen.update() except: traceback.print_exc() def add_item_sorted(self, entity): max_count = self.entity_list_widget.count() entityobj = self.level.obj_map[entity] index = 0 entity_item = BWEntityEntry(entity, "{0}[{1}]".format(entity, entityobj.type)) # Similar to loading a level, we add the entity in a sorted way by # creating this string and comparing it for every item in the list. entity_string = get_type(entityobj.type)+entityobj.type+entityobj.id inserted = False for i in range(max_count): curritem = self.entity_list_widget.item(i) currobj = self.level.obj_map[curritem.xml_ref] currstring = get_type(currobj.type)+currobj.type+currobj.id # The list is already sorted, so if we find an item bigger than # the one we are inserting, we know the position we have to insert the item in. # String comparison should be alpabetically. if currstring > entity_string: self.entity_list_widget.insertItem(i, entity_item) inserted = True break # If we couldn't insert the item, i.e. there are no items at all # or all items are smaller than the item we add, we just add it at the end. if not inserted: self.entity_list_widget.addItem(entity_item) def get_entity_item_pos(self, entityid): for i in range(self.entity_list_widget.count()): item = self.entity_list_widget.item(i) if item.xml_ref == entityid: return i return None def action_passenger_window(self): #if self.passenger_window.isVisible() print("window is visible: ", self.passenger_window.isVisible()) #self.passenger_window.reset() if not self.passenger_window.isVisible(): self.passenger_window.destroy() self.passenger_window = BWPassengerWindow() self.passenger_window.passengerlist.currentItemChanged.connect(self.passengerwindow_action_choose_entity) self.passenger_window.show() self.passenger_window.activateWindow() if self.bw_map_screen.current_entity is not None: self.passenger_window.reset() entityobj = self.level.obj_map[self.bw_map_screen.current_entity] self.passenger_window.set_title(entityobj.id) if entityobj.has_attr("mPassenger"): for i, passenger in enumerate(entityobj.get_attr_elements("mPassenger")): if passenger in self.level.obj_map: passengerobj = self.level.obj_map[passenger] list_item_name = "{0}[{1}]".format(passenger, passengerobj.type) elif passenger == "0": list_item_name = "{0}<none>".format(passenger) else: list_item_name = "{0}<missing>".format(passenger) self.passenger_window.add_passenger(list_item_name, passenger) self.passenger_window.update() def passengerwindow_action_choose_entity(self, current, previous): try: if current is not None and current.xml_ref in self.level.obj_map: self.set_entity_text(current.xml_ref) self.bw_map_screen.choose_entity(current.xml_ref) elif current is not None: self.statusbar.showMessage("No such entity: {0}".format(current.xml_ref), 1000*2) except: traceback.print_exc() def move_entity(self): if not self.dragging: if not self.moving: self.moving = True currtext = self.button_move_entity.text() self.button_move_entity.setText("Stop [Move Entity]") else: self.moving = False currtext = "Move Entity" self.button_move_entity.setText(currtext) def button_load_level(self): try: print("ok", self.default_path) self.xmlPath = "" filepath, choosentype = QFileDialog.getOpenFileName( self, "Open File", self.default_path, BW_LEVEL+";;"+BW_COMPRESSED_LEVEL+";;All files (*)") print("doooone") if filepath: print("resetting") self.reset() print("done") print("chosen type:",choosentype) # Some BW levels are clear XML files, some are compressed with GZIP # We decide between the two either based on user choice or end of filepath if choosentype == BW_COMPRESSED_LEVEL or filepath.endswith(".gz"): print("OPENING AS COMPRESSED") file_open = gzip.open else: file_open = open with file_open(filepath, "rb") as f: try: self.level = BattWarsLevel(f) self.default_path = filepath set_default_path(filepath) self.setup_visibility_toggles() for obj_id, obj in sorted(self.level.obj_map.items(), key=lambda x: get_type(x[1].type)+x[1].type+x[1].id): #print("doing", obj_id) if get_position_attribute(obj) is None: continue #if not obj.has_attr("Mat"): # continue x, y, angle = object_get_position(self.level, obj_id) assert type(x) != str x, y = bw_coords_to_image_coords(x, y) item = BWEntityEntry(obj_id, "{0}[{1}]".format(obj_id, obj.type)) self.entity_list_widget.addItem(item) self.bw_map_screen.add_entity(x, y, obj_id, obj.type, update=False) #if obj.type == "cMapZone": update_mapscreen(self.bw_map_screen, obj) print("ok") self.bw_map_screen.update() path_parts = path.split(filepath) self.setWindowTitle("BW-MapEdit - {0}".format(path_parts[-1])) except Exception as error: print("error", error) traceback.print_exc() except Exception as er: print("errrorrr", er) traceback.print_exc() print("loaded") def button_save_level(self): if self.level is not None: filepath, choosentype = QFileDialog.getSaveFileName( self, "Save File", self.default_path, BW_LEVEL+";;"+BW_COMPRESSED_LEVEL+";;All files (*)") print(filepath, "saved") if filepath: # Simiar to load level if choosentype == BW_COMPRESSED_LEVEL or filepath.endswith(".gz"): file_open = gzip.open else: file_open = open try: with file_open(filepath, "wb") as f: self.level._tree.write(f) except Exception as error: print("COULDN'T SAVE:", error) traceback.print_exc() self.default_path = filepath else: pass # no level loaded, do nothing def entity_position(self, event, entity): try: # Make it possible to select objects in move mode, but don't make it too easy to lose # a selection. if not (self.moving and len(self.bw_map_screen.selected_entities) > 1): print("got entity:",entity, self.bw_map_screen.entities[entity][2]) print(entity_get_model(self.level, entity)) self.set_entity_text(entity) self.bw_map_screen.choose_entity(entity) pos = self.get_entity_item_pos(entity) print("searching:",pos) try: self.entity_list_widget.select_item(pos) except: traceback.print_exc() self.bw_map_screen.selected_entities = {} self.bw_map_screen.update() except: traceback.print_exc() def remove_position(self): #self.bw_map_screen.entities.pop() try: # Remove the entity from the map, the list widget and the level data self.deleting_item = True entities = [] if self.bw_map_screen.current_entity is not None: entities.append(self.bw_map_screen.current_entity) elif len(self.bw_map_screen.selected_entities) > 0: entities.extend(self.bw_map_screen.selected_entities.keys()) self.bw_map_screen.selected_entities = {} self.set_entity_text_multiple(self.bw_map_screen.selected_entities) if len(entities) > 0: for entity in entities: pos = self.get_entity_item_pos(entity) item = self.entity_list_widget.takeItem(pos) assert item.xml_ref == entity #self.entity_list_widget.clearSelection() self.entity_list_widget.clearFocus() self.entity_list_widget.removeItemWidget(item) self.level.remove_object(entity) self.bw_map_screen.remove_entity(entity) self.bw_map_screen.update() except: traceback.print_exc() raise #@catch_exception def get_position(self, event): self.dragging = True self.last_x = event.x() self.last_y = event.y() self.dragged_time = default_timer() mouse_x = event.x()/self.bw_map_screen.zoom_factor mouse_y = event.y()/self.bw_map_screen.zoom_factor if event.buttons() == QtCore.Qt.LeftButton: if not self.moving: self.bw_map_screen.set_selectionbox_start((event.x(), event.y())) else: if self.bw_map_screen.current_entity is not None: newx, newy = image_coords_to_bw_coords(mouse_x, mouse_y) object_set_position(self.level, self.bw_map_screen.current_entity, newx, newy) self.bw_map_screen.move_entity(self.bw_map_screen.current_entity, mouse_x, mouse_y) self.set_entity_text(self.bw_map_screen.current_entity) update_mapscreen(self.bw_map_screen, self.level.obj_map[self.bw_map_screen.current_entity]) elif len(self.bw_map_screen.selected_entities) > 0: for entity in self.bw_map_screen.selected_entities: first_entity = entity break #first_entity = self.bw_map_screen.selected_entities.keys()[0] x, y, entitytype, metadata = self.bw_map_screen.entities[first_entity] startx = endx = x starty = endy = y for entity in self.bw_map_screen.selected_entities: x, y, dontneed, dontneed = self.bw_map_screen.entities[entity] if x < startx: startx = x if x > endx: endx = x if y < starty: starty = y if y > endy: endy = y middle_x = (startx+endx) / 2 middle_y = (starty+endy) / 2 delta_x = mouse_x - middle_x delta_y = mouse_y - middle_y for entity in self.bw_map_screen.selected_entities: x, y, dontneed, dontneed = self.bw_map_screen.entities[entity] newx, newy = image_coords_to_bw_coords(x+delta_x, y+delta_y) object_set_position(self.level, entity, newx, newy) self.bw_map_screen.move_entity(entity, x+delta_x, y+delta_y) #self.set_entity_text(self.bw_map_screen.current_entity) update_mapscreen(self.bw_map_screen, self.level.obj_map[entity]) self.bw_map_screen.update() @catch_exception def mouse_move(self, event): x, y = image_coords_to_bw_coords(event.x()/self.bw_map_screen.zoom_factor, event.y()/self.bw_map_screen.zoom_factor) self.statusbar.showMessage("x: {0} y: {1}".format(round(x, 5), round(y, 5))) if self.dragging and default_timer() - self.dragged_time > 0.1: if event.buttons() == QtCore.Qt.RightButton: delta_x = (event.x()-self.last_x)/8 delta_y = (event.y()-self.last_y)/8 #print("hi",event.x(), event.y()) vertbar = self.scrollArea.verticalScrollBar() horizbar = self.scrollArea.horizontalScrollBar() vertbar.setSliderPosition(vertbar.value()-delta_y) horizbar.setSliderPosition(horizbar.value()-delta_x) elif event.buttons() == QtCore.Qt.LeftButton: self.bw_map_screen.set_selectionbox_end((event.x(), event.y())) if len(self.bw_map_screen.selected_entities) > 0 or self.bw_map_screen.current_entity is None: self.bw_map_screen.choose_entity(None) self.set_entity_text_multiple(self.bw_map_screen.selected_entities) self.bw_map_screen.update() def mouse_release(self, event): self.dragging = False if self.bw_map_screen.selectionbox_end is not None: self.bw_map_screen.clear_selection_box() self.bw_map_screen.update() def set_entity_text_multiple(self, entities): self.label_object_id.setText("{0} objects selected".format(len(entities))) MAX = 15 listentities = [self.level.obj_map[x].name for x in sorted(entities.keys())][0:MAX] listentities.sort() if len(entities) > MAX: listentities.append("... and {0} more".format(len(entities) - len(listentities))) self.label_position.setText("\n".join(listentities[:5])) self.label_model_name.setText("\n".join(listentities[5:10])) self.label_4.setText("\n".join(listentities[10:]))#15])) self.label_5.setText("")#("\n".join(listentities[12:16])) def set_entity_text(self, entityid): try: obj = self.level.obj_map[entityid] if obj.has_attr("mBase"): base = self.level.obj_map[obj.get_attr_value("mBase")] self.label_object_id.setText("{0}\n[{1}]\nBase: {2}\n[{3}]".format( entityid, obj.type, base.id, base.type)) else: self.label_object_id.setText("{0}\n[{1}]".format(entityid, obj.type)) self.label_model_name.setText("Model: {0}".format(entity_get_model(self.level, entityid))) x, y, angle = object_get_position(self.level, entityid) self.label_position.setText("x: {0}\ny: {1}".format(x, y)) self.lineedit_angle.setText(str(round(angle,2))) self.label_4.setText("Army: {0}".format(entity_get_army(self.level, entityid))) if not obj.has_attr("mPassenger"): self.label_5.setText("Icon Type: \n{0}".format(entity_get_icon_type(self.level, entityid))) else: passengers = 0 for passenger in obj.get_attr_elements("mPassenger"): if passenger != "0": passengers += 1 self.label_5.setText("Icon Type: \n{0}\n\nPassengers: {1}".format( entity_get_icon_type(self.level, entityid), passengers)) except: traceback.print_exc() def action_listwidget_change_selection(self, current, previous): #QtWidgets.QListWidgetItem. if not self.resetting and current is not None: print("ok") print("hi", current.text(), current.xml_ref) self.set_entity_text(current.xml_ref) self.bw_map_screen.choose_entity(current.xml_ref) posx, posy, typename, metadata = self.bw_map_screen.entities[current.xml_ref] zf = self.bw_map_screen.zoom_factor try: if not self.deleting_item: x_margin = min(100, 50*zf) y_margin = min(100, 50*zf) self.scrollArea.ensureVisible(posx*zf, posy*zf, xMargin=x_margin, yMargin=y_margin) else: self.deleting_item = False except: traceback.print_exc() def zoom_out(self, noslider=False): horizbar = self.scrollArea.horizontalScrollBar() vertbar = self.scrollArea.verticalScrollBar() print(horizbar.maximum(), vertbar.maximum()) if horizbar.maximum() > 0: widthratio = horizbar.value()/horizbar.maximum() else: widthratio = 0 if vertbar.maximum() > 0: heightratio = vertbar.value()/vertbar.maximum() else: heightratio = 0 #oldzf = self.bw_map_screen.zoom_factor / (0.1+1) #diff = oldzf - self.bw_map_screen.zoom_factor zf = self.bw_map_screen.zoom_factor self.bw_map_screen.zoom(calc_zoom_out_factor(zf))#diff) # if not noslider: horizbar.setSliderPosition(horizbar.maximum()*widthratio) vertbar.setSliderPosition(vertbar.maximum()*heightratio) self.bw_map_screen.update() self.statusbar.showMessage("Zoom: {0}x".format(self.bw_map_screen.zoom_factor)) def zoom_in(self, noslider=False): horizbar = self.scrollArea.horizontalScrollBar() vertbar = self.scrollArea.verticalScrollBar() if horizbar.maximum() > 0: widthratio = horizbar.value()/horizbar.maximum() else: widthratio = 0 if vertbar.maximum() > 0: heightratio = vertbar.value()/vertbar.maximum() else: heightratio = 0 zf = self.bw_map_screen.zoom_factor self.bw_map_screen.zoom(calc_zoom_in_factor(zf))#zf) # print("wedidit?") if not noslider: horizbar.setSliderPosition(horizbar.maximum()*widthratio) vertbar.setSliderPosition(vertbar.maximum()*heightratio) self.bw_map_screen.update() self.statusbar.showMessage("Zoom: {0}x".format(self.bw_map_screen.zoom_factor)) @catch_exception def mouse_wheel_scroll_zoom(self, wheel_event): print("scrolling", wheel_event) print("Scroll", wheel_event.x(), wheel_event.y(), wheel_event.angleDelta().y())#, wheel_event.delta()) wheel_delta = wheel_event.angleDelta().y() zf = self.bw_map_screen.zoom_factor norm_x = wheel_event.x()/zf norm_y = wheel_event.y()/zf if wheel_delta > 0: if zf <= 10: self.zoom_in(True) zf = self.bw_map_screen.zoom_factor xmargin = self.scrollArea.viewport().width()//2 - 200 ymargin = self.scrollArea.viewport().height()//2 - 200 self.scrollArea.ensureVisible(norm_x*zf, norm_y*zf, xmargin, ymargin) self.bw_map_screen.update() else: self.zoom_in() elif wheel_delta < 0: self.zoom_out() def action_lineedit_changeangle(self): if not self.resetting and self.bw_map_screen.current_entity is not None: print("ok") current = self.bw_map_screen.current_entity currx, curry, angle = object_get_position(self.level, current) newangle = self.lineedit_angle.text().strip() print(newangle, newangle.isdecimal()) try: angle = float(newangle) object_set_position(self.level, current, currx, curry, angle=angle) currentobj = self.level.obj_map[current] update_mapscreen(self.bw_map_screen, currentobj) self.bw_map_screen.update() except: traceback.print_exc() def button_terrain_load_action(self): try: print("ok", self.default_path) filepath, choosentype = QFileDialog.getOpenFileName( self, "Open File", self.default_path, "BW terrain files (*.out *out.gz);;All files (*)") print("doooone") if filepath: if filepath.endswith(".gz"): file_open = gzip.open else: file_open = open with file_open(filepath, "rb") as f: try: terrain = BWArchiveBase(f) if self.level is not None: waterheight = get_water_height(self.level) else: waterheight = None image, light_image = parse_terrain_to_image(terrain, waterheight) self.bw_map_screen.set_terrain(image, light_image) except: traceback.print_exc() except: traceback.print_exc() def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(820, 760) MainWindow.setMinimumSize(QSize(720, 560)) MainWindow.setWindowTitle("BW-MapEdit") #MainWindow.setWindowTitle("Nep-Nep") self.centralwidget = QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") MainWindow.setCentralWidget(self.centralwidget) self.horizontalLayout = QHBoxLayout(self.centralwidget) self.horizontalLayout.setObjectName("horizontalLayout") self.scrollArea = QScrollArea(self.centralwidget) self.scrollArea.setWidgetResizable(True) self.bw_map_screen = BWMapViewer(self.centralwidget) self.scrollArea.setWidget(self.bw_map_screen) self.horizontalLayout.addWidget(self.scrollArea) #self.horizontalLayout.addWidget(self.bw_map_screen) self.entity_list_widget = BWEntityListWidget(self.centralwidget) self.entity_list_widget.setMaximumSize(QSize(300, 16777215)) self.entity_list_widget.setObjectName("entity_list_widget") self.horizontalLayout.addWidget(self.entity_list_widget) spacerItem = QSpacerItem(10, 20, QSizePolicy.Minimum, QSizePolicy.Expanding) self.horizontalLayout.addItem(spacerItem) self.vertLayoutWidget = QWidget(self.centralwidget) self.vertLayoutWidget.setMaximumSize(QSize(250, 1200)) self.verticalLayout = QVBoxLayout(self.vertLayoutWidget) self.verticalLayout.setObjectName("verticalLayout") #self.verticalLayout. self.button_clone_entity = QPushButton(self.centralwidget) self.button_clone_entity.setObjectName("button_clone_entity") self.verticalLayout.addWidget(self.button_clone_entity) self.button_remove_entity = QPushButton(self.centralwidget) self.button_remove_entity.setObjectName("button_remove_entity") self.verticalLayout.addWidget(self.button_remove_entity) self.button_move_entity = QPushButton(self.centralwidget) self.button_move_entity.setObjectName("button_move_entity") self.verticalLayout.addWidget(self.button_move_entity) self.button_show_passengers = QPushButton(self.centralwidget) self.button_show_passengers.setObjectName("button_move_entity") self.verticalLayout.addWidget(self.button_show_passengers) self.gridLayout = QGridLayout() self.gridLayout.setObjectName("gridLayout") self.button_zoom_in = QPushButton(self.centralwidget) self.button_zoom_in.setObjectName("button_zoom_in") self.gridLayout.addWidget(self.button_zoom_in, 0, 0, 0, 1) self.button_zoom_out = QPushButton(self.centralwidget) self.button_zoom_out.setObjectName("button_zoom_out") self.gridLayout.addWidget(self.button_zoom_out, 0, 1, 0, 1) self.button_edit_xml = QPushButton(self.centralwidget) self.button_edit_xml.setObjectName("button_edit_xml") self.button_edit_base_xml = QPushButton(self.centralwidget) self.button_edit_base_xml.setObjectName("button_edit_base_xml") self.verticalLayout.addLayout(self.gridLayout) self.verticalLayout.addWidget(self.button_edit_xml) self.verticalLayout.addWidget(self.button_edit_base_xml) spacerItem1 = QSpacerItem(10, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.verticalLayout.addItem(spacerItem1) self.verticalLayout_2 = QVBoxLayout() self.verticalLayout_2.setObjectName("verticalLayout_2") self.lineedit_angle = QLineEdit(self.centralwidget) self.lineedit_angle.setObjectName("lineedit_angle") self.lineedit_angle.setPlaceholderText("Angle") self.label_object_id = QLabel(self.centralwidget) self.label_object_id.setObjectName("label_object_id") #TextSelectableByCursor self.label_position = QLabel(self.centralwidget) self.label_position.setObjectName("label_position") self.label_model_name = QLabel(self.centralwidget) self.label_model_name.setObjectName("label_model_name") self.label_4 = QLabel(self.centralwidget) self.label_4.setObjectName("label_4") self.label_5 = QLabel(self.centralwidget) self.label_5.setObjectName("label_5") for label in (self.label_object_id, self.label_position, self.label_model_name, self.label_4, self.label_5): label.setTextInteractionFlags(QtCore.Qt.TextSelectableByMouse) self.verticalLayout_2.addWidget(self.lineedit_angle) self.verticalLayout_2.addWidget(self.label_object_id) self.verticalLayout_2.addWidget(self.label_position) self.verticalLayout_2.addWidget(self.label_model_name) self.verticalLayout_2.addWidget(self.label_4) self.verticalLayout_2.addWidget(self.label_5) self.verticalLayout.addLayout(self.verticalLayout_2) self.horizontalLayout.addWidget(self.vertLayoutWidget) self.menubar = QMenuBar(MainWindow) self.menubar.setGeometry(QRect(0, 0, 820, 29)) self.menubar.setObjectName("menubar") self.file_menu = QMenu(self.menubar) self.file_menu.setObjectName("menuLoad") self.file_load_action = QAction("Load", self) self.file_load_action.triggered.connect(self.button_load_level) self.file_menu.addAction(self.file_load_action) self.file_save_action = QAction("Save", self) self.file_save_action.triggered.connect(self.button_save_level) self.file_menu.addAction(self.file_save_action) self.visibility_menu = MenuDontClose(self.menubar)#QMenu(self.menubar) self.visibility_menu.setObjectName("visibility") #self.visibility_menu.addAction(self.toggle_action) self.visibility_actions = [] self.terrain_menu = QMenu(self.menubar) self.terrain_menu.setObjectName("terrain") self.terrain_load_action = QAction("Load Terrain", self) self.terrain_load_action.triggered.connect(self.button_terrain_load_action) self.terrain_menu.addAction(self.terrain_load_action) self.terrain_display_actions = [] self.setup_terrain_display_toggles() #self.menuLoad_2 = QMenu(self.menubar) #self.menuLoad_2.setObjectName("menuLoad_2") MainWindow.setMenuBar(self.menubar) self.statusbar = QStatusBar(MainWindow) self.statusbar.setObjectName("statusbar") MainWindow.setStatusBar(self.statusbar) self.menubar.addAction(self.file_menu.menuAction()) #self.menubar.addAction(self.menuLoad_2.menuAction()) self.menubar.addAction(self.visibility_menu.menuAction()) self.menubar.addAction(self.terrain_menu.menuAction()) self.retranslateUi(MainWindow) QMetaObject.connectSlotsByName(MainWindow) def make_terrain_toggle(self, show_mode): def terraintoggle(toggled): print("I am", show_mode, "and I was pressed") if toggled is True: for action, toggle, mode in self.terrain_display_actions: if mode != show_mode: action.setChecked(False) self.bw_map_screen.set_show_terrain_mode(show_mode) elif toggled is False: self.bw_map_screen.set_show_terrain_mode(SHOW_TERRAIN_NO_TERRAIN) else: print("This shouldn't be possible", toggled, type(toggled)) self.bw_map_screen.update() return terraintoggle def setup_terrain_display_toggles(self): for mode, name in ((SHOW_TERRAIN_REGULAR, "Show Heightmap"), (SHOW_TERRAIN_LIGHT, "Show Lightmap")): toggle = self.make_terrain_toggle(mode) toggle_action = QAction(name, self) toggle_action.setCheckable(True) if mode == SHOW_TERRAIN_REGULAR: toggle_action.setChecked(True) else: toggle_action.setChecked(False) toggle_action.triggered.connect(toggle) self.terrain_menu.addAction(toggle_action) self.terrain_display_actions.append((toggle_action, toggle, mode)) def clear_terrain_toggles(self): try: for action, func, mode in self.terrain_display_actions: self.terrain_menu.removeAction(action) self.terrain_display_actions = [] except: traceback.print_exc() def make_toggle_function(self, objtype): def toggle(toggled): print("i was pressed") my_type = copy(objtype) self.types_visible[my_type] = toggled self.bw_map_screen.set_visibility(self.types_visible) self.bw_map_screen.update() return toggle def setup_visibility_toggles(self): for objtype in sorted(self.level.objtypes_with_positions): toggle = self.make_toggle_function(objtype) toggle_action = QAction(copy(objtype), self) toggle_action.setCheckable(True) toggle_action.setChecked(True) toggle_action.triggered.connect(toggle) self.types_visible[objtype] = True self.visibility_menu.addAction(toggle_action) self.visibility_actions.append((toggle_action, toggle)) toggle_all = QAction("Toggle All", self) toggle_all.triggered.connect(self.toggle_visiblity_all) self.visibility_menu.addAction(toggle_all) self.visibility_actions.append((toggle_all, self.toggle_visiblity_all)) def toggle_visiblity_all(self): for action, func in self.visibility_actions: if action.isCheckable(): objtype = action.text() toggle = self.types_visible[objtype] self.types_visible[objtype] = not toggle action.setChecked(not toggle) self.bw_map_screen.set_visibility(self.types_visible) self.bw_map_screen.update() def clear_visibility_toggles(self): try: for action, func in self.visibility_actions: self.visibility_menu.removeAction(action) self.visibility_actions = [] self.types_visible = {} except: traceback.print_exc() def retranslateUi(self, MainWindow): _translate = QCoreApplication.translate self.button_clone_entity.setText(_translate("MainWindow", "Clone Entity")) self.button_remove_entity.setText(_translate("MainWindow", "Delete Entity")) self.button_move_entity.setText(_translate("MainWindow", "Move Entity")) self.button_zoom_in.setText(_translate("MainWindow", "Zoom In")) self.button_zoom_out.setText(_translate("MainWindow", "Zoom Out")) self.button_show_passengers.setText(_translate("MainWindow", "Show Passengers")) self.button_edit_xml.setText("Edit Object XML") self.button_edit_base_xml.setText("Edit Base Object XML") self.label_model_name.setText(_translate("MainWindow", "TextLabel1")) self.label_object_id.setText(_translate("MainWindow", "TextLabel2")) self.label_position.setText(_translate("MainWindow", "TextLabel3")) self.label_4.setText(_translate("MainWindow", "TextLabel4")) self.label_5.setText(_translate("MainWindow", "TextLabel5")) self.file_menu.setTitle(_translate("MainWindow", "File")) self.visibility_menu.setTitle(_translate("MainWindow", "Visibility")) self.terrain_menu.setTitle("Terrain")
def __init__(self, variables, parent=None): """ Constructor @param variables list of template variable names (list of strings) @param parent parent widget of this dialog (QWidget) """ super(TemplateMultipleVariablesDialog, self).__init__(parent) self.TemplateMultipleVariablesDialogLayout = QVBoxLayout(self) self.TemplateMultipleVariablesDialogLayout.setContentsMargins(6, 6, 6, 6) self.TemplateMultipleVariablesDialogLayout.setSpacing(6) self.TemplateMultipleVariablesDialogLayout.setObjectName("TemplateMultipleVariablesDialogLayout") self.setLayout(self.TemplateMultipleVariablesDialogLayout) # generate the scrollarea self.variablesView = QScrollArea(self) self.variablesView.setObjectName("variablesView") self.TemplateMultipleVariablesDialogLayout.addWidget(self.variablesView) self.variablesView.setWidgetResizable(True) self.variablesView.setFrameStyle(QFrame.NoFrame) self.top = QWidget(self) self.variablesView.setWidget(self.top) self.grid = QGridLayout(self.top) self.grid.setContentsMargins(0, 0, 0, 0) self.grid.setSpacing(6) self.top.setLayout(self.grid) # populate the scrollarea with labels and text edits self.variablesEntries = {} row = 0 for var in variables: label = QLabel("{0}:".format(var), self.top) self.grid.addWidget(label, row, 0, Qt.Alignment(Qt.AlignTop)) if var.find(":") >= 0: formatStr = var[1:-1].split(":")[1] if formatStr in ["ml", "rl"]: t = QTextEdit(self.top) t.setTabChangesFocus(True) else: t = QLineEdit(self.top) else: t = QLineEdit(self.top) self.grid.addWidget(t, row, 1) self.variablesEntries[var] = t row += 1 # add a spacer to make the entries aligned at the top spacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) self.grid.addItem(spacer, row, 1) self.variablesEntries[variables[0]].setFocus() self.top.adjustSize() # generate the buttons layout1 = QHBoxLayout() layout1.setContentsMargins(0, 0, 0, 0) layout1.setSpacing(6) layout1.setObjectName("layout1") spacer1 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) layout1.addItem(spacer1) self.okButton = QPushButton(self) self.okButton.setObjectName("okButton") self.okButton.setDefault(True) layout1.addWidget(self.okButton) self.cancelButton = QPushButton(self) self.cancelButton.setObjectName("cancelButton") layout1.addWidget(self.cancelButton) spacer2 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) layout1.addItem(spacer2) self.TemplateMultipleVariablesDialogLayout.addLayout(layout1) # set the texts of the standard widgets self.setWindowTitle(self.tr("Enter Template Variables")) self.okButton.setText(self.tr("&OK")) self.cancelButton.setText(self.tr("&Cancel")) # polish up the dialog self.resize(QSize(400, 480).expandedTo(self.minimumSizeHint())) self.okButton.clicked.connect(self.accept) self.cancelButton.clicked.connect(self.reject)
class DirectoriesDialog(QMainWindow): def __init__(self, app, **kwargs): super().__init__(None, **kwargs) self.app = app self.lastAddedFolder = platform.INITIAL_FOLDER_IN_DIALOGS self.recentFolders = Recent(self.app, 'recentFolders') self._setupUi() self._updateScanTypeList() self.directoriesModel = DirectoriesModel(self.app.model.directory_tree, view=self.treeView) self.directoriesDelegate = DirectoriesDelegate() self.treeView.setItemDelegate(self.directoriesDelegate) self._setupColumns() self.app.recentResults.addMenu(self.menuLoadRecent) self.app.recentResults.addMenu(self.menuRecentResults) self.recentFolders.addMenu(self.menuRecentFolders) self._updateAddButton() self._updateRemoveButton() self._updateLoadResultsButton() self._updateActionsState() self._setupBindings() def _setupBindings(self): self.appModeRadioBox.itemSelected.connect(self.appModeButtonSelected) self.showPreferencesButton.clicked.connect(self.app.actionPreferences.trigger) self.scanButton.clicked.connect(self.scanButtonClicked) self.loadResultsButton.clicked.connect(self.actionLoadResults.trigger) self.addFolderButton.clicked.connect(self.actionAddFolder.trigger) self.removeFolderButton.clicked.connect(self.removeFolderButtonClicked) self.treeView.selectionModel().selectionChanged.connect(self.selectionChanged) self.app.recentResults.itemsChanged.connect(self._updateLoadResultsButton) self.recentFolders.itemsChanged.connect(self._updateAddButton) self.recentFolders.mustOpenItem.connect(self.app.model.add_directory) self.directoriesModel.foldersAdded.connect(self.directoriesModelAddedFolders) self.app.willSavePrefs.connect(self.appWillSavePrefs) def _setupActions(self): # (name, shortcut, icon, desc, func) ACTIONS = [ ('actionLoadResults', 'Ctrl+L', '', tr("Load Results..."), self.loadResultsTriggered), ('actionShowResultsWindow', '', '', tr("Results Window"), self.app.showResultsWindow), ('actionAddFolder', '', '', tr("Add Folder..."), self.addFolderTriggered), ] createActions(ACTIONS, self) def _setupMenu(self): self.menubar = QMenuBar(self) self.menubar.setGeometry(QRect(0, 0, 42, 22)) self.menuFile = QMenu(self.menubar) self.menuFile.setTitle(tr("File")) self.menuView = QMenu(self.menubar) self.menuView.setTitle(tr("View")) self.menuHelp = QMenu(self.menubar) self.menuHelp.setTitle(tr("Help")) self.menuLoadRecent = QMenu(self.menuFile) self.menuLoadRecent.setTitle(tr("Load Recent Results")) self.setMenuBar(self.menubar) self.menuFile.addAction(self.actionLoadResults) self.menuFile.addAction(self.menuLoadRecent.menuAction()) self.menuFile.addSeparator() self.menuFile.addAction(self.app.actionClearPictureCache) self.menuFile.addSeparator() self.menuFile.addAction(self.app.actionQuit) self.menuView.addAction(self.app.actionPreferences) self.menuView.addAction(self.actionShowResultsWindow) self.menuView.addAction(self.app.actionIgnoreList) self.menuHelp.addAction(self.app.actionShowHelp) self.menuHelp.addAction(self.app.actionOpenDebugLog) self.menuHelp.addAction(self.app.actionAbout) self.menubar.addAction(self.menuFile.menuAction()) self.menubar.addAction(self.menuView.menuAction()) self.menubar.addAction(self.menuHelp.menuAction()) # Recent folders menu self.menuRecentFolders = QMenu() self.menuRecentFolders.addAction(self.actionAddFolder) self.menuRecentFolders.addSeparator() # Recent results menu self.menuRecentResults = QMenu() self.menuRecentResults.addAction(self.actionLoadResults) self.menuRecentResults.addSeparator() def _setupUi(self): self.setWindowTitle(self.app.NAME) self.resize(420, 338) self.centralwidget = QWidget(self) self.verticalLayout = QVBoxLayout(self.centralwidget) hl = QHBoxLayout() label = QLabel(tr("Application Mode:"), self) label.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) hl.addWidget(label) self.appModeRadioBox = RadioBox( self, items=[tr("Standard"), tr("Music"), tr("Picture")], spread=False ) hl.addWidget(self.appModeRadioBox) self.verticalLayout.addLayout(hl) hl = QHBoxLayout() hl.setAlignment(Qt.AlignLeft) label = QLabel(tr("Scan Type:"), self) label.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) hl.addWidget(label) self.scanTypeComboBox = QComboBox(self) self.scanTypeComboBox.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)) self.scanTypeComboBox.setMaximumWidth(400) hl.addWidget(self.scanTypeComboBox) self.showPreferencesButton = QPushButton(tr("More Options"), self.centralwidget) self.showPreferencesButton.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) hl.addWidget(self.showPreferencesButton) self.verticalLayout.addLayout(hl) self.promptLabel = QLabel(tr("Select folders to scan and press \"Scan\"."), self.centralwidget) self.verticalLayout.addWidget(self.promptLabel) self.treeView = QTreeView(self.centralwidget) self.treeView.setSelectionMode(QAbstractItemView.ExtendedSelection) self.treeView.setSelectionBehavior(QAbstractItemView.SelectRows) self.treeView.setAcceptDrops(True) triggers = QAbstractItemView.DoubleClicked | QAbstractItemView.EditKeyPressed\ | QAbstractItemView.SelectedClicked self.treeView.setEditTriggers(triggers) self.treeView.setDragDropOverwriteMode(True) self.treeView.setDragDropMode(QAbstractItemView.DropOnly) self.treeView.setUniformRowHeights(True) self.verticalLayout.addWidget(self.treeView) self.horizontalLayout = QHBoxLayout() self.removeFolderButton = QPushButton(self.centralwidget) self.removeFolderButton.setIcon(QIcon(QPixmap(":/minus"))) self.removeFolderButton.setShortcut("Del") self.horizontalLayout.addWidget(self.removeFolderButton) self.addFolderButton = QPushButton(self.centralwidget) self.addFolderButton.setIcon(QIcon(QPixmap(":/plus"))) self.horizontalLayout.addWidget(self.addFolderButton) spacerItem1 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout.addItem(spacerItem1) self.loadResultsButton = QPushButton(self.centralwidget) self.loadResultsButton.setText(tr("Load Results")) self.horizontalLayout.addWidget(self.loadResultsButton) self.scanButton = QPushButton(self.centralwidget) self.scanButton.setText(tr("Scan")) self.scanButton.setDefault(True) self.horizontalLayout.addWidget(self.scanButton) self.verticalLayout.addLayout(self.horizontalLayout) self.setCentralWidget(self.centralwidget) self._setupActions() self._setupMenu() if self.app.prefs.directoriesWindowRect is not None: self.setGeometry(self.app.prefs.directoriesWindowRect) else: moveToScreenCenter(self) def _setupColumns(self): header = self.treeView.header() header.setStretchLastSection(False) header.setSectionResizeMode(0, QHeaderView.Stretch) header.setSectionResizeMode(1, QHeaderView.Fixed) header.resizeSection(1, 100) def _updateActionsState(self): self.actionShowResultsWindow.setEnabled(self.app.resultWindow is not None) def _updateAddButton(self): if self.recentFolders.isEmpty(): self.addFolderButton.setMenu(None) else: self.addFolderButton.setMenu(self.menuRecentFolders) def _updateRemoveButton(self): indexes = self.treeView.selectedIndexes() if not indexes: self.removeFolderButton.setEnabled(False) return self.removeFolderButton.setEnabled(True) def _updateLoadResultsButton(self): if self.app.recentResults.isEmpty(): self.loadResultsButton.setMenu(None) else: self.loadResultsButton.setMenu(self.menuRecentResults) def _updateScanTypeList(self): try: self.scanTypeComboBox.currentIndexChanged[int].disconnect(self.scanTypeChanged) except TypeError: # Not connected, ignore pass self.scanTypeComboBox.clear() scan_options = self.app.model.SCANNER_CLASS.get_scan_options() for scan_option in scan_options: self.scanTypeComboBox.addItem(scan_option.label) SCAN_TYPE_ORDER = [so.scan_type for so in scan_options] selected_scan_type = self.app.prefs.get_scan_type(self.app.model.app_mode) scan_type_index = SCAN_TYPE_ORDER.index(selected_scan_type) self.scanTypeComboBox.setCurrentIndex(scan_type_index) self.scanTypeComboBox.currentIndexChanged[int].connect(self.scanTypeChanged) self.app._update_options() #--- QWidget overrides def closeEvent(self, event): event.accept() if self.app.model.results.is_modified: title = tr("Unsaved results") msg = tr("You have unsaved results, do you really want to quit?") if not self.app.confirm(title, msg): event.ignore() if event.isAccepted(): QApplication.quit() #--- Events def addFolderTriggered(self): title = tr("Select a folder to add to the scanning list") flags = QFileDialog.ShowDirsOnly dirpath = str(QFileDialog.getExistingDirectory(self, title, self.lastAddedFolder, flags)) if not dirpath: return self.lastAddedFolder = dirpath self.app.model.add_directory(dirpath) self.recentFolders.insertItem(dirpath) def appModeButtonSelected(self, index): if index == 2: mode = AppMode.Picture elif index == 1: mode = AppMode.Music else: mode = AppMode.Standard self.app.model.app_mode = mode self._updateScanTypeList() def appWillSavePrefs(self): self.app.prefs.directoriesWindowRect = self.geometry() def directoriesModelAddedFolders(self, folders): for folder in folders: self.recentFolders.insertItem(folder) def loadResultsTriggered(self): title = tr("Select a results file to load") files = ';;'.join([tr("dupeGuru Results (*.dupeguru)"), tr("All Files (*.*)")]) destination = QFileDialog.getOpenFileName(self, title, '', files) if destination: self.app.model.load_from(destination) self.app.recentResults.insertItem(destination) def removeFolderButtonClicked(self): self.directoriesModel.model.remove_selected() def scanButtonClicked(self): if self.app.model.results.is_modified: title = tr("Start a new scan") msg = tr("You have unsaved results, do you really want to continue?") if not self.app.confirm(title, msg): return self.app.model.start_scanning() def scanTypeChanged(self, index): scan_options = self.app.model.SCANNER_CLASS.get_scan_options() self.app.prefs.set_scan_type(self.app.model.app_mode, scan_options[index].scan_type) self.app._update_options() def selectionChanged(self, selected, deselected): self._updateRemoveButton()
class PreferencesDialogBase(QDialog): def __init__(self, parent, app, **kwargs): flags = Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowSystemMenuHint super().__init__(parent, flags, **kwargs) self.app = app self._setupUi() self.filterHardnessSlider.valueChanged['int'].connect(self.filterHardnessLabel.setNum) self.buttonBox.clicked.connect(self.buttonClicked) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) def _setupScanTypeBox(self, labels): self.scanTypeHLayout = QHBoxLayout() self.scanTypeLabel = QLabel(self) self.scanTypeLabel.setText(tr("Scan Type:")) self.scanTypeLabel.setMinimumSize(QSize(100, 0)) self.scanTypeLabel.setMaximumSize(QSize(100, 16777215)) self.scanTypeHLayout.addWidget(self.scanTypeLabel) self.scanTypeComboBox = QComboBox(self) for label in labels: self.scanTypeComboBox.addItem(label) self.scanTypeHLayout.addWidget(self.scanTypeComboBox) self.widgetsVLayout.addLayout(self.scanTypeHLayout) def _setupFilterHardnessBox(self): self.filterHardnessHLayout = QHBoxLayout() self.filterHardnessLabel = QLabel(self) self.filterHardnessLabel.setText(tr("Filter Hardness:")) self.filterHardnessLabel.setMinimumSize(QSize(0, 0)) self.filterHardnessHLayout.addWidget(self.filterHardnessLabel) self.filterHardnessVLayout = QVBoxLayout() self.filterHardnessVLayout.setSpacing(0) self.filterHardnessHLayoutSub1 = QHBoxLayout() self.filterHardnessHLayoutSub1.setSpacing(12) self.filterHardnessSlider = QSlider(self) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.filterHardnessSlider.sizePolicy().hasHeightForWidth()) self.filterHardnessSlider.setSizePolicy(sizePolicy) self.filterHardnessSlider.setMinimum(1) self.filterHardnessSlider.setMaximum(100) self.filterHardnessSlider.setTracking(True) self.filterHardnessSlider.setOrientation(Qt.Horizontal) self.filterHardnessHLayoutSub1.addWidget(self.filterHardnessSlider) self.filterHardnessLabel = QLabel(self) self.filterHardnessLabel.setText("100") self.filterHardnessLabel.setMinimumSize(QSize(21, 0)) self.filterHardnessHLayoutSub1.addWidget(self.filterHardnessLabel) self.filterHardnessVLayout.addLayout(self.filterHardnessHLayoutSub1) self.filterHardnessHLayoutSub2 = QHBoxLayout() self.filterHardnessHLayoutSub2.setContentsMargins(-1, 0, -1, -1) self.moreResultsLabel = QLabel(self) self.moreResultsLabel.setText(tr("More Results")) self.filterHardnessHLayoutSub2.addWidget(self.moreResultsLabel) spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.filterHardnessHLayoutSub2.addItem(spacerItem) self.fewerResultsLabel = QLabel(self) self.fewerResultsLabel.setText(tr("Fewer Results")) self.filterHardnessHLayoutSub2.addWidget(self.fewerResultsLabel) self.filterHardnessVLayout.addLayout(self.filterHardnessHLayoutSub2) self.filterHardnessHLayout.addLayout(self.filterHardnessVLayout) def _setupBottomPart(self): # The bottom part of the pref panel is always the same in all editions. self.fontSizeLabel = QLabel(tr("Font size:")) self.fontSizeSpinBox = QSpinBox() self.fontSizeSpinBox.setMinimum(5) self.widgetsVLayout.addLayout(horizontalWrap([self.fontSizeLabel, self.fontSizeSpinBox, None])) self.languageLabel = QLabel(tr("Language:"), self) self.languageComboBox = QComboBox(self) for lang in SUPPORTED_LANGUAGES: self.languageComboBox.addItem(LANGNAMES[lang]) self.widgetsVLayout.addLayout(horizontalWrap([self.languageLabel, self.languageComboBox, None])) self.copyMoveLabel = QLabel(self) self.copyMoveLabel.setText(tr("Copy and Move:")) self.widgetsVLayout.addWidget(self.copyMoveLabel) self.copyMoveDestinationComboBox = QComboBox(self) self.copyMoveDestinationComboBox.addItem(tr("Right in destination")) self.copyMoveDestinationComboBox.addItem(tr("Recreate relative path")) self.copyMoveDestinationComboBox.addItem(tr("Recreate absolute path")) self.widgetsVLayout.addWidget(self.copyMoveDestinationComboBox) self.customCommandLabel = QLabel(self) self.customCommandLabel.setText(tr("Custom Command (arguments: %d for dupe, %r for ref):")) self.widgetsVLayout.addWidget(self.customCommandLabel) self.customCommandEdit = QLineEdit(self) self.widgetsVLayout.addWidget(self.customCommandEdit) def _setupAddCheckbox(self, name, label, parent=None): if parent is None: parent = self cb = QCheckBox(parent) cb.setText(label) setattr(self, name, cb) def _setupPreferenceWidgets(self): # Edition-specific pass def _setupUi(self): self.setWindowTitle(tr("Preferences")) self.resize(304, 263) self.setSizeGripEnabled(False) self.setModal(True) self.mainVLayout = QVBoxLayout(self) self.widgetsVLayout = QVBoxLayout() self._setupPreferenceWidgets() self.mainVLayout.addLayout(self.widgetsVLayout) self.buttonBox = QDialogButtonBox(self) self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel|QDialogButtonBox.Ok|QDialogButtonBox.RestoreDefaults) self.mainVLayout.addWidget(self.buttonBox) if (not ISOSX) and (not ISLINUX): self.mainVLayout.removeWidget(self.ignoreHardlinkMatches) self.ignoreHardlinkMatches.setHidden(True) def _load(self, prefs, setchecked): # Edition-specific pass def _save(self, prefs, ischecked): # Edition-specific pass def load(self, prefs=None): if prefs is None: prefs = self.app.prefs self.filterHardnessSlider.setValue(prefs.filter_hardness) self.filterHardnessLabel.setNum(prefs.filter_hardness) setchecked = lambda cb, b: cb.setCheckState(Qt.Checked if b else Qt.Unchecked) setchecked(self.mixFileKindBox, prefs.mix_file_kind) setchecked(self.useRegexpBox, prefs.use_regexp) setchecked(self.removeEmptyFoldersBox, prefs.remove_empty_folders) setchecked(self.ignoreHardlinkMatches, prefs.ignore_hardlink_matches) setchecked(self.debugModeBox, prefs.debug_mode) self.copyMoveDestinationComboBox.setCurrentIndex(prefs.destination_type) self.customCommandEdit.setText(prefs.custom_command) self.fontSizeSpinBox.setValue(prefs.tableFontSize) try: langindex = SUPPORTED_LANGUAGES.index(self.app.prefs.language) except ValueError: langindex = 0 self.languageComboBox.setCurrentIndex(langindex) self._load(prefs, setchecked) def save(self): prefs = self.app.prefs prefs.filter_hardness = self.filterHardnessSlider.value() ischecked = lambda cb: cb.checkState() == Qt.Checked prefs.mix_file_kind = ischecked(self.mixFileKindBox) prefs.use_regexp = ischecked(self.useRegexpBox) prefs.remove_empty_folders = ischecked(self.removeEmptyFoldersBox) prefs.ignore_hardlink_matches = ischecked(self.ignoreHardlinkMatches) prefs.debug_mode = ischecked(self.debugModeBox) prefs.destination_type = self.copyMoveDestinationComboBox.currentIndex() prefs.custom_command = str(self.customCommandEdit.text()) prefs.tableFontSize = self.fontSizeSpinBox.value() lang = SUPPORTED_LANGUAGES[self.languageComboBox.currentIndex()] oldlang = self.app.prefs.language if oldlang not in SUPPORTED_LANGUAGES: oldlang = 'en' if lang != oldlang: QMessageBox.information(self, "", tr("dupeGuru has to restart for language changes to take effect.")) self.app.prefs.language = lang self._save(prefs, ischecked) #--- Events def buttonClicked(self, button): role = self.buttonBox.buttonRole(button) if role == QDialogButtonBox.ResetRole: self.resetToDefaults()
class MainWindow(QMainWindow): def __init__(self, app): QMainWindow.__init__(self, None) self.documentPath = None self.doc = DocumentModel(app=app.model) self.app = app self._setupUi() # Create base elements self.model = MainWindowModel(document=self.doc) self.model2view = {} self.alookup = Lookup(self, model=self.model.account_lookup) self.clookup = Lookup(self, model=self.model.completion_lookup) self.drsel = DateRangeSelector(mainwindow=self, view=self.dateRangeSelectorView) self.sfield = SearchField(model=self.model.search_field, view=self.searchLineEdit) self.recentDocuments = Recent(self.app, 'recentDocuments') self.recentDocuments.addMenu(self.menuOpenRecent) self.doc.view = self self.model.view = self self._updateUndoActions() self._bindSignals() def _setupUi(self): # has to take place *before* base elements creation self.setWindowTitle("moneyGuru") self.resize(700, 580) self.centralwidget = QWidget(self) self.verticalLayout = QVBoxLayout(self.centralwidget) self.verticalLayout.setSpacing(0) self.verticalLayout.setContentsMargins(0, 0, 0, 0) self.topBar = QWidget(self.centralwidget) self.horizontalLayout_2 = QHBoxLayout(self.topBar) self.horizontalLayout_2.setContentsMargins(2, 0, 2, 0) spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout_2.addItem(spacerItem) self.dateRangeSelectorView = DateRangeSelectorView(self.topBar) self.dateRangeSelectorView.setMinimumSize(QSize(220, 0)) self.horizontalLayout_2.addWidget(self.dateRangeSelectorView) spacerItem1 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout_2.addItem(spacerItem1) self.searchLineEdit = SearchEdit(self.topBar) self.searchLineEdit.setMaximumSize(QSize(240, 16777215)) self.horizontalLayout_2.addWidget(self.searchLineEdit) self.verticalLayout.addWidget(self.topBar) self.tabBar = TabBarPlus(self.centralwidget) self.tabBar.setMinimumSize(QSize(0, 20)) self.verticalLayout.addWidget(self.tabBar) self.mainView = QStackedWidget(self.centralwidget) self.verticalLayout.addWidget(self.mainView) # Bottom buttons & status label self.bottomBar = QWidget(self.centralwidget) self.horizontalLayout = QHBoxLayout(self.bottomBar) self.horizontalLayout.setContentsMargins(2, 2, 2, 2) self.horizontalLayout.setContentsMargins(0, 0, 0, 0) self.newItemButton = QPushButton(self.bottomBar) buttonSizePolicy = QSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed) buttonSizePolicy.setHorizontalStretch(0) buttonSizePolicy.setVerticalStretch(0) buttonSizePolicy.setHeightForWidth(self.newItemButton.sizePolicy().hasHeightForWidth()) self.newItemButton.setSizePolicy(buttonSizePolicy) self.newItemButton.setIcon(QIcon(QPixmap(':/plus_8'))) self.horizontalLayout.addWidget(self.newItemButton) self.deleteItemButton = QPushButton(self.bottomBar) self.deleteItemButton.setSizePolicy(buttonSizePolicy) self.deleteItemButton.setIcon(QIcon(QPixmap(':/minus_8'))) self.horizontalLayout.addWidget(self.deleteItemButton) self.editItemButton = QPushButton(self.bottomBar) self.editItemButton.setSizePolicy(buttonSizePolicy) self.editItemButton.setIcon(QIcon(QPixmap(':/info_gray_12'))) self.horizontalLayout.addWidget(self.editItemButton) self.horizontalLayout.addItem(horizontalSpacer(size=20)) self.graphVisibilityButton = QPushButton() self.graphVisibilityButton.setSizePolicy(buttonSizePolicy) self.graphVisibilityButton.setIcon(QIcon(QPixmap(':/graph_visibility_on_16'))) self.horizontalLayout.addWidget(self.graphVisibilityButton) self.piechartVisibilityButton = QPushButton() self.piechartVisibilityButton.setSizePolicy(buttonSizePolicy) self.piechartVisibilityButton.setIcon(QIcon(QPixmap(':/piechart_visibility_on_16'))) self.horizontalLayout.addWidget(self.piechartVisibilityButton) self.columnsVisibilityButton = QPushButton() self.columnsVisibilityButton.setSizePolicy(buttonSizePolicy) self.columnsVisibilityButton.setIcon(QIcon(QPixmap(':/columns_16'))) self.horizontalLayout.addWidget(self.columnsVisibilityButton) self.statusLabel = QLabel(tr("Status")) self.statusLabel.setAlignment(Qt.AlignCenter) self.horizontalLayout.addWidget(self.statusLabel) self.verticalLayout.addWidget(self.bottomBar) self.setCentralWidget(self.centralwidget) self.menubar = QMenuBar(self) self.menubar.setGeometry(QRect(0, 0, 700, 20)) self.menuFile = QMenu(tr("File")) self.menuOpenRecent = QMenu(tr("Open Recent")) self.menuView = QMenu(tr("View")) self.menuDateRange = QMenu(tr("Date Range")) self.menuEdit = QMenu(tr("Edit")) self.menuHelp = QMenu(tr("Help")) self.setMenuBar(self.menubar) self.actionOpenDocument = QAction(tr("Open..."), self) self.actionOpenDocument.setShortcut("Ctrl+O") self.actionShowNetWorth = QAction(tr("Net Worth"), self) self.actionShowNetWorth.setShortcut("Ctrl+1") self.actionShowNetWorth.setIcon(QIcon(QPixmap(':/balance_sheet_48'))) self.actionShowProfitLoss = QAction(escapeamp(tr("Profit & Loss")), self) self.actionShowProfitLoss.setShortcut("Ctrl+2") self.actionShowProfitLoss.setIcon(QIcon(QPixmap(':/income_statement_48'))) self.actionShowTransactions = QAction(tr("Transactions"), self) self.actionShowTransactions.setShortcut("Ctrl+3") self.actionShowTransactions.setIcon(QIcon(QPixmap(':/transaction_table_48'))) self.actionShowSelectedAccount = QAction(tr("Show Account"), self) self.actionShowSelectedAccount.setShortcut("Ctrl+]") self.actionNewItem = QAction(tr("New Item"), self) self.actionNewItem.setShortcut("Ctrl+N") self.actionDeleteItem = QAction(tr("Remove Selected"), self) self.actionEditItem = QAction(tr("Show Info"), self) self.actionEditItem.setShortcut("Ctrl+I") self.actionToggleGraph = QAction(tr("Toggle Graph"), self) self.actionToggleGraph.setShortcut("Ctrl+Alt+G") self.actionTogglePieChart = QAction(tr("Toggle Pie Chart"), self) self.actionTogglePieChart.setShortcut("Ctrl+Alt+P") self.actionMoveUp = QAction(tr("Move Up"), self) self.actionMoveUp.setShortcut("Ctrl++") self.actionMoveDown = QAction(tr("Move Down"), self) self.actionMoveDown.setShortcut("Ctrl+-") self.actionNavigateBack = QAction(tr("Go Back"), self) self.actionNavigateBack.setShortcut("Ctrl+[") self.actionNewAccountGroup = QAction(tr("New Account Group"), self) self.actionNewAccountGroup.setShortcut("Ctrl+Shift+N") self.actionShowNextView = QAction(tr("Next View"), self) self.actionShowNextView.setShortcut("Ctrl+Shift+]") self.actionShowPreviousView = QAction(tr("Previous View"), self) self.actionShowPreviousView.setShortcut("Ctrl+Shift+[") self.actionNewDocument = QAction(tr("New Document"), self) self.actionImport = QAction(tr("Import..."), self) self.actionImport.setShortcut("Ctrl+Alt+I") self.actionExport = QAction(tr("Export..."), self) self.actionExport.setShortcut("Ctrl+Alt+E") self.actionSave = QAction(tr("Save"), self) self.actionSave.setShortcut("Ctrl+S") self.actionSaveAs = QAction(tr("Save As..."), self) self.actionSaveAs.setShortcut("Ctrl+Shift+S") self.actionAbout = QAction(tr("About moneyGuru"), self) self.actionToggleReconciliationMode = QAction(tr("Toggle Reconciliation Mode"), self) self.actionToggleReconciliationMode.setShortcut("Ctrl+Shift+R") self.actionToggleAccountExclusion = QAction(tr("Toggle Exclusion Status of Account"), self) self.actionToggleAccountExclusion.setShortcut("Ctrl+Shift+X") self.actionShowSchedules = QAction(tr("Schedules"), self) self.actionShowSchedules.setShortcut("Ctrl+4") self.actionShowSchedules.setIcon(QIcon(QPixmap(':/schedules_48'))) self.actionReconcileSelected = QAction(tr("Reconcile Selection"), self) self.actionReconcileSelected.setShortcut("Ctrl+R") self.actionMakeScheduleFromSelected = QAction(tr("Make Schedule from Selected"), self) self.actionMakeScheduleFromSelected.setShortcut("Ctrl+M") self.actionShowPreferences = QAction(tr("Preferences..."), self) self.actionPrint = QAction(tr("Print..."), self) self.actionPrint.setShortcut("Ctrl+P") self.actionQuit = QAction(tr("Quit moneyGuru"), self) self.actionQuit.setShortcut("Ctrl+Q") self.actionUndo = QAction(tr("Undo"), self) self.actionUndo.setShortcut("Ctrl+Z") self.actionRedo = QAction(tr("Redo"), self) self.actionRedo.setShortcut("Ctrl+Y") self.actionShowHelp = QAction(tr("moneyGuru Help"), self) self.actionShowHelp.setShortcut("F1") self.actionDuplicateTransaction = QAction(tr("Duplicate Transaction"), self) self.actionDuplicateTransaction.setShortcut("Ctrl+D") self.actionJumpToAccount = QAction(tr("Jump to Account..."), self) self.actionJumpToAccount.setShortcut("Ctrl+Shift+A") self.actionNewTab = QAction(tr("New Tab"), self) self.actionNewTab.setShortcut("Ctrl+T") self.actionCloseTab = QAction(tr("Close Tab"), self) self.actionCloseTab.setShortcut("Ctrl+W") self.menuFile.addAction(self.actionNewDocument) self.menuFile.addAction(self.actionNewTab) self.menuFile.addAction(self.actionOpenDocument) self.menuFile.addAction(self.menuOpenRecent.menuAction()) self.menuFile.addAction(self.actionImport) self.menuFile.addSeparator() self.menuFile.addAction(self.actionCloseTab) self.menuFile.addAction(self.actionSave) self.menuFile.addAction(self.actionSaveAs) self.menuFile.addAction(self.actionExport) self.menuFile.addAction(self.actionPrint) self.menuFile.addAction(self.actionQuit) self.menuView.addAction(self.actionShowNetWorth) self.menuView.addAction(self.actionShowProfitLoss) self.menuView.addAction(self.actionShowTransactions) self.menuView.addAction(self.actionShowSchedules) self.menuView.addAction(self.actionShowPreviousView) self.menuView.addAction(self.actionShowNextView) self.menuView.addAction(self.menuDateRange.menuAction()) self.menuView.addAction(self.actionShowPreferences) self.menuView.addAction(self.actionToggleGraph) self.menuView.addAction(self.actionTogglePieChart) self.menuEdit.addAction(self.actionNewItem) self.menuEdit.addAction(self.actionNewAccountGroup) self.menuEdit.addAction(self.actionDeleteItem) self.menuEdit.addAction(self.actionEditItem) self.menuEdit.addSeparator() self.menuEdit.addAction(self.actionMoveUp) self.menuEdit.addAction(self.actionMoveDown) self.menuEdit.addAction(self.actionDuplicateTransaction) self.menuEdit.addAction(self.actionMakeScheduleFromSelected) self.menuEdit.addAction(self.actionReconcileSelected) self.menuEdit.addAction(self.actionToggleReconciliationMode) self.menuEdit.addAction(self.actionToggleAccountExclusion) self.menuEdit.addSeparator() self.menuEdit.addAction(self.actionShowSelectedAccount) self.menuEdit.addAction(self.actionNavigateBack) self.menuEdit.addAction(self.actionJumpToAccount) self.menuEdit.addSeparator() self.menuEdit.addAction(self.actionUndo) self.menuEdit.addAction(self.actionRedo) self.menuHelp.addAction(self.actionShowHelp) self.menuHelp.addAction(self.actionAbout) mainmenus = [self.menuFile, self.menuEdit, self.menuView, self.menuHelp] for menu in mainmenus: self.menubar.addAction(menu.menuAction()) setAccelKeys(menu) setAccelKeys(self.menubar) self.tabBar.setMovable(True) self.tabBar.setTabsClosable(True) self.tabBar.setExpanding(False) seq = QKeySequence(Qt.CTRL + Qt.SHIFT + Qt.Key_Right) self._shortcutNextTab = QShortcut(seq, self) seq = QKeySequence(Qt.CTRL + Qt.SHIFT + Qt.Key_Left) self._shortcutPrevTab = QShortcut(seq, self) def _bindSignals(self): self.newItemButton.clicked.connect(self.actionNewItem.trigger) self.deleteItemButton.clicked.connect(self.actionDeleteItem.trigger) self.editItemButton.clicked.connect(self.actionEditItem.trigger) self.graphVisibilityButton.clicked.connect(self.actionToggleGraph.trigger) self.piechartVisibilityButton.clicked.connect(self.actionTogglePieChart.trigger) self.columnsVisibilityButton.clicked.connect(self.columnsVisibilityButtonClicked) self.recentDocuments.mustOpenItem.connect(self.open) self.tabBar.currentChanged.connect(self.currentTabChanged) self.tabBar.tabCloseRequested.connect(self.tabCloseRequested) self.tabBar.tabMoved.connect(self.tabMoved) self.tabBar.plusClicked.connect(self.model.new_tab) # Views self.actionShowNetWorth.triggered.connect(self.showNetWorthTriggered) self.actionShowProfitLoss.triggered.connect(self.showProfitLossTriggered) self.actionShowTransactions.triggered.connect(self.showTransactionsTriggered) self.actionShowSchedules.triggered.connect(self.showSchedulesTriggered) self.actionShowPreviousView.triggered.connect(self.showPreviousViewTriggered) self.actionShowNextView.triggered.connect(self.showNextViewTriggered) self.actionShowPreferences.triggered.connect(self.app.showPreferences) self.actionToggleGraph.triggered.connect(self.toggleGraphTriggered) self.actionTogglePieChart.triggered.connect(self.togglePieChartTriggered) # Document Edition self.actionNewItem.triggered.connect(self.newItemTriggered) self.actionNewAccountGroup.triggered.connect(self.newAccountGroupTriggered) self.actionDeleteItem.triggered.connect(self.deleteItemTriggered) self.actionEditItem.triggered.connect(self.editItemTriggered) self.actionMoveUp.triggered.connect(self.moveUpTriggered) self.actionMoveDown.triggered.connect(self.moveDownTriggered) self.actionDuplicateTransaction.triggered.connect(self.model.duplicate_item) self.actionUndo.triggered.connect(self.model.undo) self.actionRedo.triggered.connect(self.model.redo) # Open / Save / Import / Export / New self.actionNewDocument.triggered.connect(self.new) self.actionOpenDocument.triggered.connect(self.openDocument) self.actionImport.triggered.connect(self.importDocument) self.actionSave.triggered.connect(self.save) self.actionSaveAs.triggered.connect(self.saveAs) self.actionExport.triggered.connect(self.model.export) # Misc self.actionNewTab.triggered.connect(self.model.new_tab) self.actionCloseTab.triggered.connect(self.closeTabTriggered) self.actionShowSelectedAccount.triggered.connect(self.model.show_account) self.actionNavigateBack.triggered.connect(self.navigateBackTriggered) self.actionJumpToAccount.triggered.connect(self.jumpToAccountTriggered) self.actionMakeScheduleFromSelected.triggered.connect(self.makeScheduleFromSelectedTriggered) self.actionReconcileSelected.triggered.connect(self.reconcileSelectedTriggered) self.actionToggleReconciliationMode.triggered.connect(self.toggleReconciliationModeTriggered) self.actionToggleAccountExclusion.triggered.connect(self.toggleAccountExclusionTriggered) self.actionPrint.triggered.connect(self._print) self.actionShowHelp.triggered.connect(self.app.showHelp) self.actionAbout.triggered.connect(self.aboutTriggered) self.actionQuit.triggered.connect(self.close) # Extra Shortcuts self._shortcutNextTab.activated.connect(self.showNextViewTriggered) self._shortcutPrevTab.activated.connect(self.showPreviousViewTriggered) # --- QWidget overrides def closeEvent(self, event): if self.confirmDestructiveAction(): event.accept() else: event.ignore() # --- Private def _print(self): dialog = QPrintDialog(self) if dialog.exec_() != QPrintDialog.Accepted: return printer = dialog.printer() currentView = self.mainView.currentWidget() viewPrinter = ViewPrinter(printer, currentView) currentView.fitViewsForPrint(viewPrinter) viewPrinter.render() def _getViewforPane(self, pane_type, pane_view): if pane_view in self.model2view: view = self.model2view[pane_view] else: view = PANETYPE2VIEWCLASS[pane_type](model=pane_view, mainwindow=self) self.model2view[pane_view] = view self.mainView.addWidget(view) view.restoreSubviewsSize() return view def _setTabIndex(self, index): if not self.tabBar.count(): return self.tabBar.setCurrentIndex(index) self._updateActionsState() pane_type = self.model.pane_type(index) pane_view = self.model.pane_view(index) view = self._getViewforPane(pane_type, pane_view) self.mainView.setCurrentWidget(view) view.setFocus() def _activeView(self): paneIndex = self.model.current_pane_index return self.model.pane_view(paneIndex) def _updateActionsState(self): # Updates enable/disable checked/unchecked state of all actions. These state can change # under various conditions: main view change, date range type change and when reconciliation # mode is toggled # Determine what actions are enabled view = self._activeView() viewType = view.VIEW_TYPE isSheet = viewType in {PaneType.NetWorth, PaneType.Profit} isTransactionOrEntryTable = viewType in {PaneType.Transaction, PaneType.Account} canToggleReconciliation = viewType == PaneType.Account and view.can_toggle_reconciliation_mode newItemLabel = { PaneType.NetWorth: tr("New Account"), PaneType.Profit: tr("New Account"), PaneType.Transaction: tr("New Transaction"), PaneType.Account: tr("New Transaction"), PaneType.Schedule: tr("New Schedule"), PaneType.GeneralLedger: tr("New Transaction"), }.get(viewType, tr("New Item")) # XXX make "New Item" disabled self.actionNewItem.setText(newItemLabel) self.actionNewAccountGroup.setEnabled(isSheet) self.actionMoveDown.setEnabled(isTransactionOrEntryTable) self.actionMoveUp.setEnabled(isTransactionOrEntryTable) self.actionDuplicateTransaction.setEnabled(isTransactionOrEntryTable) self.actionMakeScheduleFromSelected.setEnabled(isTransactionOrEntryTable) self.actionReconcileSelected.setEnabled(viewType == PaneType.Account and view.reconciliation_mode) self.actionShowNextView.setEnabled(self.model.current_pane_index < self.model.pane_count-1) self.actionShowPreviousView.setEnabled(self.model.current_pane_index > 0) self.actionShowSelectedAccount.setEnabled(isSheet or isTransactionOrEntryTable) self.actionNavigateBack.setEnabled(viewType == PaneType.Account) self.actionToggleReconciliationMode.setEnabled(canToggleReconciliation) self.actionToggleAccountExclusion.setEnabled(isSheet) def _updateUndoActions(self): if self.doc.can_undo(): self.actionUndo.setEnabled(True) self.actionUndo.setText(tr("Undo {0}").format(self.doc.undo_description())) else: self.actionUndo.setEnabled(False) self.actionUndo.setText(tr("Undo")) if self.doc.can_redo(): self.actionRedo.setEnabled(True) self.actionRedo.setText(tr("Redo {0}").format(self.doc.redo_description())) else: self.actionRedo.setEnabled(False) self.actionRedo.setText(tr("Redo")) # --- Actions # Document open/save/close def confirmDestructiveAction(self): # Asks whether the user wants to continue before continuing with an action that will replace # the current document. Will save the document as needed. Returns True if the action can # continue. if not self.model.document.is_dirty(): return True title = tr("Unsaved Document") msg = tr("Do you want to save your changes before continuing?") buttons = QMessageBox.Save | QMessageBox.Cancel | QMessageBox.Discard result = QMessageBox.question(self.app.mainWindow, title, msg, buttons) if result == QMessageBox.Save: self.save() if self.model.document.is_dirty(): # "save as" was cancelled return False else: return True elif result == QMessageBox.Cancel: return False elif result == QMessageBox.Discard: return True def new(self): if not self.confirmDestructiveAction(): return self.model.close() self.documentPath = None self.model.clear() self.documentPathChanged() def open(self, docpath, initial=False): # initial flag is true when open() is called at the document's initialization. When that's # the case, we need to create a new document when we fail opening this one. if not self.confirmDestructiveAction(): return self.model.close() try: self.model.load_from_xml(docpath) self.documentPath = docpath except FileFormatError as e: QMessageBox.warning(self.app.mainWindow, tr("Cannot load file"), str(e)) if initial: self.new() self.documentPathChanged() self.recentDocuments.insertItem(docpath) def openDocument(self): title = tr("Select a document to load") filters = tr("moneyGuru Documents (*.moneyguru)") docpath, filetype = QFileDialog.getOpenFileName(self.app.mainWindow, title, '', filters) if docpath: self.open(docpath) def save(self): if self.documentPath is not None: self.model.save_to_xml(self.documentPath) else: self.saveAs() def saveAs(self): title = tr("Save As") filters = tr("moneyGuru Documents (*.moneyguru)") docpath = QFileDialog.getSaveFileName(self.app.mainWindow, title, '', filters)[0] if docpath: if not docpath.endswith('.moneyguru'): docpath += '.moneyguru' self.model.save_to_xml(docpath) self.documentPath = docpath self.documentPathChanged() self.recentDocuments.insertItem(docpath) # Views def showNetWorthTriggered(self): self.model.select_pane_of_type(PaneType.NetWorth) def showProfitLossTriggered(self): self.model.select_pane_of_type(PaneType.Profit) def showTransactionsTriggered(self): self.model.select_pane_of_type(PaneType.Transaction) def showSchedulesTriggered(self): self.model.select_pane_of_type(PaneType.Schedule) def showPreviousViewTriggered(self): self.model.select_previous_view() def showNextViewTriggered(self): self.model.select_next_view() # Document Edition def newItemTriggered(self): self.model.new_item() def newAccountGroupTriggered(self): self.model.new_group() def deleteItemTriggered(self): self.model.delete_item() def editItemTriggered(self): self.model.edit_item() def moveUpTriggered(self): self.model.move_up() def moveDownTriggered(self): self.model.move_down() # Misc def closeTabTriggered(self): self.model.close_pane(self.model.current_pane_index) def navigateBackTriggered(self): self.model.navigate_back() def jumpToAccountTriggered(self): self.model.jump_to_account() def makeScheduleFromSelectedTriggered(self): self.model.make_schedule_from_selected() def reconcileSelectedTriggered(self): self._activeView().etable.toggle_reconciled() def toggleReconciliationModeTriggered(self): self._activeView().toggle_reconciliation_mode() self._updateActionsState() def toggleAccountExclusionTriggered(self): viewType = self.model.pane_type(self.model.current_pane_index) if viewType in {PaneType.NetWorth, PaneType.Profit}: self._activeView().sheet.toggle_excluded() def toggleGraphTriggered(self): self.model.toggle_area_visibility(PaneArea.BottomGraph) def togglePieChartTriggered(self): self.model.toggle_area_visibility(PaneArea.RightChart) def columnsVisibilityButtonClicked(self): items = self.model.column_menu_items() if not items: return menu = QMenu() for i, (display, marked) in enumerate(items): action = menu.addAction(display) action.setCheckable(True) action.setChecked(marked) action.setData(i) action.triggered.connect(self.columnsMenuItemWasClicked) self._columnMenuHolder = menu # we need to hold a reference to it while it popups button = self.columnsVisibilityButton menu.popup(button.parentWidget().mapToGlobal(button.geometry().topLeft())) def columnsMenuItemWasClicked(self): action = self.sender() if action is not None: index = action.data() self.model.toggle_column_menu_item(index) def aboutTriggered(self): self.app.showAboutBox() def importDocument(self): title = tr("Select a document to import") filters = tr("Supported files (*.moneyguru *.ofx *.qfx *.qif *.csv *.txt);;All files (*)") docpath, filetype = QFileDialog.getOpenFileName(self.app.mainWindow, title, '', filters) # There's a strange glitch under GNOME where, right after the dialog is gone, the main # window isn't the active window, but it will become active if we give it enough time. If we # start showing the import window before that happens, we'll end up with an import window # under the main window, which is bad. Therefore, we process events until this happens. We # do this in a big forloop instead of a while to avoid a possible infinite loop. for i in range(10000): if self.app.mainWindow.isActiveWindow(): break QApplication.processEvents() if docpath: try: self.model.parse_file_for_import(docpath) except FileFormatError as e: QMessageBox.warning(self.app.mainWindow, tr("Cannot import file"), str(e)) # --- Other Signals def currentTabChanged(self, index): self.model.current_pane_index = index self._setTabIndex(index) def documentPathChanged(self): if self.documentPath: title = "moneyGuru ({})".format(self.documentPath) else: title = "moneyGuru" self.setWindowTitle(title) def tabCloseRequested(self, index): self.model.close_pane(index) def tabMoved(self, fromIndex, toIndex): # We don't refresh panes because tabMoved is apparently now called *during* drag operations. # If we start a full pane refresh during a drag operation, we segfault. self.model.move_pane(fromIndex, toIndex, refresh_panes=False) # --- document model --> view def query_for_schedule_scope(self): if QApplication.keyboardModifiers() & Qt.ShiftModifier: return ScheduleScope.Global if not self.app.model.show_schedule_scope_dialog: return ScheduleScope.Local dialog = ScheduleScopeDialog(self) return dialog.queryForScope() # --- model --> view def change_current_pane(self): self._setTabIndex(self.model.current_pane_index) def get_panel_view(self, model): if isinstance(model, CustomDateRangePanelModel): return CustomDateRangePanel(model, self) elif isinstance(model, CSVOptionsModel): return CSVOptionsWindow(model, self) elif isinstance(model, ImportWindowModel): return ImportWindow(model, self, self.app.prefs) else: return ExportPanel(model, self) def refresh_panes(self): while self.tabBar.count() < self.model.pane_count: self.tabBar.addTab('') for i in range(self.model.pane_count): pane_label = self.model.pane_label(i) pane_label = escapeamp(pane_label) self.tabBar.setTabText(i, pane_label) pane_type = self.model.pane_type(i) pane_view = self.model.pane_view(i) # Ensure that the view's "view" has been created and bound self._getViewforPane(pane_type, pane_view) iconname = PANETYPE2ICON.get(pane_type) icon = QIcon(QPixmap(':/{0}'.format(iconname))) if iconname else QIcon() self.tabBar.setTabIcon(i, icon) # It's important that we proceed with tab removal *after* we've completed tab initialization. # We're walking on eggshells here. refresh_panes() can be called in multiple situations, one # of them is during the opening of a document. When that happens when another document was # previously opened, all views' model are uninitalized and don't have their "view" attribute # set yet. If we proceed with the setCurrentIndex() call below before _getViewforPane() # could be called above, we get a crash. if self.tabBar.currentIndex() >= self.model.pane_count: # Normally, we don't touch the tabBar index here and wait for change_current_pane, # but when we remove tabs, it's possible that currentTabChanged end up being called and # then the tab selection is bugged. I tried disconnecting/reconnecting the signal, but # this is buggy. So when a selected tab is about to be removed and is out of bounds, # we change the selection to the last index in the model. We don't use # self.model.current_pane_index because in some cases, it's -1 and prevents this crash # preventer from preventing its crash. self.tabBar.setCurrentIndex(self.model.pane_count - 1) while self.tabBar.count() > self.model.pane_count: self.tabBar.removeTab(self.tabBar.count()-1) self.tabBar.setTabsClosable(self.model.pane_count > 1) def refresh_status_line(self): self.statusLabel.setText(self.model.status_line) def refresh_undo_actions(self): self._updateUndoActions() def restore_window_frame(self, frame): self.setGeometry(*frame) def save_window_frame(self): r = self.geometry() return (r.x(), r.y(), r.width(), r.height()) def show_message(self, msg): title = tr("Warning") QMessageBox.warning(self, title, msg) def update_area_visibility(self): hidden = self.model.hidden_areas graphimg = ':/graph_visibility_{}_16'.format('off' if PaneArea.BottomGraph in hidden else 'on') pieimg = ':/piechart_visibility_{}_16'.format('off' if PaneArea.RightChart in hidden else 'on') self.graphVisibilityButton.setIcon(QIcon(QPixmap(graphimg))) self.piechartVisibilityButton.setIcon(QIcon(QPixmap(pieimg))) def view_closed(self, index): self.tabBar.removeTab(index) self.tabBar.setTabsClosable(self.model.pane_count > 1)
class TRPreviewer(E5MainWindow): """ Class implementing the UI Previewer main window. """ def __init__(self, filenames=[], parent=None, name=None): """ Constructor @param filenames filenames of form and/or translation files to load @param parent parent widget of this window (QWidget) @param name name of this window (string) """ self.mainWidget = None self.currentFile = QDir.currentPath() super(TRPreviewer, self).__init__(parent) if not name: self.setObjectName("TRPreviewer") else: self.setObjectName(name) self.setStyle(Preferences.getUI("Style"), Preferences.getUI("StyleSheet")) self.resize(QSize(800, 600).expandedTo(self.minimumSizeHint())) self.statusBar() self.setWindowIcon(UI.PixmapCache.getIcon("eric.png")) self.setWindowTitle(self.tr("Translations Previewer")) self.cw = QWidget(self) self.cw.setObjectName("qt_central_widget") self.TRPreviewerLayout = QVBoxLayout(self.cw) self.TRPreviewerLayout.setContentsMargins(6, 6, 6, 6) self.TRPreviewerLayout.setSpacing(6) self.TRPreviewerLayout.setObjectName("TRPreviewerLayout") self.languageLayout = QHBoxLayout() self.languageLayout.setContentsMargins(0, 0, 0, 0) self.languageLayout.setSpacing(6) self.languageLayout.setObjectName("languageLayout") self.languageLabel = QLabel( self.tr("Select language file"), self.cw) self.languageLabel.setObjectName("languageLabel") self.languageLayout.addWidget(self.languageLabel) self.languageCombo = QComboBox(self.cw) self.languageCombo.setObjectName("languageCombo") self.languageCombo.setEditable(False) self.languageCombo.setToolTip(self.tr("Select language file")) self.languageCombo.setSizePolicy( QSizePolicy.Expanding, QSizePolicy.Preferred) self.languageLayout.addWidget(self.languageCombo) languageSpacer = QSpacerItem( 40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.languageLayout.addItem(languageSpacer) self.TRPreviewerLayout.addLayout(self.languageLayout) self.preview = WidgetArea(self.cw) self.preview.setObjectName("preview") self.TRPreviewerLayout.addWidget(self.preview) self.preview.lastWidgetClosed.connect(self.__updateActions) self.setCentralWidget(self.cw) self.languageCombo.activated[str].connect(self.setTranslation) self.translations = TranslationsDict(self.languageCombo, self) self.translations.translationChanged.connect( self.preview.rebuildWidgets) self.__initActions() self.__initMenus() self.__initToolbars() self.__updateActions() # fire up the single application server from .TRSingleApplication import TRSingleApplicationServer self.SAServer = TRSingleApplicationServer(self) self.SAServer.loadForm.connect(self.preview.loadWidget) self.SAServer.loadTranslation.connect(self.translations.add) # defere loading of a UI file until we are shown self.filesToLoad = filenames[:] def show(self): """ Public slot to show this dialog. This overloaded slot loads a UI file to be previewed after the main window has been shown. This way, previewing a dialog doesn't interfere with showing the main window. """ super(TRPreviewer, self).show() if self.filesToLoad: filenames, self.filesToLoad = (self.filesToLoad[:], []) first = True for fn in filenames: fi = QFileInfo(fn) if fi.suffix().lower() == 'ui': self.preview.loadWidget(fn) elif fi.suffix().lower() == 'qm': self.translations.add(fn, first) first = False self.__updateActions() def closeEvent(self, event): """ Protected event handler for the close event. @param event close event (QCloseEvent) """ if self.SAServer is not None: self.SAServer.shutdown() self.SAServer = None event.accept() def __initActions(self): """ Private method to define the user interface actions. """ self.openUIAct = QAction( UI.PixmapCache.getIcon("openUI.png"), self.tr('&Open UI Files...'), self) self.openUIAct.setStatusTip(self.tr('Open UI files for display')) self.openUIAct.setWhatsThis(self.tr( """<b>Open UI Files</b>""" """<p>This opens some UI files for display.</p>""" )) self.openUIAct.triggered.connect(self.__openWidget) self.openQMAct = QAction( UI.PixmapCache.getIcon("openQM.png"), self.tr('Open &Translation Files...'), self) self.openQMAct.setStatusTip(self.tr( 'Open Translation files for display')) self.openQMAct.setWhatsThis(self.tr( """<b>Open Translation Files</b>""" """<p>This opens some translation files for display.</p>""" )) self.openQMAct.triggered.connect(self.__openTranslation) self.reloadAct = QAction( UI.PixmapCache.getIcon("reload.png"), self.tr('&Reload Translations'), self) self.reloadAct.setStatusTip(self.tr( 'Reload the loaded translations')) self.reloadAct.setWhatsThis(self.tr( """<b>Reload Translations</b>""" """<p>This reloads the translations for the loaded""" """ languages.</p>""" )) self.reloadAct.triggered.connect(self.translations.reload) self.exitAct = QAction( UI.PixmapCache.getIcon("exit.png"), self.tr('&Quit'), self) self.exitAct.setShortcut(QKeySequence( self.tr("Ctrl+Q", "File|Quit"))) self.exitAct.setStatusTip(self.tr('Quit the application')) self.exitAct.setWhatsThis(self.tr( """<b>Quit</b>""" """<p>Quit the application.</p>""" )) self.exitAct.triggered.connect(qApp.closeAllWindows) self.whatsThisAct = QAction( UI.PixmapCache.getIcon("whatsThis.png"), self.tr('&What\'s This?'), self) self.whatsThisAct.setShortcut(QKeySequence(self.tr("Shift+F1"))) self.whatsThisAct.setStatusTip(self.tr('Context sensitive help')) self.whatsThisAct.setWhatsThis(self.tr( """<b>Display context sensitive help</b>""" """<p>In What's This? mode, the mouse cursor shows an arrow""" """ with a question mark, and you can click on the interface""" """ elements to get a short description of what they do and""" """ how to use them. In dialogs, this feature can be accessed""" """ using the context help button in the titlebar.</p>""" )) self.whatsThisAct.triggered.connect(self.__whatsThis) self.aboutAct = QAction(self.tr('&About'), self) self.aboutAct.setStatusTip(self.tr( 'Display information about this software')) self.aboutAct.setWhatsThis(self.tr( """<b>About</b>""" """<p>Display some information about this software.</p>""" )) self.aboutAct.triggered.connect(self.__about) self.aboutQtAct = QAction(self.tr('About &Qt'), self) self.aboutQtAct.setStatusTip( self.tr('Display information about the Qt toolkit')) self.aboutQtAct.setWhatsThis(self.tr( """<b>About Qt</b>""" """<p>Display some information about the Qt toolkit.</p>""" )) self.aboutQtAct.triggered.connect(self.__aboutQt) self.tileAct = QAction(self.tr('&Tile'), self) self.tileAct.setStatusTip(self.tr('Tile the windows')) self.tileAct.setWhatsThis(self.tr( """<b>Tile the windows</b>""" """<p>Rearrange and resize the windows so that they are""" """ tiled.</p>""" )) self.tileAct.triggered.connect(self.preview.tileSubWindows) self.cascadeAct = QAction(self.tr('&Cascade'), self) self.cascadeAct.setStatusTip(self.tr('Cascade the windows')) self.cascadeAct.setWhatsThis(self.tr( """<b>Cascade the windows</b>""" """<p>Rearrange and resize the windows so that they are""" """ cascaded.</p>""" )) self.cascadeAct.triggered.connect(self.preview.cascadeSubWindows) self.closeAct = QAction( UI.PixmapCache.getIcon("close.png"), self.tr('&Close'), self) self.closeAct.setShortcut(QKeySequence(self.tr( "Ctrl+W", "File|Close"))) self.closeAct.setStatusTip(self.tr('Close the current window')) self.closeAct.setWhatsThis(self.tr( """<b>Close Window</b>""" """<p>Close the current window.</p>""" )) self.closeAct.triggered.connect(self.preview.closeWidget) self.closeAllAct = QAction(self.tr('Clos&e All'), self) self.closeAllAct.setStatusTip(self.tr('Close all windows')) self.closeAllAct.setWhatsThis(self.tr( """<b>Close All Windows</b>""" """<p>Close all windows.</p>""" )) self.closeAllAct.triggered.connect(self.preview.closeAllWidgets) def __initMenus(self): """ Private method to create the menus. """ mb = self.menuBar() menu = mb.addMenu(self.tr('&File')) menu.setTearOffEnabled(True) menu.addAction(self.openUIAct) menu.addAction(self.openQMAct) menu.addAction(self.reloadAct) menu.addSeparator() menu.addAction(self.closeAct) menu.addAction(self.closeAllAct) menu.addSeparator() menu.addAction(self.exitAct) self.windowMenu = mb.addMenu(self.tr('&Window')) self.windowMenu.setTearOffEnabled(True) self.windowMenu.aboutToShow.connect(self.__showWindowMenu) self.windowMenu.triggered.connect(self.preview.toggleSelectedWidget) mb.addSeparator() menu = mb.addMenu(self.tr('&Help')) menu.setTearOffEnabled(True) menu.addAction(self.aboutAct) menu.addAction(self.aboutQtAct) menu.addSeparator() menu.addAction(self.whatsThisAct) def __initToolbars(self): """ Private method to create the toolbars. """ filetb = self.addToolBar(self.tr("File")) filetb.setIconSize(UI.Config.ToolBarIconSize) filetb.addAction(self.openUIAct) filetb.addAction(self.openQMAct) filetb.addAction(self.reloadAct) filetb.addSeparator() filetb.addAction(self.closeAct) filetb.addSeparator() filetb.addAction(self.exitAct) helptb = self.addToolBar(self.tr("Help")) helptb.setIconSize(UI.Config.ToolBarIconSize) helptb.addAction(self.whatsThisAct) def __whatsThis(self): """ Private slot called in to enter Whats This mode. """ QWhatsThis.enterWhatsThisMode() def __updateActions(self): """ Private slot to update the actions state. """ if self.preview.hasWidgets(): self.closeAct.setEnabled(True) self.closeAllAct.setEnabled(True) self.tileAct.setEnabled(True) self.cascadeAct.setEnabled(True) else: self.closeAct.setEnabled(False) self.closeAllAct.setEnabled(False) self.tileAct.setEnabled(False) self.cascadeAct.setEnabled(False) if self.translations.hasTranslations(): self.reloadAct.setEnabled(True) else: self.reloadAct.setEnabled(False) def __about(self): """ Private slot to show the about information. """ E5MessageBox.about( self, self.tr("TR Previewer"), self.tr( """<h3> About TR Previewer </h3>""" """<p>The TR Previewer loads and displays Qt User-Interface""" """ files and translation files and shows dialogs for a""" """ selected language.</p>""" ) ) def __aboutQt(self): """ Private slot to show info about Qt. """ E5MessageBox.aboutQt(self, self.tr("TR Previewer")) def __openWidget(self): """ Private slot to handle the Open Dialog action. """ fileNameList = E5FileDialog.getOpenFileNames( None, self.tr("Select UI files"), "", self.tr("Qt User-Interface Files (*.ui)")) for fileName in fileNameList: self.preview.loadWidget(fileName) self.__updateActions() def __openTranslation(self): """ Private slot to handle the Open Translation action. """ fileNameList = E5FileDialog.getOpenFileNames( None, self.tr("Select translation files"), "", self.tr("Qt Translation Files (*.qm)")) first = True for fileName in fileNameList: self.translations.add(fileName, first) first = False self.__updateActions() def setTranslation(self, name): """ Public slot to activate a translation. @param name name (language) of the translation (string) """ self.translations.set(name) def __showWindowMenu(self): """ Private slot to handle the aboutToShow signal of the window menu. """ self.windowMenu.clear() self.windowMenu.addAction(self.tileAct) self.windowMenu.addAction(self.cascadeAct) self.windowMenu.addSeparator() self.preview.showWindowMenu(self.windowMenu) def reloadTranslations(self): """ Public slot to reload all translations. """ self.translations.reload()
class PreferencesDialog(PreferencesDialogBase): def __init__(self, parent, app): PreferencesDialogBase.__init__(self, parent, app) self.scanTypeComboBox.currentIndexChanged[int].connect(self.scanTypeChanged) def _setupPreferenceWidgets(self): scanTypeLabels = [ tr("Filename"), tr("Filename - Fields"), tr("Filename - Fields (No Order)"), tr("Tags"), tr("Contents"), tr("Audio Contents"), ] self._setupScanTypeBox(scanTypeLabels) self._setupFilterHardnessBox() self.widgetsVLayout.addLayout(self.filterHardnessHLayout) self.widget = QWidget(self) self.widget.setMinimumSize(QSize(0, 40)) self.verticalLayout_4 = QVBoxLayout(self.widget) self.verticalLayout_4.setSpacing(0) self.verticalLayout_4.setContentsMargins(0, 0, 0, 0) self.label_6 = QLabel(self.widget) self.label_6.setText(tr("Tags to scan:")) self.verticalLayout_4.addWidget(self.label_6) self.horizontalLayout_2 = QHBoxLayout() self.horizontalLayout_2.setSpacing(0) spacerItem1 = QSpacerItem(15, 20, QSizePolicy.Fixed, QSizePolicy.Minimum) self.horizontalLayout_2.addItem(spacerItem1) self._setupAddCheckbox('tagTrackBox', tr("Track"), self.widget) self.horizontalLayout_2.addWidget(self.tagTrackBox) self._setupAddCheckbox('tagArtistBox', tr("Artist"), self.widget) self.horizontalLayout_2.addWidget(self.tagArtistBox) self._setupAddCheckbox('tagAlbumBox', tr("Album"), self.widget) self.horizontalLayout_2.addWidget(self.tagAlbumBox) self._setupAddCheckbox('tagTitleBox', tr("Title"), self.widget) self.horizontalLayout_2.addWidget(self.tagTitleBox) self._setupAddCheckbox('tagGenreBox', tr("Genre"), self.widget) self.horizontalLayout_2.addWidget(self.tagGenreBox) self._setupAddCheckbox('tagYearBox', tr("Year"), self.widget) self.horizontalLayout_2.addWidget(self.tagYearBox) self.verticalLayout_4.addLayout(self.horizontalLayout_2) self.widgetsVLayout.addWidget(self.widget) self._setupAddCheckbox('wordWeightingBox', tr("Word weighting")) self.widgetsVLayout.addWidget(self.wordWeightingBox) self._setupAddCheckbox('matchSimilarBox', tr("Match similar words")) self.widgetsVLayout.addWidget(self.matchSimilarBox) self._setupAddCheckbox('mixFileKindBox', tr("Can mix file kind")) self.widgetsVLayout.addWidget(self.mixFileKindBox) self._setupAddCheckbox('useRegexpBox', tr("Use regular expressions when filtering")) self.widgetsVLayout.addWidget(self.useRegexpBox) self._setupAddCheckbox('removeEmptyFoldersBox', tr("Remove empty folders on delete or move")) self.widgetsVLayout.addWidget(self.removeEmptyFoldersBox) self._setupAddCheckbox('ignoreHardlinkMatches', tr("Ignore duplicates hardlinking to the same file")) self.widgetsVLayout.addWidget(self.ignoreHardlinkMatches) self._setupAddCheckbox('debugModeBox', tr("Debug mode (restart required)")) self.widgetsVLayout.addWidget(self.debugModeBox) self._setupBottomPart() def _load(self, prefs, setchecked): scan_type_index = SCAN_TYPE_ORDER.index(prefs.scan_type) self.scanTypeComboBox.setCurrentIndex(scan_type_index) setchecked(self.tagTrackBox, prefs.scan_tag_track) setchecked(self.tagArtistBox, prefs.scan_tag_artist) setchecked(self.tagAlbumBox, prefs.scan_tag_album) setchecked(self.tagTitleBox, prefs.scan_tag_title) setchecked(self.tagGenreBox, prefs.scan_tag_genre) setchecked(self.tagYearBox, prefs.scan_tag_year) setchecked(self.matchSimilarBox, prefs.match_similar) setchecked(self.wordWeightingBox, prefs.word_weighting) def _save(self, prefs, ischecked): prefs.scan_type = SCAN_TYPE_ORDER[self.scanTypeComboBox.currentIndex()] prefs.scan_tag_track = ischecked(self.tagTrackBox) prefs.scan_tag_artist = ischecked(self.tagArtistBox) prefs.scan_tag_album = ischecked(self.tagAlbumBox) prefs.scan_tag_title = ischecked(self.tagTitleBox) prefs.scan_tag_genre = ischecked(self.tagGenreBox) prefs.scan_tag_year = ischecked(self.tagYearBox) prefs.match_similar = ischecked(self.matchSimilarBox) prefs.word_weighting = ischecked(self.wordWeightingBox) def resetToDefaults(self): self.load(preferences.Preferences()) #--- Events def scanTypeChanged(self, index): scan_type = SCAN_TYPE_ORDER[self.scanTypeComboBox.currentIndex()] word_based = scan_type in ( ScanType.Filename, ScanType.Fields, ScanType.FieldsNoOrder, ScanType.Tag ) tag_based = scan_type == ScanType.Tag self.filterHardnessSlider.setEnabled(word_based) self.matchSimilarBox.setEnabled(word_based) self.wordWeightingBox.setEnabled(word_based) self.tagTrackBox.setEnabled(tag_based) self.tagArtistBox.setEnabled(tag_based) self.tagAlbumBox.setEnabled(tag_based) self.tagTitleBox.setEnabled(tag_based) self.tagGenreBox.setEnabled(tag_based) self.tagYearBox.setEnabled(tag_based)