class LayerListDialog(QDialog): def __init__(self, parent): QDialog.__init__(self, parent) # add a button box self.layout = QVBoxLayout() self.layer_list = LayerListWidget(self) self.button_box = QDialogButtonBox(self) self.button_box.setOrientation(Qt.Horizontal) self.button_box.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok) self.button_box.accepted.connect(self.accept) self.button_box.rejected.connect(self.reject) self.layout.addWidget(self.layer_list) self.layout.addWidget(self.button_box) self.setLayout(self.layout) def set_labeling_model(self, model): self.layer_list.set_model(model) def exec_(self): self.layer_list.update_from_layers() return QDialog.exec_(self) def accept(self): # update layers self.layer_list.update_labeling_from_list() QDialog.accept(self)
class AboutBox(QDialog): def __init__(self, parent, app, **kwargs): flags = Qt.CustomizeWindowHint | Qt.WindowTitleHint | Qt.WindowSystemMenuHint | Qt.MSWindowsFixedSizeDialogHint super().__init__(parent, flags, **kwargs) self.app = app self._setupUi() self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) def _setupUi(self): self.setWindowTitle(tr("About {}").format(QCoreApplication.instance().applicationName())) self.resize(400, 190) sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.sizePolicy().hasHeightForWidth()) self.setSizePolicy(sizePolicy) self.horizontalLayout = QHBoxLayout(self) self.logoLabel = QLabel(self) self.logoLabel.setPixmap(QPixmap(':/%s_big' % self.app.LOGO_NAME)) self.horizontalLayout.addWidget(self.logoLabel) self.verticalLayout = QVBoxLayout() self.nameLabel = QLabel(self) font = QFont() font.setWeight(75) font.setBold(True) self.nameLabel.setFont(font) self.nameLabel.setText(QCoreApplication.instance().applicationName()) self.verticalLayout.addWidget(self.nameLabel) self.versionLabel = QLabel(self) self.versionLabel.setText(tr("Version {}").format(QCoreApplication.instance().applicationVersion())) self.verticalLayout.addWidget(self.versionLabel) self.label_3 = QLabel(self) self.verticalLayout.addWidget(self.label_3) self.label_3.setText(tr("Licensed under GPLv3")) self.label = QLabel(self) font = QFont() font.setWeight(75) font.setBold(True) self.label.setFont(font) self.verticalLayout.addWidget(self.label) self.buttonBox = QDialogButtonBox(self) self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Ok) self.verticalLayout.addWidget(self.buttonBox) self.horizontalLayout.addLayout(self.verticalLayout)
class BudgetPanel(Panel): FIELDS = [ ('amountEdit', 'amount'), ('notesEdit', 'notes'), ] PERSISTENT_NAME = 'budgetPanel' def __init__(self, model, mainwindow): Panel.__init__(self, mainwindow) self.setAttribute(Qt.WA_DeleteOnClose) self._setupUi() self.model = model self.accountComboBox = ComboboxModel(model=self.model.account_list, view=self.accountComboBoxView) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) def _setupUi(self): self.setWindowTitle(tr("Budget Info")) self.resize(230, 230) self.setModal(True) self.verticalLayout = QVBoxLayout(self) self.formLayout = QFormLayout() self.formLayout.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow) self.accountComboBoxView = QComboBox(self) self.formLayout.setWidget(0, QFormLayout.FieldRole, self.accountComboBoxView) self.label_3 = QLabel(tr("Account:")) self.formLayout.setWidget(0, QFormLayout.LabelRole, self.label_3) self.amountEdit = QLineEdit(self) self.amountEdit.setMaximumWidth(120) self.formLayout.setWidget(1, QFormLayout.FieldRole, self.amountEdit) self.label_5 = QLabel(tr("Amount:")) self.formLayout.setWidget(1, QFormLayout.LabelRole, self.label_5) self.notesEdit = QPlainTextEdit(tr("Notes:")) self.formLayout.setWidget(2, QFormLayout.FieldRole, self.notesEdit) self.label = QLabel(self) self.formLayout.setWidget(2, QFormLayout.LabelRole, self.label) self.verticalLayout.addLayout(self.formLayout) self.buttonBox = QDialogButtonBox(self) self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel|QDialogButtonBox.Save) self.verticalLayout.addWidget(self.buttonBox) self.label_3.setBuddy(self.accountComboBoxView) self.label_5.setBuddy(self.amountEdit)
class PasswordInputView(QWidget, Ui_PasswordInputWidget): """ The model of Navigation component """ def __init__(self, parent): # construct from qtDesigner super().__init__(parent) self.setupUi(self) self.button_box = QDialogButtonBox(self) self.button_box.setOrientation(Qt.Horizontal) self.button_box.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok) self.button_box.button(QDialogButtonBox.Ok).setEnabled(False) self.layout().addWidget(self.button_box) self.button_box.hide() def error(self, text): self.label_info.setText(text) self.button_box.button(QDialogButtonBox.Ok).setEnabled(False) def clear(self): self.edit_password.clear() self.edit_secret_key.clear() def valid(self): self.label_info.setText(self.tr("Password is valid")) self.button_box.button(QDialogButtonBox.Ok).setEnabled(True) def changeEvent(self, event): """ Intercepte LanguageChange event to translate UI :param QEvent QEvent: Event :return: """ if event.type() == QEvent.LanguageChange: self.retranslateUi(self) return super(PasswordInputView, self).changeEvent(event)
def showDialog(self, currentCard=None): # Handle for dialog open without a current card from IR model did = None cid = None if not currentCard: deck = mw._selectedDeck() did = deck['id'] else: did = currentCard.did cid = currentCard.id cardDataList = self.getCardDataList(did, cid) if not cardDataList: showInfo(_('Please select an Incremental Reading deck.')) return d = QDialog(mw) l = QVBoxLayout() w = AnkiWebView() l.addWidget(w) script = ''' var cardList = new Array(); ''' index = 0 for cardData in cardDataList: index += 1 script += "card = new Object();" script += "card.id = " + str(cardData['id']) + ";" script += "card.title = '" + str(cardData['title']) + "';" script += "card.isCurrent = " + str(cardData['isCurrent']) + ";" script += "card.checkbox = document.createElement('input');" script += "card.checkbox.type = 'checkbox';" if cardData['isCurrent'] == 'true': script += "card.checkbox.setAttribute('checked', 'true');" script += "cardList[cardList.length] = card;" script += """ function buildCardData() { var container = document.getElementById('cardList'); container.innerHTML = ''; var list = document.createElement('div'); list.setAttribute('style','overflow:auto;'); var table = document.createElement('table'); list.appendChild(table); container.appendChild(list); var row; var col; var cardData; for (var i = 0; i < cardList.length; i++) { row = document.createElement('tr'); row.setAttribute('id','row' + i); cardData = cardList[i]; col = document.createElement('td'); col.setAttribute('style','width:4em;'); col.innerHTML = '' + i; row.appendChild(col); col = document.createElement('td'); col.setAttribute('style','width:10em;'); col.innerHTML = '' + cardData.id; row.appendChild(col); col = document.createElement('td'); col.setAttribute('style','width:30em;'); col.innerHTML = '' + cardData.title; row.appendChild(col); col = document.createElement('td'); col.setAttribute('style','width:2em;'); col.appendChild(cardData.checkbox); row.appendChild(col); table.appendChild(row); } } function reposition(origIndex, newIndex, isTopOfRange) { if (newIndex < 0 || newIndex > (cardList.length-1)) return -1; if (cardList[newIndex].checkbox.checked) return -1; if (isTopOfRange) { document.getElementById('newPos').value = newIndex; } var removedCards = cardList.splice(origIndex,1); cardList.splice(newIndex, 0, removedCards[0]); return newIndex; } function moveSelectedUp() { var topOfRange = -1; for (var i = 0; i < cardList.length; i++) { if (cardList[i].checkbox.checked) { if (topOfRange == -1) { topOfRange = i; } if (i == topOfRange) { if (document.getElementById('anchor').checked) { continue; //Don't move end of range if anchored. } else { reposition(i, i - 1, true); } } else { reposition(i, i - 1, false); } } } buildCardData(); } function moveSelectedDown() { var topOfRange = -1; var bottomOfRange = -1; for (var i = 0; i < cardList.length; i++) { if (cardList[i].checkbox.checked) { if (topOfRange == -1) { topOfRange = i; } bottomOfRange = i; } } for (var i = cardList.length-1; i > -1; i--) { if (cardList[i].checkbox.checked) { if (i == bottomOfRange && document.getElementById('anchor').checked) { continue; //Don't move end of range if anchored. } if (i == topOfRange) { reposition(i, i + 1, true); } else { reposition(i, i + 1, false); } } } buildCardData(); } function selectAll() { for (var i = 0; i < cardList.length; i++) { cardList[i].checkbox.checked = true; } } function selectNone() { for (var i = 0; i < cardList.length; i++) { cardList[i].checkbox.checked = false; } } function directMove() { var newIndex = document.getElementById('newPos').value; var topOfRange = -1; origIndex = -1; for (var i = 0; i < cardList.length; i++) { if (cardList[i].checkbox.checked) { if (topOfRange == -1) { topOfRange = i; } if (origIndex == -1) { origIndex = i; sizeOfMove = (newIndex - origIndex); } } } if (sizeOfMove < 0) { for (var i = 0; i < cardList.length; i++) { if (cardList[i].checkbox.checked) { if (i == topOfRange) { reposition(i, i + sizeOfMove, true); } else { reposition(i, i + sizeOfMove, false); } } } } else { for (var i = cardList.length-1; i > -1; i--) { if (cardList[i].checkbox.checked) { if (i == topOfRange) { reposition(i, i + sizeOfMove, true); } else { reposition(i, i + sizeOfMove, false); } } } } buildCardData(); } function updatePositions() { var cids = new Array(); for (var i=0; i < cardList.length; i++) { cids[cids.length] = parseInt(cardList[i].id); } return cids.join(); }; """ newPosField = "<span style='font-weight:bold'>Card Position: </span><input type='text' id='newPos' size='5' value='0' /> <span style='font-weight:bold'>of " + str( len(cardDataList)) + "</span> " newPosField += "<input type='button' value='Apply' onclick='directMove()' /> <span style='font-weight:bold'>Pin Top/Bottom? </span><input type='checkbox' id='anchor'/>" upDownButtons = "<input type='button' value='Move Up' onclick='moveSelectedUp()'/><input type='button' value='Move Down' onclick='moveSelectedDown()'/>" upDownButtons += "<input type='button' value='Select All' onclick='selectAll()'/><input type='button' value='Select None' onclick='selectNone()'/>" html = "<html><head><script>" + script + "</script></head><body onLoad='buildCardData()'>" html += "<p>" + newPosField html += "<p>" + upDownButtons html += "<div id='cardList'></div>" html += "</body></html>" w.stdHtml(html) bb = QDialogButtonBox(QDialogButtonBox.Close | QDialogButtonBox.Save) bb.accepted.connect(d.accept) bb.rejected.connect(d.reject) bb.setOrientation(Qt.Horizontal) l.addWidget(bb) d.setLayout(l) d.setWindowModality(Qt.WindowModal) d.resize(500, 500) choice = d.exec_() if choice == 1: if ANKI_21: cids = w.page().runJavaScript('updatePositions()', self.callback) else: cids = w.page().mainFrame().evaluateJavaScript( 'updatePositions()') self.repositionCards(cids) elif currentCard: self.repositionCard(currentCard, -1)
class TransactionPanel(Panel): FIELDS = [ ('dateEdit', 'date'), ('descriptionEdit', 'description'), ('payeeEdit', 'payee'), ('checkNoEdit', 'checkno'), ('notesEdit', 'notes'), ] PERSISTENT_NAME = 'transactionPanel' def __init__(self, model, mainwindow): Panel.__init__(self, mainwindow) self.setAttribute(Qt.WA_DeleteOnClose) self.model = model self._setupUi() self.splitTable = SplitTable(model=self.model.split_table, view=self.splitTableView) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) self.mctButton.clicked.connect(self.model.mct_balance) self.assignImbalanceButton.clicked.connect(self.model.assign_imbalance) self.addSplitButton.clicked.connect(self.splitTable.model.add) self.removeSplitButton.clicked.connect(self.splitTable.model.delete) def _setupUi(self): self.setWindowTitle(tr("Transaction Info")) self.resize(462, 329) self.setModal(True) self.mainLayout = QVBoxLayout(self) self.tabWidget = QTabWidget(self) self.infoTab = QWidget() self.infoLayout = QVBoxLayout(self.infoTab) self.formLayout = QFormLayout() self.formLayout.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow) self.dateEdit = DateEdit(self.infoTab) self.dateEdit.setMaximumSize(QSize(120, 16777215)) self.formLayout.addRow(tr("Date:"), self.dateEdit) self.descriptionEdit = DescriptionEdit(self.model.completable_edit, self.infoTab) self.formLayout.addRow(tr("Description:"), self.descriptionEdit) self.payeeEdit = PayeeEdit(self.model.completable_edit, self.infoTab) self.formLayout.addRow(tr("Payee:"), self.payeeEdit) self.checkNoEdit = QLineEdit(self.infoTab) self.checkNoEdit.setMaximumSize(QSize(120, 16777215)) self.formLayout.addRow(tr("Check #:"), self.checkNoEdit) self.infoLayout.addLayout(self.formLayout) self.amountLabel = QLabel(tr("Transfers:"), self.infoTab) self.infoLayout.addWidget(self.amountLabel) self.splitTableView = TableView(self.infoTab) self.splitTableView.setAcceptDrops(True) self.splitTableView.setEditTriggers(QAbstractItemView.DoubleClicked | QAbstractItemView.EditKeyPressed) self.splitTableView.setDragEnabled(True) self.splitTableView.setDragDropMode(QAbstractItemView.InternalMove) self.splitTableView.setSelectionMode(QAbstractItemView.SingleSelection) self.splitTableView.setSelectionBehavior(QAbstractItemView.SelectRows) self.splitTableView.horizontalHeader().setDefaultSectionSize(40) self.splitTableView.verticalHeader().setVisible(False) self.splitTableView.verticalHeader().setDefaultSectionSize(18) self.infoLayout.addWidget(self.splitTableView) self.mctButtonsLayout = QHBoxLayout() self.mctButtonsLayout.setContentsMargins(0, 0, 0, 0) spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.mctButtonsLayout.addItem(spacerItem) self.mctButton = QPushButton(tr("&Multi-currency balance"), self.infoTab) self.mctButtonsLayout.addWidget(self.mctButton) self.assignImbalanceButton = QPushButton(tr("Assign &imbalance"), self.infoTab) self.mctButtonsLayout.addWidget(self.assignImbalanceButton) self.addSplitButton = QPushButton(self.infoTab) icon = QIcon() icon.addPixmap(QPixmap(":/plus_8"), QIcon.Normal, QIcon.Off) self.addSplitButton.setIcon(icon) self.mctButtonsLayout.addWidget(self.addSplitButton) self.removeSplitButton = QPushButton(self.infoTab) icon1 = QIcon() icon1.addPixmap(QPixmap(":/minus_8"), QIcon.Normal, QIcon.Off) self.removeSplitButton.setIcon(icon1) self.mctButtonsLayout.addWidget(self.removeSplitButton) self.infoLayout.addLayout(self.mctButtonsLayout) self.tabWidget.addTab(self.infoTab, tr("Info")) self.notesTab = QWidget() self.notesLayout = QVBoxLayout(self.notesTab) self.notesEdit = QPlainTextEdit(self.notesTab) self.notesLayout.addWidget(self.notesEdit) self.tabWidget.addTab(self.notesTab, tr("Notes")) self.tabWidget.setCurrentIndex(0) self.mainLayout.addWidget(self.tabWidget) self.buttonBox = QDialogButtonBox(self) self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Save) self.mainLayout.addWidget(self.buttonBox) def _loadFields(self): Panel._loadFields(self) self.tabWidget.setCurrentIndex(0) # --- model --> view def refresh_for_multi_currency(self): self.mctButton.setEnabled(self.model.is_multi_currency)
class MoveFileDialog(QDialog): '''移动文件对话框''' new_infos = pyqtSignal(object) def __init__(self, infos, all_dirs_dict, parent=None): super(MoveFileDialog, self).__init__(parent) self.infos = infos self.dirs = all_dirs_dict self.initUI() self.setStyleSheet(dialog_qss_style) def initUI(self): for i in self.infos: if not i[2]: # 非文件 self.infos.remove(i) self.setWindowTitle("移动文件") self.setWindowIcon(QIcon("./src/move.ico")) self.lb_name = QLabel() self.lb_name.setText("文件路径:") self.lb_name.setAlignment(Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self.tx_name = QLineEdit() names = " | ".join([i[1] for i in self.infos]) names_tip = "\n".join([i[1] for i in self.infos]) self.tx_name.setText(names) self.tx_name.setToolTip(names_tip) # 只读 self.tx_name.setFocusPolicy(Qt.NoFocus) self.tx_name.setReadOnly(True) self.lb_new_path = QLabel() self.lb_new_path.setText("目标文件夹:") self.lb_new_path.setAlignment(Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self.tx_new_path = QComboBox() f_icon = QIcon("./src/folder.gif") for f_name, fid in self.dirs.items(): if len(f_name) > 50: # 防止文件夹名字过长? f_name = f_name[:47] + "..." self.tx_new_path.addItem(f_icon, "id:{:>8},name:{}".format(fid, f_name)) self.buttonBox = QDialogButtonBox() self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.buttonBox.button(QDialogButtonBox.Ok).setText("确定") self.buttonBox.button(QDialogButtonBox.Cancel).setText("取消") self.grid = QGridLayout() self.grid.setSpacing(10) self.grid.addWidget(self.lb_name, 1, 0) self.grid.addWidget(self.tx_name, 1, 1) self.grid.addWidget(self.lb_new_path, 2, 0) self.grid.addWidget(self.tx_new_path, 2, 1) self.grid.addWidget(self.buttonBox, 3, 0, 1, 2) self.setLayout(self.grid) self.buttonBox.accepted.connect(self.btn_ok) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) self.setMinimumWidth(280) def btn_ok(self): selected = self.tx_new_path.currentText().split(",")[0].split(":")[1] self.new_infos.emit([(info[0], selected, info[1]) for info in self.infos])
class CityListDlg(QDialog): citieslist_signal = pyqtSignal([list]) citiesdict_signal = pyqtSignal([dict]) def __init__( self, citylist, accurate_url, appid, trans_cities_dict, parent=None ): super(CityListDlg, self).__init__(parent) self.settings = QSettings() self.citylist = citylist self.trans_cities_dict = trans_cities_dict self.accurate_url = accurate_url self.appid = appid self.listWidget = QListWidget() self.listWidget.itemDoubleClicked.connect(self.translate) cities_list = [] for i in self.citylist: cities_list.append(self.trans_cities_dict.get(i, i)) self.listWidget.addItems(cities_list) buttonLayout = QVBoxLayout() self.buttonBox = QDialogButtonBox() self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons( QDialogButtonBox.Ok | QDialogButtonBox.Cancel ) self.buttonBox.rejected.connect(self.reject) self.buttonBox.accepted.connect(self.accept) layoutT = QVBoxLayout() layout = QHBoxLayout() layout.addWidget(self.listWidget) layout.addLayout(buttonLayout) for text, slot in ((self.tr("&Add..."), self.add), (self.tr("&Remove..."), self.remove), (self.tr("&Up"), self.up), (self.tr("&Down"), self.down), (self.tr("De&fault"), self.default), (self.tr("&Sort"), self.listWidget.sortItems)): button = QPushButton(text) buttonLayout.addWidget(button) button.clicked.connect(slot) self.translate_button = QPushButton( QCoreApplication.translate( 'Button', '&Translate', 'Edit cities name' ) ) buttonLayout.addWidget(self.translate_button) self.translate_button.clicked.connect(self.translate) buttonLayout.addWidget(self.buttonBox) self.status = QLabel() layoutT.addLayout(layout) layoutT.addWidget(self.status) self.setLayout(layoutT) self.setWindowTitle( QCoreApplication.translate( 'Window title', 'Cities', 'Cities list dialogue' ) ) self.checklength() def add(self): self.status.setText('') lista = [] newitem = '' self.citytoadd = '' self.countrytoadd = '' self._idtoadd = '' dialog = searchcity.SearchCity(self.accurate_url, self.appid, self) dialog.id_signal.connect(self.addcity) dialog.city_signal.connect(self.addcity) dialog.country_signal.connect(self.addcity) if dialog.exec_() == 1: newitem = ( self.citytoadd + '_' + self.countrytoadd + '_' + self._idtoadd ) for row in range(self.listWidget.count()): lista.append(self.listWidget.item(row).text()) if newitem in lista: self.status.setText( QCoreApplication.translate( 'Status bar message', 'The city already exists in the list', 'Cities list dialogue' ) ) return else: self.listWidget.addItem(newitem) self.checklength() self.status.setText( 'ℹ ' + QCoreApplication.translate( 'Status bar message', 'Toggle cities with mouse scroll on the weather window', 'Cities list dialogue' ) ) def addcity(self, what): self.status.setText('') if what[0] == 'ID': self._idtoadd = what[1] elif what[0] == 'City': self.citytoadd = what[1] elif what[0] == 'Country': self.countrytoadd = what[1] def remove(self): self.status.setText('') if self.listWidget.count() == 1: self.status.setText( QCoreApplication.translate( 'Message when trying to remove the' 'last and unique city in the list', 'This is the default city !', 'Cities list dialogue' ) ) return row = self.listWidget.currentRow() item = self.listWidget.item(row) if item is None: return message = self.tr('The city "{0}" has been removed').format( self.listWidget.item(row).text()) item = self.listWidget.takeItem(row) del item self.status.setText(message) def up(self): self.status.setText('') row = self.listWidget.currentRow() if row >= 1: item = self.listWidget.takeItem(row) self.listWidget.insertItem(row - 1, item) self.listWidget.setCurrentItem(item) def down(self): self.status.setText('') row = self.listWidget.currentRow() if row < self.listWidget.count() - 1: item = self.listWidget.takeItem(row) self.listWidget.insertItem(row + 1, item) self.listWidget.setCurrentItem(item) def default(self): self.status.setText('') row = self.listWidget.currentRow() if row >= 1: item = self.listWidget.takeItem(row) self.listWidget.insertItem(0, item) self.listWidget.setCurrentItem(item) def checklength(self): if self.listWidget.count() == 1: # After adding the first city the entry is not activated self.listWidget.setCurrentRow(0) if self.listWidget.count() > 0: self.translate_button.setEnabled(True) self.listWidget.setMinimumWidth( self.listWidget.sizeHintForColumn(0) ) else: self.translate_button.setEnabled(False) def translate(self): city = self.listWidget.currentItem().text() dialog = citytranslate.CityTranslate( city, self.trans_cities_dict, self ) dialog.city_signal.connect(self.current_translation) if dialog.exec_() == 1: row = self.listWidget.currentRow() item = self.listWidget.takeItem(row) del item self.listWidget.insertItem(row, self.current_translated_city) self.listWidget.setCurrentRow(row) def current_translation(self, translated_city): for city, translated in translated_city.items(): if translated == '': translated = city self.trans_cities_dict[city] = translated self.current_translated_city = translated def accept(self): listtosend = [] for row in range(self.listWidget.count()): city = self.find_city_key(self.listWidget.item(row).text()) listtosend.append(city) if self.listWidget.count() == 0: return self.citieslist_signal[list].emit(listtosend) self.citiesdict_signal[dict].emit(self.trans_cities_dict) QDialog.accept(self) def find_city_key(self, city): for key, value in self.trans_cities_dict.items(): if value == city: return key return city
class TorrentCreatingDialog(QDialog): SELECTION_LABEL_FORMAT = 'Selected {} files ({})' def _get_directory_browse_widget(self): widget = QWidget() hbox = QHBoxLayout(widget) hbox.setContentsMargins(0, 0, 0, 0) self._path_edit = QLineEdit(self) self._path_edit.setReadOnly(True) hbox.addWidget(self._path_edit, 4) browse_button = QPushButton('Browse...') browse_button.clicked.connect(self._browse) hbox.addWidget(browse_button, 1) widget.setLayout(hbox) return widget def _browse(self): new_download_dir = QFileDialog.getExistingDirectory( self, 'Select download directory', self.path) if not new_download_dir: return self._download_dir = new_download_dir self._path_edit.setText(new_download_dir) def __init__(self, parent: QWidget, path): super().__init__(parent) # download_info = torrent_info.download_info vbox = QVBoxLayout(self) vbox.addWidget(QLabel('Path to file:')) vbox.addWidget(self._get_directory_browse_widget()) vbox.addWidget(QLabel('Tracker:')) self._path_edit = QLineEdit(self) self._path_edit.setReadOnly(False) vbox.addWidget(self._path_edit, 4) self._button_box = QDialogButtonBox(self) self._button_box.setOrientation(Qt.Horizontal) self._button_box.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok) self._button_box.button(QDialogButtonBox.Ok).clicked.connect( self.submit_torrent) self._button_box.button(QDialogButtonBox.Cancel).clicked.connect( self.close) vbox.addWidget(self._button_box) # self.setFixedSize(250, 200) self.setWindowTitle('Create torrent') self.path = path def _set_check_state_to_tree(self, item: QTreeWidgetItem, check_state: Qt.CheckState): for i in range(item.childCount()): child = item.child(i) child.setCheckState(0, check_state) self._set_check_state_to_tree(child, check_state) def _update_checkboxes(self, item: QTreeWidgetItem, column: int): if column != 0: return new_check_state = item.checkState(0) self._set_check_state_to_tree(item, new_check_state) while True: item = item.parent() if item is None: break has_checked_children = False has_partially_checked_children = False has_unchecked_children = False for i in range(item.childCount()): state = item.child(i).checkState(0) if state == Qt.Checked: has_checked_children = True elif state == Qt.PartiallyChecked: has_partially_checked_children = True else: has_unchecked_children = True if not has_partially_checked_children and not has_unchecked_children: new_state = Qt.Checked elif has_checked_children or has_partially_checked_children: new_state = Qt.PartiallyChecked else: new_state = Qt.Unchecked item.setCheckState(0, new_state) self._update_selection_label() def _update_selection_label(self): selected_file_count = 0 selected_size = 0 for node, item in self._file_items: if item.checkState(0) == Qt.Checked: selected_file_count += 1 selected_size += node.length ok_button = self._button_box.button(QDialogButtonBox.Ok) if not selected_file_count: ok_button.setEnabled(False) self._selection_label.setText('Nothing to download') else: ok_button.setEnabled(True) # self._selection_label.setText(TorrentAddingDialog.SELECTION_LABEL_FORMAT.format( # selected_file_count, humanize_size(selected_size))) def submit_torrent(self): # self._torrent_info.download_dir = self._download_dir # self._control.last_download_dir = os.path.abspath(self._download_dir) # # file_paths = [] # for node, item in self._file_items: # if item.checkState(0) == Qt.Checked: # file_paths.append(node.path) # if not self._torrent_info.download_info.single_file_mode: # self._torrent_info.download_info.select_files(file_paths, 'whitelist') # # self._control_thread.loop.call_soon_threadsafe(self._control.add, self._torrent_info) # # self.close() pass
class UploadDialog(QDialog): """文件上传对话框""" new_infos = pyqtSignal(object) def __init__(self): super().__init__() self.cwd = os.getcwd() self.selected = [] self.max_len = 400 self.initUI() self.set_size() self.setStyleSheet(dialog_qss_style) def set_values(self, folder_name): self.setWindowTitle("上传文件至 ➩ " + str(folder_name)) def initUI(self): self.setWindowTitle("上传文件") self.setWindowIcon(QIcon("./icon/upload.ico")) self.logo = QLabel() self.logo.setPixmap(QPixmap("./icon/logo3.gif")) self.logo.setStyleSheet("background-color:rgb(0,153,255);") self.logo.setAlignment(Qt.AlignCenter) # btn 1 self.btn_chooseDir = QPushButton("选择文件夹", self) self.btn_chooseDir.setObjectName("btn_chooseDir") self.btn_chooseDir.setObjectName("btn_chooseDir") self.btn_chooseDir.setIcon(QIcon("./icon/folder.gif")) # btn 2 self.btn_chooseMutiFile = QPushButton("选择多文件", self) self.btn_chooseDir.setObjectName("btn_chooseMutiFile") self.btn_chooseMutiFile.setObjectName("btn_chooseMutiFile") self.btn_chooseMutiFile.setIcon(QIcon("./icon/file.ico")) # btn 3 self.btn_deleteSelect = QPushButton("删除", self) self.btn_deleteSelect.setObjectName("btn_deleteSelect") self.btn_deleteSelect.setIcon(QIcon("./icon/delete.ico")) # 列表 self.list_view = QListView(self) self.list_view.setViewMode(QListView.ListMode) self.slm = QStandardItem() self.model = QStandardItemModel() self.list_view.setModel(self.model) self.model.removeRows(0, self.model.rowCount()) # 清除旧的选择 self.list_view.setEditTriggers(QAbstractItemView.NoEditTriggers) self.list_view.setSelectionBehavior(QAbstractItemView.SelectRows) self.list_view.setSelectionMode(QAbstractItemView.ExtendedSelection) self.buttonBox = QDialogButtonBox() self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) grid = QGridLayout() grid.setSpacing(10) grid.addWidget(self.logo, 1, 0, 1, 3) grid.addWidget(self.btn_chooseDir, 2, 0) grid.addWidget(self.btn_chooseMutiFile, 2, 2) grid.addWidget(self.list_view, 3, 0, 2, 3) grid.addWidget(self.btn_deleteSelect, 5, 0) grid.addWidget(self.buttonBox, 5, 1, 1, 2) self.setLayout(grid) self.setMinimumWidth(350) # 设置信号 self.btn_chooseDir.clicked.connect(self.slot_btn_chooseDir) self.btn_chooseMutiFile.clicked.connect(self.slot_btn_chooseMutiFile) self.btn_deleteSelect.clicked.connect(self.slot_btn_deleteSelect) self.buttonBox.accepted.connect(self.slot_btn_ok) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.clear_old) self.buttonBox.rejected.connect(self.reject) def set_size(self): rows = self.model.rowCount() for i in range(rows): m_len = int(len(self.model.item(i, 0).text()) * 4) if m_len > self.max_len: self.max_len = m_len rows = 10 if rows >= 10 else rows # 限制最大高度 self.resize(self.max_len, 250 + rows * 28) def clear_old(self): self.selected = [] self.model.removeRows(0, self.model.rowCount()) self.set_size() def slot_btn_ok(self): if self.selected: self.new_infos.emit(self.selected) self.clear_old() def slot_btn_deleteSelect(self): _indexes = self.list_view.selectionModel().selection().indexes() if not _indexes: return indexes = [] for i in _indexes: # 获取所选行号 indexes.append(i.row()) indexes = set(indexes) for i in sorted(indexes, reverse=True): self.selected.remove(self.model.item(i, 0).text()) self.model.removeRow(i) self.set_size() def slot_btn_chooseDir(self): dir_choose = QFileDialog.getExistingDirectory(self, "选择文件夹", self.cwd) # 起始路径 if dir_choose == "": return if dir_choose not in self.selected: self.selected.append(dir_choose) self.model.appendRow( QStandardItem(QIcon("./icon/folder.gif"), dir_choose)) self.set_size() def slot_btn_chooseMutiFile(self): files, _ = QFileDialog.getOpenFileNames(self, "选择多文件", self.cwd, "All Files (*)") if len(files) == 0: return for _file in files: if _file not in self.selected: self.selected.append(_file) self.model.appendRow( QStandardItem(QIcon("./icon/file.ico"), _file)) self.set_size()
class TransactionPanel(Panel): FIELDS = [ ('dateEdit', 'date'), ('descriptionEdit', 'description'), ('payeeEdit', 'payee'), ('checkNoEdit', 'checkno'), ('notesEdit', 'notes'), ] PERSISTENT_NAME = 'transactionPanel' def __init__(self, model, mainwindow): Panel.__init__(self, mainwindow) self.setAttribute(Qt.WA_DeleteOnClose) self.model = model self._setupUi() self.splitTable = SplitTable(model=self.model.split_table, view=self.splitTableView) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) self.mctButton.clicked.connect(self.model.mct_balance) self.assignImbalanceButton.clicked.connect(self.model.assign_imbalance) self.addSplitButton.clicked.connect(self.splitTable.model.add) self.removeSplitButton.clicked.connect(self.splitTable.model.delete) @pyqtSlot() def on_focus_transactions(self): self.splitTableView.setFocus() def _setupUi(self): self.setWindowTitle(tr("Transaction Info")) self.resize(462, 329) self.setModal(True) self.mainLayout = QVBoxLayout(self) self.tabWidget = QTabWidget(self) self.infoTab = QWidget() self.infoLayout = QVBoxLayout(self.infoTab) self.formLayout = QFormLayout() self.formLayout.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow) self.dateEdit = DateEdit(self.infoTab) self.dateEdit.setMaximumSize(QSize(120, 16777215)) self.formLayout.addRow(tr("Date:"), self.dateEdit) self.descriptionEdit = DescriptionEdit(self.model.completable_edit, self.infoTab) self.formLayout.addRow(tr("Description:"), self.descriptionEdit) self.payeeEdit = PayeeEdit(self.model.completable_edit, self.infoTab) self.formLayout.addRow(tr("Payee:"), self.payeeEdit) self.checkNoEdit = QLineEdit(self.infoTab) self.checkNoEdit.setMaximumSize(QSize(120, 16777215)) self.formLayout.addRow(tr("Check #:"), self.checkNoEdit) self.infoLayout.addLayout(self.formLayout) self.amountLabel = QLabel(tr("Transfers:"), self.infoTab) self.infoLayout.addWidget(self.amountLabel) self.splitTableView = TableView(self.infoTab) self.splitTableView.setAcceptDrops(True) self.splitTableView.setEditTriggers(QAbstractItemView.DoubleClicked|QAbstractItemView.EditKeyPressed) self.splitTableView.setDragEnabled(True) self.splitTableView.setDragDropMode(QAbstractItemView.InternalMove) self.splitTableView.setSelectionMode(QAbstractItemView.SingleSelection) self.splitTableView.setSelectionBehavior(QAbstractItemView.SelectRows) self.splitTableView.horizontalHeader().setDefaultSectionSize(40) self.splitTableView.verticalHeader().setVisible(False) self.splitTableView.verticalHeader().setDefaultSectionSize(18) self.tvShortcut = QShortcut(QKeySequence("Alt+T"), self) self.tvShortcut.activated.connect(self.on_focus_transactions) self.infoLayout.addWidget(self.splitTableView) self.mctButtonsLayout = QHBoxLayout() self.mctButtonsLayout.setContentsMargins(0, 0, 0, 0) spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.mctButtonsLayout.addItem(spacerItem) self.mctButton = QPushButton(tr("&Multi-currency balance"), self.infoTab) self.mctButtonsLayout.addWidget(self.mctButton) self.assignImbalanceButton = QPushButton(tr("Assign &imbalance"), self.infoTab) self.mctButtonsLayout.addWidget(self.assignImbalanceButton) self.addSplitButton = QPushButton(self.infoTab) icon = QIcon() icon.addPixmap(QPixmap(":/plus_8"), QIcon.Normal, QIcon.Off) self.addSplitButton.setIcon(icon) self.mctButtonsLayout.addWidget(self.addSplitButton) self.removeSplitButton = QPushButton(self.infoTab) icon1 = QIcon() icon1.addPixmap(QPixmap(":/minus_8"), QIcon.Normal, QIcon.Off) self.removeSplitButton.setIcon(icon1) self.mctButtonsLayout.addWidget(self.removeSplitButton) self.infoLayout.addLayout(self.mctButtonsLayout) self.tabWidget.addTab(self.infoTab, tr("Info")) self.notesTab = QWidget() self.notesLayout = QVBoxLayout(self.notesTab) self.notesEdit = QPlainTextEdit(self.notesTab) self.notesLayout.addWidget(self.notesEdit) self.tabWidget.addTab(self.notesTab, tr("Notes")) self.tabWidget.setCurrentIndex(0) self.mainLayout.addWidget(self.tabWidget) self.buttonBox = QDialogButtonBox(self) self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.addButton(tr("&Save"), QDialogButtonBox.AcceptRole) self.buttonBox.addButton(tr("Cancel"), QDialogButtonBox.RejectRole) self.mainLayout.addWidget(self.buttonBox) def _loadFields(self): Panel._loadFields(self) self.tabWidget.setCurrentIndex(0) # --- model --> view def refresh_for_multi_currency(self): self.mctButton.setEnabled(self.model.is_multi_currency)
class HighpassExtension(Extension): def __init__(self, parent): super().__init__(parent) def setup(self): pass def createActions(self, window): action = window.createAction("high_pass_filter", i18n("High Pass")) action.triggered.connect(self.showDialog) def showDialog(self): doc = Application.activeDocument() if doc is None: QMessageBox.information(Application.activeWindow().qwindow(), i18n("High Pass Filter"), i18n("There is no active image.")) return self.dialog = QDialog(Application.activeWindow().qwindow()) self.intRadius = QSpinBox() self.intRadius.setValue(10) self.intRadius.setRange(2, 200) self.cmbMode = QComboBox() self.cmbMode.addItems([ "Color", "Preserve DC", "Greyscale", "Greyscale, Apply Chroma", "Redrobes" ]) self.keepOriginal = QCheckBox(i18n("Keep original layer")) self.keepOriginal.setChecked(True) form = QFormLayout() form.addRow( i18nc("Filter radius in Highpass filter settings", "Filter radius:"), self.intRadius) form.addRow(i18n("Mode:"), self.cmbMode) form.addRow("", self.keepOriginal) self.buttonBox = QDialogButtonBox(self.dialog) self.buttonBox.setOrientation(QtCore.Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.buttonBox.accepted.connect(self.dialog.accept) self.buttonBox.accepted.connect(self.highpass) self.buttonBox.rejected.connect(self.dialog.reject) vbox = QVBoxLayout(self.dialog) vbox.addLayout(form) vbox.addWidget(self.buttonBox) self.dialog.show() self.dialog.activateWindow() self.dialog.exec_() def highpass(self): # XXX: Start undo macro image = Application.activeDocument() original = image.activeNode() working_layer = original # We can only highpass on paint layers if self.keepOriginal.isChecked() or original.type() != "paintlayer": working_layer = image.createNode("working", "paintlayer") working_layer.setColorSpace(original.colorModel(), original.colorSpace(), original.profile()) working_layer.writeBytes( original.readBytes(0, 0, image.width(), image.height()), 0, 0, image.width(), image.height()) # XXX: Unimplemented: original.parentNode().addChildNode(working_layer, original) image.setActiveNode(working_layer) colors_layer = None # if keeping colors if (self.cmbMode.currentIndex() == 1 or self.cmbMode.currentIndex() == 3): # XXX: Unimplemented: colors_layer = working_layer.duplicate() colors_layer.setName("colors") # XXX: Unimplemented: original.parentNode().addChildNode(working_layer, colors_layer) # if greyscale, desature if (self.cmbMode.currentIndex() == 2 or self.cmbMode.currentIndex() == 3): filter = Application.filter("desaturate") filter.apply(working_layer, 0, 0, image.width(), image.height()) # Duplicate on top and blur blur_layer = working_layer.duplicate() blur_layer.setName("blur") # XXX: Unimplemented: original.parentNode().addChildNode(blur_layer, working_layer) # blur filter = Application.filter("gaussian blur") filter_configuration = filter.configuration() filter_configuration.setProperty("horizRadius", self.intRadius.value()) filter_configuration.setProperty("vertRadius", self.intRadius.value()) filter_configuration.setProperty("lockAspect", True) filter.setConfiguration(filter_configuration) filter.apply(blur_layer, 0, 0, image.width(), image.height()) if self.cmbMode.currentIndex() <= 3: blur_layer.setBlendingMode("grain_extract") working_layer = image.mergeDown(blur_layer) # if preserve chroma, change set the mode to value and # merge down with the layer we kept earlier. if self.cmbMode.currentIndex() == 3: working_layer.setBlendingMode("value") working_layer = image.mergeDown(working_layer) # if preserve DC, change set the mode to overlay and merge # down with the average color of the layer we kept # earlier. if self.cmbMode.currentIndex() == 1: # get the average color of the entire image # clear the colors layer to the given color working_layer = image.mergeDown(working_layer) else: # Mode == 4, RedRobes image.setActiveNode(blur_layer)
class PreferencesPanel(QDialog): def __init__(self, parent, app): # The flags we pass are that so we don't get the "What's this" button in the title bar QDialog.__init__(self, parent, Qt.WindowTitleHint | Qt.WindowSystemMenuHint) self.app = app self._setupUi() self.dateFormatEdit.editingFinished.connect(self.dateFormatEdited) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) def _setupUi(self): self.setWindowTitle(tr("Preferences")) self.resize(332, 170) self.verticalLayout = QVBoxLayout(self) self.formLayout = QFormLayout() self.autoSaveIntervalSpinBox = QSpinBox(self) self.autoSaveIntervalSpinBox.setMaximumSize(QSize(70, 0xffffff)) self.label_5 = QLabel(tr("step(s) (0 for none)"), self) self.formLayout.addRow( tr("Auto-save interval:"), horizontalWrap([self.autoSaveIntervalSpinBox, self.label_5]) ) self.dateFormatEdit = QLineEdit(self) self.dateFormatEdit.setMaximumSize(QSize(140, 0xffffff)) self.formLayout.addRow(tr("Date format:"), self.dateFormatEdit) self.fontSizeSpinBox = QSpinBox() self.fontSizeSpinBox.setMinimum(5) self.fontSizeSpinBox.setMaximumSize(QSize(70, 0xffffff)) self.formLayout.addRow(tr("Font size:"), self.fontSizeSpinBox) self.verticalLayout.addLayout(self.formLayout) self.scopeDialogCheckBox = QCheckBox(tr("Show scope dialog when modifying a scheduled transaction"), self) self.verticalLayout.addWidget(self.scopeDialogCheckBox) self.autoDecimalPlaceCheckBox = QCheckBox(tr("Automatically place decimals when typing"), self) self.verticalLayout.addWidget(self.autoDecimalPlaceCheckBox) self.dateEntryBox = QCheckBox(tr("Enter dates in day → month → year order"), self) self.verticalLayout.addWidget(self.dateEntryBox) self.verticalLayout.addItem(verticalSpacer()) self.buttonBox = QDialogButtonBox(self) self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel|QDialogButtonBox.Ok) self.verticalLayout.addWidget(self.buttonBox) def load(self): appm = self.app.model self.autoSaveIntervalSpinBox.setValue(appm.autosave_interval) self.dateFormatEdit.setText(self.app.prefs.dateFormat) self.fontSizeSpinBox.setValue(self.app.prefs.tableFontSize) self.scopeDialogCheckBox.setChecked(appm.show_schedule_scope_dialog) self.autoDecimalPlaceCheckBox.setChecked(appm.auto_decimal_place) self.dateEntryBox.setChecked(appm.day_first_date_entry) def save(self): restartRequired = False appm = self.app.model appm.autosave_interval = self.autoSaveIntervalSpinBox.value() if self.dateFormatEdit.text() != self.app.prefs.dateFormat: restartRequired = True self.app.prefs.dateFormat = self.dateFormatEdit.text() self.app.prefs.tableFontSize = self.fontSizeSpinBox.value() appm.show_schedule_scope_dialog = self.scopeDialogCheckBox.isChecked() appm.auto_decimal_place = self.autoDecimalPlaceCheckBox.isChecked() appm.day_first_date_entry = self.dateEntryBox.isChecked() if restartRequired: QMessageBox.information(self, "", tr("moneyGuru has to restart for these changes to take effect")) # --- Signals def dateFormatEdited(self): self.dateFormatEdit.setText(clean_format(self.dateFormatEdit.text()))
class BudgetPanel(Panel): FIELDS = [ ('startDateEdit', 'start_date'), ('repeatEverySpinBox', 'repeat_every'), ('stopDateEdit', 'stop_date'), ('amountEdit', 'amount'), ('notesEdit', 'notes'), ] PERSISTENT_NAME = 'budgetPanel' def __init__(self, model, mainwindow): Panel.__init__(self, mainwindow) self.setAttribute(Qt.WA_DeleteOnClose) self._setupUi() self.model = model self.repeatTypeComboBox = ComboboxModel(model=self.model.repeat_type_list, view=self.repeatTypeComboBoxView) self.accountComboBox = ComboboxModel(model=self.model.account_list, view=self.accountComboBoxView) self.targetComboBox = ComboboxModel(model=self.model.target_list, view=self.targetComboBoxView) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) def _setupUi(self): self.setWindowTitle(tr("Budget Info")) self.resize(230, 369) self.setModal(True) self.verticalLayout = QVBoxLayout(self) self.formLayout = QFormLayout() self.formLayout.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow) self.label_2 = QLabel(tr("Start Date:")) self.formLayout.setWidget(0, QFormLayout.LabelRole, self.label_2) self.startDateEdit = DateEdit(self) self.startDateEdit.setMaximumSize(QSize(120, 16777215)) self.formLayout.setWidget(0, QFormLayout.FieldRole, self.startDateEdit) self.label_7 = QLabel(tr("Repeat Type:")) self.formLayout.setWidget(1, QFormLayout.LabelRole, self.label_7) self.repeatTypeComboBoxView = QComboBox(self) self.formLayout.setWidget(1, QFormLayout.FieldRole, self.repeatTypeComboBoxView) self.label_8 = QLabel(tr("Every:")) self.formLayout.setWidget(2, QFormLayout.LabelRole, self.label_8) self.horizontalLayout_2 = QHBoxLayout() self.repeatEverySpinBox = QSpinBox(self) self.repeatEverySpinBox.setMinimum(1) self.horizontalLayout_2.addWidget(self.repeatEverySpinBox) self.repeatEveryDescLabel = QLabel(self) self.horizontalLayout_2.addWidget(self.repeatEveryDescLabel) self.formLayout.setLayout(2, QFormLayout.FieldRole, self.horizontalLayout_2) self.label_9 = QLabel(tr("Stop Date:")) self.formLayout.setWidget(3, QFormLayout.LabelRole, self.label_9) self.stopDateEdit = DateEdit(self) self.stopDateEdit.setMaximumSize(QSize(120, 16777215)) self.formLayout.setWidget(3, QFormLayout.FieldRole, self.stopDateEdit) self.accountComboBoxView = QComboBox(self) self.formLayout.setWidget(4, QFormLayout.FieldRole, self.accountComboBoxView) self.label_3 = QLabel(tr("Account:")) self.formLayout.setWidget(4, QFormLayout.LabelRole, self.label_3) self.targetComboBoxView = QComboBox(self) self.formLayout.setWidget(5, QFormLayout.FieldRole, self.targetComboBoxView) self.label_4 = QLabel(tr("Target:")) self.formLayout.setWidget(5, QFormLayout.LabelRole, self.label_4) self.amountEdit = QLineEdit(self) self.amountEdit.setMaximumSize(QSize(120, 16777215)) self.formLayout.setWidget(6, QFormLayout.FieldRole, self.amountEdit) self.label_5 = QLabel(tr("Amount:")) self.formLayout.setWidget(6, QFormLayout.LabelRole, self.label_5) self.notesEdit = QPlainTextEdit(tr("Notes:")) self.formLayout.setWidget(7, QFormLayout.FieldRole, self.notesEdit) self.label = QLabel(self) self.formLayout.setWidget(7, QFormLayout.LabelRole, self.label) self.verticalLayout.addLayout(self.formLayout) self.buttonBox = QDialogButtonBox(self) self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel|QDialogButtonBox.Save) self.verticalLayout.addWidget(self.buttonBox) self.label_2.setBuddy(self.startDateEdit) self.label_7.setBuddy(self.repeatTypeComboBoxView) self.label_8.setBuddy(self.repeatEverySpinBox) self.label_9.setBuddy(self.stopDateEdit) self.label_3.setBuddy(self.accountComboBoxView) self.label_4.setBuddy(self.targetComboBoxView) self.label_5.setBuddy(self.amountEdit) #--- model --> view def refresh_repeat_every(self): self.repeatEveryDescLabel.setText(self.model.repeat_every_desc)
class TorrentAddingDialog(QDialog): SELECTION_LABEL_FORMAT = 'Selected {} files ({})' def _traverse_file_tree(self, name: str, node: FileTreeNode, parent: QWidget): item = QTreeWidgetItem(parent) item.setCheckState(0, Qt.Checked) item.setText(0, name) if isinstance(node, FileInfo): item.setText(1, humanize_size(node.length)) item.setIcon(0, file_icon) self._file_items.append((node, item)) return item.setIcon(0, directory_icon) for name, child in node.items(): self._traverse_file_tree(name, child, item) def _get_directory_browse_widget(self): widget = QWidget() hbox = QHBoxLayout(widget) hbox.setContentsMargins(0, 0, 0, 0) self._path_edit = QLineEdit(self._download_dir) self._path_edit.setReadOnly(True) hbox.addWidget(self._path_edit, 3) browse_button = QPushButton('Browse...') browse_button.clicked.connect(self._browse) hbox.addWidget(browse_button, 1) widget.setLayout(hbox) return widget def _browse(self): new_download_dir = QFileDialog.getExistingDirectory(self, 'Select download directory', self._download_dir) if not new_download_dir: return self._download_dir = new_download_dir self._path_edit.setText(new_download_dir) def __init__(self, parent: QWidget, filename: str, torrent_info: TorrentInfo, control_thread: 'ControlManagerThread'): super().__init__(parent) self._torrent_info = torrent_info download_info = torrent_info.download_info self._control_thread = control_thread self._control = control_thread.control vbox = QVBoxLayout(self) self._download_dir = get_directory(self._control.last_download_dir) vbox.addWidget(QLabel('Download directory:')) vbox.addWidget(self._get_directory_browse_widget()) vbox.addWidget(QLabel('Announce URLs:')) url_tree = QTreeWidget() url_tree.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel) url_tree.header().close() vbox.addWidget(url_tree) for i, tier in enumerate(torrent_info.announce_list): tier_item = QTreeWidgetItem(url_tree) tier_item.setText(0, 'Tier {}'.format(i + 1)) for url in tier: url_item = QTreeWidgetItem(tier_item) url_item.setText(0, url) url_tree.expandAll() vbox.addWidget(url_tree, 1) file_tree = QTreeWidget() file_tree.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel) file_tree.setHeaderLabels(('Name', 'Size')) file_tree.header().setSectionResizeMode(0, QHeaderView.ResizeToContents) self._file_items = [] self._traverse_file_tree(download_info.suggested_name, download_info.file_tree, file_tree) file_tree.sortItems(0, Qt.AscendingOrder) file_tree.expandAll() file_tree.itemClicked.connect(self._update_checkboxes) vbox.addWidget(file_tree, 3) self._selection_label = QLabel(TorrentAddingDialog.SELECTION_LABEL_FORMAT.format( len(download_info.files), humanize_size(download_info.total_size))) vbox.addWidget(self._selection_label) self._button_box = QDialogButtonBox(self) self._button_box.setOrientation(Qt.Horizontal) self._button_box.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok) self._button_box.button(QDialogButtonBox.Ok).clicked.connect(self.submit_torrent) self._button_box.button(QDialogButtonBox.Cancel).clicked.connect(self.close) vbox.addWidget(self._button_box) self.setFixedSize(450, 550) self.setWindowTitle('Adding "{}"'.format(filename)) def _set_check_state_to_tree(self, item: QTreeWidgetItem, check_state: Qt.CheckState): for i in range(item.childCount()): child = item.child(i) child.setCheckState(0, check_state) self._set_check_state_to_tree(child, check_state) def _update_checkboxes(self, item: QTreeWidgetItem, column: int): if column != 0: return new_check_state = item.checkState(0) self._set_check_state_to_tree(item, new_check_state) while True: item = item.parent() if item is None: break has_checked_children = False has_partially_checked_children = False has_unchecked_children = False for i in range(item.childCount()): state = item.child(i).checkState(0) if state == Qt.Checked: has_checked_children = True elif state == Qt.PartiallyChecked: has_partially_checked_children = True else: has_unchecked_children = True if not has_partially_checked_children and not has_unchecked_children: new_state = Qt.Checked elif has_checked_children or has_partially_checked_children: new_state = Qt.PartiallyChecked else: new_state = Qt.Unchecked item.setCheckState(0, new_state) self._update_selection_label() def _update_selection_label(self): selected_file_count = 0 selected_size = 0 for node, item in self._file_items: if item.checkState(0) == Qt.Checked: selected_file_count += 1 selected_size += node.length ok_button = self._button_box.button(QDialogButtonBox.Ok) if not selected_file_count: ok_button.setEnabled(False) self._selection_label.setText('Nothing to download') else: ok_button.setEnabled(True) self._selection_label.setText(TorrentAddingDialog.SELECTION_LABEL_FORMAT.format( selected_file_count, humanize_size(selected_size))) def submit_torrent(self): self._torrent_info.download_dir = self._download_dir self._control.last_download_dir = os.path.abspath(self._download_dir) file_paths = [] for node, item in self._file_items: if item.checkState(0) == Qt.Checked: file_paths.append(node.path) if not self._torrent_info.download_info.single_file_mode: self._torrent_info.download_info.select_files(file_paths, 'whitelist') self._control_thread.loop.call_soon_threadsafe(self._control.add, self._torrent_info) self.close()
class MassEditionPanel(Panel): FIELDS = [ ('dateCheckBox', 'date_enabled'), ('descriptionCheckBox', 'description_enabled'), ('payeeCheckBox', 'payee_enabled'), ('checknoCheckBox', 'checkno_enabled'), ('fromCheckBox', 'from_enabled'), ('toCheckBox', 'to_enabled'), ('amountCheckBox', 'amount_enabled'), ('currencyCheckBox', 'currency_enabled'), ] PERSISTENT_NAME = 'massEditionPanel' def __init__(self, model, mainwindow): Panel.__init__(self, mainwindow) self.setAttribute(Qt.WA_DeleteOnClose) self.mainwindow = mainwindow self.model = model self._setupUi() self.dateEdit = TextField(model=self.model.date_field, view=self.dateEditView) self.descriptionEdit = TextField(model=self.model.description_field, view=self.descriptionEditView) self.payeeEdit = TextField(model=self.model.payee_field, view=self.payeeEditView) self.checknoEdit = TextField(model=self.model.checkno_field, view=self.checknoEditView) self.fromEdit = TextField(model=self.model.from_field, view=self.fromEditView) self.toEdit = TextField(model=self.model.to_field, view=self.toEditView) self.amountEdit = TextField(model=self.model.amount_field, view=self.amountEditView) self.currencyComboBox = ComboboxModel(model=self.model.currency_list, view=self.currencyComboBoxView) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) def _setupUi(self): self.resize(314, 267) self.setModal(True) self.verticalLayout = QVBoxLayout(self) self.formLayout = QFormLayout() self.formLayout.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow) self.label = QLabel(tr("Date:"), self) self.formLayout.setWidget(0, QFormLayout.LabelRole, self.label) self.horizontalLayout = QHBoxLayout() self.dateCheckBox = QCheckBox(self) self.horizontalLayout.addWidget(self.dateCheckBox) self.dateEditView = DateEdit(self) self.horizontalLayout.addWidget(self.dateEditView) self.formLayout.setLayout(0, QFormLayout.FieldRole, self.horizontalLayout) self.label_2 = QLabel(tr("Description:"), self) self.formLayout.setWidget(1, QFormLayout.LabelRole, self.label_2) self.horizontalLayout_2 = QHBoxLayout() self.descriptionCheckBox = QCheckBox(self) self.horizontalLayout_2.addWidget(self.descriptionCheckBox) self.descriptionEditView = DescriptionEdit(self.model.completable_edit, self) self.horizontalLayout_2.addWidget(self.descriptionEditView) self.formLayout.setLayout(1, QFormLayout.FieldRole, self.horizontalLayout_2) self.label_3 = QLabel(tr("Payee:"), self) self.formLayout.setWidget(2, QFormLayout.LabelRole, self.label_3) self.horizontalLayout_3 = QHBoxLayout() self.payeeCheckBox = QCheckBox(self) self.horizontalLayout_3.addWidget(self.payeeCheckBox) self.payeeEditView = PayeeEdit(self.model.completable_edit, self) self.horizontalLayout_3.addWidget(self.payeeEditView) self.formLayout.setLayout(2, QFormLayout.FieldRole, self.horizontalLayout_3) self.label_4 = QLabel(tr("Check #"), self) self.formLayout.setWidget(3, QFormLayout.LabelRole, self.label_4) self.horizontalLayout_4 = QHBoxLayout() self.checknoCheckBox = QCheckBox(self) self.horizontalLayout_4.addWidget(self.checknoCheckBox) self.checknoEditView = QLineEdit(self) self.horizontalLayout_4.addWidget(self.checknoEditView) self.formLayout.setLayout(3, QFormLayout.FieldRole, self.horizontalLayout_4) self.label_5 = QLabel(tr("From:"), self) self.formLayout.setWidget(4, QFormLayout.LabelRole, self.label_5) self.horizontalLayout_5 = QHBoxLayout() self.fromCheckBox = QCheckBox(self) self.horizontalLayout_5.addWidget(self.fromCheckBox) self.fromEditView = AccountEdit(self.model.completable_edit, self) self.horizontalLayout_5.addWidget(self.fromEditView) self.formLayout.setLayout(4, QFormLayout.FieldRole, self.horizontalLayout_5) self.label_6 = QLabel(tr("To:"), self) self.formLayout.setWidget(5, QFormLayout.LabelRole, self.label_6) self.horizontalLayout_6 = QHBoxLayout() self.toCheckBox = QCheckBox(self) self.horizontalLayout_6.addWidget(self.toCheckBox) self.toEditView = AccountEdit(self.model.completable_edit, self) self.horizontalLayout_6.addWidget(self.toEditView) self.formLayout.setLayout(5, QFormLayout.FieldRole, self.horizontalLayout_6) self.label_7 = QLabel(tr("Amount:"), self) self.formLayout.setWidget(6, QFormLayout.LabelRole, self.label_7) self.horizontalLayout_7 = QHBoxLayout() self.amountCheckBox = QCheckBox(self) self.horizontalLayout_7.addWidget(self.amountCheckBox) self.amountEditView = QLineEdit(self) self.horizontalLayout_7.addWidget(self.amountEditView) self.formLayout.setLayout(6, QFormLayout.FieldRole, self.horizontalLayout_7) self.label_8 = QLabel(tr("Currency:"), self) self.formLayout.setWidget(7, QFormLayout.LabelRole, self.label_8) self.horizontalLayout_8 = QHBoxLayout() self.currencyCheckBox = QCheckBox(self) self.horizontalLayout_8.addWidget(self.currencyCheckBox) self.currencyComboBoxView = QComboBox(self) self.currencyComboBoxView.setEditable(True) self.horizontalLayout_8.addWidget(self.currencyComboBoxView) self.formLayout.setLayout(7, QFormLayout.FieldRole, self.horizontalLayout_8) self.verticalLayout.addLayout(self.formLayout) self.buttonBox = QDialogButtonBox(self) self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel|QDialogButtonBox.Save) self.verticalLayout.addWidget(self.buttonBox) self.label.setBuddy(self.dateEditView) self.label_2.setBuddy(self.descriptionEditView) self.label_3.setBuddy(self.payeeEditView) self.label_4.setBuddy(self.checknoEditView) self.label_5.setBuddy(self.fromEditView) self.label_6.setBuddy(self.toEditView) self.label_7.setBuddy(self.amountEditView) self.label_8.setBuddy(self.currencyComboBoxView) def _loadFields(self): Panel._loadFields(self) disableableWidgets = [self.fromCheckBox, self.fromEdit, self.toCheckBox, self.toEdit] for widget in disableableWidgets: self.fromCheckBox.setEnabled(self.model.can_change_accounts) disableableWidgets = [self.amountCheckBox, self.amountEdit] for widget in disableableWidgets: self.fromCheckBox.setEnabled(self.model.can_change_amount) # --- model --> view def refresh(self): # We have to refresh the checkboxes' state. self._loadFields()
class MeteoSettings(QDialog): applied_signal = pyqtSignal() def __init__(self, accurate_url, appid, parent=None): super(MeteoSettings, self).__init__(parent) self.layout = QVBoxLayout() self.accurate_url = accurate_url self.appid = appid self.settings = QSettings() self.set_city = self.settings.value("City") or "?" locale = QLocale.system().name() locale_long = ["pt_BR", "zh_CN", "zh_TW"] if locale not in locale_long: locale = locale[:2] self.interval_set = self.settings.value("Interval") or "30" self.temp_tray_color = self.settings.value("TrayColor") or "" # -----Cities comboBox------------------------ self.first = True self.clear_combo = False self.city_list_before = [] self.citylist = [] self.city_combo = QComboBox() if self.set_city != "?": self.add_cities_incombo() self.city_combo.currentIndexChanged.connect(self.city_default) self.city_title = QLabel(self.tr("City")) self.city_button = QPushButton() self.city_button.setIcon(QIcon(":/configure")) self.city_button.setToolTip(self.tr("Click to edit the cities list")) self.city_button.clicked.connect(self.edit_cities_list) # ------Language------------------------------ self.language_label = QLabel(self.tr("Language")) self.language_combo = QComboBox() self.language_combo.setToolTip( QCoreApplication.translate( "Tooltip", "The application has to be restared to apply the language setting", "Settings dialogue" ) ) self.language_dico = { "bg": self.tr("Bulgarian"), "ca": self.tr("Catalan"), "cs": self.tr("Czech"), "da": self.tr("Danish"), "de": self.tr("German"), "el": self.tr("Greek"), "en": self.tr("English"), "es": self.tr("Spanish"), "fi": self.tr("Finnish"), "fr": self.tr("French"), "he": self.tr("Hebrew"), "hr": self.tr("Croatian"), "hu": self.tr("Hungarian"), "it": self.tr("Italian"), "ja": self.tr("Japanese"), "lt": self.tr("Lithuanian"), "nb": self.tr("Norwegian (Bokmaal)"), "nl": self.tr("Dutch"), "pl": self.tr("Polish"), "pt": self.tr("Portuguese"), "pt_BR": self.tr("Brazil Portuguese"), "ro": self.tr("Romanian"), "ru": self.tr("Russian"), "sk": self.tr("Slovak"), "sv": self.tr("Swedish"), "tr": self.tr("Turkish"), "uk": self.tr("Ukrainian"), "zh_TW": self.tr("Chinese Traditional"), "zh_CN": self.tr("Chinese Simplified"), } lang_list = sorted(self.language_dico.values()) # English as fallback language if locale not in self.language_dico: locale = "en" self.setLanguage = self.settings.value("Language") or locale self.language_combo.addItems(lang_list) self.language_combo.setCurrentIndex(self.language_combo.findText(self.language_dico[self.setLanguage])) self.language_combo.currentIndexChanged.connect(self.language) self.lang_changed = False # Unit system self.units_changed = False self.temp_unit = self.settings.value("Unit") if self.temp_unit is None or self.temp_unit == "": self.temp_unit = "metric" self.units_changed = True self.units_label = QLabel(self.tr("Temperature unit")) self.units_combo = QComboBox() self.units_dico = {"metric": "°C", "imperial": "°F", " ": "°K"} units_list = sorted(self.units_dico.values()) self.units_combo.addItems(units_list) self.units_combo.setCurrentIndex(self.units_combo.findText(self.units_dico[self.temp_unit])) self.units_combo.currentIndexChanged.connect(self.units) # Decimal in trayicon self.temp_decimal_label = QLabel( QCoreApplication.translate( "If the temperature will be shown with a decimal or rounded in tray icon", "Temperature accuracy in system tray", "Settings dialogue", ) ) self.temp_decimal_combo = QComboBox() temp_decimal_combo_dico = {"False": "0°", "True": "0.1°"} temp_decimal_combo_list = [temp_decimal_combo_dico["False"], temp_decimal_combo_dico["True"]] self.temp_decimal_combo.addItems(temp_decimal_combo_list) temp_decimal_bool_str = self.settings.value("Decimal") or "False" self.temp_decimal_combo.setCurrentIndex( self.temp_decimal_combo.findText(temp_decimal_combo_dico[temp_decimal_bool_str]) ) self.temp_decimal_combo.currentIndexChanged.connect(self.temp_decimal) self.temp_decimal_changed = False # Interval of updates self.interval_label = QLabel(self.tr("Update interval")) self.interval_min = QLabel(self.tr("minutes")) self.interval_combo = QComboBox() self.interval_list = ["15", "30", "45", "60", "90", "120"] self.interval_combo.addItems(self.interval_list) self.interval_combo.setCurrentIndex( self.interval_combo.findText(self.interval_list[self.interval_list.index(self.interval_set)]) ) self.interval_combo.currentIndexChanged.connect(self.interval) self.interval_changed = False # OK Cancel Apply Buttons self.buttonLayout = QHBoxLayout() self.buttonLayout.addStretch() self.buttonBox = QDialogButtonBox() self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Apply | QDialogButtonBox.Cancel) self.buttonBox.setContentsMargins(0, 30, 0, 0) self.buttonLayout.addWidget(self.buttonBox) self.buttonBox.button(QDialogButtonBox.Apply).clicked.connect(self.apply_settings) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(False) # Autostart self.autostart_label = QLabel(self.tr("Launch at startup")) self.autostart_checkbox = QCheckBox() autostart_bool = self.settings.value("Autostart") or "False" autostart_bool = eval(autostart_bool) self.autostart_checkbox.setChecked(autostart_bool) self.autostart_checkbox.stateChanged.connect(self.autostart) self.autostart_changed = False # Tray temp° color self.temp_colorLabel = QLabel(self.tr("Font colour in the tray")) self.temp_colorButton = QPushButton() self.temp_colorButton.setStyleSheet("QWidget {{ background-color: {0} }}".format(self.temp_tray_color)) self.temp_colorButton.setMaximumSize(QSize(44, 24)) self.temp_colorButton.clicked.connect(self.color_chooser) self.temp_color_resetButton = QPushButton(self.tr("Reset")) self.temp_color_resetButton.setToolTip(self.tr("Reset font colour to system default")) self.temp_color_resetButton.clicked.connect(self.color_reset) # Display notifications self.notifier_label = QLabel(self.tr("Notification on weather update")) self.notifier_checkbox = QCheckBox() notifier_bool = self.settings.value("Notifications") or "True" notifier_bool = eval(notifier_bool) self.notifier_checkbox.setChecked(notifier_bool) self.notifier_checkbox.stateChanged.connect(self.notifier) self.notifier_changed = False # Icon & Temp self.tray_icon_temp_label = QLabel( QCoreApplication.translate( "Settings dialogue", "System tray icon", """Setting to choose the type of the icon on the tray (only icon, only text, icon&text""", ) ) self.tray_icon_combo = QComboBox() tray_icon_temp = QCoreApplication.translate( "Settings dialogue", "Icon & temperature", "Setting to choose the type of the icon on the tray" ) tray_icon = QCoreApplication.translate( "Settings dialogue", "Icon", "Setting to choose the type of the icon on the tray" ) tray_temp = QCoreApplication.translate( "Settings dialogue", "Temperature", "Setting to choose the type of the icon on the tray" ) self.tray_dico = {"icon&temp": tray_icon_temp, "icon": tray_icon, "temp": tray_temp} set_tray_icon = self.settings.value("TrayType") or "icon&temp" tray_icon_list = sorted(self.tray_dico.values()) self.tray_icon_combo.addItems(tray_icon_list) self.tray_icon_combo.setCurrentIndex(self.tray_icon_combo.findText(self.tray_dico[set_tray_icon])) self.tray_icon_combo.currentIndexChanged.connect(self.tray) self.tray_changed = False # Font size fontsize = self.settings.value("FontSize") or "18" self.fontsize_label = QLabel( QCoreApplication.translate( "Settings dialog", "Font size in tray", "Setting for the font size of the temperature in the tray icon" ) ) self.fontsize_spinbox = QSpinBox() self.fontsize_spinbox.setRange(12, 32) self.fontsize_spinbox.setValue(int(fontsize)) if fontsize is None or fontsize == "": self.settings.setValue("FontSize", "18") self.fontsize_changed = False self.fontsize_spinbox.valueChanged.connect(self.fontsize_change) # Proxy self.proxy_label = QLabel(QCoreApplication.translate("Checkbox", "Connection by proxy", "Settings dialogue")) self.proxy_chbox = QCheckBox() proxy_bool = self.settings.value("Proxy") or "False" self.proxy_bool = eval(proxy_bool) self.proxy_chbox.setChecked(self.proxy_bool) self.proxy_chbox.stateChanged.connect(self.proxy) self.proxy_changed = False self.proxy_button = QPushButton( QCoreApplication.translate("Label of button to open the proxy dialogue", "Settings", "Settings dialogue") ) self.proxy_button.clicked.connect(self.proxy_settings) self.proxy_button.setEnabled(self.proxy_bool) # Openweathermap key self.owmkey_label = QLabel( QCoreApplication.translate( "The key that user can generate in his OpenWeatherMap profile", "OpenWeatherMap key", "Settings dialogue", ) ) self.owmkey_create = QLabel( QCoreApplication.translate( "Link to create a profile in OpenWeatherMap", '<a href="http://home.openweathermap.org/users/sign_up">Create key</a>', "Settings dialogue", ) ) self.owmkey_create.setOpenExternalLinks(True) apikey = self.settings.value("APPID") or "" self.owmkey_text = QLineEdit() self.owmkey_text.setText(apikey) self.owmkey_text.textChanged.connect(self.apikey_changed) # ---------- self.panel = QGridLayout() self.panel.addWidget(self.city_title, 0, 0) self.panel.addWidget(self.city_combo, 0, 1) self.panel.addWidget(self.city_button, 0, 2) self.panel.addWidget(self.language_label, 1, 0) self.panel.addWidget(self.language_combo, 1, 1) self.panel.addWidget(self.units_label, 2, 0) self.panel.addWidget(self.units_combo, 2, 1) self.panel.addWidget(self.temp_decimal_label, 3, 0) self.panel.addWidget(self.temp_decimal_combo, 3, 1) self.panel.addWidget(self.interval_label, 4, 0) self.panel.addWidget(self.interval_combo, 4, 1) self.panel.addWidget(self.interval_min, 4, 2) self.panel.addWidget(self.autostart_label, 5, 0) self.panel.addWidget(self.autostart_checkbox, 5, 1) self.panel.addWidget(self.temp_colorLabel, 6, 0) self.panel.addWidget(self.temp_colorButton, 6, 1) self.panel.addWidget(self.temp_color_resetButton, 6, 2) self.panel.addWidget(self.notifier_label, 7, 0) self.panel.addWidget(self.notifier_checkbox, 7, 1) self.panel.addWidget(self.tray_icon_temp_label, 8, 0) self.panel.addWidget(self.tray_icon_combo, 8, 1) self.panel.addWidget(self.fontsize_label, 9, 0) self.panel.addWidget(self.fontsize_spinbox, 9, 1) self.panel.addWidget(self.proxy_label, 10, 0) self.panel.addWidget(self.proxy_chbox, 10, 1) self.panel.addWidget(self.proxy_button, 10, 2) self.panel.addWidget(self.owmkey_label, 11, 0) self.panel.addWidget(self.owmkey_text, 11, 1) self.panel.addWidget(self.owmkey_create, 11, 2) self.layout.addLayout(self.panel) self.layout.addLayout(self.buttonLayout) self.statusbar = QLabel() self.layout.addWidget(self.statusbar) self.nokey_message = QCoreApplication.translate( "Warning message after pressing Ok", "Please enter your OpenWeatherMap key", "Settings dialogue" ) self.nocity_message = QCoreApplication.translate( "Warning message after pressing OK", "Please add a city", "Settings dialogue" ) self.setLayout(self.layout) self.setWindowTitle(self.tr("Meteo-qt Configuration")) def units(self): self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(True) self.units_changed = True def language(self): self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(True) self.lang_changed = True def city_default(self): allitems = [self.city_combo.itemText(i) for i in range(self.city_combo.count())] city_name = self.city_combo.currentText() citytosave = city_name.split("_") if len(citytosave) < 3: return self.id_before = citytosave[2] self.city_before = citytosave[0] self.country_before = citytosave[1] self.city_list_before = allitems[:] self.city_list_before.pop(self.city_list_before.index(city_name)) self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(True) def interval(self): self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(True) self.interval_changed = True def edit_cities_list(self): apikey = self.owmkey_text.text() apiid = "&APPID=" + apikey if apikey == "": self.statusbar.setText(self.nokey_message) return dialog = citylistdlg.CityListDlg(self.citylist, self.accurate_url, apiid, self) dialog.citieslist_signal.connect(self.cities_list) dialog.exec_() def cities_list(self, cit_list): if len(cit_list) > 0: citytosave = cit_list[0].split("_") self.id_before = citytosave[2] self.city_before = citytosave[0] self.country_before = citytosave[1] if len(cit_list) > 1: self.city_list_before = cit_list[1:] else: self.city_list_before = str("") else: self.id_before = "" self.city_before = "" self.country_before = "" self.city_list_before = [] self.clear_combo = True self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(True) self.first = False self.add_cities_incombo() def autostart(self, state): self.autostart_state = state self.autostart_changed = True self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(True) def autostart_apply(self): dir_auto = "/.config/autostart/" d_file = "meteo-qt.desktop" home = os.getenv("HOME") total_path = home + dir_auto + d_file if self.autostart_state == 2: desktop_file = [ "[Desktop Entry]\n", "Exec=meteo-qt\n", "Name=meteo-qt\n", "Type=Application\n", "Version=1.0\n", "X-LXQt-Need-Tray=true\n", ] if not os.path.exists(home + dir_auto): os.system("mkdir -p {}".format(os.path.dirname(total_path))) with open(total_path, "w") as out_file: out_file.writelines(desktop_file) self.settings.setValue("Autostart", "True") logging.debug("Write desktop file in ~/.config/autostart") elif self.autostart_state == 0: if os.path.exists(total_path): os.remove(total_path) self.settings.setValue("Autostart", "False") logging.debug("Remove desktop file from ~/.config/autostart") else: return def color_chooser(self): col = QColorDialog.getColor() if col.isValid(): self.temp_colorButton.setStyleSheet("QWidget {{ background-color: {0} }}".format(col.name())) # focus to next elem to show immediatley the colour # in the button (in some DEs) self.temp_color_resetButton.setFocus() self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(True) self.color_before = col.name() else: logging.debug("Invalid color:" + str(col)) def color_reset(self): self.temp_colorButton.setStyleSheet("QWidget { background-color: }") self.color_before = "" self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(True) def notifier(self, state): self.notifier_state = state self.notifier_changed = True self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(True) def notifier_apply(self): if self.notifier_state == 2: self.settings.setValue("Notifications", "True") logging.debug("Write: Notifications = True") elif self.notifier_state == 0: self.settings.setValue("Notifications", "False") logging.debug("Write: Notifications = False") def temp_decimal(self, state): self.temp_decimal_state = state self.temp_decimal_changed = True self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(True) def tray(self): self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(True) self.tray_changed = True def tray_apply(self): tray = self.tray_icon_combo.currentText() self.settings.setValue("Tray", tray) logging.debug("Write >" + "Tray >" + str(tray)) settray = [key for key, value in self.tray_dico.items() if value == tray] self.settings.setValue("TrayType", settray[0]) def fontsize_change(self, size): self.fontsize_changed = True self.fontsize_value = size self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(True) def fontsize_apply(self): logging.debug("Apply fontsize: " + str(self.fontsize_value)) self.settings.setValue("FontSize", str(self.fontsize_value)) def proxy(self, state): self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(True) if state == 2: self.proxy_bool = True self.proxy_button.setEnabled(True) else: self.proxy_bool = False self.proxy_button.setEnabled(False) def proxy_settings(self): dialog = proxydlg.Proxy(self) dialog.exec_() def apikey_changed(self): self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(True) def apply_settings(self): self.accepted() def accepted(self): apikey = self.owmkey_text.text() city_name = self.city_combo.currentText() if apikey == "": self.statusbar.setText(self.nokey_message) return else: self.statusbar.setText("") self.settings.setValue("APPID", str(self.owmkey_text.text())) if city_name == "": self.statusbar.setText(self.nocity_message) return else: self.statusbar.setText("") self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(False) if hasattr(self, "id_before"): self.settings.setValue("ID", self.id_before) logging.debug("write " + "ID" + str(self.id_before)) if hasattr(self, "city_before"): self.settings.setValue("City", self.city_before) logging.debug("write " + "City" + str(self.city_before)) if hasattr(self, "country_before"): self.settings.setValue("Country", self.country_before) logging.debug("write " + "Country" + str(self.country_before)) if hasattr(self, "city_list_before"): self.settings.setValue("CityList", str(self.city_list_before)) logging.debug("write " + "CityList" + str(self.city_list_before)) if hasattr(self, "color_before"): self.settings.setValue("TrayColor", self.color_before) if self.color_before == "": self.color_before = "None" logging.debug("Write font color for temp in tray: {0}".format(self.color_before)) if self.autostart_changed: self.autostart_apply() if self.interval_changed: time = self.interval_combo.currentText() self.settings.setValue("Interval", time) logging.debug("Write " + "Interval " + str(time)) if self.lang_changed: lang = self.language_combo.currentText() setlang = [key for key, value in self.language_dico.items() if value == lang] self.settings.setValue("Language", setlang[0]) logging.debug("Write " + "Language " + str(setlang[0])) if self.units_changed: unit = self.units_combo.currentText() setUnit = [key for key, value in self.units_dico.items() if value == unit] self.settings.setValue("Unit", setUnit[0]) logging.debug("Write " + "Unit " + str(setUnit[0])) if self.temp_decimal_changed: decimal = self.temp_decimal_combo.currentText() decimal_bool_str = "False" if decimal == "0.1°": decimal_bool_str = "True" self.settings.setValue("Decimal", decimal_bool_str) logging.debug("Write: Decimal in tray icon = " + decimal_bool_str) if self.notifier_changed: self.notifier_apply() if self.tray_changed: self.tray_apply() if self.fontsize_changed: self.fontsize_apply() proxy_url = self.settings.value("Proxy_url") or "" if proxy_url == "": self.proxy_bool = False self.settings.setValue("Proxy", str(self.proxy_bool)) self.applied_signal.emit() def accept(self): self.accepted() apikey = self.owmkey_text.text() city_name = self.city_combo.currentText() if apikey == "": self.statusbar.setText(self.nokey_message) return if city_name == "": self.statusbar.setText(self.nocity_message) return QDialog.accept(self) def add_cities_incombo(self): list_cities = "" self.city_combo.clear() if self.clear_combo: return if self.first: list_cities = self.settings.value("CityList") if list_cities is not None: self.city_list_before = list_cities[:] self.citylist = [self.set_city + "_" + self.settings.value("Country") + "_" + self.settings.value("ID")] else: self.citylist = [self.city_before + "_" + self.country_before + "_" + self.id_before] list_cities = self.city_list_before[:] if list_cities is None: list_cities = [] if list_cities != "" and list_cities is not None: if type(list_cities) is str: list_cities = eval(list_cities) self.citylist = self.citylist + list_cities duplicate = [] for i in self.citylist: if i not in duplicate: duplicate.append(i) self.citylist = duplicate[:] self.city_combo.addItems(self.citylist) if len(list_cities) > 0: maxi = len(max(list_cities, key=len)) self.city_combo.setMinimumSize(maxi * 8, 23)
def initUI(self): self.setWindowTitle("设置") logo = QLabel() # logo logo.setPixmap(QPixmap("./src/logo2.gif")) logo.setStyleSheet("background-color:rgb(255,255,255);") logo.setAlignment(Qt.AlignCenter) self.download_threads_lb = QLabel("同时下载文件数") # about self.download_threads_var = QLineEdit() self.download_threads_var.setPlaceholderText("范围:1-9") self.download_threads_var.setToolTip("范围:1-9") self.download_threads_var.setInputMask("D") self.max_size_lb = QLabel("分卷大小(MB)") self.max_size_var = QLineEdit() self.max_size_var.setPlaceholderText("普通用户最大100,vip用户根据具体情况设置") self.max_size_var.setToolTip("普通用户最大100,vip用户根据具体情况设置") self.max_size_var.setInputMask("D99") self.timeout_lb = QLabel("请求超时(秒)") self.timeout_var = QLineEdit() self.timeout_var.setPlaceholderText("范围:1-99") self.timeout_var.setToolTip("范围:1-99") self.timeout_var.setInputMask("D9") self.upload_delay_lb = QLabel("上传延时(秒)") self.upload_delay_var = QLineEdit() self.upload_delay_var.setPlaceholderText("范围:1-99") self.upload_delay_var.setToolTip("范围:1-99") self.upload_delay_var.setInputMask("D9") self.dl_path_lb = QLabel("下载保存路径") self.dl_path_var = MyLineEdit(self) self.dl_path_var.clicked.connect(self.set_download_path) self.time_fmt_box = QCheckBox("使用[年-月-日]时间格式") self.to_tray_box = QCheckBox("关闭到系统托盘") self.watch_clipboard_box = QCheckBox("监听系统剪切板") self.debug_box = QCheckBox("开启调试日志") self.set_pwd_box = QCheckBox("上传文件自动设置密码") self.set_pwd_var = AutoResizingTextEdit() self.set_pwd_var.setPlaceholderText(" 2-8 位数字或字母") self.set_pwd_var.setToolTip("2-8 位数字或字母") self.set_desc_box = QCheckBox("上传文件自动设置描述") self.set_desc_var = AutoResizingTextEdit() self.big_file_box = QCheckBox(f"允许上传超过 {self.max_size}MB 的大文件") self.time_fmt_box.toggle() self.time_fmt_box.stateChanged.connect(self.change_time_fmt) self.to_tray_box.stateChanged.connect(self.change_to_tray) self.watch_clipboard_box.stateChanged.connect( self.change_watch_clipboard) self.debug_box.stateChanged.connect(self.change_debug) self.set_pwd_box.stateChanged.connect(self.change_set_pwd) self.set_pwd_var.editingFinished.connect(self.check_pwd) self.set_desc_box.stateChanged.connect(self.change_set_desc) self.big_file_box.stateChanged.connect(self.change_big_file) buttonBox = QDialogButtonBox() buttonBox.setOrientation(Qt.Horizontal) buttonBox.setStandardButtons(QDialogButtonBox.Reset | QDialogButtonBox.Save | QDialogButtonBox.Cancel) buttonBox.button(QDialogButtonBox.Reset).setText("重置") buttonBox.button(QDialogButtonBox.Save).setText("保存") buttonBox.button(QDialogButtonBox.Cancel).setText("取消") buttonBox.button(QDialogButtonBox.Reset).clicked.connect( lambda: self.set_values(reset=True)) buttonBox.button(QDialogButtonBox.Save).clicked.connect(self.slot_save) buttonBox.rejected.connect(self.reject) form = QFormLayout() form.setLabelAlignment(Qt.AlignRight) form.setSpacing(10) form.addRow(self.download_threads_lb, self.download_threads_var) form.addRow(self.timeout_lb, self.timeout_var) form.addRow(self.upload_delay_lb, self.upload_delay_var) form.addRow(self.max_size_lb, self.max_size_var) form.addRow(self.dl_path_lb, self.dl_path_var) vbox = QVBoxLayout() vbox.addWidget(logo) vbox.addStretch(1) vbox.addLayout(form) vbox.addStretch(1) hbox = QHBoxLayout() hbox.addWidget(self.time_fmt_box) hbox.addWidget(self.to_tray_box) hbox.addWidget(self.watch_clipboard_box) hbox.addWidget(self.debug_box) vbox.addLayout(hbox) vbox.addStretch(1) hbox_2 = QHBoxLayout() hbox_2.addWidget(self.set_pwd_box) hbox_2.addWidget(self.set_pwd_var) vbox.addLayout(hbox_2) vbox.addStretch(1) hbox_3 = QHBoxLayout() hbox_3.addWidget(self.set_desc_box) hbox_3.addWidget(self.set_desc_var) vbox.addLayout(hbox_3) vbox.addWidget(self.big_file_box) vbox.addStretch(2) vbox.addWidget(buttonBox) self.setLayout(vbox) self.setMinimumWidth(500)
class DPlayerUI(QWidget): def __init__(self): """Initializes core and ui""" super().__init__() self.playerCore = DPlayerCore() self.player = self.playerCore.player self.playlist = self.playerCore.playlist self.initUI() self.connectSignals() def initUI(self): """Initialize user interface - buttons, sliders, labels, playlist.""" self.grid = QGridLayout() self.initButtons() self.initVolumeSlider() self.initPositionSlider() self.initDurationLabel() self.initPlaylist() self.initSongLabel() self.setLayout(self.grid) self.setGeometry(0, 0, 700, 700) self.setWindowTitle('DPlayer') self.setWindowIcon(QIcon('icons/logo.png')) self.center() self.show() def connectSignals(self): """Connect player signals to functions.""" self.player.durationChanged.connect(self.durationChanged) self.player.positionChanged.connect(self.positionChanged) self.player.stateChanged.connect(self.stateChanged) self.player.currentMediaChanged.connect(self.songChanged) def initButtons(self): """Create, set and connect buttons.""" self.buttons = {} self.buttonNames = ['stop', 'previous', 'play', 'next', 'mute', 'addFiles', 'addFolder', 'shuffle', 'repeatPlaylist', 'repeatSong', 'Save playlist', 'Load playlist', 'Clear playlist', 'Find lyrics', 'Find info', 'Login', 'Logout', 'Love', 'Unlove'] shortcuts = ['q', 'w', 'e', 'r', 't', 'a', 's', 'd', 'f', 'g', 'z', 'x', 'c', 'v', 'b', 'o', 'p', 'k', 'l'] for name, cut in zip(self.buttonNames, shortcuts): button = QPushButton(self) button.setToolTip(name) button.setShortcut(QKeySequence(cut)) self.buttons[name] = button for name in self.buttonNames[:10]: self.buttons[name].setIcon(QIcon('icons/{}.png'.format(name))) self.buttons[name].setIconSize(QSize(20, 20)) for name, position in zip(self.buttonNames[:5], range(5)): self.grid.addWidget(self.buttons[name], 1, position) self.buttons['stop'].clicked.connect(self.stopClicked) self.buttons['previous'].clicked.connect(self.previousClicked) self.previousButtonClicked = False self.buttons['play'].clicked.connect(self.playClicked) self.buttons['play'].setFocus() self.buttons['next'].clicked.connect(self.nextClicked) self.buttons['mute'].clicked.connect(self.muteClicked) self.buttons['mute'].setIcon(QIcon('icons/volumeMiddle.png')) for name, position in zip(self.buttonNames[5:], range(5)): self.grid.addWidget(self.buttons[name], 3, position) self.buttons['addFiles'].clicked.connect(self.addFiles) self.buttons['addFolder'].clicked.connect(self.addFolder) self.buttons['shuffle'].clicked[bool].connect(self.playerCore.shuffle) self.buttons['shuffle'].setCheckable(True) self.buttons['repeatPlaylist'].clicked[bool].connect( self.playerCore.repeatPlaylist) self.buttons['repeatPlaylist'].setCheckable(True) self.buttons['repeatSong'].clicked[bool].connect( self.playerCore.repeatSong) self.buttons['repeatSong'].setCheckable(True) for name, position in zip(self.buttonNames[10:15], range(5)): self.buttons[name].setIcon(QIcon('icons/{}.png'.format(name))) self.buttons[name].setIconSize(QSize(120, 20)) self.grid.addWidget(self.buttons[name], 4, position) self.buttons['Save playlist'].clicked.connect(self.savePlaylist) self.buttons['Load playlist'].clicked.connect(self.loadPlaylist) self.buttons['Clear playlist'].clicked.connect(self.clearPlaylist) self.buttons['Find lyrics'].clicked.connect(self.findLyrics) self.buttons['Find info'].clicked.connect(self.findInfo) self.lastFMbuttons = QDialogButtonBox() self.lastFMbuttons.setOrientation(Qt.Vertical) for name, position in zip(self.buttonNames[15:], range(4)): self.buttons[name].setIcon(QIcon('icons/{}.png'.format(name))) self.buttons[name].setIconSize(QSize(120, 20)) self.lastFMbuttons.addButton(self.buttons[name], QDialogButtonBox.ActionRole) self.grid.addWidget(self.lastFMbuttons, 2, 4, Qt.AlignCenter) # self.userLabel = QLabel('Username:\n') # self.userLabel.setBuddy(self.buttons['Login']) # self.grid.addWidget( # self.userLabel, 2, 4, Qt.AlignTop | Qt.AlignHCenter) self.buttons['Login'].clicked.connect(self.login) self.buttons['Logout'].clicked.connect(self.logout) self.buttons['Love'].clicked.connect(self.love) self.buttons['Unlove'].clicked.connect(self.unlove) def previousClicked(self): """Play previous song.""" self.playerCore.songChanged = True self.previousButtonClicked = True self.playerCore.previous() self.stateChanged() def stopClicked(self): """Stop the player. Set icon to play button.""" self.playerCore.stop() self.buttons['play'].setIcon(QIcon('icons/play.png')) self.buttons['play'].setToolTip('play') self.songLabel.setText('') def playClicked(self): """Play / Pause the player. Set icon to play button.""" if self.player.state() in (QMediaPlayer.StoppedState, QMediaPlayer.PausedState): self.playerCore.play() if self.player.state() == QMediaPlayer.PlayingState: self.buttons['play'].setIcon(QIcon('icons/pause.png')) self.buttons['play'].setToolTip('pause') else: # QMediaPlayer.PlayingState self.playerCore.pause() self.buttons['play'].setIcon(QIcon('icons/play.png')) self.buttons['play'].setToolTip('play') self.songLabel.setText('{} - {}'.format( self.playlistTable.item(self.currentPlaying, 0).text(), self.playlistTable.item(self.currentPlaying, 1).text())) def nextClicked(self): """Play next song.""" self.playerCore.next() self.stateChanged() def muteClicked(self): """Mute / Unmute the player. Set volume slider position.""" if self.playerCore.isMuted(): self.playerCore.unmute() self.volumeChanged(self.currentVolume) else: self.playerCore.mute() self.volumeChanged(0) def addFiles(self): """Choose files (*.mp3) to add to the playlist.""" fileNames, _ = QFileDialog.getOpenFileNames( self, 'Add songs', filter='Music (*.mp3 *.ogg *.flac *wav)') self.playerCore.add(fileNames) self.addClicked(fileNames) def addFolder(self): """Choose folder to add to the playlist.""" directory = QFileDialog.getExistingDirectory(self, 'Add a folder') self.getFromDir(directory) def getFromDir(self, directory): """Extract files from directory and add them to the playlist.""" if not directory: return dirContent = os.listdir(directory) fileNames = [] for file in dirContent: path = '{}/{}'.format(directory, file) if os.path.isfile(path) and \ path[len(path) - 4:] in ['.mp3', '.ogg', 'flac', '.wav']: fileNames.append(path) elif os.path.isdir(path): self.getFromDir(path) self.playerCore.add(fileNames) self.addClicked(fileNames) def addClicked(self, fileNames): """Fill the playlist with fileNames' info.""" if fileNames is None: return self.playlistTable.setSortingEnabled(False) songsToAdd = len(fileNames) for name, row in zip(fileNames, range(songsToAdd)): currentRow = row + self.playlist.mediaCount() - songsToAdd self.playlistTable.insertRow(currentRow) artist = self.playerCore.getArtist(name)[0] title = self.playerCore.getTitle(name)[0] album = self.playerCore.getAlbum(name)[0] seconds = self.playerCore.getDuration(name) duration = QTime(0, seconds // 60, seconds % 60) duration = duration.toString('mm:ss') rowInfo = [artist, title, album, duration] for info, index in zip(rowInfo, range(4)): cell = QTableWidgetItem(info) self.playlistTable.setItem(currentRow, index, cell) font = QFont(info, weight=QFont.Normal) cell.setFont(font) cell.setTextAlignment(Qt.AlignCenter) self.playlistTable.setSortingEnabled(True) for index in range(4): self.playlistTable.resizeColumnToContents(index) def initVolumeSlider(self): """Initialize volume slider.""" self.volumeSlider = QSlider(Qt.Vertical, self) self.volumeSlider.setRange(0, 100) self.currentVolume = 70 self.volumeSlider.setValue(self.currentVolume) self.volumeSlider.setToolTip('volume: {}'.format(self.currentVolume)) self.volumeSlider.valueChanged[int].connect(self.volumeChanged) self.grid.addWidget(self.volumeSlider, 0, 4, Qt.AlignHCenter) self.playerCore.setVolume(self.currentVolume) def volumeChanged(self, value): """Set player's volume to value. Set icon for sound.""" self.playerCore.setVolume(value) if value == 0: self.buttons['mute'].setIcon(QIcon('icons/mute.png')) elif value <= 35: self.buttons['mute'].setIcon(QIcon('icons/volumeMin.png')) elif value <= 70: self.buttons['mute'].setIcon(QIcon('icons/volumeMiddle.png')) else: # value <= 100 self.buttons['mute'].setIcon(QIcon('icons/volumeMax.png')) self.volumeSlider.setValue(value) self.volumeSlider.setToolTip('volume: {}'.format(value)) if self.playerCore.isMuted(): self.buttons['mute'].setToolTip('unmute') else: self.currentVolume = value self.buttons['mute'].setToolTip('mute') def initPositionSlider(self): """Initialize position slider.""" self.positionSlider = QSlider(Qt.Horizontal, self) self.positionSlider.setValue(0) self.positionSlider.valueChanged[int].connect(self.position) self.positionSliderClicked = False self.grid.addWidget(self.positionSlider, 0, 0, 1, 3, Qt.AlignBottom) def initDurationLabel(self): """Initialize duration label.""" self.durationLabel = QLabel('00:00 / 00:00') self.grid.addWidget(self.durationLabel, 0, 3, Qt.AlignBottom) def durationChanged(self, value): """Set the maximum of position slider to value when song is changed.""" self.positionSlider.setMaximum(value) def songChanged(self, _): """Handle UI when song changes.""" if self.doubleClicked or self.playlist.mediaCount() == 0: self.doubleClicked = False return self.lastPlayed = self.currentPlaying self.currentPlaying = self.playlist.currentIndex() if self.currentPlaying >= 0: self.setStyle(self.currentPlaying, QFont.Bold) self.songLabel.setText('{} - {}'.format( self.playlistTable.item(self.currentPlaying, 0).text(), self.playlistTable.item(self.currentPlaying, 1).text())) self.playlistTable.scrollToItem( self.playlistTable.item(self.currentPlaying, 0)) if self.lastPlayed >= 0 and self.lastPlayed != self.currentPlaying: self.setStyle(self.lastPlayed, QFont.Normal) for index in range(4): self.playlistTable.resizeColumnToContents(index) self.previousButtonClicked = False def setStyle(self, row, style): """Set row's font to style.""" for idx in range(4): text = self.playlistTable.item(row, idx).text() font = QFont(text, weight=style) self.playlistTable.item(row, idx).setFont(font) def position(self, value): """Set the position of player at value.""" if not self.positionSliderClicked: self.positionSliderClicked = True self.player.setPosition(value) def positionChanged(self, value): """Update duration label according to value.""" if not self.positionSliderClicked: self.positionSliderClicked = True self.positionSlider.setValue(value) self.positionSliderClicked = False songIndex = self.playlist.currentIndex() if songIndex >= 0: duration = self.playlistTable.item( self.playlist.currentIndex(), 3).text() currentSeconds = value // 1000 currentTime = QTime(0, currentSeconds // 60, currentSeconds % 60) time = '{} / {}'.format( currentTime.toString('mm:ss'), duration) else: time = '00:00 / 00:00' self.durationLabel.setText(time) def stateChanged(self): """Check if stopped to update UI.""" if self.player.state() == QMediaPlayer.StoppedState: self.stopClicked() def initSongLabel(self): """Initialize song label.""" self.songLabel = QLabel() self.songLabel.setAlignment(Qt.AlignCenter) self.font = QFont() self.font.setBold(True) self.font.setItalic(True) self.font.setCapitalization(QFont.AllUppercase) self.font.setPixelSize(20) self.songLabel.setFont(self.font) self.grid.addWidget(self.songLabel, 0, 0, 1, 4, Qt.AlignVCenter) def initPlaylist(self): """Initialize song playlist.""" self.playlistTable = QTableWidget() self.playlistTable.setSelectionBehavior(QAbstractItemView.SelectRows) self.playlistTable.setSelectionMode( QAbstractItemView.ExtendedSelection) self.playlistTable.setSortingEnabled(True) self.playlistTable.setTabKeyNavigation(False) self.playlistTable.setEditTriggers(QAbstractItemView.NoEditTriggers) self.playlistTable.setAlternatingRowColors(True) self.playlistTable.setVerticalScrollMode( QAbstractItemView.ScrollPerPixel) self.playlistTable.setHorizontalScrollMode( QAbstractItemView.ScrollPerPixel) self.playlistTable.itemDoubleClicked.connect(self.doubleClicked) self.doubleClicked = False self.lastPlayed = -1 self.currentPlaying = -1 delete = QShortcut( QKeySequence.Delete, self.playlistTable, self.deleteSongs) delete.setContext(Qt.WidgetShortcut) self.playlistTable.setColumnCount(4) self.playlistTable.setHorizontalHeaderLabels( ['Artist', 'Title', 'Album', 'Duration']) # False - ascending order, True - descending self.descendingOrder = [False] * 4 self.playlistTable.horizontalHeader().sectionClicked.connect( self.toSort) self.windows = [] names = [] for index in range(self.playlist.mediaCount()): names.append(self.playlist.media(index).canonicalUrl().path()) self.addClicked(names) self.grid.addWidget(self.playlistTable, 2, 0, 1, 4) self.grid.setRowStretch(2, 1) def doubleClicked(self, item): """Play song at item's row.""" self.doubleClicked = True self.lastPlayed = self.playlist.currentIndex() if self.lastPlayed >= 0: self.setStyle(self.lastPlayed, QFont.Normal) self.currentPlaying = item.row() self.playerCore.songChanged = True self.playlist.setCurrentIndex(self.currentPlaying) self.setStyle(self.currentPlaying, QFont.Bold) self.stopClicked() self.playClicked() self.songLabel.setText('{} - {}'.format( self.playlistTable.item(self.currentPlaying, 0).text(), self.playlistTable.item(self.currentPlaying, 1).text())) for index in range(4): self.playlistTable.resizeColumnToContents(index) def toSort(self, column): """Sort music by column.""" if self.lastPlayed >= 0: self.setStyle(self.lastPlayed, QFont.Normal) self.playerCore.sort(column, self.descendingOrder[column]) self.descendingOrder[column] = bool(1 - self.descendingOrder[column]) for index in range(4): if index != column: self.descendingOrder[index] = False def deleteSongs(self): """Delete selected songs.""" selectedSongs = self.playlistTable.selectedIndexes() indexes = [index.row() for index in selectedSongs] toBeRemoved = sorted(indexes[::4], reverse=True) currentIndex = self.playlist.currentIndex() if currentIndex >= 0: self.setStyle(currentIndex, QFont.Normal) self.playerCore.remove(toBeRemoved) for index in toBeRemoved: self.playlistTable.removeRow(index) if self.playlistTable.rowCount() == 0: return currentIndex = self.playlist.currentIndex() if currentIndex >= 0: self.setStyle(self.playlist.currentIndex(), QFont.Bold) self.songLabel.setText('{} - {}'.format( self.playlistTable.item(self.currentPlaying, 0).text(), self.playlistTable.item(self.currentPlaying, 1).text())) for index in range(4): self.playlistTable.resizeColumnToContents(index) def savePlaylist(self): """Save playlist.""" url, _ = QFileDialog.getSaveFileUrl(self, 'Save playlist') self.playerCore.savePlaylist(url) def loadPlaylist(self): """Load playlist.""" url, _ = QFileDialog.getOpenFileUrl( self, 'Load playlist', filter='Playlists (*.m3u)') count = self.playlist.mediaCount() self.playerCore.loadPlaylist(url) names = [] for index in range(count, self.playlist.mediaCount()): names.append(self.playlist.media(index).canonicalUrl().path()) self.addClicked(names) def clearPlaylist(self): """Remove all music from playlist.""" self.playlistTable.setRowCount(0) self.playerCore.clearPlaylist() def closeEvent(self, event): """Saves current playlist and quits.""" self.playerCore.savePlaylist(QUrl( 'file://{}/lastListened.m3u'.format(os.getcwd()))) event.accept() def findLyrics(self): """Finds and shows lyrics for selected song(s).""" songs = self.playlistTable.selectedIndexes()[::4] if not songs: return for index in songs: name = '{} - {}'.format(self.playerCore.musicOrder[index.row()][1], self.playerCore.musicOrder[index.row()][2]) lyrics = 'Lyrics:\n\n{}'.format( self.playerCore.findLyrics(index.row())) self.windows.append(Window(name, lyrics)) for window in self.windows: if window.isClosed: self.windows.remove(window) def findInfo(self): """Opens window with info for selected album at the table.""" albums = self.playlistTable.selectedIndexes()[::4] if not albums: return for index in albums: info = self.playerCore.findInfo(index.row()) text = '\n'.join(info) self.windows.append(Window('Info', text)) def login(self): """Opens window for user to log in lastFM.""" self.loginWindow = LoginDialog(self.playerCore) def logout(self): """Logs out current user""" if self.playerCore.network is None: return self.logoutWindow = Window('Logout', 'GoodBye, {}!'.format( self.playerCore.username)) self.playerCore.logout() def love(self): """Loves selected songs in lastFM.""" if self.playerCore.network is None: self.errorWindow = Window('Error', 'You shoud login first.') return songs = self.playlistTable.selectedIndexes()[::4] if not songs: return loved = [] for index in songs: loved.append(self.playerCore.loveTrack(index.row())) if all(loved): self.successWindow = Window('Success', 'Songs loved!') else: self.errorWindow = Window( 'Error', 'Something went wrong! Try again later.') def unlove(self): """Unloves selected songs in lastFM.""" if self.playerCore.network is None: self.errorWindow = Window('Error', 'You shoud login first.') return songs = self.playlistTable.selectedIndexes()[::4] if not songs: return for index in songs: self.playerCore.unloveTrack(index.row()) def center(self): """Position player application at the center of the screen.""" # rectangle specifying the geometry of the widget rectangle = self.frameGeometry() # screen resolution -> center point centerPoint = QDesktopWidget().availableGeometry().center() # set the center of the rectangle to the center of the screen rectangle.moveCenter(centerPoint) # move the top-left point of the application window to the top-left # point of the rectangle self.move(rectangle.topLeft())
class MainWindow(QDialog, SetupTabStopsMixin, CenterOnScreenMixin): WINDOW_TITLE_TEXT = 'BAON' OPTIONS_BOX_TEXT = 'Options' SCAN_RECURSIVE_CHECKBOX_TEXT = 'Recursively scan subfolders' USE_PATH_CHECKBOX_TEXT = 'Use path' USE_EXTENSION_CHECKBOX_TEXT = 'Use extension' RULES_BOX_TEXT = 'Rename Rules' FILES_BOX_TEXT = 'Renamed Files' RENAME_WARNINGS_DIALOG_CAPTION = 'Please Confirm' RENAME_WARNINGS_DIALOG_TEXT = 'There are warnings for some of the files. Proceed with the rename operation anyway?' RENAME_COMPLETE_DIALOG_CAPTION = 'Rename Complete' RENAME_COMPLETE_DIALOG_TEXT =\ 'The files have been renamed successfully. Do you wish to perform another rename operation?' DEFAULT_WINDOW_WIDTH = 800 DEFAULT_WINDOW_HEIGHT = 600 RULES_BOX_HEIGHT = 112 base_path_edited = pyqtSignal(str) scan_recursive_changed = pyqtSignal(bool) rules_text_changed = pyqtSignal(str) use_path_changed = pyqtSignal(bool) use_extension_changed = pyqtSignal(bool) request_add_override = pyqtSignal(BAONPath, BAONPath) request_remove_override = pyqtSignal(BAONPath) request_do_rename = pyqtSignal() request_rescan = pyqtSignal() _base_path_panel = None _scan_recursive_checkbox = None _use_path_checkbox = None _use_extension_checkbox = None _rules_editor = None _files_display = None _files_display_summary_panel = None _status_box = None _dialog_button_box = None def __init__(self, args): super().__init__() self._init_ui() self._fill_in_controls(args) self._center_on_screen() def _init_ui(self): self.setWindowTitle(self.WINDOW_TITLE_TEXT) self.resize(self.DEFAULT_WINDOW_WIDTH, self.DEFAULT_WINDOW_HEIGHT) main_layout = QVBoxLayout(self) main_layout.addWidget(self._create_base_path_panel()) main_layout.addWidget(self._create_options_box()) main_layout.addWidget(self._create_rules_box()) main_layout.addWidget(self._create_files_box()) main_layout.addWidget(self._create_status_box()) main_layout.addWidget(self._create_dialog_buttons()) self._setup_tab_stops( self._base_path_panel, self._scan_recursive_checkbox, self._use_path_checkbox, self._use_extension_checkbox, self._rules_editor, self._files_display, self._files_display_summary, self._dialog_button_box, ) def _create_base_path_panel(self): self._base_path_panel = BasePathPanel(self) self._base_path_panel.path_edited.connect(self.base_path_edited) return self._base_path_panel def _create_options_box(self): box = QGroupBox(self.OPTIONS_BOX_TEXT, self) self._scan_recursive_checkbox = QCheckBox(self.SCAN_RECURSIVE_CHECKBOX_TEXT, box) self._scan_recursive_checkbox.toggled.connect(self.scan_recursive_changed) self._use_path_checkbox = QCheckBox(self.USE_PATH_CHECKBOX_TEXT, box) self._use_path_checkbox.toggled.connect(self.use_path_changed) self._use_extension_checkbox = QCheckBox(self.USE_EXTENSION_CHECKBOX_TEXT, box) self._use_extension_checkbox.toggled.connect(self.use_extension_changed) layout = QHBoxLayout(box) layout.addWidget(self._scan_recursive_checkbox) layout.addWidget(self._use_path_checkbox) layout.addWidget(self._use_extension_checkbox) layout.addStretch() return box def _create_rules_box(self): box = QGroupBox(self.RULES_BOX_TEXT, self) box.setMaximumHeight(self.RULES_BOX_HEIGHT) self._rules_editor = RulesEditor(box) self._rules_editor.rules_edited.connect(self.rules_text_changed) layout = QHBoxLayout(box) layout.addWidget(self._rules_editor) return box def _create_files_box(self): box = QGroupBox(self.FILES_BOX_TEXT, self) box.setSizePolicy(QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding)) self._files_display = FilesDisplay(box) self._files_display_summary = FilesDisplaySummaryPanel(box) self._files_display.request_add_override.connect(self.request_add_override) self._files_display.request_remove_override.connect(self.request_remove_override) self._files_display.counts_changed.connect(self._files_display_summary.set_counts) self._files_display.is_browsing_category_changed.connect(self._files_display_summary.set_is_browsing_category) self._files_display.has_next_in_category_changed.connect(self._files_display_summary.set_has_next_in_category) self._files_display.has_prev_in_category_changed.connect(self._files_display_summary.set_has_prev_in_category) self._files_display_summary.start_browsing_category.connect(self._files_display.start_browsing_category) self._files_display_summary.next_in_category.connect(self._files_display.next_in_category) self._files_display_summary.prev_in_category.connect(self._files_display.prev_in_category) layout = QVBoxLayout(box) layout.addWidget(self._files_display) layout.addWidget(self._files_display_summary) return box def _create_status_box(self): self._status_box = StatusBox(self) return self._status_box def _create_dialog_buttons(self): self._dialog_button_box = QDialogButtonBox(self) self._dialog_button_box.setOrientation(Qt.Horizontal) self._dialog_button_box.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok) self._dialog_button_box.setCenterButtons(True) self._dialog_button_box.accepted.connect(self._confirm_rename) self._dialog_button_box.rejected.connect(self.reject) return self._dialog_button_box def _fill_in_controls(self, args): if args.base_path is not None: self._base_path_panel.set_base_path(args.base_path) if args.scan_recursive is not None: self._scan_recursive_checkbox.setChecked(args.scan_recursive) if args.use_extension is not None: self._use_extension_checkbox.setChecked(args.use_extension) if args.use_path is not None: self._use_path_checkbox.setChecked(args.use_path) if args.rules_text is not None: self._rules_editor.set_rules(args.rules_text) @pyqtSlot() def show_first_time(self): self.show() self.raise_() # We need to do this here as otherwise the operation may fail on some platforms self.setWindowIcon(QIcon(':/app_icon.png')) @pyqtSlot(str) def set_base_path(self, base_path): self._base_path_panel.set_base_path(base_path) @pyqtSlot(BAONStatus) def report_status(self, status): files_busy = \ status.scan_status in [BAONStatus.IN_PROGRESS, BAONStatus.PENDING] or \ status.rename_status in [BAONStatus.IN_PROGRESS, BAONStatus.PENDING] self._files_display.setEnabled(not files_busy) if status.rules_status == BAONStatus.ERROR: self._rules_editor.show_error(status.rules_status_extra.source_span) else: self._rules_editor.clear_error() self._status_box.show_status(status) self._dialog_button_box.button(QDialogButtonBox.Ok).setEnabled( status.execute_status in [BAONStatus.WAITING_FOR_USER, BAONStatus.ERROR] ) if status.execute_status == BAONStatus.AVAILABLE: self._on_rename_completed() @pyqtSlot(list) def update_scanned_files(self, files): self._files_display.set_original_files(files) @pyqtSlot(list) def update_renamed_files(self, files): self._files_display.set_renamed_files(files) @pyqtSlot() def _confirm_rename(self): if self._files_display.has_rename_warnings(): if not self._ask_user(self.RENAME_WARNINGS_DIALOG_CAPTION, self.RENAME_WARNINGS_DIALOG_TEXT): return self.request_do_rename.emit() def _on_rename_completed(self): self._rules_editor.clear() self.request_rescan.emit() if self._ask_user(self.RENAME_COMPLETE_DIALOG_CAPTION, self.RENAME_COMPLETE_DIALOG_TEXT): pass else: self.reject() def _ask_user(self, caption, text): on_mac = platform.system() == 'Darwin' dialog = QMessageBox( QMessageBox.Question, caption, text, QMessageBox.Yes | QMessageBox.No, self, Qt.Sheet if on_mac else Qt.Dialog | Qt.MSWindowsFixedSizeDialogHint, ) dialog.setDefaultButton(QMessageBox.No) dialog.setWindowModality(Qt.WindowModal) return dialog.exec_() == QMessageBox.Yes
class CityTranslate(QDialog): city_signal = pyqtSignal([dict]) def __init__(self, city, cities_list, parent=None): super(CityTranslate, self).__init__(parent) self.city = city self.settings = QSettings() self.trans_cities_dict = cities_list self.layout = QVBoxLayout() self.buttonLayout = QHBoxLayout() self.buttonBox = QDialogButtonBox() self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons( QDialogButtonBox.Ok | QDialogButtonBox.Cancel ) self.buttonBox.rejected.connect(self.reject) self.buttonBox.accepted.connect(self.accept) self.buttonLayout.addWidget(self.buttonBox) self.untranslate_city_label = QLabel(self.find_city_key(self.city)) self.translate_line = QLineEdit(self.city) self.translate_line.selectAll() self.translate_line.setMinimumWidth(300) self.status_layout = QHBoxLayout() self.status_label = QLabel() self.status_layout.addWidget(self.status_label) self.panel = QGridLayout() self.panel.addWidget(self.untranslate_city_label, 0, 0) self.panel.addWidget(self.translate_line, 1, 0) self.layout.addLayout(self.panel) self.layout.addLayout(self.status_layout) self.layout.addLayout(self.buttonLayout) self.setLayout(self.layout) self.setWindowTitle(QCoreApplication.translate('Window title', 'City translation', 'City translation dialogue')) def find_city_key(self, city): for key, value in self.trans_cities_dict.items(): if value == city: return key return city def accept(self): city_dict = {} current_city = self.translate_line.text() for city, trans in self.trans_cities_dict.items(): if ( current_city == trans and city != self.untranslate_city_label.text() ): self.status_label.setText( QCoreApplication.translate( 'Warning message in dialog status bar', 'The city allready exist', 'City translation' ) ) return city_dict[self.untranslate_city_label.text()] = ( self.translate_line.text() ) self.city_signal[dict].emit(city_dict) QDialog.accept(self)
class PlotDialog(QDialog): def __init__(self, df=None): super().__init__() self.df = df self.resize(721, 586) # set up ok and cancel buttin box self.buttonBox = QDialogButtonBox(self) self.buttonBox.setGeometry(QRect(360, 520, 341, 32)) self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok) self.buttonBox.setObjectName("buttonBox") # set up chart select type tree widget in the left self.select_chart_type = QTreeWidget(self) self.select_chart_type.setGeometry(QRect(30, 30, 191, 471)) self.select_chart_type.setObjectName("select_chart_type") self.scatter_plot = QTreeWidgetItem(self.select_chart_type) self.scatter = QTreeWidgetItem(self.scatter_plot) self.scatter_3d = QTreeWidgetItem(self.scatter_plot) self.line_plot = QTreeWidgetItem(self.select_chart_type) self.line = QTreeWidgetItem(self.line_plot) self.bar_plot = QTreeWidgetItem(self.select_chart_type) self.bar = QTreeWidgetItem(self.bar_plot) self.density_plot = QTreeWidgetItem(self.select_chart_type) self.density_contour = QTreeWidgetItem(self.density_plot) self.density_heatmap = QTreeWidgetItem(self.density_plot) self.histogram = QTreeWidgetItem(self.select_chart_type) self.select_chart_type.setCurrentItem(self.scatter) self.select_chart_type.currentItemChanged.connect(self.updateSetting) # set tab widget in the right self.scatter_tw = PlotSetting_2d(self, self.df) self.scatter_3d_tw = PlotSetting_3d(self, self.df) self.line_tw = PlotSetting_line_bar(self, self.df) self.bar_tw = PlotSetting_bar(self, self.df) self.density_contour_tw = PlotSetting_density_contour(self, self.df) self.density_heatmap_tw = PlotSetting_density_heatmap(self, self.df) self.histogram_tw = PlotSetting_histogram(self, self.df) self.scatter_tw.show() self.scatter_3d_tw.hide() self.line_tw.hide() self.bar_tw.hide() self.density_contour_tw.hide() self.density_heatmap_tw.hide() self.histogram_tw.hide() self.buttonBox.accepted.connect(self.ok) self.buttonBox.rejected.connect(self.cancel) QMetaObject.connectSlotsByName(self) self.setText() self.setWindowTitle("Plot Setting") self.setWindowIcon(QIcon('resource/icon.ico')) self.setWindowIconText('viuplot') self.show() # set up tab with in each element def setText(self): # select_chart_type self.select_chart_type.headerItem().setText(0, "Chart type") __sortingEnabled = self.select_chart_type.isSortingEnabled() self.select_chart_type.setSortingEnabled(False) self.scatter_plot.setText(0, "scatter plot") self.scatter.setText(0, "scatter") self.scatter_3d.setText(0, "scatter 3d") self.line_plot.setText(0, "line plot") self.line.setText(0, "line") self.bar_plot.setText(0, "bar plot") self.bar.setText(0, "bar") self.density_plot.setText(0, "density plot") self.density_contour.setText(0, "density contour") self.density_heatmap.setText(0, "density heatmap") self.histogram.setText(0, "histogram") self.select_chart_type.setSortingEnabled(__sortingEnabled) # update func for tab widget view when current tree widget changes def updateSetting(self): if self.select_chart_type.currentItem() == self.scatter: self.scatter_tw.show() self.scatter_3d_tw.hide() self.line_tw.hide() self.bar_tw.hide() self.density_contour_tw.hide() self.density_heatmap_tw.hide() self.histogram_tw.hide() print("scatter") elif self.select_chart_type.currentItem() == self.scatter_3d: self.scatter_tw.hide() self.scatter_3d_tw.show() self.line_tw.hide() self.bar_tw.hide() self.density_contour_tw.hide() self.density_heatmap_tw.hide() self.histogram_tw.hide() print("scatter 3d") elif self.select_chart_type.currentItem() == self.line: self.scatter_tw.hide() self.scatter_3d_tw.hide() self.line_tw.show() self.bar_tw.hide() self.density_contour_tw.hide() self.density_heatmap_tw.hide() self.histogram_tw.hide() print("line") elif self.select_chart_type.currentItem() == self.bar: self.scatter_tw.hide() self.scatter_3d_tw.hide() self.line_tw.hide() self.bar_tw.show() self.density_contour_tw.hide() self.density_heatmap_tw.hide() self.histogram_tw.hide() print("bar") elif self.select_chart_type.currentItem() == self.density_contour: self.scatter_tw.hide() self.scatter_3d_tw.hide() self.line_tw.hide() self.bar_tw.hide() self.density_contour_tw.show() self.density_heatmap_tw.hide() self.histogram_tw.hide() print("density contour") elif self.select_chart_type.currentItem() == self.density_heatmap: self.scatter_tw.hide() self.scatter_3d_tw.hide() self.line_tw.hide() self.bar_tw.hide() self.density_contour_tw.hide() self.density_heatmap_tw.show() self.histogram_tw.hide() print("density heatmap") elif self.select_chart_type.currentItem() == self.histogram: self.scatter_tw.hide() self.scatter_3d_tw.hide() self.line_tw.hide() self.bar_tw.hide() self.density_contour_tw.hide() self.density_heatmap_tw.hide() self.histogram_tw.show() print("histogram") # func for creating chart when clicking ok def ok(self): currentItem = self.select_chart_type.currentItem() if currentItem == self.scatter: info = self.scatter_tw.getCurrentInfo() info['chart_type'] = 'scatter' elif currentItem == self.scatter_3d: info = self.scatter_3d_tw.getCurrentInfo() info['chart_type'] = 'scatter_3d' elif currentItem == self.line: info = self.line_tw.getCurrentInfo() info['chart_type'] = 'line' elif currentItem == self.bar: info = self.bar_tw.getCurrentInfo() info['chart_type'] = 'bar' elif currentItem == self.density_contour: info = self.density_contour_tw.getCurrentInfo() info['chart_type'] = 'density_contour' elif currentItem == self.density_heatmap: info = self.density_heatmap_tw.getCurrentInfo() info['chart_type'] = 'density_heatmap' elif currentItem == self.histogram: info = self.histogram_tw.getCurrentInfo() info['chart_type'] = 'histogram' print(info) try: self.chart = Chart(self.df, info) self.close() except (AttributeError, ValueError, TypeError) as e: self.err_msg = QMessageBox() self.err_msg.setIcon(QMessageBox.Critical) self.err_msg.setText("Error") self.err_msg.setInformativeText( 'Unable to plot with current setting.') self.err_msg.setWindowTitle("Error") self.err_msg.exec_() def cancel(self): self.close()
class IndputChapterDialog(QDialog): chapterInput = pyqtSignal(str, str) def init_ui(self): # Dialog self.Dialog = QDialog() self.Dialog.setWindowModality(Qt.NonModal) self.Dialog.resize(410, 190) self.Dialog.setWindowFlags(Qt.MSWindowsFixedSizeDialogHint) self.Dialog.setWindowIcon(QIcon((resource_path('icon.ico')))) font = QFont() font.setFamily('Verdana') self.Dialog.setFont(font) self.Dialog.setModal(True) self.Dialog.setWindowTitle('Please Input Chapter ...') # Button Box self.buttonBox = QDialogButtonBox(self.Dialog) self.buttonBox.setGeometry(QRect(190, 140, 201, 32)) self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok) # From Chapter self.labelFromChapter = QLabel(self.Dialog) self.labelFromChapter.setGeometry(QRect(20, 30, 121, 31)) font = QFont() font.setFamily('Verdana') font.setPointSize(9) self.labelFromChapter.setFont(font) self.labelFromChapter.setText('From Chapter:') self.inputFromChapter = QLineEdit(self.Dialog) self.inputFromChapter.setGeometry(QRect(140, 30, 251, 31)) # To Chapter self.labelToChapter = QLabel(self.Dialog) self.labelToChapter.setGeometry(QRect(20, 80, 91, 31)) font = QFont() font.setFamily('Verdana') font.setPointSize(9) self.labelToChapter.setFont(font) self.labelToChapter.setText('To Chapter:') self.inputToChapter = QLineEdit(self.Dialog) self.inputToChapter.setGeometry(QRect(140, 80, 251, 31)) # Signal self.buttonBox.accepted.connect(self.get_chapter_input) self.buttonBox.rejected.connect(self.Dialog.reject) QMetaObject.connectSlotsByName(self.Dialog) def start(self): self.init_ui() self.Dialog.exec_() def get_chapter_input(self): self.chapterInput.emit(self.inputFromChapter.text(), self.inputToChapter.text()) self.Dialog.close()
class Ui_WineASIOSettings(object): OBJECT_NAME = "WineASIOSettings" def setupUi(self, WineASIOSettings): WineASIOSettings.setObjectName(self.OBJECT_NAME) WineASIOSettings.resize(400, 310) self.verticalLayout = QVBoxLayout(WineASIOSettings) self.verticalLayout.setObjectName("verticalLayout") self.group_ports = QGroupBox(WineASIOSettings) self.group_ports.setObjectName("group_ports") self.verticalLayout_22 = QVBoxLayout(self.group_ports) self.verticalLayout_22.setObjectName("verticalLayout_22") self.layout_ports_in = QHBoxLayout() self.layout_ports_in.setObjectName("layout_ports_in") self.label_ports_in = QLabel(self.group_ports) self.label_ports_in.setAlignment(Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self.label_ports_in.setObjectName("label_ports_in") self.layout_ports_in.addWidget(self.label_ports_in) self.sb_ports_in = QSpinBox(self.group_ports) self.sb_ports_in.setMaximum(128) self.sb_ports_in.setSingleStep(2) self.sb_ports_in.setObjectName("sb_ports_in") self.layout_ports_in.addWidget(self.sb_ports_in) self.verticalLayout_22.addLayout(self.layout_ports_in) self.layout_ports_out = QHBoxLayout() self.layout_ports_out.setObjectName("layout_ports_out") self.label_ports_out = QLabel(self.group_ports) self.label_ports_out.setAlignment(Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self.label_ports_out.setObjectName("label_ports_out") self.layout_ports_out.addWidget(self.label_ports_out) self.sb_ports_out = QSpinBox(self.group_ports) self.sb_ports_out.setMinimum(2) self.sb_ports_out.setMaximum(128) self.sb_ports_out.setSingleStep(2) self.sb_ports_out.setObjectName("sb_ports_out") self.layout_ports_out.addWidget(self.sb_ports_out) self.verticalLayout_22.addLayout(self.layout_ports_out) self.layout_ports_connect_hw = QHBoxLayout() self.layout_ports_connect_hw.setObjectName("layout_ports_connect_hw") spacerItem = QSpacerItem(150, 20, QSizePolicy.Fixed, QSizePolicy.Minimum) self.layout_ports_connect_hw.addItem(spacerItem) self.cb_ports_connect_hw = QCheckBox(self.group_ports) self.cb_ports_connect_hw.setObjectName("cb_ports_connect_hw") self.layout_ports_connect_hw.addWidget(self.cb_ports_connect_hw) self.verticalLayout_22.addLayout(self.layout_ports_connect_hw) self.verticalLayout.addWidget(self.group_ports) self.group_jack = QGroupBox(WineASIOSettings) self.group_jack.setObjectName("group_jack") self.verticalLayout_23 = QVBoxLayout(self.group_jack) self.verticalLayout_23.setObjectName("verticalLayout_23") self.layout_jack_autostart = QHBoxLayout() self.layout_jack_autostart.setObjectName("layout_jack_autostart") spacerItem1 = QSpacerItem(150, 20, QSizePolicy.Fixed, QSizePolicy.Minimum) self.layout_jack_autostart.addItem(spacerItem1) self.cb_jack_autostart = QCheckBox(self.group_jack) self.cb_jack_autostart.setObjectName("cb_jack_autostart") self.layout_jack_autostart.addWidget(self.cb_jack_autostart) self.verticalLayout_23.addLayout(self.layout_jack_autostart) self.layout_jack_fixed_bsize = QHBoxLayout() self.layout_jack_fixed_bsize.setObjectName("layout_jack_fixed_bsize") spacerItem2 = QSpacerItem(150, 20, QSizePolicy.Fixed, QSizePolicy.Minimum) self.layout_jack_fixed_bsize.addItem(spacerItem2) self.cb_jack_fixed_bsize = QCheckBox(self.group_jack) self.cb_jack_fixed_bsize.setObjectName("cb_jack_fixed_bsize") self.layout_jack_fixed_bsize.addWidget(self.cb_jack_fixed_bsize) self.verticalLayout_23.addLayout(self.layout_jack_fixed_bsize) self.layout_jack_buffer_size = QHBoxLayout() self.layout_jack_buffer_size.setObjectName("layout_jack_buffer_size") self.label_jack_buffer_size = QLabel(self.group_jack) self.label_jack_buffer_size.setAlignment(Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self.label_jack_buffer_size.setObjectName("label_jack_buffer_size") self.layout_jack_buffer_size.addWidget(self.label_jack_buffer_size) self.cb_jack_buffer_size = QComboBox(self.group_jack) self.cb_jack_buffer_size.setObjectName("cb_jack_buffer_size") self.layout_jack_buffer_size.addWidget(self.cb_jack_buffer_size) self.verticalLayout_23.addLayout(self.layout_jack_buffer_size) self.verticalLayout.addWidget(self.group_jack) self.buttonBox = QDialogButtonBox(WineASIOSettings) self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok | QDialogButtonBox.RestoreDefaults) self.buttonBox.setObjectName("buttonBox") self.verticalLayout.addWidget(self.buttonBox) self.retranslateUi(WineASIOSettings) self.buttonBox.accepted.connect(WineASIOSettings.accept) self.buttonBox.rejected.connect(WineASIOSettings.reject) QMetaObject.connectSlotsByName(WineASIOSettings) # --------------------------------------------------------------------------------------------------------------------- def retranslateUi(self, WineASIOSettings): _tr = QCoreApplication.translate WineASIOSettings.setWindowTitle( _tr(self.OBJECT_NAME, "WineASIO Settings")) # Audio Ports self.group_ports.setTitle(_tr(self.OBJECT_NAME, "Audio Ports")) self.label_ports_in.setText(_tr(self.OBJECT_NAME, "Number of inputs:")) self.label_ports_in.setToolTip( _tr( self.OBJECT_NAME, "Number of jack ports that wineasio will try to open.\n" "Default is 16")) self.sb_ports_in.setToolTip( _tr( self.OBJECT_NAME, "Number of jack ports that wineasio will try to open.\n" "Default is 16")) self.label_ports_out.setText( _tr(self.OBJECT_NAME, "Number of outputs:")) self.label_ports_out.setToolTip( _tr( self.OBJECT_NAME, "Number of jack ports that wineasio will try to open.\n" "Default is 16")) self.sb_ports_out.setToolTip( _tr( self.OBJECT_NAME, "Number of jack ports that wineasio will try to open.\n" "Default is 16")) self.cb_ports_connect_hw.setText( _tr(self.OBJECT_NAME, "Connect to hardware")) self.cb_ports_connect_hw.setToolTip( _tr( self.OBJECT_NAME, "Try to connect the asio channels to the\n" "physical I/O ports on your hardware.\n" "Default is on")) # JACK Options self.group_jack.setTitle(_tr(self.OBJECT_NAME, "JACK Options")) self.cb_jack_autostart.setText( _tr(self.OBJECT_NAME, "Autostart server")) self.cb_jack_autostart.setToolTip( _tr( self.OBJECT_NAME, "Enable wineasio to launch the jack server.\n" "Default is off")) self.cb_jack_fixed_bsize.setText( _tr(self.OBJECT_NAME, "Fixed buffersize")) self.cb_jack_fixed_bsize.setToolTip( _tr( self.OBJECT_NAME, "When on, an asio app will be able to change the jack buffer size.\n" "Default is off")) self.label_jack_buffer_size.setText( _tr(self.OBJECT_NAME, "Preferred buffersize:"))
class PlainTextImportDialog(QDialog): class TableModel(QAbstractTableModel): ROW_BATCH_COUNT: Final[int] = 10 def __init__(self, parent=None): super().__init__(parent) self._data: List[Tuple[Union[str, int, float], ...]] = [] self._header: Dict[int, Union[str, int, float]] = dict() self._rows_loaded: int = self.ROW_BATCH_COUNT def rowCount(self, parent=None): if self._data is None: return 0 return len(self._data) def columnCount(self, parent=None): if self._data is None: return 0 return len(self._header) def data(self, index, role=Qt.DisplayRole): if index.isValid(): if role == Qt.DisplayRole: return QVariant( str(self._data[index.row()][index.column()])) return QVariant() def set_data(self, new_data: List[Tuple[Union[str, int, float], ...]]): self._data = new_data def headerData(self, col, orientation, role=None): if orientation == Qt.Horizontal and role == Qt.DisplayRole: return self._header[col] return None def setHeaderData(self, section: int, orientation: Qt.Orientation, value, role: int = ...) -> bool: if orientation == Qt.Horizontal and role == Qt.DisplayRole and 0 <= section < len( self._header): self._header[section] = value return True return False def sort(self, column: int, order: Qt.SortOrder = Qt.AscendingOrder) -> None: self.beginResetModel() data_column: Final[int] = {0: 1, 1: 3, 2: 5, 3: 7}[column] self._data.sort(key=lambda l: l[data_column], reverse=bool(order != Qt.AscendingOrder)) self.endResetModel() def canFetchMore(self, index=QModelIndex()): return len(self._data) > self._rows_loaded def fetchMore(self, index=QModelIndex()): # https://sateeshkumarb.wordpress.com/2012/04/01/paginated-display-of-table-data-in-pyqt/ reminder: int = len(self._data) - self._rows_loaded items_to_fetch: int = min(reminder, self.ROW_BATCH_COUNT) self.beginInsertRows(QModelIndex(), self._rows_loaded, self._rows_loaded + items_to_fetch - 1) self._rows_loaded += items_to_fetch self.endInsertRows() def __init__(self, file_name: str): super(PlainTextImportDialog, self).__init__() self._translate = QCoreApplication.translate self.setWindowModality(Qt.ApplicationModal) self.resize(594, 546) self.main_layout = QGridLayout(self) self.table_preview = QTableView(self) self.table_preview.setEditTriggers(QAbstractItemView.NoEditTriggers) self.table_preview.setAlternatingRowColors(True) self.table_preview_model = self.TableModel() self.table_preview.setModel(self.table_preview_model) self.main_layout.addWidget(self.table_preview, 0, 0, 1, 1) self.frame_settings = QFrame(self) self.frame_settings.setFrameShape(QFrame.StyledPanel) self.frame_settings.setFrameShadow(QFrame.Raised) self.layout_settings = QGridLayout(self.frame_settings) self.frame_column_naming = QFrame(self.frame_settings) self.layout_column_naming = QFormLayout(self.frame_column_naming) self.text_column_prefix = QLineEdit(self.frame_column_naming) self.layout_column_naming.addRow( self._translate('PlainTextImportDialog', 'Column prefix:'), self.text_column_prefix) self.text_column_suffix = QLineEdit(self.frame_column_naming) self.layout_column_naming.addRow( self._translate('PlainTextImportDialog', 'Column suffix:'), self.text_column_suffix) self.layout_settings.addWidget(self.frame_column_naming, 3, 1, 1, 1) self.frame_skip = QFrame(self.frame_settings) self.layout_skip = QFormLayout(self.frame_skip) self.spin_skip_rows_before_header = QSpinBox(self.frame_skip) self.spin_skip_rows_before_header.setMaximum(999) self.layout_skip.addRow( self._translate('PlainTextImportDialog', 'Skip rows before header:'), self.spin_skip_rows_before_header) self.check_has_header = QCheckBox(self.frame_skip) self.layout_skip.setWidget(1, QFormLayout.SpanningRole, self.check_has_header) self.check_has_units = QCheckBox(self.frame_skip) self.layout_skip.setWidget(2, QFormLayout.SpanningRole, self.check_has_units) self.spin_skip_rows_after_header = QSpinBox(self.frame_skip) self.spin_skip_rows_after_header.setMaximum(999) self.layout_skip.addRow( self._translate('PlainTextImportDialog', 'Skip rows after header:'), self.spin_skip_rows_after_header) self.spin_skip_rows_at_bottom = QSpinBox(self.frame_skip) self.spin_skip_rows_at_bottom.setMaximum(999) self.layout_skip.addRow( self._translate('PlainTextImportDialog', 'Skip rows at bottom:'), self.spin_skip_rows_at_bottom) self.text_skip_columns = QLineEdit(self.frame_skip) self.layout_skip.addRow( self._translate('PlainTextImportDialog', 'Skip columns:'), self.text_skip_columns) self.layout_settings.addWidget(self.frame_skip, 2, 0, 2, 1) self.layout_preview_rows = QFormLayout() self.spin_preview_rows = QSpinBox(self.frame_settings) self.spin_preview_rows.setMinimum(1) self.spin_preview_rows.setProperty('value', 10) self.layout_preview_rows.addRow( self._translate('PlainTextImportDialog', 'Rows in the preview:'), self.spin_preview_rows) self.layout_settings.addLayout(self.layout_preview_rows, 1, 0, 1, 1) self.frame_separators = QFrame(self.frame_settings) self.layout_separators = QFormLayout(self.frame_separators) self.combo_separator = QComboBox(self.frame_separators) self.combo_separator.setEditable(True) self.combo_separator.setSizeAdjustPolicy(QComboBox.AdjustToContents) self.combo_separator.addItem( self._translate('PlainTextImportDialog', 'comma (,)')) self.combo_separator.addItem( self._translate('PlainTextImportDialog', 'semicolon (;)')) self.combo_separator.addItem( self._translate('PlainTextImportDialog', 'space')) self.combo_separator.addItem( self._translate('PlainTextImportDialog', 'tab')) self.combo_separator.addItem( self._translate('PlainTextImportDialog', 'space or tab')) self.layout_separators.addRow( self._translate('PlainTextImportDialog', 'Separator:'), self.combo_separator) self.check_combine_separators = QCheckBox(self.frame_separators) self.layout_separators.setWidget(1, QFormLayout.SpanningRole, self.check_combine_separators) self.combo_comment = QComboBox(self.frame_separators) self.combo_comment.setEditable(True) self.combo_comment.setCurrentText('#') self.combo_comment.addItems(('#', ';', '%', '!')) self.layout_separators.addRow( self._translate('PlainTextImportDialog', 'Comment:'), self.combo_comment) self.combo_text_start = QComboBox(self.frame_separators) self.combo_text_start.setEditable(True) self.combo_text_start.setCurrentText("'") self.combo_text_start.addItems(('"', "'", '«', '„', '“', '‘', '`')) self.layout_separators.addRow( self._translate('PlainTextImportDialog', 'Text start:'), self.combo_text_start) self.combo_text_end = QComboBox(self.frame_separators) self.combo_text_end.setEditable(True) self.combo_text_end.setCurrentText("'") self.combo_text_end.addItems(('"', "'", '»', '”', '’', '`')) self.layout_separators.addRow( self._translate('PlainTextImportDialog', 'Text end:'), self.combo_text_end) self.layout_settings.addWidget(self.frame_separators, 1, 1, 2, 1) self.main_layout.addWidget(self.frame_settings, 2, 0, 1, 1) self.buttonBox = QDialogButtonBox(self) self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Open) self.main_layout.addWidget(self.buttonBox, 5, 0, 1, 1) self.setWindowTitle( self._translate('PlainTextImportDialog', 'Plain Text Import')) self.text_skip_columns.setPlaceholderText( self._translate('PlainTextImportDialog', 'e.g., 1, 2, 4-6')) self.check_has_units.setText( self._translate('PlainTextImportDialog', 'The units are placed just after the header')) self.check_has_header.setText( self._translate('PlainTextImportDialog', 'The file has a header')) self.check_combine_separators.setText( self._translate('PlainTextImportDialog', 'Combine separators')) self.combo_comment.setToolTip( self._translate( 'PlainTextImportDialog', 'This marks comment lines. Separate multiple marks with spaces.' )) self.adjustSize() self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) # QMetaObject.connectSlotsByName(self) self._file_name: Path = Path(file_name)
class PreferencesPanel(QDialog): def __init__(self, parent, app): # The flags we pass are that so we don't get the "What's this" button in the title bar QDialog.__init__(self, parent, Qt.WindowTitleHint | Qt.WindowSystemMenuHint) self.app = app self._setupUi() self.dateFormatEdit.editingFinished.connect(self.dateFormatEdited) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) def _setupUi(self): self.setWindowTitle(tr("Preferences")) self.resize(332, 170) self.verticalLayout = QVBoxLayout(self) self.formLayout = QFormLayout() self.autoSaveIntervalSpinBox = QSpinBox(self) self.autoSaveIntervalSpinBox.setMaximumSize(QSize(70, 0xffffff)) self.label_5 = QLabel(tr("minute(s) (0 for none)"), self) self.formLayout.addRow( tr("Auto-save interval:"), horizontalWrap([self.autoSaveIntervalSpinBox, self.label_5]) ) self.dateFormatEdit = QLineEdit(self) self.dateFormatEdit.setMaximumSize(QSize(140, 0xffffff)) self.formLayout.addRow(tr("Date format:"), self.dateFormatEdit) self.fontSizeSpinBox = QSpinBox() self.fontSizeSpinBox.setMinimum(5) self.fontSizeSpinBox.setMaximumSize(QSize(70, 0xffffff)) self.formLayout.addRow(tr("Font size:"), self.fontSizeSpinBox) self.languageComboBox = QComboBox(self) LANGNAMES = get_langnames() for lang in SUPPORTED_LANGUAGES: self.languageComboBox.addItem(LANGNAMES[lang]) self.languageComboBox.setMaximumSize(QSize(140, 0xffffff)) self.formLayout.addRow(tr("Language:"), self.languageComboBox) self.verticalLayout.addLayout(self.formLayout) self.scopeDialogCheckBox = QCheckBox(tr("Show scope dialog when modifying a scheduled transaction"), self) self.verticalLayout.addWidget(self.scopeDialogCheckBox) self.autoDecimalPlaceCheckBox = QCheckBox(tr("Automatically place decimals when typing"), self) self.verticalLayout.addWidget(self.autoDecimalPlaceCheckBox) self.debugModeCheckBox = QCheckBox(tr("Debug mode (restart required)"), self) self.verticalLayout.addWidget(self.debugModeCheckBox) self.verticalLayout.addItem(verticalSpacer()) self.buttonBox = QDialogButtonBox(self) self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel|QDialogButtonBox.Ok) self.verticalLayout.addWidget(self.buttonBox) def load(self): appm = self.app.model self.autoSaveIntervalSpinBox.setValue(appm.autosave_interval) self.dateFormatEdit.setText(self.app.prefs.dateFormat) self.fontSizeSpinBox.setValue(self.app.prefs.tableFontSize) self.scopeDialogCheckBox.setChecked(appm.show_schedule_scope_dialog) self.autoDecimalPlaceCheckBox.setChecked(appm.auto_decimal_place) self.debugModeCheckBox.setChecked(self.app.prefs.debugMode) try: langindex = SUPPORTED_LANGUAGES.index(self.app.prefs.language) except ValueError: langindex = 0 self.languageComboBox.setCurrentIndex(langindex) def save(self): restartRequired = False appm = self.app.model appm.autosave_interval = self.autoSaveIntervalSpinBox.value() if self.dateFormatEdit.text() != self.app.prefs.dateFormat: restartRequired = True self.app.prefs.dateFormat = self.dateFormatEdit.text() self.app.prefs.tableFontSize = self.fontSizeSpinBox.value() appm.show_schedule_scope_dialog = self.scopeDialogCheckBox.isChecked() appm.auto_decimal_place = self.autoDecimalPlaceCheckBox.isChecked() self.app.prefs.debugMode = self.debugModeCheckBox.isChecked() lang = SUPPORTED_LANGUAGES[self.languageComboBox.currentIndex()] oldlang = self.app.prefs.language if oldlang not in SUPPORTED_LANGUAGES: oldlang = 'en' if lang != oldlang: restartRequired = True self.app.prefs.language = lang if restartRequired: QMessageBox.information(self, "", tr("moneyGuru has to restart for these changes to take effect")) #--- Signals def dateFormatEdited(self): self.dateFormatEdit.setText(clean_format(self.dateFormatEdit.text()))
class NewProjectDialog(QDialog): #此处定义常量 #此处定义信号 def __init__(self): QDialog.__init__(self) self.project_dir = None self.project_name = None def setup(self): self.resize(450, 120) sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.sizePolicy().hasHeightForWidth()) self.setSizePolicy(sizePolicy) self.verticalLayout = QVBoxLayout(self) self.verticalLayout.setObjectName("verticalLayout") self.horizontalLayout = QHBoxLayout() self.horizontalLayout.setObjectName("horizontalLayout") self.label_project_name = QLabel(self) sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.label_project_name.sizePolicy().hasHeightForWidth()) self.label_project_name.setSizePolicy(sizePolicy) self.label_project_name.setMinimumSize(QSize(80, 24)) self.label_project_name.setMaximumSize(QSize(80, 24)) self.label_project_name.setObjectName("label_project_name") self.horizontalLayout.addWidget(self.label_project_name) self.lineEdit_project_name = QLineEdit(self) self.lineEdit_project_name.setObjectName("lineEdit_project_name") self.horizontalLayout.addWidget(self.lineEdit_project_name) self.verticalLayout.addLayout(self.horizontalLayout) self.horizontalLayout_2 = QHBoxLayout() self.horizontalLayout_2.setObjectName("horizontalLayout_2") self.label_location = QLabel(self) sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.label_location.sizePolicy().hasHeightForWidth()) self.label_location.setSizePolicy(sizePolicy) self.label_location.setMinimumSize(QSize(80, 24)) self.label_location.setMaximumSize(QSize(80, 24)) self.label_location.setObjectName("label_location") self.horizontalLayout_2.addWidget(self.label_location) self.lineEdit_location = QLineEdit(self) self.lineEdit_location.setObjectName("lineEdit_location") self.lineEdit_location.setReadOnly(True) self.lineEdit_location.setText(os.getcwd()) self.horizontalLayout_2.addWidget(self.lineEdit_location) self.toolbutton_open = QToolButton(self) self.toolbutton_open.setMinimumSize(QSize(24, 24)) self.toolbutton_open.setMaximumSize(QSize(24, 24)) self.toolbutton_open.setObjectName("toolbutton_open") self.horizontalLayout_2.addWidget(self.toolbutton_open) self.verticalLayout.addLayout(self.horizontalLayout_2) self.buttonBox = QDialogButtonBox(self) self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok) self.buttonBox.setObjectName("buttonBox") self.verticalLayout.addWidget(self.buttonBox) self.retranslateUi() # 给项目路径和项目赋初值 self.project_dir = self.lineEdit_location.text() self.project_name = self.lineEdit_project_name.text() # 信号与槽进行连接 self.buttonBox.accepted.connect(self.slot_accept) self.buttonBox.rejected.connect(self.reject) self.toolbutton_open.clicked.connect(self.slot_open) self.lineEdit_project_name.textChanged.connect(self.slot_set_dir) QMetaObject.connectSlotsByName(self) def get_project_info(self): self.setup() flag = self.exec_() if (flag == QDialog.Accepted): # 返回一个元组,包含路径和项目名 return (self.project_dir, self.project_name) else: return (None, None) # ============================================================================= # Slots # ============================================================================= # 让用户选择项目的路径 def slot_open(self): sel_dir = QFileDialog.getExistingDirectory(self, 'Select Folder') if sel_dir: sel_dir = sel_dir.replace('/', '\\') self.project_dir = sel_dir if self.project_name: self.lineEdit_location.setText(self.project_dir + '\\' + self.project_name) else: self.lineEdit_location.setText(self.project_dir) # 自定义一个接受的事件,需要判断用户是否已完成项目的创建 def slot_accept(self): if (self.project_dir and self.project_name): self.accept() else: tipDialog = QMessageBox(self) tipDialog.resize(300, 100) tipDialog.setWindowTitle("Caution") tipDialog.setText("You have not created a project yet!") tipDialog.exec_() def slot_set_dir(self): # 这里还应该判断用户输入正确的项目名字符串 self.project_name = self.lineEdit_project_name.text() if self.project_name: self.lineEdit_location.setText(self.project_dir + '\\' + self.project_name) else: self.lineEdit_location.setText(self.project_dir) def retranslateUi(self): _translate = QCoreApplication.translate self.setWindowTitle(_translate("NewProjectDialog", "创建新项目")) self.label_project_name.setText(_translate("NewProjectDialog", "项目名")) self.label_location.setText(_translate("NewProjectDialog", "路径")) self.toolbutton_open.setText(_translate("NewProjectDialog", "...")) # def retranslateUi(self): # _translate = QCoreApplication.translate # self.setWindowTitle(_translate("NewProjectDialog", "Create new project")) # self.label_project_name.setText(_translate("NewProjectDialog", "Project name")) # self.label_location.setText(_translate("NewProjectDialog", "Location")) # self.toolbutton_open.setText(_translate("NewProjectDialog", "..."))
class CalibrateDialog(QDialog): def __init__(self, parent=None): super(CalibrateDialog, self).__init__(parent) self.parent = parent self.verticalLayout = QVBoxLayout(self) self.verticalLayout.addWidget(self.createCallStepButtons()) self.verticalLayout.addWidget(self.createCallSaveLoadButtons()) self.verticalLayout.addStretch(1) self.verticalLayout.addWidget(self.createCloseButttonContainer()) self.plot_paths = ['S21'] def createCloseButttonContainer(self): self.buttonBox = QDialogButtonBox(self) self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Ok) # Cheat a bit here, and just call the close method directly. self.buttonBox.clicked.connect(self.close) return self.buttonBox def createCallSaveLoadButtons(self): steps = [ ("CAL_LOAD", QPushButton('Load')), ("CAL_SAVE", QPushButton('Save')), ] layout = QHBoxLayout() for key, wid in steps: layout.addWidget(wid) wid.setProperty("btn_name", key) wid.clicked.connect(self.callDataButtonClicked) calstep_container = QGroupBox("Save/Load Cal"); calstep_container.setLayout(layout) return calstep_container def createCallStepButtons(self): steps = [ ("STEP_THRU", QPushButton('Through')), ("STEP_P1_OPEN", QPushButton('Port 1 Open')), ("STEP_P1_SHORT", QPushButton('Port 1 Short')), ("STEP_P1_LOAD", QPushButton('Port 1 Load')), ("STEP_P2_OPEN", QPushButton('Port 2 Open')), ("STEP_P2_SHORT", QPushButton('Port 2 Short')), ("STEP_P2_LOAD", QPushButton('Port 2 Load')), ] layout = QVBoxLayout() for key, wid in steps: layout.addWidget(wid) wid.setProperty("btn_name", key) wid.clicked.connect(self.callButtonClicked) calstep_container = QGroupBox("Calibration Steps"); calstep_container.setLayout(layout) return calstep_container def callDataButtonClicked(self): stepname = self.sender().property('btn_name') self.parent.doCalDataManip(stepname) def callButtonClicked(self): stepname = self.sender().property('btn_name') self.parent.doCalStep(stepname)
class AboutVM(QDialog): def __init__(self, parent=None): """Class initializer.""" super(AboutVM, self).__init__(parent) self.setWindowTitle(self.tr('About VideoMorph')) self.resize(374, 404) self.horizontalLayout_3 = QHBoxLayout(self) self.verticalLayout_4 = QVBoxLayout() self.horizontalLayout_2 = QHBoxLayout() self.label = QLabel(self) self.label.setMinimumSize(QSize(64, 64)) self.label.setMaximumSize(QSize(64, 64)) self.label.setText("") self.label.setPixmap(QPixmap(':/logo/images/videomorph.png')) self.label.setScaledContents(True) self.horizontalLayout_2.addWidget(self.label) self.label_2 = QLabel( "<p align=\"center\"><span style=\" font-size:20pt; font-weight:600;\">VideoMorph</span></p><p align=\"center\"><span style=\" font-size:9pt; font-weight:600;\">version {v}</span></p>".format( v=VERSION)) self.label_2.setMinimumSize(QSize(0, 64)) self.label_2.setMaximumSize(QSize(16777215, 64)) self.horizontalLayout_2.addWidget(self.label_2) self.verticalLayout_4.addLayout(self.horizontalLayout_2) self.tabWidget = QTabWidget(self) self.tab = QWidget() self.verticalLayout_2 = QVBoxLayout(self.tab) self.textEdit_3 = QTextEdit(self.tab) self.textEdit_3.setReadOnly(True) self.verticalLayout_2.addWidget(self.textEdit_3) self.tabWidget.addTab(self.tab, "") self.tab_2 = QWidget() self.verticalLayout_3 = QVBoxLayout(self.tab_2) self.textEdit_2 = QTextEdit(self.tab_2) self.textEdit_2.setReadOnly(True) self.verticalLayout_3.addWidget(self.textEdit_2) self.tabWidget.addTab(self.tab_2, "") self.tab_3 = QWidget() self.verticalLayout = QVBoxLayout(self.tab_3) self.plainTextEdit = QPlainTextEdit(self.tab_3) self.plainTextEdit.setReadOnly(True) self.verticalLayout.addWidget(self.plainTextEdit) self.tabWidget.addTab(self.tab_3, "") self.verticalLayout_4.addWidget(self.tabWidget) self.horizontalLayout = QHBoxLayout() spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout.addItem(spacerItem) self.buttonBox = QDialogButtonBox(self) self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Ok) self.buttonBox.accepted.connect(self.accept) self.horizontalLayout.addWidget(self.buttonBox) self.verticalLayout_4.addLayout(self.horizontalLayout) self.horizontalLayout_3.addLayout(self.verticalLayout_4) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), self.tr("Info")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), self.tr("Credits")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_3), self.tr("License")) self.textEdit_2.setHtml(self.tr( "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n" "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n" "p, li { white-space: pre-wrap; }\n" "</style></head><body style=\" font-family:\'Sans Serif\'; font-size:10pt; font-weight:400; font-style:normal;\">\n" "<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-size:11pt; font-weight:600;\">Developers:</span></p>\n" "<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Ozkar L. Garcell - project leader</p>\n" "<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><[email protected]></p>\n" "<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><br /></p>\n" "<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Leodanis Pozo Ramos - main developer</p>\n" "<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><[email protected]></p>\n" "<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt; font-weight:600;\"><br /></p>\n" "<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-size:11pt; font-weight:600;\">Translators:</span></p>\n" "<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Ozkar L. Garcell - en_US, es_ES</p>\n" "<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt; font-weight:600;\"><br /></p>\n" "<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-size:11pt; font-weight:600;\">Contributors:</span></p>\n" "<p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">Carlos Parra Zaldivar - Artwork.</p>\n" "<p style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt; font-weight:600;\"><br /></p></body></html>" )) self.textEdit_3.setHtml(self.tr( "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n" "<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n" "p, li { white-space: pre-wrap; }\n" "</style></head><body style=\" font-family:\'Sans Serif\'; font-size:10pt; font-weight:400; font-style:normal;\">\n" "<p align=\"center\" style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-size:12pt; font-weight:600;\">A simple and lightweight video transcoder.</span></p>\n" "<p align=\"center\" style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:12pt; font-weight:600;\"><br /></p>\n" "<p align=\"justify\" style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><span style=\" font-size:11pt; font-weight:600;\">VideoMorph</span><span style=\" font-size:11pt;\"> is a small GUI front-end for </span><a href=\"http://ffmpeg.org/\"><span style=\" font-size:11pt; text-decoration: underline; color:#2980b9;\">ffmpeg</span></a><span style=\" font-size:11pt;\"> and avconv, based on code from </span><a href=\"https://github.com/senko/python-video-converter\"><span style=\" font-size:11pt; text-decoration: underline; color:#2980b9;\">python-video-converter</span></a><span style=\" font-size:11pt;\"> and presets idea from </span><a href=\"http://qwinff.github.io/\"><span style=\" font-size:11pt; text-decoration: underline; color:#2980b9;\">QWinFF</span></a><span style=\" font-size:11pt;\">.</span></p>\n" "<p align=\"justify\" style=\"-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:11pt;\"><br /></p>\n" "<p align=\"center\" style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\"><a href=\"https://github.com/codeshard/videomorph\"><span style=\" text-decoration: underline; color:#2980b9;\">https://github.com/codeshard/videomorph</span></a></p></body></html>" )) self.plainTextEdit.setPlainText(self.tr( " Apache License\n" " Version 2.0, January 2004\n" " http://www.apache.org/licenses/\n" "\n" " TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n" "\n" " 1. Definitions.\n" "\n" " \"License\" shall mean the terms and conditions for use, reproduction,\n" " and distribution as defined by Sections 1 through 9 of this document.\n" "\n" " \"Licensor\" shall mean the copyright owner or entity authorized by\n" " the copyright owner that is granting the License.\n" "\n" " \"Legal Entity\" shall mean the union of the acting entity and all\n" " other entities that control, are controlled by, or are under common\n" " control with that entity. For the purposes of this definition,\n" " \"control\" means (i) the power, direct or indirect, to cause the\n" " direction or management of such entity, whether by contract or\n" " otherwise, or (ii) ownership of fifty percent (50%) or more of the\n" " outstanding shares, or (iii) beneficial ownership of such entity.\n" "\n" " \"You\" (or \"Your\") shall mean an individual or Legal Entity\n" " exercising permissions granted by this License.\n" "\n" " \"Source\" form shall mean the preferred form for making modifications,\n" " including but not limited to software source code, documentation\n" " source, and configuration files.\n" "\n" " \"Object\" form shall mean any form resulting from mechanical\n" " transformation or translation of a Source form, including but\n" " not limited to compiled object code, generated documentation,\n" " and conversions to other media types.\n" "\n" " \"Work\" shall mean the work of authorship, whether in Source or\n" " Object form, made available under the License, as indicated by a\n" " copyright notice that is included in or attached to the work\n" " (an example is provided in the Appendix below).\n" "\n" " \"Derivative Works\" shall mean any work, whether in Source or Object\n" " form, that is based on (or derived from) the Work and for which the\n" " editorial revisions, annotations, elaborations, or other modifications\n" " represent, as a whole, an original work of authorship. For the purposes\n" " of this License, Derivative Works shall not include works that remain\n" " separable from, or merely link (or bind by name) to the interfaces of,\n" " the Work and Derivative Works thereof.\n" "\n" " \"Contribution\" shall mean any work of authorship, including\n" " the original version of the Work and any modifications or additions\n" " to that Work or Derivative Works thereof, that is intentionally\n" " submitted to Licensor for inclusion in the Work by the copyright owner\n" " or by an individual or Legal Entity authorized to submit on behalf of\n" " the copyright owner. For the purposes of this definition, \"submitted\"\n" " means any form of electronic, verbal, or written communication sent\n" " to the Licensor or its representatives, including but not limited to\n" " communication on electronic mailing lists, source code control systems,\n" " and issue tracking systems that are managed by, or on behalf of, the\n" " Licensor for the purpose of discussing and improving the Work, but\n" " excluding communication that is conspicuously marked or otherwise\n" " designated in writing by the copyright owner as \"Not a Contribution.\"\n" "\n" " \"Contributor\" shall mean Licensor and any individual or Legal Entity\n" " on behalf of whom a Contribution has been received by Licensor and\n" " subsequently incorporated within the Work.\n" "\n" " 2. Grant of Copyright License. Subject to the terms and conditions of\n" " this License, each Contributor hereby grants to You a perpetual,\n" " worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n" " copyright license to reproduce, prepare Derivative Works of,\n" " publicly display, publicly perform, sublicense, and distribute the\n" " Work and such Derivative Works in Source or Object form.\n" "\n" " 3. Grant of Patent License. Subject to the terms and conditions of\n" " this License, each Contributor hereby grants to You a perpetual,\n" " worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n" " (except as stated in this section) patent license to make, have made,\n" " use, offer to sell, sell, import, and otherwise transfer the Work,\n" " where such license applies only to those patent claims licensable\n" " by such Contributor that are necessarily infringed by their\n" " Contribution(s) alone or by combination of their Contribution(s)\n" " with the Work to which such Contribution(s) was submitted. If You\n" " institute patent litigation against any entity (including a\n" " cross-claim or counterclaim in a lawsuit) alleging that the Work\n" " or a Contribution incorporated within the Work constitutes direct\n" " or contributory patent infringement, then any patent licenses\n" " granted to You under this License for that Work shall terminate\n" " as of the date such litigation is filed.\n" "\n" " 4. Redistribution. You may reproduce and distribute copies of the\n" " Work or Derivative Works thereof in any medium, with or without\n" " modifications, and in Source or Object form, provided that You\n" " meet the following conditions:\n" "\n" " (a) You must give any other recipients of the Work or\n" " Derivative Works a copy of this License; and\n" "\n" " (b) You must cause any modified files to carry prominent notices\n" " stating that You changed the files; and\n" "\n" " (c) You must retain, in the Source form of any Derivative Works\n" " that You distribute, all copyright, patent, trademark, and\n" " attribution notices from the Source form of the Work,\n" " excluding those notices that do not pertain to any part of\n" " the Derivative Works; and\n" "\n" " (d) If the Work includes a \"NOTICE\" text file as part of its\n" " distribution, then any Derivative Works that You distribute must\n" " include a readable copy of the attribution notices contained\n" " within such NOTICE file, excluding those notices that do not\n" " pertain to any part of the Derivative Works, in at least one\n" " of the following places: within a NOTICE text file distributed\n" " as part of the Derivative Works; within the Source form or\n" " documentation, if provided along with the Derivative Works; or,\n" " within a display generated by the Derivative Works, if and\n" " wherever such third-party notices normally appear. The contents\n" " of the NOTICE file are for informational purposes only and\n" " do not modify the License. You may add_file Your own attribution\n" " notices within Derivative Works that You distribute, alongside\n" " or as an addendum to the NOTICE text from the Work, provided\n" " that such additional attribution notices cannot be construed\n" " as modifying the License.\n" "\n" " You may add_file Your own copyright statement to Your modifications and\n" " may provide additional or different license terms and conditions\n" " for use, reproduction, or distribution of Your modifications, or\n" " for any such Derivative Works as a whole, provided Your use,\n" " reproduction, and distribution of the Work otherwise complies with\n" " the conditions stated in this License.\n" "\n" " 5. Submission of Contributions. Unless You explicitly state otherwise,\n" " any Contribution intentionally submitted for inclusion in the Work\n" " by You to the Licensor shall be under the terms and conditions of\n" " this License, without any additional terms or conditions.\n" " Notwithstanding the above, nothing herein shall supersede or modify\n" " the terms of any separate license agreement you may have executed\n" " with Licensor regarding such Contributions.\n" "\n" " 6. Trademarks. This License does not grant permission to use the trade\n" " names, trademarks, service marks, or product names of the Licensor,\n" " except as required for reasonable and customary use in describing the\n" " origin of the Work and reproducing the content of the NOTICE file.\n" "\n" " 7. Disclaimer of Warranty. Unless required by applicable law or\n" " agreed to in writing, Licensor provides the Work (and each\n" " Contributor provides its Contributions) on an \"AS IS\" BASIS,\n" " WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n" " implied, including, without limitation, any warranties or conditions\n" " of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n" " PARTICULAR PURPOSE. You are solely responsible for determining the\n" " appropriateness of using or redistributing the Work and assume any\n" " risks associated with Your exercise of permissions under this License.\n" "\n" " 8. Limitation of Liability. In no event and under no legal theory,\n" " whether in tort (including negligence), contract, or otherwise,\n" " unless required by applicable law (such as deliberate and grossly\n" " negligent acts) or agreed to in writing, shall any Contributor be\n" " liable to You for damages, including any direct, indirect, special,\n" " incidental, or consequential damages of any character arising as a\n" " result of this License or out of the use or inability to use the\n" " Work (including but not limited to damages for loss of goodwill,\n" " work stoppage, computer failure or malfunction, or any and all\n" " other commercial damages or losses), even if such Contributor\n" " has been advised of the possibility of such damages.\n" "\n" " 9. Accepting Warranty or Additional Liability. While redistributing\n" " the Work or Derivative Works thereof, You may choose to offer,\n" " and charge a fee for, acceptance of support, warranty, indemnity,\n" " or other liability obligations and/or rights consistent with this\n" " License. However, in accepting such obligations, You may act only\n" " on Your own behalf and on Your sole responsibility, not on behalf\n" " of any other Contributor, and only if You agree to indemnify,\n" " defend, and hold each Contributor harmless for any liability\n" " incurred by, or claims asserted against, such Contributor by reason\n" " of your accepting any such warranty or additional liability.\n" "\n" " END OF TERMS AND CONDITIONS" ))
class CustomDateRangePanel(Panel): FIELDS = [ ('startDateEdit', 'start_date'), ('endDateEdit', 'end_date'), ('slotIndexComboBox', 'slot_index'), ('slotNameEdit', 'slot_name'), ] PERSISTENT_NAME = 'customDateRangePanel' def __init__(self, model, mainwindow): Panel.__init__(self, mainwindow) self.setAttribute(Qt.WA_DeleteOnClose) self._setupUi() self.model = model self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) def _setupUi(self): self.setWindowTitle(tr("Custom Date Range")) self.resize(292, 86) self.setModal(True) self.verticalLayout = QVBoxLayout(self) self.label = QLabel(tr("Select start and end dates from your custom range:")) self.verticalLayout.addWidget(self.label) self.horizontalLayout = QHBoxLayout() self.label_2 = QLabel(tr("Start:")) self.horizontalLayout.addWidget(self.label_2) self.startDateEdit = DateEdit(self) self.horizontalLayout.addWidget(self.startDateEdit) self.label_3 = QLabel(tr("End:")) self.horizontalLayout.addWidget(self.label_3) self.endDateEdit = DateEdit(self) self.horizontalLayout.addWidget(self.endDateEdit) self.verticalLayout.addLayout(self.horizontalLayout) self.horizontalLayout_2 = QHBoxLayout() self.label_4 = QLabel(tr("Save this range under slot:")) self.horizontalLayout_2.addWidget(self.label_4) self.slotIndexComboBox = QComboBox(self) sizePolicy = QSizePolicy(QSizePolicy.Maximum, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.slotIndexComboBox.sizePolicy().hasHeightForWidth()) self.slotIndexComboBox.setSizePolicy(sizePolicy) for s in [tr("None"), tr("#1"), tr("#2"), tr("#3")]: self.slotIndexComboBox.addItem(s) self.horizontalLayout_2.addWidget(self.slotIndexComboBox) spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout_2.addItem(spacerItem) self.verticalLayout.addLayout(self.horizontalLayout_2) self.horizontalLayout_3 = QHBoxLayout() self.label_5 = QLabel(tr("Under the name:")) self.horizontalLayout_3.addWidget(self.label_5) self.slotNameEdit = QLineEdit(self) sizePolicy = QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.slotNameEdit.sizePolicy().hasHeightForWidth()) self.slotNameEdit.setSizePolicy(sizePolicy) self.horizontalLayout_3.addWidget(self.slotNameEdit) self.verticalLayout.addLayout(self.horizontalLayout_3) self.buttonBox = QDialogButtonBox(self) self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel|QDialogButtonBox.Ok) self.verticalLayout.addWidget(self.buttonBox)
class FiltersDialog(QDialog): def __init__( self, application: "Application", engine: Engine, parent: QObject = None ) -> None: super().__init__(parent) self.setAttribute(Qt.WA_DeleteOnClose) # The window doesn't raise on Windows when the app is not in focus, # so after the login in the browser, we open the filters window with # the "stay on top" hint to make sure it comes back to the front # instead of just having a blinking icon in the taskbar. self.setWindowFlags(Qt.WindowStaysOnTopHint) self.setWindowTitle(Translator.get("FILTERS_WINDOW_TITLE")) self.vertical_layout = QVBoxLayout(self) self.vertical_layout.setContentsMargins(0, 0, 0, 0) self._engine = engine self.syncing = self._engine.is_syncing() # NXDRIVE-959 self.application = application self.setWindowIcon(self.application.icon) self.no_root_label = self.get_no_roots_label() self.tree_view = self.get_tree_view() self.vertical_layout.addWidget(self.tree_view) self.vertical_layout.addWidget(self.no_root_label) # Select/Unselect roots self.select_all_state = True self.select_all_text = ( Translator.get("UNSELECT_ALL"), Translator.get("SELECT_ALL"), ) self.button_box = QDialogButtonBox(self) self.button_box.setOrientation(Qt.Horizontal) buttons = QDialogButtonBox.Ok if not self.syncing: buttons |= QDialogButtonBox.Cancel self.select_all_button = self.button_box.addButton( self.select_all_text[self.select_all_state], QDialogButtonBox.ActionRole ) self.select_all_button.clicked.connect(self._select_unselect_all_roots) self.button_box.setStandardButtons(buttons) self.vertical_layout.addWidget(self.button_box) self.button_box.accepted.connect(self.accept) self.button_box.rejected.connect(self.reject) def get_tree_view(self) -> Union[QLabel, FolderTreeview]: if self.syncing: # Prevent filter modifications while syncing label = QLabel(Translator.get("FILTERS_DISABLED")) label.setMargin(15) label.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) return label self.resize(491, 443) filters = self._engine.get_dao().get_filters() remote = self._engine.remote client = FsClient(remote, filters) tree_view = FolderTreeview(self, client) tree_view.noRoots.connect(self._handle_no_roots) return tree_view def get_no_roots_label(self) -> QLabel: label = QLabel(parent=self) text = Translator.get( "NO_ROOTS", [ self._engine.server_url, "https://doc.nuxeo.com/nxdoc/nuxeo-drive/#synchronizing-a-folder", ], ) label.setText(text) label.setMargin(15) label.resize(400, 200) label.setWordWrap(True) label.setVisible(False) label.setOpenExternalLinks(True) label.setAlignment(Qt.AlignHCenter | Qt.AlignVCenter) return label def _handle_no_roots(self) -> None: self.no_root_label.setVisible(True) self.select_all_button.setVisible(False) self.tree_view.setVisible(False) self.tree_view.resize(0, 0) self.setGeometry(self.x() + 50, self.y() + 150, 400, 200) def accept(self) -> None: """ When you click on the OK button. """ if not self.syncing: # Prevent filter modifications while syncing self.apply_filters() super().accept() def apply_filters(self) -> None: items = sorted(self.tree_view.dirty_items, key=lambda x: x.get_path()) for item in items: path = item.get_path() if item.state == Qt.Unchecked: self._engine.add_filter(path) elif item.state == Qt.Checked: self._engine.remove_filter(path) elif item.old_state == Qt.Unchecked: # Now partially checked and was before a filter # Remove current parent filter and need to commit to enable the # add self._engine.remove_filter(path) # We need to browse every child and create a filter for # unchecked as they are not dirty but has become root filter for child in item.get_children(): if child.state == Qt.Unchecked: self._engine.add_filter(child.get_path()) if not self._engine.is_started(): self._engine.start() def _select_unselect_all_roots(self, _: Qt.CheckState) -> None: """Select/Unselect all roots.""" state = Qt.Checked if self.select_all_state else Qt.Unchecked roots = sorted(self.tree_view.client.roots, key=lambda x: x.get_path()) for num, root in enumerate(roots): index = self.tree_view.model().index(num, 0) item = self.tree_view.model().itemFromIndex(index) if item.checkState() != state: item.setCheckState(state) self.tree_view.update_item_changed(item) self.select_all_state = not self.select_all_state self.select_all_button.setText(self.select_all_text[self.select_all_state])
class SinogramDialog(QDialog): def __init__(self, image, alpha, detectors, width, parent=None): super(SinogramDialog, self).__init__(parent) self.image = image self.alpha = float(alpha) self.detectors = int(detectors) self.width = int(width) self.scene = QGraphicsScene() self.sscene = QGraphicsScene() self.sinogram = np.zeros((1, self.detectors)) self.setWindowTitle("Sinogram") self.slider = QtWidgets.QSlider(Qt.Horizontal) self.slider.setFixedWidth(360) self.slider.setRange(0, 100) self.slider.valueChanged.connect(self.valuechange) self.slabel = QLabel("") self.testButton = QPushButton("Click") self.testButton.clicked.connect(lambda: self.computeSinogram(self.slider.value())) self.buttonBox = QDialogButtonBox(self) self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok) # self.buttonBox.accepted.connect() <- what will happen on Ok self.buttonBox.rejected.connect(self.close) # <- what will happen on Cancel self.gv = QGraphicsView(self.scene, self) self.gv.setGeometry(QRect(0, 0, 300, 300)) self.gvresult = QGraphicsView(self.sscene, self) self.gvresult.setGeometry(QRect(0, 0, 300, 300)) self.verticalLayout = QtWidgets.QVBoxLayout(self) self.horizontalLayout = QtWidgets.QHBoxLayout(self) self.verticalform = QtWidgets.QVBoxLayout(self) self.patient_sex = QTextEdit() self.patient_sex.setFixedWidth(200) self.patient_sex.setFixedHeight(25) self.patient_sex_label = QLabel("Type patient's sex (M F)") self.patient_sex_label.setFixedHeight(25) self.patient_name = QTextEdit() self.patient_name.setFixedWidth(200) self.patient_name.setFixedHeight(25) self.patient_name_label = QLabel("Type patient's name (Name^Surname)") self.patient_name_label.setFixedHeight(25) self.patients_ID = QTextEdit() self.patients_ID.setFixedWidth(200) self.patients_ID.setFixedHeight(25) self.patients_ID_label = QLabel("Type patient's ID") self.patients_ID_label.setFixedHeight(25) self.comment = QTextEdit() self.comment.setFixedWidth(200) self.comment.setFixedHeight(25) self.comment_label = QLabel("Type your comment") self.comment_label.setFixedHeight(25) self.date = QTextEdit() self.date.setFixedWidth(200) self.date.setFixedHeight(25) self.date_label = QLabel("Type date of photo (YYYYMMDD)") self.date_label.setFixedHeight(25) self.time = QTextEdit() self.time.setFixedWidth(200) self.time.setFixedHeight(25) self.time_label = QLabel("Type time of photo (HHMMSS.MMMMM") self.time_label.setFixedHeight(25) self.dicom_button = QPushButton("Save result to DICOM") self.dicom_button.setFixedHeight(25) self.dicom_button.clicked.connect(self.save_to_dicom) self.verticalform.addWidget(self.patient_name_label) self.verticalform.addWidget(self.patient_name) self.verticalform.addWidget(self.patients_ID_label) self.verticalform.addWidget(self.patients_ID) self.verticalform.addWidget(self.patient_sex_label) self.verticalform.addWidget(self.patient_sex) self.verticalform.addWidget(self.comment_label) self.verticalform.addWidget(self.comment) self.verticalform.addWidget(self.date_label) self.verticalform.addWidget(self.date) self.verticalform.addWidget(self.time_label) self.verticalform.addWidget(self.time) self.verticalform.addWidget(self.dicom_button) self.verticalform.addStretch(1) self.horizontalLayout.addLayout(self.verticalform) self.horizontalLayout.addWidget(self.gv) self.horizontalLayout.addWidget(self.gvresult) self.verticalLayout.addWidget(self.slider) self.verticalLayout.addWidget(self.slabel) self.verticalLayout.addWidget(self.testButton) self.verticalLayout.addLayout(self.horizontalLayout) self.verticalLayout.addWidget(self.buttonBox) self.sinogramLogic = SinogramLogic(self.image, self.alpha, self.detectors, self.width) def save_to_dicom(self): save_to_dicom_file(self.invsg, "dicom_output.dcm", self.patient_name.toPlainText(), self.patients_ID.toPlainText(), self.patient_sex.toPlainText(), self.comment.toPlainText(), self.date.toPlainText(), self.time.toPlainText()) self.info = QMessageBox.information(self, "File saved", "File saved to .dcm", QMessageBox.Ok) def valuechange(self): self.slabel.setText(str(self.slider.value())+"%") # sg = self.sinograms[self.slider.value()] # invsg = self.invsinograms[self.slider.value()] # self.img = QImage(sg.astype(np.uint8), sg.shape[1], sg.shape[0], sg.shape[1], QImage.Format_Grayscale8) # self.pict = QPixmap(self.img) # print(type(self.pict)) # self.scene.clear() # self.scene.addPixmap(self.pict) # self.gv.fitInView(QGraphicsPixmapItem(self.pict).boundingRect(), Qt.KeepAspectRatio) # self.gv.setScene(self.scene) # self.img2 = QImage(invsg.astype(np.uint8), invsg.shape[1], invsg.shape[0], invsg.shape[1], QImage.Format_Grayscale8) # self.pict2 = QPixmap(self.img2) # self.sscene.clear() # self.sscene.addPixmap(self.pict2) # self.gvresult.fitInView(QGraphicsPixmapItem(self.pict2).boundingRect(), Qt.KeepAspectRatio) # self.gvresult.setScene(self.sscene) def plotEmitersAndDecoders(self, x, y, iks, igrek, detectors_x_list, detectors_y_list): plt.scatter(iks, igrek, color="red") plt.scatter(detectors_x_list, detectors_y_list, color="blue") circle = plt.Circle([x / 2, y / 2], radius=x / 2, fill=False, color='green') for (x2, y2) in zip(detectors_x_list, detectors_y_list): plt.plot([iks, x2], [igrek, y2], color='gray', linestyle='dashed', linewidth=2) ax = plt.gca() ax.set_xlim(-1, x + 1) ax.set_ylim(-1, y + 1) ax.imshow(self.image, cmap='gray') ax.add_artist(circle) # plt.show() plt.savefig('wiz.png') def computeSinogram(self, progress): progress = progress*1.0/100 sinogram = SinogramLogic(self.image, self.alpha, self.detectors, self.width) print("ok") sg, invsg = sinogram.image_processing(self.image, self.alpha, progress, self.detectors, self.width) print(sg.shape, type(sg), invsg.shape, type(invsg)) sg = sg*1.0/np.max(sg)*255 # normalize self.invsg = invsg*1.0/np.max(invsg)*255 # normalize plt.imshow(sg, cmap="gray") plt.savefig('foo.png') self.img = QImage(sg.astype(np.uint8), sg.shape[1], sg.shape[0], sg.shape[1], QImage.Format_Grayscale8) self.pict = QPixmap(self.img) print(type(self.pict)) self.scene.clear() self.scene.addPixmap(self.pict) self.gv.fitInView(QGraphicsPixmapItem(self.pict).boundingRect(), Qt.KeepAspectRatio) self.gv.setScene(self.scene) self.img2 = QImage(self.invsg.astype(np.uint8), self.invsg.shape[1], self.invsg.shape[0], self.invsg.shape[1], QImage.Format_Grayscale8) self.pict2 = QPixmap(self.img2) self.sscene.clear() self.sscene.addPixmap(self.pict2) self.gvresult.fitInView(QGraphicsPixmapItem(self.pict2).boundingRect(), Qt.KeepAspectRatio) self.gvresult.setScene(self.sscene) plt.imshow(sg, cmap="gray") plt.savefig('result.png')
class AccountPanel(Panel): FIELDS = [ ('nameEdit', 'name'), ('accountNumberEdit', 'account_number'), ('inactiveBox', 'inactive'), ('notesEdit', 'notes'), ] PERSISTENT_NAME = 'accountPanel' def __init__(self, model, mainwindow): Panel.__init__(self, mainwindow) self.setAttribute(Qt.WA_DeleteOnClose) self._setupUi() self.model = model self.typeComboBox = ComboboxModel(model=self.model.type_list, view=self.typeComboBoxView) self.currencyComboBox = ComboboxModel(model=self.model.currency_list, view=self.currencyComboBoxView) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) def _setupUi(self): self.setWindowTitle(tr("Account Info")) self.resize(274, 121) self.setModal(True) self.verticalLayout = QVBoxLayout(self) self.formLayout = QFormLayout() self.formLayout.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow) self.label = QLabel(tr("Name")) self.formLayout.setWidget(0, QFormLayout.LabelRole, self.label) self.nameEdit = QLineEdit() self.formLayout.setWidget(0, QFormLayout.FieldRole, self.nameEdit) self.label_2 = QLabel(tr("Type")) self.formLayout.setWidget(1, QFormLayout.LabelRole, self.label_2) self.typeComboBoxView = QComboBox() self.formLayout.setWidget(1, QFormLayout.FieldRole, self.typeComboBoxView) self.label_3 = QLabel(tr("Currency")) self.formLayout.setWidget(2, QFormLayout.LabelRole, self.label_3) self.currencyComboBoxView = QComboBox() sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.currencyComboBoxView.sizePolicy().hasHeightForWidth()) self.currencyComboBoxView.setSizePolicy(sizePolicy) self.currencyComboBoxView.setEditable(True) self.currencyComboBoxView.setInsertPolicy(QComboBox.NoInsert) self.formLayout.setWidget(2, QFormLayout.FieldRole, self.currencyComboBoxView) self.accountNumberLabel = QLabel(tr("Account #")) self.formLayout.setWidget(3, QFormLayout.LabelRole, self.accountNumberLabel) self.accountNumberEdit = QLineEdit() self.accountNumberEdit.setMaximumSize(QSize(80, 16777215)) self.formLayout.setWidget(3, QFormLayout.FieldRole, self.accountNumberEdit) self.inactiveBox = QCheckBox() self.formLayout.addRow(tr("Inactive:"), self.inactiveBox) self.notesEdit = QPlainTextEdit() self.formLayout.addRow(tr("Notes:"), self.notesEdit) self.verticalLayout.addLayout(self.formLayout) self.buttonBox = QDialogButtonBox() self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel|QDialogButtonBox.Save) self.verticalLayout.addWidget(self.buttonBox) self.label.setBuddy(self.nameEdit) self.label_2.setBuddy(self.typeComboBoxView) self.label_3.setBuddy(self.currencyComboBoxView) def _loadFields(self): Panel._loadFields(self) self.currencyComboBoxView.setEnabled(self.model.can_change_currency)
class Bookmarks_Dialog(object): def setupUi(self, Dialog, bookmark_data, favourites): Dialog.resize(740, 450) Dialog.setWindowTitle('Bookmarks Manager') self.layout = QGridLayout(Dialog) self.urlLabel = QLabel('URL :', Dialog) self.layout.addWidget(self.urlLabel, 0, 0, 1, 1) self.urlBox = UrlBox(Dialog) self.layout.addWidget(self.urlBox, 0, 1, 1, 5) # Create Tab Widget self.tabWidget = QTabWidget(Dialog) self.tabWidget.setDocumentMode(True) self.tabWidget.tabBar().setExpanding(True) # Add Bookmarks Table self.bookmarks_table = BookmarksTable(Dialog, bookmark_data, True) self.tabWidget.addTab(self.bookmarks_table, 'Bookmarks') # Add Favourites table self.layout.addWidget(self.tabWidget, 1, 0, 1, 6) # Add Buttons self.moveUpBtn = QPushButton(QIcon(":/go-up.png"), '', Dialog) self.moveUpBtn.clicked.connect(self.moveItemUp) self.layout.addWidget(self.moveUpBtn, 2, 0, 1, 1) self.moveDownBtn = QPushButton(QIcon(":/go-down.png"), '', Dialog) self.moveDownBtn.clicked.connect(self.moveItemDown) self.layout.addWidget(self.moveDownBtn, 2, 1, 1, 1) self.copyLinkBtn = QPushButton(QIcon(":/edit-copy.png"), '', Dialog) self.copyLinkBtn.clicked.connect(self.copyItemLink) self.layout.addWidget(self.copyLinkBtn, 2, 2, 1, 1) self.editBtn = QPushButton(QIcon(":/edit.png"), '', Dialog) self.editBtn.clicked.connect(self.editItem) self.layout.addWidget(self.editBtn, 2, 3, 1, 1) self.deleteBtn = QPushButton(QIcon(":/edit-delete.png"), '', Dialog) self.deleteBtn.clicked.connect(self.deleteItem) self.layout.addWidget(self.deleteBtn, 2, 4, 1, 1) # Add ButtonBox self.buttonBox = QDialogButtonBox(Dialog) self.buttonBox.setOrientation(QtCore.Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Close) self.layout.addWidget(self.buttonBox, 2, 5, 1, 1) self.bookmarks_table.urlSelected.connect(self.urlBox.setText) self.bookmarks_table.doubleclicked.connect(Dialog.accept) self.bookmarks_table.itemSelectionChanged.connect( self.toggleButtonAccess) self.tabWidget.currentChanged.connect(self.toggleButtonAccess) self.buttonBox.accepted.connect(Dialog.accept) self.buttonBox.rejected.connect(Dialog.reject) self.bookmarks_table.selectRow(0) self.bookmarks_table.setFocus() def toggleButtonAccess(self): selection_count = len(self.tabWidget.currentWidget().selectedIndexes()) if selection_count == 1: self.setButtonEnabled(True, True, True, True, True) elif selection_count > 1: self.setButtonEnabled(False, False, False, False, True) else: self.setButtonEnabled(False, False, False, False, False) def setButtonEnabled(self, state1, state2, state3, state4, state5): self.moveUpBtn.setEnabled(state1) self.moveDownBtn.setEnabled(state2) self.copyLinkBtn.setEnabled(state3) self.editBtn.setEnabled(state4) self.deleteBtn.setEnabled(state5) def moveItemUp(self): self.tabWidget.currentWidget().moveItemUp() self.tabWidget.currentWidget().setFocus() def moveItemDown(self): self.tabWidget.currentWidget().moveItemDown() self.tabWidget.currentWidget().setFocus() def copyItemLink(self): self.tabWidget.currentWidget().copyItemLink() self.tabWidget.currentWidget().setFocus() def editItem(self): self.tabWidget.currentWidget().editItem() self.tabWidget.currentWidget().setFocus() def deleteItem(self): self.tabWidget.currentWidget().deleteItem()
class VentanaCajero(QDialog): def __init__(self, parent=None, username=""): super(VentanaCajero, self).__init__(parent) self.buttonBox = QDialogButtonBox(self) self.buttonBox.setOrientation(QtCore.Qt.Horizontal) self.buttonBox.setStandardButtons( QDialogButtonBox.Cancel | QDialogButtonBox.Ok) self.clienteLabel = QLabel("Nombre cliente", self) self.clienteText = QLineEdit(self) self.idLabel = QLabel("RUT", self) self.idText = QLineEdit(self) self.gastadoLabel = QLabel("Gastado", self) self.gastadoText = QLineEdit(self) self.verticalLayout = QVBoxLayout(self) self.verticalLayout.addWidget(self.clienteLabel) self.verticalLayout.addWidget(self.clienteText) self.verticalLayout.addWidget(self.idLabel) self.verticalLayout.addWidget(self.idText) self.verticalLayout.addWidget(self.gastadoLabel) self.verticalLayout.addWidget(self.gastadoText) self.verticalLayout.addWidget(self.buttonBox) self.buttonBox.accepted.connect(self.serializarCliente) self.buttonBox.rejected.connect(self.close) def serializarCliente(self): ##### ID_cliente = self.idText.text() Archivo_cliente = str(ID_cliente) + ".walkcart" # Verificamos si cliente existe en DB if Archivo_cliente in os.listdir("ClientesDB"): # Existe -> Abrimos, cambiamos y cerramos with open("ClientesDB/" + Archivo_cliente, "rb") as file: cliente_existente = pickle.load(file) cliente_existente.actualizarGasto(int(self.gastadoText.text())) with open("ClientesDB/" + Archivo_cliente, "wb") as file: pickle.dump(cliente_existente, file) else: # No existe -> Creamos y cerramos nuevo_cliente = Cliente( self.clienteText.text(), int(self.idText.text()), int(self.gastadoText.text()) ) nuevo_archivo = "ClientesDB/" + str(nuevo_cliente.ID) + ".walkcart" with open(nuevo_archivo, "wb") as file: pickle.dump(nuevo_cliente) ##### self.clienteText.setText("") self.idText.setText("") self.gastadoText.setText("")
class MeteoSettings(QDialog): applied_signal = pyqtSignal() def __init__(self, accurate_url, appid, parent=None): super(MeteoSettings, self).__init__(parent) self.settings = QSettings() trans_cities_dict = self.settings.value('CitiesTranslation') or '{}' self.trans_cities_dict = eval(trans_cities_dict) self.layout = QVBoxLayout() self.accurate_url = accurate_url self.appid = appid self.set_city = self.settings.value('City') or '?' locale = QLocale.system().name() locale_long = ['pt_BR', 'zh_CN', 'zh_TW'] if locale not in locale_long: locale = locale[:2] self.interval_set = self.settings.value('Interval') or '30' self.temp_tray_color = self.settings.value('TrayColor') or '' # -----Cities comboBox------------------------ self.first = True self.clear_combo = False self.city_list_before = [] self.citylist = [] self.city_combo = QComboBox() if self.set_city != '?': self.add_cities_incombo() self.city_combo.currentIndexChanged.connect(self.city_default) self.city_title = QLabel(self.tr('City')) self.city_button = QPushButton() self.city_button.setIcon(QIcon(':/configure')) self.city_button.setToolTip(self.tr('Click to edit the cities list')) self.city_button.clicked.connect(self.edit_cities_list) # ------Language------------------------------ self.language_label = QLabel(self.tr('Language')) self.language_combo = QComboBox() self.language_combo.setToolTip( QCoreApplication.translate('Tooltip', 'The application has to be restared to apply the language setting', 'Settings dialogue')) self.language_dico = {'bg': self.tr('Bulgarian'), 'ca': self.tr('Catalan'), 'cs': self.tr('Czech'), 'da': self.tr('Danish'), 'de': self.tr('German'), 'el': self.tr('Greek'), 'en': self.tr('English'), 'es': self.tr('Spanish'), 'fi': self.tr('Finnish'), 'fr': self.tr('French'), 'he': self.tr('Hebrew'), 'hr': self.tr('Croatian'), 'hu': self.tr('Hungarian'), 'it': self.tr('Italian'), 'ja': self.tr('Japanese'), 'lt': self.tr('Lithuanian'), 'nb': self.tr('Norwegian (Bokmaal)'), 'nl': self.tr('Dutch'), 'pl': self.tr('Polish'), 'pt': self.tr('Portuguese'), 'pt_BR': self.tr('Brazil Portuguese'), 'ro': self.tr('Romanian'), 'ru': self.tr('Russian'), 'sk': self.tr('Slovak'), 'sv': self.tr('Swedish'), 'tr': self.tr('Turkish'), 'uk': self.tr('Ukrainian'), 'zh_TW': self.tr('Chinese Traditional'), 'zh_CN': self.tr('Chinese Simplified')} lang_list = sorted(self.language_dico.values()) # English as fallback language if locale not in self.language_dico: locale = 'en' self.setLanguage = self.settings.value('Language') or locale self.language_combo.addItems(lang_list) self.language_combo.setCurrentIndex(self.language_combo.findText (self.language_dico[self.setLanguage])) self.language_combo.currentIndexChanged.connect(self.language) self.lang_changed = False # Unit system self.units_changed = False self.temp_unit = self.settings.value('Unit') if self.temp_unit is None or self.temp_unit == '': self.temp_unit = 'metric' self.units_changed = True self.units_label = QLabel(self.tr('Temperature unit')) self.units_combo = QComboBox() self.units_dico = {'metric': '°C', 'imperial': '°F', ' ': '°K'} units_list = sorted(self.units_dico.values()) self.units_combo.addItems(units_list) self.units_combo.setCurrentIndex(self.units_combo.findText( self.units_dico[self.temp_unit])) self.units_combo.currentIndexChanged.connect(self.units) # Beaufort self.bft_checkbox = QCheckBox(QCoreApplication.translate('Wind unit - Checkbox label', 'Wind unit in Beaufort', 'Settings dialogue')) bft_bool = self.settings.value('Beaufort') or 'False' self.bft_bool = eval(bft_bool) self.bft_checkbox.setChecked(self.bft_bool) self.bft_checkbox.stateChanged.connect(self.beaufort) self.bft_changed = False # Decimal in trayicon self.temp_decimal_label = QLabel(QCoreApplication.translate( 'If the temperature will be shown with a decimal or rounded in tray icon', 'Temperature accuracy in system tray', 'Settings dialogue')) self.temp_decimal_combo = QComboBox() temp_decimal_combo_dico = {'False': '0°', 'True': '0.1°'} temp_decimal_combo_list = [temp_decimal_combo_dico['False'], temp_decimal_combo_dico['True']] self.temp_decimal_combo.addItems(temp_decimal_combo_list) temp_decimal_bool_str = self.settings.value('Decimal') or 'False' self.temp_decimal_combo.setCurrentIndex(self.temp_decimal_combo.findText( temp_decimal_combo_dico[temp_decimal_bool_str])) self.temp_decimal_combo.currentIndexChanged.connect(self.temp_decimal) self.temp_decimal_changed = False # Interval of updates self.interval_label = QLabel(self.tr('Update interval')) self.interval_min = QLabel(self.tr('minutes')) self.interval_combo = QComboBox() self.interval_list = ['15', '30', '45', '60', '90', '120'] self.interval_combo.addItems(self.interval_list) self.interval_combo.setCurrentIndex(self.interval_combo.findText( self.interval_list[self.interval_list.index(self.interval_set)])) self.interval_combo.currentIndexChanged.connect(self.interval) self.interval_changed = False # OK Cancel Apply Buttons self.buttonLayout = QHBoxLayout() self.buttonLayout.addStretch() self.buttonBox = QDialogButtonBox() self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons( QDialogButtonBox.Ok | QDialogButtonBox.Apply | QDialogButtonBox.Cancel) self.buttonBox.setContentsMargins(0, 30, 0, 0) self.buttonLayout.addWidget(self.buttonBox) self.buttonBox.button(QDialogButtonBox.Apply).clicked.connect(self.apply_settings) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(False) # Autostart self.autostart_label = QLabel(self.tr('Launch at startup')) self.autostart_checkbox = QCheckBox() autostart_bool = self.settings.value('Autostart') or 'False' autostart_bool = eval(autostart_bool) self.autostart_checkbox.setChecked(autostart_bool) self.autostart_checkbox.stateChanged.connect(self.autostart) self.autostart_changed = False # Tray temp° color self.temp_colorLabel = QLabel(self.tr('Font colour in the tray')) self.temp_colorButton = QPushButton() self.temp_colorButton.setStyleSheet( 'QWidget {{ background-color: {0} }}'.format(self.temp_tray_color)) self.temp_colorButton.setMaximumSize(QSize(44, 24)) self.temp_colorButton.clicked.connect(self.color_chooser) self.temp_color_resetButton = QPushButton(self.tr('Reset')) self.temp_color_resetButton.setToolTip( self.tr('Reset font colour to system default')) self.temp_color_resetButton.clicked.connect(self.color_reset) # Display notifications self.notifier_label = QLabel(self.tr('Notification on weather update')) self.notifier_checkbox = QCheckBox() notifier_bool = self.settings.value('Notifications') or 'True' notifier_bool = eval(notifier_bool) self.notifier_checkbox.setChecked(notifier_bool) self.notifier_checkbox.stateChanged.connect(self.notifier) self.notifier_changed = False # Icon & Temp self.tray_icon_temp_label = QLabel(QCoreApplication.translate( "Settings dialogue", "System tray icon", '''Setting to choose the type of the icon on the tray (only icon, only text, icon&text''')) self.tray_icon_combo = QComboBox() tray_icon_temp = QCoreApplication.translate( "Settings dialogue", "Icon & temperature", 'Setting to choose the type of the icon on the tray') tray_icon = QCoreApplication.translate( "Settings dialogue", "Icon", 'Setting to choose the type of the icon on the tray') tray_temp = QCoreApplication.translate( "Settings dialogue", "Temperature", 'Setting to choose the type of the icon on the tray') self.tray_dico = {'icon&temp': tray_icon_temp, 'icon': tray_icon, 'temp': tray_temp} set_tray_icon = self.settings.value('TrayType') or 'icon&temp' tray_icon_list = sorted(self.tray_dico.values()) self.tray_icon_combo.addItems(tray_icon_list) self.tray_icon_combo.setCurrentIndex(self.tray_icon_combo.findText (self.tray_dico[set_tray_icon])) self.tray_icon_combo.currentIndexChanged.connect(self.tray) self.tray_changed = False # Font size fontsize = self.settings.value('FontSize') or '18' self.fontsize_label = QLabel(QCoreApplication.translate( "Settings dialog", "Font size in tray", "Setting for the font size of the temperature in the tray icon")) self.fontsize_spinbox = QSpinBox() self.fontsize_spinbox.setRange(12, 32) self.fontsize_spinbox.setValue(int(fontsize)) if fontsize is None or fontsize == '': self.settings.setValue('FontSize', '18') self.fontsize_changed = False self.fontsize_spinbox.valueChanged.connect(self.fontsize_change) # Font weight self.bold_checkbox = QCheckBox(QCoreApplication.translate('Font setting - Checkbox label', 'Bold', 'Settings dialogue')) bold_bool = self.settings.value('Bold') or 'False' self.bold_bool = eval(bold_bool) self.bold_checkbox.setChecked(self.bold_bool) self.bold_checkbox.stateChanged.connect(self.bold) self.bold_changed = False # Proxy self.proxy_label = QLabel(QCoreApplication.translate( 'Checkbox', 'Connection by proxy', 'Settings dialogue')) self.proxy_chbox = QCheckBox() proxy_bool = self.settings.value('Proxy') or 'False' self.proxy_bool = eval(proxy_bool) self.proxy_chbox.setChecked(self.proxy_bool) self.proxy_chbox.stateChanged.connect(self.proxy) self.proxy_changed = False self.proxy_button = QPushButton(QCoreApplication.translate( 'Label of button to open the proxy dialogue', 'Settings', 'Settings dialogue')) self.proxy_button.clicked.connect(self.proxy_settings) self.proxy_button.setEnabled(self.proxy_bool) # Openweathermap key self.owmkey_label = QLabel(QCoreApplication.translate( 'The key that user can generate in his OpenWeatherMap profile', 'OpenWeatherMap key', 'Settings dialogue')) self.owmkey_create = QLabel(QCoreApplication.translate( 'Link to create a profile in OpenWeatherMap', "<a href=\"http://home.openweathermap.org/users/sign_up\">Create key</a>", 'Settings dialogue')) self.owmkey_create.setOpenExternalLinks(True) apikey = self.settings.value('APPID') or '' self.owmkey_text = QLineEdit() self.owmkey_text.setText(apikey) self.owmkey_text.textChanged.connect(self.apikey_changed) # ---------- self.panel = QGridLayout() self.panel.addWidget(self.city_title, 0, 0) self.panel.addWidget(self.city_combo, 0, 1) self.panel.addWidget(self.city_button, 0, 2) self.panel.addWidget(self.language_label, 1, 0) self.panel.addWidget(self.language_combo, 1, 1) self.panel.addWidget(self.units_label, 2, 0) self.panel.addWidget(self.units_combo, 2, 1) self.panel.addWidget(self.bft_checkbox, 2, 2) self.panel.addWidget(self.temp_decimal_label, 3, 0) self.panel.addWidget(self.temp_decimal_combo, 3, 1) self.panel.addWidget(self.interval_label, 4, 0) self.panel.addWidget(self.interval_combo, 4, 1) self.panel.addWidget(self.interval_min, 4, 2) self.panel.addWidget(self.autostart_label, 5, 0) self.panel.addWidget(self.autostart_checkbox, 5, 1) self.panel.addWidget(self.temp_colorLabel, 6, 0) self.panel.addWidget(self.temp_colorButton, 6, 1) self.panel.addWidget(self.temp_color_resetButton, 6, 2) self.panel.addWidget(self.notifier_label, 7, 0) self.panel.addWidget(self.notifier_checkbox, 7, 1) self.panel.addWidget(self.tray_icon_temp_label, 8, 0) self.panel.addWidget(self.tray_icon_combo, 8, 1) self.panel.addWidget(self.fontsize_label, 9, 0) self.panel.addWidget(self.fontsize_spinbox, 9, 1) self.panel.addWidget(self.bold_checkbox, 9, 2) self.panel.addWidget(self.proxy_label, 10, 0) self.panel.addWidget(self.proxy_chbox, 10, 1) self.panel.addWidget(self.proxy_button, 10, 2) self.panel.addWidget(self.owmkey_label, 11, 0) self.panel.addWidget(self.owmkey_text, 11, 1) self.panel.addWidget(self.owmkey_create, 11, 2) self.layout.addLayout(self.panel) self.layout.addLayout(self.buttonLayout) self.statusbar = QLabel() self.layout.addWidget(self.statusbar) self.nokey_message = QCoreApplication.translate( 'Warning message after pressing Ok', 'Please enter your OpenWeatherMap key', 'Settings dialogue') self.nocity_message = QCoreApplication.translate( 'Warning message after pressing OK', 'Please add a city', 'Settings dialogue') self.setLayout(self.layout) self.setWindowTitle(self.tr('Meteo-qt Configuration')) def units(self): self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(True) self.units_changed = True def language(self): self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(True) self.lang_changed = True def city_default(self): allitems = [self.city_combo.itemText(i) for i in range(self.city_combo.count())] allitems_not_translated = [] for i in allitems: allitems_not_translated.append(self.find_city_key(i)) city_name = self.city_combo.currentText() city_name = self.find_city_key(city_name) citytosave = city_name.split('_') # This self variable will serve to check if a translation # exist for the current city when quitting self.citytosave = '_'.join(citytosave) if len(citytosave) < 3: return self.id_before = citytosave[2] self.city_before = citytosave[0] self.country_before = citytosave[1] self.city_list_before = allitems_not_translated[:] self.city_list_before.pop(self.city_list_before.index(city_name)) self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(True) def interval(self): self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(True) self.interval_changed = True def edit_cities_list(self): apikey = self.owmkey_text.text() apiid = '&APPID=' + apikey if apikey == '': self.statusbar.setText(self.nokey_message) return dialog = citylistdlg.CityListDlg(self.citylist, self.accurate_url, apiid, self.trans_cities_dict, self) dialog.citieslist_signal.connect(self.cities_list) dialog.citiesdict_signal.connect(self.cities_dict) dialog.exec_() def cities_dict(self, cit_dict): self.trans_cities_dict = cit_dict def cities_list(self, cit_list): if len(cit_list) > 0: citytosave = cit_list[0].split('_') self.id_before = citytosave[2] self.city_before = citytosave[0] self.country_before = citytosave[1] if len(cit_list) > 1: self.city_list_before = cit_list[1:] else: self.city_list_before = str('') else: self.id_before = '' self.city_before = '' self.country_before = '' self.city_list_before = [] self.clear_combo = True self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(True) self.first = False self.add_cities_incombo() def autostart(self, state): self.autostart_state = state self.autostart_changed = True self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(True) def autostart_apply(self): dir_auto = '/.config/autostart/' d_file = 'meteo-qt.desktop' home = os.getenv('HOME') total_path = home + dir_auto + d_file if self.autostart_state == 2: desktop_file = ['[Desktop Entry]\n', 'Exec=meteo-qt\n', 'Name=meteo-qt\n', 'Type=Application\n', 'Version=1.0\n', 'X-LXQt-Need-Tray=true\n'] if not os.path.exists(home + dir_auto): os.system('mkdir -p {}'.format(os.path.dirname(total_path))) with open(total_path, 'w') as out_file: out_file.writelines(desktop_file) self.settings.setValue('Autostart', 'True') logging.debug('Write desktop file in ~/.config/autostart') elif self.autostart_state == 0: if os.path.exists(total_path): os.remove(total_path) self.settings.setValue('Autostart', 'False') logging.debug('Remove desktop file from ~/.config/autostart') else: return def color_chooser(self): col = QColorDialog.getColor() if col.isValid(): self.temp_colorButton.setStyleSheet( 'QWidget {{ background-color: {0} }}'.format(col.name())) # focus to next elem to show immediatley the colour # in the button (in some DEs) self.temp_color_resetButton.setFocus() self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(True) self.color_before = col.name() else: logging.debug('Invalid color:' + str(col)) def color_reset(self): self.temp_colorButton.setStyleSheet('QWidget { background-color: }') self.color_before = '' self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(True) def notifier(self, state): self.notifier_state = state self.notifier_changed = True self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(True) def notifier_apply(self): if self.notifier_state == 2: self.settings.setValue('Notifications', 'True') logging.debug('Write: Notifications = True') elif self.notifier_state == 0: self.settings.setValue('Notifications', 'False') logging.debug('Write: Notifications = False') def temp_decimal(self, state): self.temp_decimal_state = state self.temp_decimal_changed = True self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(True) def tray(self): self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(True) self.tray_changed = True def tray_apply(self): tray = self.tray_icon_combo.currentText() self.settings.setValue('Tray', tray) logging.debug('Write >' + 'Tray >' + str(tray)) settray = [key for key, value in self.tray_dico.items() if value == tray] self.settings.setValue('TrayType', settray[0]) def fontsize_change(self, size): self.fontsize_changed = True self.fontsize_value = size self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(True) def fontsize_apply(self): logging.debug('Apply fontsize: ' + str(self.fontsize_value)) self.settings.setValue('FontSize', str(self.fontsize_value)) def bold(self, state): self.bold_state = state self.bold_changed = True self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(True) def bold_apply(self): if self.bold_state == 2: bold = 'True' else: bold = 'False' self.settings.setValue('Bold', str(bold)) def beaufort(self, state): self.bft_state = state self.bft_changed = True self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(True) def beaufort_apply(self): if self.bft_state == 2: bft = 'True' else: bft = 'False' self.settings.setValue('Beaufort', str(bft)) def proxy(self, state): self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(True) if state == 2: self.proxy_bool = True self.proxy_button.setEnabled(True) else: self.proxy_bool = False self.proxy_button.setEnabled(False) def proxy_settings(self): dialog = proxydlg.Proxy(self) dialog.exec_() def apikey_changed(self): self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(True) def apply_settings(self): self.accepted() def clear_translations(self): ''' Save the list of the current cities list and remove the odd or blank translations''' cities = self.citylist if hasattr(self, 'city_list_before'): self.settings.setValue('CityList', str(self.city_list_before)) logging.debug('write ' + 'CityList ' + str(self.city_list_before)) try: cities = self.city_list_before cities.append(self.citytosave) except: logging.debug('Empty cities list, default city: ' + str(cities)) pass translations_to_delete = [] for key, value in self.trans_cities_dict.items(): if key == value or value == '' or key not in cities: translations_to_delete.append(key) for i in translations_to_delete: del self.trans_cities_dict[i] self.settings.setValue('CitiesTranslation', str(self.trans_cities_dict)) logging.debug('write ' + 'CitiesTranslation ' + str(self.trans_cities_dict)) def accepted(self): self.clear_translations() apikey = self.owmkey_text.text() city_name = self.city_combo.currentText() if apikey == '': self.statusbar.setText(self.nokey_message) return else: self.statusbar.setText('') self.settings.setValue('APPID', str(self.owmkey_text.text())) if city_name == '': self.statusbar.setText(self.nocity_message) return else: self.statusbar.setText('') self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(False) if hasattr(self, 'id_before'): self.settings.setValue('ID', self.id_before) logging.debug('write ' + 'ID' + str(self.id_before)) if hasattr(self, 'city_before'): self.settings.setValue('City', self.city_before) logging.debug('write ' + 'City' + str(self.city_before)) if hasattr(self, 'country_before'): self.settings.setValue('Country', self.country_before) logging.debug('write ' + 'Country' + str(self.country_before)) if hasattr(self, 'color_before'): self.settings.setValue('TrayColor', self.color_before) if self.color_before == '': self.color_before = 'None' logging.debug('Write font color for temp in tray: {0}'.format(self.color_before)) if self.autostart_changed: self.autostart_apply() if self.interval_changed: time = self.interval_combo.currentText() self.settings.setValue('Interval', time) logging.debug('Write ' + 'Interval ' + str(time)) if self.lang_changed: lang = self.language_combo.currentText() setlang = [key for key, value in self.language_dico.items() if value == lang] self.settings.setValue('Language', setlang[0]) logging.debug('Write ' + 'Language ' + str(setlang[0])) if self.units_changed: unit = self.units_combo.currentText() setUnit = [key for key, value in self.units_dico.items() if value == unit] self.settings.setValue('Unit', setUnit[0]) logging.debug('Write ' + 'Unit ' + str(setUnit[0])) if self.temp_decimal_changed: decimal = self.temp_decimal_combo.currentText() decimal_bool_str = 'False' if decimal == '0.1°': decimal_bool_str = 'True' self.settings.setValue('Decimal', decimal_bool_str) logging.debug('Write: Decimal in tray icon = ' + decimal_bool_str) if self.notifier_changed: self.notifier_apply() if self.tray_changed: self.tray_apply() if self.fontsize_changed: self.fontsize_apply() if self.bold_changed: self.bold_apply() if self.bft_changed: self.beaufort_apply() proxy_url = self.settings.value('Proxy_url') or '' if proxy_url == '': self.proxy_bool = False self.settings.setValue('Proxy', str(self.proxy_bool)) self.applied_signal.emit() def accept(self): self.accepted() apikey = self.owmkey_text.text() city_name = self.city_combo.currentText() if apikey == '': self.statusbar.setText(self.nokey_message) return if city_name == '': self.statusbar.setText(self.nocity_message) return QDialog.accept(self) def add_cities_incombo(self): list_cities = '' self.city_combo.clear() if self.clear_combo: return if self.first: list_cities = self.settings.value('CityList') if list_cities is not None: self.city_list_before = list_cities[:] self.citylist = [self.set_city + '_' + self.settings.value('Country') + '_' + self.settings.value('ID')] else: self.citylist = [self.city_before + '_' + self.country_before + '_' + self.id_before] list_cities = self.city_list_before[:] if list_cities is None: list_cities = [] if list_cities != '' and list_cities is not None: if type(list_cities) is str: list_cities = eval(list_cities) self.citylist = self.citylist + list_cities duplicate = [] for i in self.citylist: if i not in duplicate: duplicate.append(i) self.citylist = duplicate[:] self.translated = [] for city in self.citylist: self.translated.append(self.trans_cities_dict.get(city, city)) self.city_combo.addItems(self.translated) if len(list_cities) > 0: maxi = len(max(list_cities, key=len)) self.city_combo.setMinimumSize(maxi*8, 23) def find_city_key(self, city): for key, value in self.trans_cities_dict.items(): if value == city: return key return city
class SchedulePanel(Panel): FIELDS = [ ('startDateEdit', 'start_date'), ('repeatEverySpinBox', 'repeat_every'), ('stopDateEdit', 'stop_date'), ('descriptionEdit', 'description'), ('payeeEdit', 'payee'), ('checkNoEdit', 'checkno'), ('notesEdit', 'notes'), ] PERSISTENT_NAME = 'schedulePanel' def __init__(self, model, mainwindow): Panel.__init__(self, mainwindow) self.setAttribute(Qt.WA_DeleteOnClose) self.model = model self._setupUi() self.splitTable = SplitTable(model=self.model.split_table, view=self.splitTableView) self.repeatTypeComboBox = ComboboxModel(model=self.model.repeat_type_list, view=self.repeatTypeComboBoxView) self.addSplitButton.clicked.connect(self.splitTable.model.add) self.removeSplitButton.clicked.connect(self.splitTable.model.delete) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) def _setupUi(self): self.setWindowTitle(tr("Schedule Info")) self.resize(469, 416) self.setModal(True) self.verticalLayout_2 = QVBoxLayout(self) self.tabWidget = QTabWidget(self) self.tab = QWidget() self.formLayout = QFormLayout(self.tab) self.formLayout.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow) self.label_2 = QLabel(tr("Start Date:")) self.formLayout.setWidget(0, QFormLayout.LabelRole, self.label_2) self.startDateEdit = DateEdit(self.tab) self.startDateEdit.setMaximumSize(QSize(120, 16777215)) self.formLayout.setWidget(0, QFormLayout.FieldRole, self.startDateEdit) self.label_7 = QLabel(tr("Repeat Type:")) self.formLayout.setWidget(1, QFormLayout.LabelRole, self.label_7) self.repeatTypeComboBoxView = QComboBox(self.tab) self.formLayout.setWidget(1, QFormLayout.FieldRole, self.repeatTypeComboBoxView) self.label_8 = QLabel(tr("Every:")) self.formLayout.setWidget(2, QFormLayout.LabelRole, self.label_8) self.horizontalLayout_2 = QHBoxLayout() self.repeatEverySpinBox = QSpinBox(self.tab) self.repeatEverySpinBox.setMinimum(1) self.horizontalLayout_2.addWidget(self.repeatEverySpinBox) self.repeatEveryDescLabel = QLabel(self.tab) self.horizontalLayout_2.addWidget(self.repeatEveryDescLabel) self.formLayout.setLayout(2, QFormLayout.FieldRole, self.horizontalLayout_2) self.label_9 = QLabel(tr("Stop Date:")) self.formLayout.setWidget(3, QFormLayout.LabelRole, self.label_9) self.stopDateEdit = DateEdit(self.tab, is_clearable=True) self.stopDateEdit.setMaximumSize(QSize(120, 16777215)) self.formLayout.setWidget(3, QFormLayout.FieldRole, self.stopDateEdit) self.label_3 = QLabel(tr("Description:")) self.formLayout.setWidget(4, QFormLayout.LabelRole, self.label_3) self.descriptionEdit = DescriptionEdit(self.model.completable_edit, self.tab) self.formLayout.setWidget(4, QFormLayout.FieldRole, self.descriptionEdit) self.label_4 = QLabel(tr("Payee:")) self.formLayout.setWidget(5, QFormLayout.LabelRole, self.label_4) self.payeeEdit = PayeeEdit(self.model.completable_edit, self.tab) self.formLayout.setWidget(5, QFormLayout.FieldRole, self.payeeEdit) self.label_5 = QLabel(tr("Check #:")) self.formLayout.setWidget(6, QFormLayout.LabelRole, self.label_5) self.checkNoEdit = QLineEdit(self.tab) self.checkNoEdit.setMaximumSize(QSize(120, 16777215)) self.formLayout.setWidget(6, QFormLayout.FieldRole, self.checkNoEdit) self.amountLabel = QLabel(tr("Transfers:")) self.formLayout.setWidget(7, QFormLayout.LabelRole, self.amountLabel) self.splitTableView = TableView(self.tab) self.splitTableView.setMinimumSize(QSize(355, 0)) self.splitTableView.setAcceptDrops(True) self.splitTableView.setDragEnabled(True) self.splitTableView.setDragDropOverwriteMode(False) self.splitTableView.setDragDropMode(QAbstractItemView.InternalMove) self.splitTableView.setSelectionBehavior(QAbstractItemView.SelectRows) self.splitTableView.horizontalHeader().setDefaultSectionSize(40) self.splitTableView.verticalHeader().setVisible(False) self.splitTableView.verticalHeader().setDefaultSectionSize(18) self.formLayout.setWidget(7, QFormLayout.FieldRole, self.splitTableView) self.widget = QWidget(self.tab) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.widget.sizePolicy().hasHeightForWidth()) self.widget.setSizePolicy(sizePolicy) self.horizontalLayout_6 = QHBoxLayout(self.widget) self.horizontalLayout_6.setContentsMargins(0, 0, 0, 0) spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.horizontalLayout_6.addItem(spacerItem) self.addSplitButton = QPushButton(self.widget) icon = QIcon() icon.addPixmap(QPixmap(':/plus_8'), QIcon.Normal, QIcon.Off) self.addSplitButton.setIcon(icon) self.horizontalLayout_6.addWidget(self.addSplitButton) self.removeSplitButton = QPushButton(self.widget) icon1 = QIcon() icon1.addPixmap(QPixmap(':/minus_8'), QIcon.Normal, QIcon.Off) self.removeSplitButton.setIcon(icon1) self.horizontalLayout_6.addWidget(self.removeSplitButton) self.formLayout.setWidget(8, QFormLayout.FieldRole, self.widget) self.tabWidget.addTab(self.tab, tr("Info")) self.tab_3 = QWidget() self.horizontalLayout_5 = QHBoxLayout(self.tab_3) self.notesEdit = QPlainTextEdit(self.tab_3) self.horizontalLayout_5.addWidget(self.notesEdit) self.tabWidget.addTab(self.tab_3, tr("Notes")) self.verticalLayout_2.addWidget(self.tabWidget) self.buttonBox = QDialogButtonBox(self) self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel|QDialogButtonBox.Save) self.verticalLayout_2.addWidget(self.buttonBox) self.label_2.setBuddy(self.startDateEdit) self.label_7.setBuddy(self.repeatTypeComboBoxView) self.label_3.setBuddy(self.descriptionEdit) self.label_4.setBuddy(self.payeeEdit) self.label_5.setBuddy(self.checkNoEdit) self.tabWidget.setCurrentIndex(0) def _loadFields(self): Panel._loadFields(self) self.tabWidget.setCurrentIndex(0) # --- model --> view def refresh_for_multi_currency(self): pass def refresh_repeat_every(self): self.repeatEveryDescLabel.setText(self.model.repeat_every_desc)
class LoadKineticsDialog(PersistentDialog): def __init__(self, accept_func: Callable, parent=None): super(LoadKineticsDialog, self).__init__(parent) self.setWindowTitle("Batch Load Kinetics") self.sett = Settings() self.description = QLabel(""" Loads UV-Vis kinetics. The spectra can be in various formats (dx, csv, txt, etc.). If blank spectrum is provided, it will be subtracted from each of the spectra. Time corresponding to each spectrum will be set as the name for that spectrum. Times can be provided by time difference (in case kinetics was measured reguraly) or from filename. Postprocessing (baseline correction and/or cut of spectra) can be performed on loaded dataset. Required folder structure for one kinetics: [kinetics folder] [spectra folder] 01.dx 02.dx ... times.txt (optional) blank.dx (optional) """) self.description.setWordWrap(True) self.accept_func = accept_func self.btnChooseDirs = QToolButton() self.btnChooseDirs.setText('...') self.layout_button = QHBoxLayout() self.layout_button.addWidget(QLabel('Folders to load:')) self.layout_button.addWidget(self.btnChooseDirs) self.lwFolders = MyQListWidget(self) self.grid_layout = QGridLayout() self.lbl1 = QLabel('Spectra folder name:') self.lbl2 = QLabel('Blank spectrum name (optional):') self.cbKineticsMeasuredByEach = QCheckBox('Kinetics measured by each (time unit):') self.cbKineticsMeasuredByEach.setChecked(True) self.lbl4 = QLabel('Use times from filename (optional):') self.cbBCorr = QCheckBox('Apply baseline correction in range:') self.cbCut = QCheckBox('Cut spectra to range:') self.leSpectra = QLineEdit('spectra') self.leBlank = QLineEdit('blank.dx') self.leTimeUnit = QLineEdit('1') self.leTimes = QLineEdit('times.txt') self.leBCorr0 = QLineEdit('700') self.leBCorr1 = QLineEdit('800') self.leCut0 = QLineEdit('230') self.leCut1 = QLineEdit('650') self.Hlayout1 = QHBoxLayout() self.Hlayout1.addWidget(self.leBCorr0) self.Hlayout1.addWidget(QLabel('to')) self.Hlayout1.addWidget(self.leBCorr1) self.Hlayout2 = QHBoxLayout() self.Hlayout2.addWidget(self.leCut0) self.Hlayout2.addWidget(QLabel('to')) self.Hlayout2.addWidget(self.leCut1) self.grid_layout.addWidget(self.lbl1, 0, 0, 1, 1) self.grid_layout.addWidget(self.lbl2, 1, 0, 1, 1) self.grid_layout.addWidget(self.cbKineticsMeasuredByEach, 2, 0, 1, 1) self.grid_layout.addWidget(self.lbl4, 3, 0, 1, 1) self.grid_layout.addWidget(self.cbBCorr, 4, 0, 1, 1) self.grid_layout.addWidget(self.cbCut, 5, 0, 1, 1) self.grid_layout.addWidget(self.leSpectra, 0, 1, 1, 1) self.grid_layout.addWidget(self.leBlank, 1, 1, 1, 1) self.grid_layout.addWidget(self.leTimeUnit, 2, 1, 1, 1) self.grid_layout.addWidget(self.leTimes, 3, 1, 1, 1) self.grid_layout.addLayout(self.Hlayout1, 4, 1, 1, 1) self.grid_layout.addLayout(self.Hlayout2, 5, 1, 1, 1) self.button_box = QDialogButtonBox() self.button_box.setOrientation(Qt.Horizontal) self.button_box.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.button_box.accepted.connect(self.accept) # OK button self.button_box.rejected.connect(self.reject) # Cancel button self.main_layout = QVBoxLayout(self) self.main_layout.addWidget(self.description) self.main_layout.addLayout(self.layout_button) self.main_layout.addWidget(self.lwFolders) self.main_layout.addLayout(self.grid_layout) self.main_layout.addWidget(self.button_box) self.setLayout(self.main_layout) self.cbKineticsMeasuredByEach.toggled.connect(self.cbKineticsMeasuredByEach_toggled) self.cbBCorr.toggled.connect(self.cbBCorr_toggled) self.cbCut.toggled.connect(self.cbCut_toggled) self.btnChooseDirs.clicked.connect(self.btnChooseDirs_clicked) self.cbKineticsMeasuredByEach_toggled() self.cbBCorr_toggled() self.cbCut_toggled() def btnChooseDirs_clicked(self): # https://stackoverflow.com/questions/38252419/how-to-get-qfiledialog-to-select-and-return-multiple-folders # just copied :) file_dialog = QFileDialog() file_dialog.setFileMode(QFileDialog.DirectoryOnly) file_dialog.setOption(QFileDialog.DontUseNativeDialog, True) file_dialog.setDirectory(self.sett['/Private settings/Load kinetics last path']) file_view = file_dialog.findChild(QListView, 'listView') # to make it possible to select multiple directories: if file_view: file_view.setSelectionMode(QAbstractItemView.MultiSelection) f_tree_view = file_dialog.findChild(QTreeView) if f_tree_view: f_tree_view.setSelectionMode(QAbstractItemView.MultiSelection) if file_dialog.exec(): for path in file_dialog.selectedFiles(): head, tail = os.path.split(path) head2, tail2 = os.path.split(head) name = os.path.join(tail2, tail) self.sett['/Private settings/Load kinetics last path'] = head if name not in self.lwFolders.item_names: self.lwFolders.addItem(name, path) def cbBCorr_toggled(self): checked = self.cbBCorr.isChecked() self.leBCorr0.setEnabled(checked) self.leBCorr1.setEnabled(checked) def cbCut_toggled(self): checked = self.cbCut.isChecked() self.leCut0.setEnabled(checked) self.leCut1.setEnabled(checked) def cbKineticsMeasuredByEach_toggled(self): checked = self.cbKineticsMeasuredByEach.isChecked() self.leTimeUnit.setEnabled(checked) self.leTimes.setEnabled(not checked) def accept(self): try: float(self.leTimeUnit.text()) float(self.leCut0.text()) float(self.leCut1.text()) float(self.leBCorr0.text()) float(self.leBCorr1.text()) except ValueError: QMessageBox.critical(self, 'Error', "Invalid input, please check the fields.") return self.sett.save() self.accept_func() super(LoadKineticsDialog, self).accept()
def showDialog(self, currentCard=None): if currentCard: self.did = currentCard.did elif mw._selectedDeck(): self.did = mw._selectedDeck()['id'] else: return if not self._getCardInfo(self.did): showInfo('Please select an Incremental Reading deck.') return dialog = QDialog(mw) layout = QVBoxLayout() self.cardListWidget = QListWidget() self.cardListWidget.setAlternatingRowColors(True) self.cardListWidget.setSelectionMode( QAbstractItemView.ExtendedSelection) self.cardListWidget.setWordWrap(True) self.cardListWidget.itemDoubleClicked.connect(lambda: showBrowser( self.cardListWidget.currentItem().data(Qt.UserRole)['nid'])) self._updateListItems() upButton = QPushButton('Up') upButton.clicked.connect(self._moveUp) downButton = QPushButton('Down') downButton.clicked.connect(self._moveDown) topButton = QPushButton('Top') topButton.clicked.connect(self._moveToTop) bottomButton = QPushButton('Bottom') bottomButton.clicked.connect(self._moveToBottom) randomizeButton = QPushButton('Randomize') randomizeButton.clicked.connect(self._randomize) controlsLayout = QHBoxLayout() controlsLayout.addWidget(topButton) controlsLayout.addWidget(upButton) controlsLayout.addWidget(downButton) controlsLayout.addWidget(bottomButton) controlsLayout.addStretch() controlsLayout.addWidget(randomizeButton) buttonBox = QDialogButtonBox(QDialogButtonBox.Close | QDialogButtonBox.Save) buttonBox.accepted.connect(dialog.accept) buttonBox.rejected.connect(dialog.reject) buttonBox.setOrientation(Qt.Horizontal) layout.addLayout(controlsLayout) layout.addWidget(self.cardListWidget) layout.addWidget(buttonBox) dialog.setLayout(layout) dialog.setWindowModality(Qt.WindowModal) dialog.resize(500, 500) choice = dialog.exec_() if choice == 1: cids = [] for i in range(self.cardListWidget.count()): card = self.cardListWidget.item(i).data(Qt.UserRole) cids.append(card['id']) self.reorder(cids)
class Proxy(QDialog): id_signal = pyqtSignal([tuple]) city_signal = pyqtSignal([tuple]) country_signal = pyqtSignal([tuple]) def __init__(self, parent=None): super(Proxy, self).__init__(parent) self.settings = QSettings() self.layout = QVBoxLayout() self.buttonLayout = QHBoxLayout() self.buttonBox = QDialogButtonBox() self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons( QDialogButtonBox.Ok | QDialogButtonBox.Cancel ) self.buttonBox.rejected.connect(self.reject) self.buttonBox.accepted.connect(self.accept) self.buttonLayout.addWidget(self.buttonBox) self.proxy_url_label = QLabel( QCoreApplication.translate( 'Entry label for the proxy url', 'Proxy URL:', 'Proxy settings dialogue' ) ) self.proxy_url_line = QLineEdit() url = self.settings.value('Proxy_url') or '' self.proxy_url_line = QLineEdit(url) self.proxy_url_line.setMinimumWidth(300) self.proxy_port_label = QLabel( QCoreApplication.translate( 'Entry label for the proxy port', 'Port:', 'Proxy settings dialogue' ) ) port = self.settings.value('Proxy_port') or '' self.proxy_port_line = QLineEdit(port) self.proxy_auth_label = QLabel( QCoreApplication.translate( 'Checkbox', 'Use proxy authentification', 'Proxy settings dialogue' ) ) self.proxy_auth_checkbox = QCheckBox() self.proxy_auth_bool = eval( self.settings.value('Use_proxy_authentification') or 'False' ) self.proxy_auth_checkbox.setChecked(self.proxy_auth_bool) self.proxy_auth_checkbox.stateChanged.connect(self.proxy_auth) self.proxy_user_label = QLabel(QCoreApplication.translate( 'Proxy username authentification', 'User ID:', 'Proxy configuration dialogue')) self.proxy_user_label.setEnabled(self.proxy_auth_bool) self.proxy_pass_label = QLabel(QCoreApplication.translate( 'Proxy password authentification', 'Password:'******'Proxy configuration dialogue')) self.proxy_pass_label.setEnabled(self.proxy_auth_bool) user = self.settings.value('Proxy_user') or '' self.proxy_user_line = QLineEdit(user) self.proxy_user_line.setEnabled(self.proxy_auth_bool) password = self.settings.value('Proxy_password') or '' self.proxy_pass_line = QLineEdit(password) self.proxy_pass_line.setEnabled(self.proxy_auth_bool) self.proxy_pass_line.setEchoMode(QLineEdit.Password) self.status_layout = QHBoxLayout() self.status_label = QLabel() self.status_layout.addWidget(self.status_label) self.panel = QGridLayout() self.panel.addWidget(self.proxy_url_label, 0, 0) self.panel.addWidget(self.proxy_url_line, 0, 1) self.panel.addWidget(self.proxy_port_label, 0, 2) self.panel.addWidget(self.proxy_port_line, 0, 3) self.panel.addWidget(self.proxy_auth_label, 1, 0) self.panel.addWidget(self.proxy_auth_checkbox, 1, 1) self.panel.addWidget(self.proxy_user_label, 2, 0) self.panel.addWidget(self.proxy_user_line, 2, 1) self.panel.addWidget(self.proxy_pass_label, 3, 0) self.panel.addWidget(self.proxy_pass_line, 3, 1) self.layout.addLayout(self.panel) self.layout.addLayout(self.status_layout) self.layout.addLayout(self.buttonLayout) self.setLayout(self.layout) def proxy_auth(self, state): if state == 2: self.proxy_auth_bool = True self.proxy_user_label.setEnabled(True) self.proxy_pass_label.setEnabled(True) self.proxy_user_line.setEnabled(True) self.proxy_pass_line.setEnabled(True) else: self.proxy_auth_bool = False self.proxy_user_label.setEnabled(False) self.proxy_pass_label.setEnabled(False) self.proxy_user_line.setEnabled(False) self.proxy_pass_line.setEnabled(False) def accept(self): port = self.proxy_port_line.text() if port.isdigit() or port == '': self.settings.setValue('Proxy_url', self.proxy_url_line.text()) self.settings.setValue('Proxy_port', port) self.settings.setValue('Use_proxy_authentification', str(self.proxy_auth_bool)) if self.proxy_auth_bool: self.settings.setValue('Proxy_user', self.proxy_user_line.text()) self.settings.setValue('Proxy_password', self.proxy_pass_line.text()) else: self.status_label.setText('Port number must contain only digits') return QDialog.accept(self)
class ExportPanel(Panel): FIELDS = [] PERSISTENT_NAME = 'exportPanel' def __init__(self, model, mainwindow): Panel.__init__(self, mainwindow) self.setAttribute(Qt.WA_DeleteOnClose) self.mainwindow = mainwindow self._setupUi() self.model = model self.accountTable = ExportAccountTable(model=self.model.account_table, view=self.tableView) self.exportTypeButtons.buttonClicked[int].connect(self.exportTypeSelected) self.exportFormatButtons.buttonClicked[int].connect(self.exportFormatSelected) self.buttonBox.rejected.connect(self.reject) self.exportButton.clicked.connect(self.exportButtonClicked) def _setupUi(self): self.setWindowTitle(tr("Export Options")) self.mainLayout = QVBoxLayout(self) self.label1 = QLabel(tr("Which accounts do you want to export?"), self) self.mainLayout.addWidget(self.label1) self.exportTypeButtons = QButtonGroup(self) self.exportAllButton = QRadioButton(tr("All"), self) self.mainLayout.addWidget(self.exportAllButton) self.exportTypeButtons.addButton(self.exportAllButton, ExportType.All) self.exportAllButton.setChecked(True) self.exportSelectedButton = QRadioButton(tr("Selected"), self) self.mainLayout.addWidget(self.exportSelectedButton) self.exportTypeButtons.addButton(self.exportSelectedButton, ExportType.Selected) self.tableView = QTableView(self) self.tableView.setSelectionMode(QAbstractItemView.SingleSelection) self.tableView.setSelectionBehavior(QAbstractItemView.SelectRows) self.tableView.verticalHeader().setVisible(False) self.tableView.verticalHeader().setDefaultSectionSize(18) self.mainLayout.addWidget(self.tableView) self.label2 = QLabel(tr("Export format:"), self) self.mainLayout.addWidget(self.label2) self.exportFormatButtons = QButtonGroup(self) self.exportAsQIFButton = QRadioButton("QIF", self) self.mainLayout.addWidget(self.exportAsQIFButton) self.exportFormatButtons.addButton(self.exportAsQIFButton, ExportFormat.QIF) self.exportAsQIFButton.setChecked(True) self.exportAsCSVButton = QRadioButton("CSV", self) self.mainLayout.addWidget(self.exportAsCSVButton) self.exportFormatButtons.addButton(self.exportAsCSVButton, ExportFormat.CSV) self.label3 = QLabel(tr("Export scope:")) self.mainLayout.addWidget(self.label3) self.dateRangeOnlyCheckbox = QCheckBox(tr("Current date range only")) self.mainLayout.addWidget(self.dateRangeOnlyCheckbox) self.buttonBox = QDialogButtonBox(self) self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel) self.exportButton = self.buttonBox.addButton(tr("Export"), QDialogButtonBox.ActionRole) self.mainLayout.addWidget(self.buttonBox) #--- Overrides def _loadFields(self): self.exportAllButton.setChecked(self.model.export_all) self.exportAsQIFButton.setChecked(self.model.export_format == ExportFormat.QIF) self.dateRangeOnlyCheckbox.setChecked(self.model.current_daterange_only) def _saveFields(self): self.model.current_daterange_only = self.dateRangeOnlyCheckbox.isChecked() #--- Event Handlers def exportButtonClicked(self): title = tr("Export") fileext = 'qif' if self.model.export_format == ExportFormat.QIF else 'csv' filters = tr("{0} Files (*.{1})").format(fileext.upper(), fileext) filename = 'export.{0}'.format(fileext) docpath = str(QFileDialog.getSaveFileName(self.mainwindow, title, filename, filters)) if docpath: self.model.export_path = docpath self.accept() def exportTypeSelected(self, typeId): self.model.export_all = typeId == ExportType.All def exportFormatSelected(self, typeId): self.model.export_format = typeId #--- model --> view def set_table_enabled(self, enabled): self.tableView.setEnabled(enabled) def set_export_button_enabled(self, enabled): self.exportButton.setEnabled(enabled)
class AddConnectedPointsDialogWidget(QDialog): def __init__(self, parent=None, command=None): """Constructor Args: parent: Qt parent Widget iface: QGiS interface command: Command instance with a run_it method which will be called on acceptance of the dialog """ super().__init__(parent) self.setupUi() self.command = command self.databases = get_databases() self.database_combo.addItems(list(self.databases.keys())) # Connect signals self.buttonBox.accepted.connect(self.on_accept) self.buttonBox.rejected.connect(self.on_reject) self.filename = None def on_accept(self): """Accept and run the Command.run_it method.""" db_key = self.database_combo.currentText() db_entry = self.databases[db_key] db_type = db_entry["db_type"] _db_settings = db_entry["db_settings"] if db_type == "spatialite": # usage of db_type 'spatialite' instead of 'sqlite' # makes much more sense because it also used internally # by qgis, for example when by the ``QgsVectorLayer()``-object host = _db_settings["db_path"] db_settings = { "host": host, "port": "", "name": "", "username": "", "password": "", "schema": "", "database": "", "db_path": host, } else: db_settings = _db_settings db_settings["schema"] = "public" self.command.run_it(db_settings, db_type) self.accept() def on_reject(self): """Cancel""" self.reject() logger.debug("Reject") def closeEvent(self, event): """ Close widget, called by Qt on close :param event: QEvent, close event """ self.buttonBox.accepted.disconnect(self.on_accept) self.buttonBox.rejected.disconnect(self.on_reject) event.accept() def setupUi(self): self.resize(815, 250) self.verticalLayout = QVBoxLayout(self) self.groupBox_2 = QGroupBox(self) self.groupBox_2.setObjectName("groupBox_2") self.database_combo = QComboBox(self.groupBox_2) self.database_combo.setGeometry(QRect(10, 30, 481, 34)) sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.database_combo.sizePolicy().hasHeightForWidth() ) self.database_combo.setSizePolicy(sizePolicy) self.database_combo.setObjectName("database_combo") self.verticalLayout.addWidget(self.groupBox_2) self.groupBox = QGroupBox(self) self.verticalLayoutBox = QVBoxLayout(self.groupBox) self.buttonBox = QDialogButtonBox(self) self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok) self.buttonBox.setObjectName("buttonBox") self.verticalLayout.addWidget(self.buttonBox) self.retranslateUi() self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) QMetaObject.connectSlotsByName(self) def retranslateUi(self): self.setWindowTitle("Add connected points") self.groupBox_2.setTitle("Load from model database")
class LoginDialog(QDialog): """登录对话框""" clicked_ok = pyqtSignal() def __init__(self, config): super().__init__() self._config = config self._user = "" self._pwd = "" self._cookie = "" self.initUI() self.setStyleSheet(dialog_qss_style) self.setMinimumWidth(300) # 信号 self.name_ed.textChanged.connect(self.set_user) self.pwd_ed.textChanged.connect(self.set_pwd) self.cookie_ed.textChanged.connect(self.set_cookie) self.buttonBox.accepted.connect(self._ok) self.buttonBox.rejected.connect(self._cancel) def default_var(self): try: with open(self._config, "rb") as _file: _info = load(_file) self._user = _info["user"] self._pwd = _info["pwd"] self._cookie = _info["cookie"] except Exception: pass self.name_ed.setText(self._user) self.pwd_ed.setText(self._pwd) self.cookie_ed.setPlainText(self._cookie) def initUI(self): self.setWindowTitle("登录蓝奏云") self.setWindowIcon(QIcon("./icon/login.ico")) self.logo = QLabel() self.logo.setPixmap(QPixmap("./icon/logo3.gif")) self.logo.setStyleSheet("background-color:rgb(0,153,255);") self.logo.setAlignment(Qt.AlignCenter) self.name_lb = QLabel("&User") self.name_lb.setAlignment(Qt.AlignCenter) self.name_ed = QLineEdit() self.name_lb.setBuddy(self.name_ed) self.pwd_lb = QLabel("&Password") self.pwd_lb.setAlignment(Qt.AlignCenter) self.pwd_ed = QLineEdit() self.pwd_ed.setEchoMode(QLineEdit.Password) self.pwd_lb.setBuddy(self.pwd_ed) self.cookie_lb = QLabel("&Cookie") self.cookie_ed = QTextEdit() notice = "如果由于滑动验证,无法使用用户名与密码登录,则需要输入cookie,自行使用浏览器获取," \ "cookie会保持在本地,下次使用。其格式如下:\n\n key1=value1; key2=value2" self.cookie_ed.setPlaceholderText(notice) self.cookie_lb.setBuddy(self.cookie_ed) self.buttonBox = QDialogButtonBox() self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) main_layout = QGridLayout() main_layout.addWidget(self.logo, 0, 0, 2, 4) main_layout.addWidget(self.name_lb, 2, 0) main_layout.addWidget(self.name_ed, 2, 1, 1, 3) main_layout.addWidget(self.pwd_lb, 3, 0) main_layout.addWidget(self.pwd_ed, 3, 1, 1, 3) # main_layout.addWidget(self.cookie_lb, 4, 0) # cookie输入框 # main_layout.addWidget(self.cookie_ed, 4, 1, 2, 3) main_layout.addWidget(self.buttonBox, 4, 2) self.setLayout(main_layout) self.default_var() def set_user(self, user): self._user = user def set_pwd(self, pwd): self._pwd = pwd def set_cookie(self): self._cookie = self.cookie_ed.toPlainText() def _cancel(self): self.default_var() self.close() def _ok(self): up_info = {"user": self._user, "pwd": self._pwd, "cookie": self._cookie} update_settings(self._config, up_info) self.clicked_ok.emit() self.close()
def initUI(self): # Dialog stuff self.setWindowTitle("Select features and label") self.setWindowFlags(Qt.WindowTitleHint | Qt.CustomizeWindowHint) self.setStyleSheet(""" QDialog { background-color: rgb(255, 229, 204); color: #fffff8; } """) self.resize(1280, 720) # Outer layout to contain the tableview and the groupbox for selections layout = QVBoxLayout() # Datatable self.tableView = TableView(self.data, self.columns) # Groupbox to split into two groupboxes for selections groupbox = QGroupBox("Selections") groupboxLayout = QHBoxLayout() groupbox.setLayout(groupboxLayout) # Feature groupbox featureGroupbox = QGroupBox("Select your features") featureGroupboxLayout = QVBoxLayout() featureGroupbox.setLayout(featureGroupboxLayout) # Label groupbox labelGroupbox = QGroupBox("Select your label") labelGroupboxLayout = QVBoxLayout() labelGroupbox.setLayout(labelGroupboxLayout) groupboxLayout.addWidget(featureGroupbox) groupboxLayout.addWidget(labelGroupbox) # Save the buttons in arrays for each group box self.arrayOfFeatureCheckboxes = [] self.arrayOfLabelRadioButtons = [] for column in self.columns: checkbox = QCheckBox(column) radioButton = QRadioButton(column) checkbox.stateChanged.connect(partial(self.changeCheckboxState, checkbox)) radioButton.toggled.connect(partial(self.changeRadioButtonState, radioButton)) self.arrayOfFeatureCheckboxes.append(checkbox) self.arrayOfLabelRadioButtons.append(radioButton) featureGroupboxLayout.addWidget(checkbox) labelGroupboxLayout.addWidget(radioButton) # Ok and Cancel buttons confirmButtonBox = QDialogButtonBox(self) confirmButtonBox.setOrientation(Qt.Horizontal) confirmButtonBox.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) confirmButtonBox.accepted.connect(self.confirm) confirmButtonBox.rejected.connect(self.reject) layout.addWidget(self.tableView) layout.addWidget(groupbox) layout.addWidget(confirmButtonBox) self.setLayout(layout)
class AboutDialog(QDialog): check_update = pyqtSignal(str, bool) def __init__(self, parent=None): super(AboutDialog, self).__init__(parent) self._ver = '' self._github = 'https://github.com/rachpt/lanzou-gui' self._api_url = 'https://github.com/zaxtyson/LanZouCloud-API' self._gitee = 'https://gitee.com/rachpt/lanzou-gui' self._home_page = 'https://rachpt.cn/lanzou-gui/' self.initUI() self.setStyleSheet(others_style) def set_values(self, version): self._ver = version self.lb_name_text.setText(f"{version} (点击检查更新)") # 更新版本 def show_update(self, ver, msg): self.lb_new_ver = QLabel("新版") # 检测新版 self.lb_new_ver_msg = QLabel() self.lb_new_ver_msg.setOpenExternalLinks(True) self.lb_new_ver_msg.setWordWrap(True) if ver != '0': self.lb_name_text.setText(f"{self._ver} ➡ {ver}") self.lb_new_ver_msg.setText(msg) self.lb_new_ver_msg.setMinimumWidth(700) if self.form.rowCount() < 5: self.form.insertRow(1, self.lb_new_ver, self.lb_new_ver_msg) def initUI(self): self.setWindowTitle("关于 lanzou-gui") about = f'本项目使用PyQt5实现图形界面,可以完成蓝奏云的大部分功能<br/> \ 得益于 <a href="{self._api_url}">API</a> 的功能,可以间接突破单文件最大 100MB 的限制,同时增加了批量上传/下载的功能<br/> \ Python 依赖见<a href="{self._github }/blob/master/requirements.txt">requirements.txt</a>,\ <a href="{self._github}/releases">releases</a> 有打包好了的 Windows 可执行程序,但可能不是最新的' project_url = f'<a href="{self._home_page}">主页</a> | <a href="{self._github}">repo</a> | \ <a href="{self._gitee}">mirror repo</a>' self.logo = QLabel() # logo self.logo.setPixmap(QPixmap("./src/logo2.gif")) self.logo.setStyleSheet("background-color:rgb(255,255,255);") self.logo.setAlignment(Qt.AlignCenter) self.lb_name = QLabel("版本") # 版本 self.lb_name_text = QPushButton("") # 版本 self.lb_name_text.setToolTip("点击检查更新") ver_style = "QPushButton {border:none; background:transparent;font-weight:bold;color:blue;}" self.lb_name_text.setStyleSheet(ver_style) self.lb_name_text.clicked.connect( lambda: self.check_update.emit(self._ver, True)) self.lb_about = QLabel("关于") # about self.lb_about_text = QLabel() self.lb_about_text.setText(about) self.lb_about_text.setOpenExternalLinks(True) self.lb_author = QLabel("作者") # author self.lb_author_mail = QLabel( "<a href='mailto:[email protected]'>rachpt</a>") self.lb_author_mail.setOpenExternalLinks(True) self.lb_update = QLabel("项目") # 更新 self.lb_update_url = QLabel(project_url) self.lb_update_url.setOpenExternalLinks(True) self.buttonBox = QDialogButtonBox() self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Close) self.buttonBox.button(QDialogButtonBox.Close).setText("关闭") self.buttonBox.rejected.connect(self.reject) self.buttonBox.setStyleSheet(btn_style) self.line = QLine(QPoint(), QPoint(550, 0)) self.lb_line = QLabel() self.lb_line.setText('<html><hr /></html>') vbox = QVBoxLayout() vbox.addWidget(self.logo) vbox.addStretch(1) self.form = QFormLayout() self.form.setLabelAlignment(Qt.AlignRight) self.form.setFormAlignment(Qt.AlignLeft) self.form.setHorizontalSpacing(40) self.form.setVerticalSpacing(15) self.form.addRow(self.lb_name, self.lb_name_text) self.form.addRow(self.lb_update, self.lb_update_url) self.form.addRow(self.lb_author, self.lb_author_mail) self.form.addRow(self.lb_about, self.lb_about_text) vbox.addLayout(self.form) vbox.addStretch(1) vbox.addWidget(self.lb_line) donate = QLabel() donate.setText("<b>捐助我</b> 如果你愿意") donate.setAlignment(Qt.AlignCenter) hbox = QHBoxLayout() hbox.addStretch(2) for it in ["wechat", "alipay", "qqpay"]: lb = QLabel() lb.setPixmap(QPixmap(f"./src/{it}.jpg")) hbox.addWidget(lb) hbox.addStretch(1) hbox.addWidget(self.buttonBox) vbox.addWidget(donate) vbox.addLayout(hbox) self.setLayout(vbox) self.setMinimumWidth(720) def paintEvent(self, event): QDialog.paintEvent(self, event) if not self.line.isNull(): painter = QPainter(self) pen = QPen(Qt.red, 3) painter.setPen(pen) painter.drawLine(self.line)
class UploadDialog(QDialog): """文件上传对话框""" new_infos = pyqtSignal(object) def __init__(self): super().__init__() self.cwd = os.getcwd() self._folder_id = -1 self._folder_name = "LanZouCloud" self.set_pwd = False self.set_desc = False self.pwd = '' self.desc = '' self.allow_big_file = False self.max_size = 100 self.selected = [] self.initUI() self.set_size() self.setStyleSheet(dialog_qss_style) def set_pwd_desc_bigfile(self, set_pwd, pwd, set_desc, desc, allow_big_file, max_size): self.set_pwd = set_pwd self.set_desc = set_desc self.pwd = pwd self.desc = desc self.allow_big_file = allow_big_file self.max_size = max_size if self.allow_big_file: self.btn_chooseMultiFile.setToolTip("") else: self.btn_chooseMultiFile.setToolTip(f"文件大小上线 {self.max_size}MB") def set_values(self, folder_name, folder_id, files): self.setWindowTitle("上传文件至 ➩ " + str(folder_name)) self._folder_id = folder_id self._folder_name = folder_name if files: self.selected = files self.show_selected() self.exec() def initUI(self): self.setWindowTitle("上传文件") self.setWindowIcon(QIcon("./src/upload.ico")) self.logo = QLabel() self.logo.setPixmap(QPixmap("./src/logo3.gif")) self.logo.setStyleSheet("background-color:rgb(0,153,255);") self.logo.setAlignment(Qt.AlignCenter) # btn 1 self.btn_chooseDir = QPushButton("选择文件夹", self) self.btn_chooseDir.setObjectName("btn_chooseDir") self.btn_chooseDir.setObjectName("btn_chooseDir") self.btn_chooseDir.setIcon(QIcon("./src/folder.gif")) # btn 2 self.btn_chooseMultiFile = QPushButton("选择多文件", self) self.btn_chooseDir.setObjectName("btn_chooseMultiFile") self.btn_chooseMultiFile.setObjectName("btn_chooseMultiFile") self.btn_chooseMultiFile.setIcon(QIcon("./src/file.ico")) # btn 3 self.btn_deleteSelect = QPushButton("移除", self) self.btn_deleteSelect.setObjectName("btn_deleteSelect") self.btn_deleteSelect.setIcon(QIcon("./src/delete.ico")) self.btn_deleteSelect.setToolTip("按 Delete 移除选中文件") # 列表 self.list_view = MyListView() self.list_view.drop_files.connect(self.add_drop_files) self.list_view.setViewMode(QListView.ListMode) self.slm = QStandardItem() self.model = QStandardItemModel() self.list_view.setModel(self.model) self.model.removeRows(0, self.model.rowCount()) # 清除旧的选择 self.list_view.setEditTriggers(QAbstractItemView.NoEditTriggers) self.list_view.setSelectionBehavior(QAbstractItemView.SelectRows) self.list_view.setSelectionMode(QAbstractItemView.ExtendedSelection) self.buttonBox = QDialogButtonBox() self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.buttonBox.button(QDialogButtonBox.Ok).setText("确定") self.buttonBox.button(QDialogButtonBox.Cancel).setText("取消") vbox = QVBoxLayout() hbox_head = QHBoxLayout() hbox_button = QHBoxLayout() hbox_head.addWidget(self.btn_chooseDir) hbox_head.addStretch(1) hbox_head.addWidget(self.btn_chooseMultiFile) hbox_button.addWidget(self.btn_deleteSelect) hbox_button.addStretch(1) hbox_button.addWidget(self.buttonBox) vbox.addWidget(self.logo) vbox.addLayout(hbox_head) vbox.addWidget(self.list_view) vbox.addLayout(hbox_button) self.setLayout(vbox) self.setMinimumWidth(350) # 设置信号 self.btn_chooseDir.clicked.connect(self.slot_btn_chooseDir) self.btn_chooseMultiFile.clicked.connect(self.slot_btn_chooseMultiFile) self.btn_deleteSelect.clicked.connect(self.slot_btn_deleteSelect) self.buttonBox.accepted.connect(self.slot_btn_ok) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.clear_old) self.buttonBox.rejected.connect(self.reject) def set_size(self): if self.selected: h = 18 if len(self.selected) > 18 else 10 w = 40 for i in self.selected: i_len = len(i) if i_len > 100: w = 100 break if i_len > w: w = i_len self.resize(120 + w * 7, h * 30) else: self.resize(400, 300) def clear_old(self): self.selected = [] self.model.removeRows(0, self.model.rowCount()) self.set_size() def show_selected(self): self.model.removeRows(0, self.model.rowCount()) for item in self.selected: if os.path.isfile(item): self.model.appendRow( QStandardItem(QIcon("./src/file.ico"), item)) else: self.model.appendRow( QStandardItem(QIcon("./src/folder.gif"), item)) self.set_size() def backslash(self): """Windows backslash""" tasks = {} for item in self.selected: furl = os.path.normpath(item) tasks[furl] = UpJob(furl=furl, id=self._folder_id, folder=self._folder_name, set_pwd=self.set_pwd, pwd=self.pwd, set_desc=self.set_desc, desc=self.desc) return tasks def slot_btn_ok(self): tasks = self.backslash() if self.selected: self.new_infos.emit(tasks) self.clear_old() def slot_btn_deleteSelect(self): _indexes = self.list_view.selectionModel().selection().indexes() if not _indexes: return indexes = [] for i in _indexes: # 获取所选行号 indexes.append(i.row()) indexes = set(indexes) for i in sorted(indexes, reverse=True): self.selected.remove(self.model.item(i, 0).text()) self.model.removeRow(i) self.set_size() def add_drop_files(self, files): for item in files: if item not in self.selected: self.selected.append(item) self.show_selected() def slot_btn_chooseDir(self): dir_choose = QFileDialog.getExistingDirectory(self, "选择文件夹", self.cwd) # 起始路径 if dir_choose == "": return if dir_choose not in self.selected: self.selected.append(dir_choose) self.show_selected() def slot_btn_chooseMultiFile(self): files, _ = QFileDialog.getOpenFileNames(self, "选择多文件", self.cwd, "All Files (*)") if len(files) == 0: return for _file in files: if _file not in self.selected: if os.path.getsize(_file) <= self.max_size * 1048576: self.selected.append(_file) elif self.allow_big_file: self.selected.append(_file) self.show_selected() def keyPressEvent(self, e): if e.key() == Qt.Key_Delete: # delete self.slot_btn_deleteSelect()
def initUI(self): self.setWindowTitle("设置") logo = QLabel() # logo logo.setPixmap(QPixmap("./src/logo2.gif")) logo.setStyleSheet("background-color:rgb(255,255,255);") logo.setAlignment(Qt.AlignCenter) self.download_threads_lb = QLabel("同时下载文件数") # about self.download_threads_var = QLineEdit() self.download_threads_var.setPlaceholderText("范围:1-9") self.download_threads_var.setToolTip("范围:1-9") self.download_threads_var.setInputMask("D") self.max_size_lb = QLabel("分卷大小(MB)") self.max_size_var = QLineEdit() self.max_size_var.setPlaceholderText("普通用户最大100,vip用户根据具体情况设置") self.max_size_var.setToolTip("普通用户最大100,vip用户根据具体情况设置") self.max_size_var.setInputMask("D99") self.timeout_lb = QLabel("请求超时(秒)") self.timeout_var = QLineEdit() self.timeout_var.setPlaceholderText("范围:1-99") self.timeout_var.setToolTip("范围:1-99") self.timeout_var.setInputMask("D9") self.dl_path_lb = QLabel("下载保存路径") self.dl_path_var = MyLineEdit(self) self.dl_path_var.clicked.connect(self.set_download_path) self.time_fmt_box = QCheckBox("使用[年-月-日]时间格式") self.to_tray_box = QCheckBox("关闭到系统托盘") self.time_fmt_box.toggle() self.time_fmt_box.stateChanged.connect(self.change_time_fmt) self.to_tray_box.stateChanged.connect(self.change_to_tray) buttonBox = QDialogButtonBox() buttonBox.setOrientation(Qt.Horizontal) buttonBox.setStandardButtons(QDialogButtonBox.Reset | QDialogButtonBox.Save | QDialogButtonBox.Cancel) buttonBox.button(QDialogButtonBox.Reset).setText("重置") buttonBox.button(QDialogButtonBox.Save).setText("保存") buttonBox.button(QDialogButtonBox.Cancel).setText("取消") buttonBox.button(QDialogButtonBox.Reset).clicked.connect( lambda: self.set_values(reset=True)) buttonBox.button(QDialogButtonBox.Save).clicked.connect(self.slot_save) buttonBox.rejected.connect(self.reject) form = QFormLayout() form.setLabelAlignment(Qt.AlignRight) form.setSpacing(10) form.addRow(self.download_threads_lb, self.download_threads_var) form.addRow(self.timeout_lb, self.timeout_var) form.addRow(self.max_size_lb, self.max_size_var) form.addRow(self.dl_path_lb, self.dl_path_var) vbox = QVBoxLayout() vbox.addWidget(logo) vbox.addStretch(1) vbox.addLayout(form) vbox.addStretch(1) hbox = QHBoxLayout() hbox.addWidget(self.time_fmt_box) hbox.addWidget(self.to_tray_box) vbox.addLayout(hbox) vbox.addStretch(1) vbox.addWidget(buttonBox) self.setLayout(vbox) self.setMinimumWidth(500)
class TorrentAddingDialog(QDialog): SELECTION_LABEL_FORMAT = 'Selected {} files ({})' def __init__(self, parent: QWidget, filename: str, torrent_info: TorrentInfo, control_thread: 'ControlManagerThread'): super().__init__(parent) self.app = QApplication.instance() self._torrent_filepath = Path(filename) self._torrent_info = torrent_info download_info = torrent_info.download_info self._control_thread = control_thread self._control = control_thread.control vbox = QVBoxLayout(self) self._download_dir = self.get_directory( self._control.last_download_dir) vbox.addWidget(QLabel('Download directory:')) vbox.addWidget(self._get_directory_browse_widget()) vbox.addWidget(QLabel('Announce URLs:')) url_tree = QTreeWidget() url_tree.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel) url_tree.header().close() vbox.addWidget(url_tree) for i, tier in enumerate(torrent_info.announce_list): tier_item = QTreeWidgetItem(url_tree) tier_item.setText(0, 'Tier {}'.format(i + 1)) for url in tier: url_item = QTreeWidgetItem(tier_item) url_item.setText(0, url) url_tree.expandAll() vbox.addWidget(url_tree, 1) file_tree = QTreeWidget() file_tree.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel) file_tree.setHeaderLabels(('Name', 'Size')) file_tree.header().setSectionResizeMode(0, QHeaderView.ResizeToContents) self._file_items = [] self._traverse_file_tree(download_info.suggested_name, download_info.file_tree, file_tree) file_tree.sortItems(0, Qt.AscendingOrder) file_tree.expandAll() file_tree.itemClicked.connect(self._update_checkboxes) vbox.addWidget(file_tree, 3) self._selection_label = QLabel( TorrentAddingDialog.SELECTION_LABEL_FORMAT.format( len(download_info.files), humanize_size(download_info.total_size))) vbox.addWidget(self._selection_label) self._ipfsadd_checkbox = QCheckBox( 'Import files to IPFS when download is complete') self._ipfsadd_checkbox.setCheckState(Qt.Unchecked) # vbox.addWidget(self._ipfsadd_checkbox) self._button_box = QDialogButtonBox(self) self._button_box.setOrientation(Qt.Horizontal) self._button_box.setStandardButtons(QDialogButtonBox.Cancel | QDialogButtonBox.Ok) self._button_box.button(QDialogButtonBox.Ok).clicked.connect( self.submit_torrent) self._button_box.button(QDialogButtonBox.Cancel).clicked.connect( self.close) vbox.addWidget(self._button_box) self.setWindowTitle('Add Torrent') self.setMinimumSize( QSize(self.app.desktopGeometry.width() / 3, (2 * self.app.desktopGeometry.height()) / 3)) def get_directory(self, directory: Optional[str]): dlPath = Path(self.app.settingsMgr.downloadsDir) downloadsDir = dlPath.joinpath('torrent') return directory if directory is not None else str(downloadsDir) def _traverse_file_tree(self, name: str, node: FileTreeNode, parent: QWidget): item = QTreeWidgetItem(parent) item.setCheckState(0, Qt.Checked) item.setText(0, name) if isinstance(node, FileInfo): item.setText(1, humanize_size(node.length)) item.setIcon(0, getMimeIcon('unknown')) self._file_items.append((node, item)) return item.setIcon(0, getIcon('folder-open.png')) for name, child in node.items(): self._traverse_file_tree(name, child, item) def _get_directory_browse_widget(self): widget = QWidget() hbox = QHBoxLayout(widget) hbox.setContentsMargins(0, 0, 0, 0) self._path_edit = QLineEdit(self._download_dir) self._path_edit.setReadOnly(True) hbox.addWidget(self._path_edit, 3) browse_button = QPushButton('Browse...') browse_button.clicked.connect(self._browse) hbox.addWidget(browse_button, 1) widget.setLayout(hbox) return widget def _browse(self): new_download_dir = QFileDialog.getExistingDirectory( self, 'Select download directory', self._download_dir) if not new_download_dir: return self._download_dir = new_download_dir self._path_edit.setText(new_download_dir) def _set_check_state_to_tree(self, item: QTreeWidgetItem, check_state: Qt.CheckState): for i in range(item.childCount()): child = item.child(i) child.setCheckState(0, check_state) self._set_check_state_to_tree(child, check_state) def _update_checkboxes(self, item: QTreeWidgetItem, column: int): if column != 0: return new_check_state = item.checkState(0) self._set_check_state_to_tree(item, new_check_state) while True: item = item.parent() if item is None: break has_checked_children = False has_partially_checked_children = False has_unchecked_children = False for i in range(item.childCount()): state = item.child(i).checkState(0) if state == Qt.Checked: has_checked_children = True elif state == Qt.PartiallyChecked: has_partially_checked_children = True else: has_unchecked_children = True if not has_partially_checked_children and \ not has_unchecked_children: new_state = Qt.Checked elif has_checked_children or has_partially_checked_children: new_state = Qt.PartiallyChecked else: new_state = Qt.Unchecked item.setCheckState(0, new_state) self._update_selection_label() def _update_selection_label(self): selected_file_count = 0 selected_size = 0 for node, item in self._file_items: if item.checkState(0) == Qt.Checked: selected_file_count += 1 selected_size += node.length ok_button = self._button_box.button(QDialogButtonBox.Ok) if not selected_file_count: ok_button.setEnabled(False) self._selection_label.setText('Nothing to download') else: ok_button.setEnabled(True) self._selection_label.setText( TorrentAddingDialog.SELECTION_LABEL_FORMAT.format( selected_file_count, humanize_size(selected_size))) def submit_torrent(self): p = Path(self._download_dir) try: name = self._torrent_filepath.name.replace('.torrent', '') pFinal = p.joinpath(name) pFinal.mkdir(parents=True, exist_ok=True) self._torrent_info.download_dir = str(pFinal) except Exception: messageBox('Cannot create torrent destination directory') return self._control.last_download_dir = os.path.abspath(self._download_dir) file_paths = [] for node, item in self._file_items: if item.checkState(0) == Qt.Checked: file_paths.append(node.path) if not self._torrent_info.download_info.single_file_mode: self._torrent_info.download_info.select_files( file_paths, 'whitelist') if self._ipfsadd_checkbox.checkState() == Qt.Checked: log.debug('Importing torrent to IPFS when complete') self._torrent_info.ipfsImportWhenComplete = True self._control_thread.loop.call_soon_threadsafe(self._control.add, self._torrent_info) self.close()
class InfoDialog(QDialog): """文件信息对话框""" get_dl_link = pyqtSignal(str, str) def __init__(self, parent=None): super().__init__(parent) self.infos = None self.initUI() self.setStyleSheet(dialog_qss_style) def update_ui(self): self.tx_dl_link.setPlaceholderText("单击获取") self.tx_name.setText(self.infos[1]) if self.infos[2]: self.setWindowTitle("文件信息") self.lb_name.setText("文件名:") self.lb_desc.setText("文件描述:") self.tx_dl_link.setText("") # 清空旧的信息 self.lb_dl_link.setVisible(True) self.tx_dl_link.setVisible(True) else: self.setWindowTitle("文件夹信息") self.lb_name.setText("文件夹名:") self.lb_desc.setText("文件夹描述:") self.lb_dl_link.setVisible(False) self.tx_dl_link.setVisible(False) if self.infos[2]: self.tx_size.setText(self.infos[2]) self.lb_size.setVisible(True) self.tx_size.setVisible(True) else: self.tx_size.setVisible(False) self.lb_size.setVisible(False) if self.infos[3]: self.lb_time.setVisible(True) self.tx_time.setVisible(True) self.tx_time.setText(self.infos[3]) else: self.lb_time.setVisible(False) self.tx_time.setVisible(False) if self.infos[4]: self.lb_dl_count.setVisible(True) self.tx_dl_count.setVisible(True) self.tx_dl_count.setText(str(self.infos[4])) else: self.tx_dl_count.setVisible(False) self.lb_dl_count.setVisible(False) if self.infos[5]: self.tx_pwd.setText(self.infos[5]) self.tx_pwd.setPlaceholderText("") else: self.tx_pwd.setText("") self.tx_pwd.setPlaceholderText("无") if self.infos[6]: self.tx_desc.setText(self.infos[6]) self.tx_desc.setPlaceholderText("") else: self.tx_desc.setText("") self.tx_desc.setPlaceholderText("无") self.tx_share_url.setText(self.infos[7]) def set_values(self, infos): self.infos = infos self.update_ui() self.exec() def call_get_dl_link(self): url = self.tx_share_url.text() pwd = self.tx_pwd.text() self.get_dl_link.emit(url, pwd) self.tx_dl_link.setPlaceholderText("后台获取中,请稍后!") def initUI(self): self.setWindowIcon(QIcon("./src/share.ico")) self.setWindowTitle("文件信息") self.buttonBox = QDialogButtonBox() self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Close) self.buttonBox.button(QDialogButtonBox.Close).setText("关闭") self.buttonBox.rejected.connect(self.reject) self.logo = QLabel() self.logo.setPixmap(QPixmap("./src/q9.gif")) self.logo.setAlignment(Qt.AlignCenter) self.logo.setStyleSheet("background-color:rgb(255,204,51);") self.lb_name = QLabel() self.lb_name.setText("文件名:") self.tx_name = QLineEdit() self.tx_name.setReadOnly(True) self.lb_size = QLabel() self.lb_size.setText("文件大小:") self.tx_size = QLabel() self.lb_time = QLabel() self.lb_time.setText("上传时间:") self.tx_time = QLabel() self.lb_dl_count = QLabel() self.lb_dl_count.setText("下载次数:") self.tx_dl_count = QLabel() self.lb_share_url = QLabel() self.lb_share_url.setText("分享链接:") self.tx_share_url = QLineEdit() self.tx_share_url.setReadOnly(True) self.lb_pwd = QLabel() self.lb_pwd.setText("提取码:") self.tx_pwd = QLineEdit() self.tx_pwd.setReadOnly(True) self.lb_desc = QLabel() self.lb_desc.setText("文件描述:") self.tx_desc = AutoResizingTextEdit() self.tx_desc.setReadOnly(True) self.lb_dl_link = QLabel() self.lb_dl_link.setText("下载直链:") self.tx_dl_link = AutoResizingTextEdit(self) self.tx_dl_link.setPlaceholderText("单击获取") self.tx_dl_link.clicked.connect(self.call_get_dl_link) self.tx_dl_link.setReadOnly(True) vbox = QVBoxLayout() vbox.addWidget(self.logo) vbox.addStretch(1) form = QFormLayout() form.setLabelAlignment(Qt.AlignRight) form.addRow(self.lb_name, self.tx_name) form.addRow(self.lb_size, self.tx_size) form.addRow(self.lb_time, self.tx_time) form.addRow(self.lb_dl_count, self.tx_dl_count) form.addRow(self.lb_share_url, self.tx_share_url) form.addRow(self.lb_pwd, self.tx_pwd) form.addRow(self.lb_desc, self.tx_desc) form.addRow(self.lb_dl_link, self.tx_dl_link) vbox.addLayout(form) vbox.addStretch(1) vbox.addWidget(self.buttonBox) self.setLayout(vbox)
def showDialog(self, currentCard=None): if currentCard: did = currentCard.did else: did = mw._selectedDeck()['id'] cardInfo = self._getCardInfo(did) if not cardInfo: showInfo('Please select an Incremental Reading deck.') return dialog = QDialog(mw) layout = QVBoxLayout() self.cardListWidget = QListWidget() self.cardListWidget.setAlternatingRowColors(True) self.cardListWidget.setSelectionMode( QAbstractItemView.ExtendedSelection) self.cardListWidget.setWordWrap(True) posWidth = len(str(len(cardInfo) + 1)) for i, card in enumerate(cardInfo, start=1): text = '❰ {} ❱\t{}'.format( str(i).zfill(posWidth), stripHTML(card['title'])) item = QListWidgetItem(text) item.setData(Qt.UserRole, card) self.cardListWidget.addItem(item) upButton = QPushButton('Up') upButton.clicked.connect(self._moveUp) downButton = QPushButton('Down') downButton.clicked.connect(self._moveDown) topButton = QPushButton('Top') topButton.clicked.connect(self._moveToTop) bottomButton = QPushButton('Bottom') bottomButton.clicked.connect(self._moveToBottom) randomizeButton = QPushButton('Randomize') randomizeButton.clicked.connect(self._randomize) controlsLayout = QHBoxLayout() controlsLayout.addWidget(topButton) controlsLayout.addWidget(upButton) controlsLayout.addWidget(downButton) controlsLayout.addWidget(bottomButton) controlsLayout.addStretch() controlsLayout.addWidget(randomizeButton) buttonBox = QDialogButtonBox(QDialogButtonBox.Close | QDialogButtonBox.Save) buttonBox.accepted.connect(dialog.accept) buttonBox.rejected.connect(dialog.reject) buttonBox.setOrientation(Qt.Horizontal) layout.addLayout(controlsLayout) layout.addWidget(self.cardListWidget) layout.addWidget(buttonBox) dialog.setLayout(layout) dialog.setWindowModality(Qt.WindowModal) dialog.resize(500, 500) choice = dialog.exec_() if choice == 1: cids = [] for i in range(self.cardListWidget.count()): card = self.cardListWidget.item(i).data(Qt.UserRole) cids.append(card['id']) self.reorder(cids)
class SetPwdDialog(QDialog): new_infos = pyqtSignal(object) def __init__(self, parent=None): super(SetPwdDialog, self).__init__(parent) self.infos = None self.initUI() self.update_text() self.setStyleSheet(dialog_qss_style) def set_values(self, infos): self.infos = infos self.update_text() # 更新界面 def set_tip(self): # 用于提示状态 self.setWindowTitle("请稍等……") def initUI(self): self.setWindowTitle("请稍等……") self.setWindowIcon(QIcon("./src/password.ico")) self.lb_oldpwd = QLabel() self.lb_oldpwd.setText("当前提取码:") self.lb_oldpwd.setAlignment(Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self.tx_oldpwd = QLineEdit() # 当前提取码 只读 self.tx_oldpwd.setFocusPolicy(Qt.NoFocus) self.tx_oldpwd.setReadOnly(True) self.lb_newpwd = QLabel() self.lb_newpwd.setText("新的提取码:") self.lb_newpwd.setAlignment(Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self.tx_newpwd = QLineEdit() self.buttonBox = QDialogButtonBox() self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.buttonBox.button(QDialogButtonBox.Ok).setText("确定") self.buttonBox.button(QDialogButtonBox.Cancel).setText("取消") self.grid = QGridLayout() self.grid.setSpacing(10) self.grid.addWidget(self.lb_oldpwd, 1, 0) self.grid.addWidget(self.tx_oldpwd, 1, 1) self.grid.addWidget(self.lb_newpwd, 2, 0) self.grid.addWidget(self.tx_newpwd, 2, 1) self.grid.addWidget(self.buttonBox, 3, 0, 1, 2) self.setLayout(self.grid) self.buttonBox.accepted.connect(self.btn_ok) self.buttonBox.accepted.connect(self.accept) self.buttonBox.accepted.connect(self.set_tip) self.buttonBox.rejected.connect(self.reject) self.buttonBox.rejected.connect(self.set_tip) self.setMinimumWidth(280) def update_text(self): if self.infos: if self.infos[5]: self.tx_oldpwd.setText(str(self.infos[5])) self.tx_oldpwd.setPlaceholderText("") else: self.tx_oldpwd.setText("") self.tx_oldpwd.setPlaceholderText("无") if self.infos[2]: # 文件 通过size列判断是否为文件 self.setWindowTitle("修改文件提取码") self.tx_newpwd.setPlaceholderText("2-6位字符,关闭请留空") self.tx_newpwd.setMaxLength(6) # 最长6个字符 else: # 文件夹 self.setWindowTitle("修改文件夹名提取码") self.tx_newpwd.setPlaceholderText("2-12位字符,关闭请留空") self.tx_newpwd.setMaxLength(12) # 最长12个字符 def btn_ok(self): new_pwd = self.tx_newpwd.text() if new_pwd != self.infos[5]: self.new_infos.emit( (self.infos[0], new_pwd, self.infos[2])) # 最后一位用于标示文件还是文件夹
class RenameDialog(QDialog): out = pyqtSignal(object) def __init__(self, parent=None): super(RenameDialog, self).__init__(parent) self.infos = None self.min_width = 400 self.initUI() self.update_text() self.setStyleSheet(dialog_qss_style) def set_values(self, infos): self.infos = infos self.update_text() # 更新界面 def initUI(self): self.setWindowIcon(QIcon("./icon/desc.ico")) self.lb_name = QLabel() self.lb_name.setText("文件夹名:") self.lb_name.setAlignment(Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self.tx_name = QLineEdit() self.lb_desc = QLabel() self.tx_desc = QTextEdit() self.lb_desc.setText("描 述:") self.lb_desc.setAlignment(Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self.buttonBox = QDialogButtonBox() self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.grid = QGridLayout() self.grid.setSpacing(10) self.grid.addWidget(self.lb_name, 1, 0) self.grid.addWidget(self.tx_name, 1, 1) self.grid.addWidget(self.lb_desc, 2, 0) self.grid.addWidget(self.tx_desc, 2, 1, 5, 1) self.grid.addWidget(self.buttonBox, 7, 1, 1, 1) self.setLayout(self.grid) self.buttonBox.accepted.connect(self.btn_ok) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) def update_text(self): if self.infos: self.setWindowTitle("修改文件夹名与描述") self.tx_name.setText(str(self.infos[1])) if self.infos[6]: self.tx_desc.setText("") self.tx_desc.setPlaceholderText(str(self.infos[6])) else: self.tx_desc.setPlaceholderText("无") self.min_width = len(str(self.infos[1])) * 8 if self.infos[2]: # 文件无法重命名,由 infos[2] size表示文件 self.setWindowTitle("修改文件描述") self.tx_name.setFocusPolicy(Qt.NoFocus) self.tx_name.setReadOnly(True) else: self.tx_name.setFocusPolicy(Qt.StrongFocus) self.tx_name.setReadOnly(False) else: self.setWindowTitle("新建文件夹") self.tx_name.setText("") self.tx_name.setFocusPolicy(Qt.StrongFocus) self.tx_name.setReadOnly(False) self.tx_desc.setPlaceholderText("可选项,建议160字数以内。") if self.min_width < 400: self.min_width = 400 self.resize(self.min_width, 200) def btn_ok(self): new_name = self.tx_name.text() new_desc = self.tx_desc.toPlainText() if not self.infos and new_name: # 在 work_id 新建文件夹 self.out.emit(("new", "", new_name, new_desc)) return if new_name != self.infos[1] or (new_desc and new_desc != self.infos[6]): if self.infos[2]: # 文件 self.out.emit(("file", self.infos[0], new_name, new_desc)) else: self.out.emit(("folder", self.infos[0], new_name, new_desc))
class ExportPanel(Panel): FIELDS = [] PERSISTENT_NAME = 'exportPanel' def __init__(self, model, mainwindow): Panel.__init__(self, mainwindow) self.setAttribute(Qt.WA_DeleteOnClose) self.mainwindow = mainwindow self._setupUi() self.model = model self.accountTable = ExportAccountTable(model=self.model.account_table, view=self.tableView) self.exportTypeButtons.buttonClicked[int].connect( self.exportTypeSelected) self.exportFormatButtons.buttonClicked[int].connect( self.exportFormatSelected) self.buttonBox.rejected.connect(self.reject) self.exportButton.clicked.connect(self.exportButtonClicked) def _setupUi(self): self.setWindowTitle(tr("Export Options")) self.mainLayout = QVBoxLayout(self) self.label1 = QLabel(tr("Which accounts do you want to export?"), self) self.mainLayout.addWidget(self.label1) self.exportTypeButtons = QButtonGroup(self) self.exportAllButton = QRadioButton(tr("All"), self) self.mainLayout.addWidget(self.exportAllButton) self.exportTypeButtons.addButton(self.exportAllButton, ExportType.All) self.exportAllButton.setChecked(True) self.exportSelectedButton = QRadioButton(tr("Selected"), self) self.mainLayout.addWidget(self.exportSelectedButton) self.exportTypeButtons.addButton(self.exportSelectedButton, ExportType.Selected) self.tableView = QTableView(self) self.tableView.setSelectionMode(QAbstractItemView.SingleSelection) self.tableView.setSelectionBehavior(QAbstractItemView.SelectRows) self.tableView.verticalHeader().setVisible(False) self.tableView.verticalHeader().setDefaultSectionSize(18) self.mainLayout.addWidget(self.tableView) self.label2 = QLabel(tr("Export format:"), self) self.mainLayout.addWidget(self.label2) self.exportFormatButtons = QButtonGroup(self) self.exportAsQIFButton = QRadioButton("QIF", self) self.mainLayout.addWidget(self.exportAsQIFButton) self.exportFormatButtons.addButton(self.exportAsQIFButton, ExportFormat.QIF) self.exportAsQIFButton.setChecked(True) self.exportAsCSVButton = QRadioButton("CSV", self) self.mainLayout.addWidget(self.exportAsCSVButton) self.exportFormatButtons.addButton(self.exportAsCSVButton, ExportFormat.CSV) self.label3 = QLabel(tr("Export scope:")) self.mainLayout.addWidget(self.label3) self.dateRangeOnlyCheckbox = QCheckBox(tr("Current date range only")) self.mainLayout.addWidget(self.dateRangeOnlyCheckbox) self.buttonBox = QDialogButtonBox(self) self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Cancel) self.exportButton = self.buttonBox.addButton( tr("Export"), QDialogButtonBox.ActionRole) self.mainLayout.addWidget(self.buttonBox) # --- Overrides def _loadFields(self): self.exportAllButton.setChecked(self.model.export_all) self.exportAsQIFButton.setChecked( self.model.export_format == ExportFormat.QIF) self.dateRangeOnlyCheckbox.setChecked( self.model.current_daterange_only) def _saveFields(self): self.model.current_daterange_only = self.dateRangeOnlyCheckbox.isChecked( ) # --- Event Handlers def exportButtonClicked(self): title = tr("Export") fileext = 'qif' if self.model.export_format == ExportFormat.QIF else 'csv' filters = tr("{0} Files (*.{1})").format(fileext.upper(), fileext) filename = 'export.{0}'.format(fileext) docpath = QFileDialog.getSaveFileName(self.mainwindow, title, filename, filters)[0] if docpath: self.model.export_path = docpath self.accept() def exportTypeSelected(self, typeId): self.model.export_all = typeId == ExportType.All def exportFormatSelected(self, typeId): self.model.export_format = typeId # --- model --> view def set_table_enabled(self, enabled): self.tableView.setEnabled(enabled) def set_export_button_enabled(self, enabled): self.exportButton.setEnabled(enabled)
class CityListDlg(QDialog): citieslist_signal = pyqtSignal([list]) def __init__(self, citylist, accurate_url, appid, parent=None): super(CityListDlg, self).__init__(parent) self.citylist = citylist self.accurate_url = accurate_url self.appid = appid self.listWidget = QListWidget() self.listWidget.addItems(self.citylist) buttonLayout = QVBoxLayout() self.buttonBox = QDialogButtonBox() self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.buttonBox.rejected.connect(self.reject) self.buttonBox.accepted.connect(self.accept) layoutT = QVBoxLayout() layout = QHBoxLayout() layout.addWidget(self.listWidget) layout.addLayout(buttonLayout) for text, slot in ((self.tr("&Add..."), self.add), (self.tr("&Remove..."), self.remove), (self.tr("&Up"), self.up), (self.tr("&Down"), self.down), (self.tr("De&fault"), self.default), (self.tr("&Sort"), self.listWidget.sortItems)): button = QPushButton(text) buttonLayout.addWidget(button) button.clicked.connect(slot) buttonLayout.addWidget(self.buttonBox) self.status = QLabel() layoutT.addLayout(layout) layoutT.addWidget(self.status) self.setLayout(layoutT) self.checklength() def add(self): self.status.setText('') lista = [] newitem = '' self.citytoadd = '' self.countrytoadd = '' self._idtoadd = '' dialog = searchcity.SearchCity(self.accurate_url, self.appid, self) dialog.id_signal.connect(self.addcity) dialog.city_signal.connect(self.addcity) dialog.country_signal.connect(self.addcity) if dialog.exec_() == 1: newitem = (self.citytoadd + '_' + self.countrytoadd + '_' + self._idtoadd) for row in range(self.listWidget.count()): lista.append(self.listWidget.item(row).text()) if newitem in lista: self.status.setText(QCoreApplication.translate('Status bar message', 'The city already exists in the list', 'Cities list dialogue')) return else: self.listWidget.addItem(newitem) self.checklength() def addcity(self, what): self.status.setText('') if what[0] == 'ID': self._idtoadd = what[1] elif what[0] == 'City': self.citytoadd = what[1] elif what[0] == 'Country': self.countrytoadd = what[1] def remove(self): self.status.setText('') if self.listWidget.count() == 0: self.status.setText(self.tr('The list is empty')) return row = self.listWidget.currentRow() item = self.listWidget.item(row) if item is None: return message = self.tr('The city "{0}" has been removed').format( self.listWidget.item(row).text()) item = self.listWidget.takeItem(row) del item self.status.setText(message) def up(self): self.status.setText('') row = self.listWidget.currentRow() if row >= 1: item = self.listWidget.takeItem(row) self.listWidget.insertItem(row - 1, item) self.listWidget.setCurrentItem(item) def down(self): self.status.setText('') row = self.listWidget.currentRow() if row < self.listWidget.count() - 1: item = self.listWidget.takeItem(row) self.listWidget.insertItem(row + 1, item) self.listWidget.setCurrentItem(item) def default(self): self.status.setText('') row = self.listWidget.currentRow() if row >= 1: item = self.listWidget.takeItem(row) self.listWidget.insertItem(0, item) self.listWidget.setCurrentItem(item) def checklength(self): listtosend = [] for row in range(self.listWidget.count()): listtosend.append(self.listWidget.item(row).text()) if len(listtosend) == 0: return self.listWidget.setMinimumWidth(self.listWidget.sizeHintForColumn(0)) def accept(self): listtosend = [] for row in range(self.listWidget.count()): listtosend.append(self.listWidget.item(row).text()) self.citieslist_signal[list].emit(listtosend) QDialog.accept(self)
class OnkyoSettings(QDialog): applied_signal = pyqtSignal() def __init__(self, parent=None): super(OnkyoSettings, self).__init__(parent) self.layout = QVBoxLayout() # Host IP self.settings = QSettings('onkyoqt', 'settings') host = self.settings.value('host') or '' self.host_label = QLabel(QCoreApplication.translate('Get it from receiver settings','Receiver IP (Restart needed after change)', 'Settings dialogue')) self.host_text = QLineEdit() self.host_text.setText(host) self.host_text.textChanged.connect(self.host_changed) self.nohost_message = QCoreApplication.translate('Warning message after pressing Ok', 'Please enter your receiver IP address', 'Settings dialogue') # Hide main window on start to tray or not self.hide_label = QLabel(self.tr('Run in tray')) self.hide_checkbox = QCheckBox() self.hide_bool = self.settings.value('hide') or 'False' self.hide_bool = eval(self.hide_bool) self.hide_checkbox.setChecked(self.hide_bool) self.hide_checkbox.stateChanged.connect(self.hide) self.hide_changed = False # OK Cancel Apply Buttons self.buttonLayout = QHBoxLayout() self.buttonLayout.addStretch() self.buttonBox = QDialogButtonBox() self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Apply | QDialogButtonBox.Cancel) self.buttonBox.setContentsMargins(0, 30, 0, 0) self.buttonLayout.addWidget(self.buttonBox) self.buttonBox.button(QDialogButtonBox.Apply).clicked.connect(self.apply_settings) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(False) self.statusbar = QLabel() self.layout.addWidget(self.statusbar) self.panel = QGridLayout() self.panel.addWidget(self.hide_label, 0, 0) self.panel.addWidget(self.hide_checkbox, 0, 1) self.panel.addWidget(self.host_label, 1, 0) self.panel.addWidget(self.host_text, 1, 1) self.layout.addLayout(self.panel) self.layout.addLayout(self.buttonLayout) self.setLayout(self.layout) self.setWindowTitle(self.tr('Onkyo QT Configuration')) def apply_settings(self): self.accepted() def host_changed(self): self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(True) def accepted(self): host = self.host_text.text() if host == '': self.statusbar.setText(self.nohost_message) return else: self.settings.setValue('host', str(self.host_text.text())) self.applied_signal.emit() if self.hide_changed: self.hide_apply() def hide(self, state): self.hide_state = state self.hide_changed = True self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(True) def hide_apply(self): if self.hide_state == 2: self.settings.setValue('hide', 'True') elif self.hide_state == 0: self.settings.setValue('hide', 'False') else: return
class ConfigurationWidget(QWidget): """ Class implementing a dialog for the configuration of eric6. @signal preferencesChanged() emitted after settings have been changed @signal masterPasswordChanged(str, str) emitted after the master password has been changed with the old and the new password @signal accepted() emitted to indicate acceptance of the changes @signal rejected() emitted to indicate rejection of the changes """ preferencesChanged = pyqtSignal() masterPasswordChanged = pyqtSignal(str, str) accepted = pyqtSignal() rejected = pyqtSignal() DefaultMode = 0 HelpBrowserMode = 1 TrayStarterMode = 2 HexEditorMode = 3 def __init__(self, parent=None, fromEric=True, displayMode=DefaultMode, expandedEntries=[]): """ Constructor @param parent The parent widget of this dialog. (QWidget) @keyparam fromEric flag indicating a dialog generation from within the eric6 ide (boolean) @keyparam displayMode mode of the configuration dialog (DefaultMode, HelpBrowserMode, TrayStarterMode, HexEditorMode) @exception RuntimeError raised to indicate an invalid dialog mode @keyparam expandedEntries list of entries to be shown expanded (list of strings) """ assert displayMode in ( ConfigurationWidget.DefaultMode, ConfigurationWidget.HelpBrowserMode, ConfigurationWidget.TrayStarterMode, ConfigurationWidget.HexEditorMode, ) super(ConfigurationWidget, self).__init__(parent) self.fromEric = fromEric self.displayMode = displayMode self.__setupUi() self.itmDict = {} if not fromEric: from PluginManager.PluginManager import PluginManager try: self.pluginManager = e5App().getObject("PluginManager") except KeyError: self.pluginManager = PluginManager(self) e5App().registerObject("PluginManager", self.pluginManager) if displayMode == ConfigurationWidget.DefaultMode: self.configItems = { # key : [display string, pixmap name, dialog module name or # page creation function, parent key, # reference to configuration page (must always be last)] # The dialog module must have the module function 'create' to # create the configuration page. This must have the method # 'save' to save the settings. "applicationPage": [self.tr("Application"), "preferences-application.png", "ApplicationPage", None, None], "cooperationPage": [self.tr("Cooperation"), "preferences-cooperation.png", "CooperationPage", None, None], "corbaPage": [self.tr("CORBA"), "preferences-orbit.png", "CorbaPage", None, None], "emailPage": [self.tr("Email"), "preferences-mail_generic.png", "EmailPage", None, None], "graphicsPage": [self.tr("Graphics"), "preferences-graphics.png", "GraphicsPage", None, None], "hexEditorPage": [self.tr("Hex Editor"), "hexEditor.png", "HexEditorPage", None, None], "iconsPage": [self.tr("Icons"), "preferences-icons.png", "IconsPage", None, None], "ircPage": [self.tr("IRC"), "irc.png", "IrcPage", None, None], "logViewerPage": [self.tr("Log-Viewer"), "preferences-logviewer.png", "LogViewerPage", None, None], "mimeTypesPage": [self.tr("Mimetypes"), "preferences-mimetypes.png", "MimeTypesPage", None, None], "networkPage": [self.tr("Network"), "preferences-network.png", "NetworkPage", None, None], "notificationsPage": [self.tr("Notifications"), "preferences-notifications.png", "NotificationsPage", None, None], "pluginManagerPage": [self.tr("Plugin Manager"), "preferences-pluginmanager.png", "PluginManagerPage", None, None], "printerPage": [self.tr("Printer"), "preferences-printer.png", "PrinterPage", None, None], "pythonPage": [self.tr("Python"), "preferences-python.png", "PythonPage", None, None], "qtPage": [self.tr("Qt"), "preferences-qtlogo.png", "QtPage", None, None], "securityPage": [self.tr("Security"), "preferences-security.png", "SecurityPage", None, None], "shellPage": [self.tr("Shell"), "preferences-shell.png", "ShellPage", None, None], "tasksPage": [self.tr("Tasks"), "task.png", "TasksPage", None, None], "templatesPage": [self.tr("Templates"), "preferences-template.png", "TemplatesPage", None, None], "trayStarterPage": [self.tr("Tray Starter"), "erict.png", "TrayStarterPage", None, None], "vcsPage": [self.tr("Version Control Systems"), "preferences-vcs.png", "VcsPage", None, None], "0debuggerPage": [self.tr("Debugger"), "preferences-debugger.png", None, None, None], "debuggerGeneralPage": [self.tr("General"), "preferences-debugger.png", "DebuggerGeneralPage", "0debuggerPage", None], "debuggerPythonPage": [self.tr("Python"), "preferences-pyDebugger.png", "DebuggerPythonPage", "0debuggerPage", None], "debuggerPython3Page": [self.tr("Python3"), "preferences-pyDebugger.png", "DebuggerPython3Page", "0debuggerPage", None], "0editorPage": [self.tr("Editor"), "preferences-editor.png", None, None, None], "editorAPIsPage": [self.tr("APIs"), "preferences-api.png", "EditorAPIsPage", "0editorPage", None], "editorAutocompletionPage": [self.tr("Autocompletion"), "preferences-autocompletion.png", "EditorAutocompletionPage", "0editorPage", None], "editorAutocompletionQScintillaPage": [self.tr("QScintilla"), "qscintilla.png", "EditorAutocompletionQScintillaPage", "editorAutocompletionPage", None], "editorCalltipsPage": [self.tr("Calltips"), "preferences-calltips.png", "EditorCalltipsPage", "0editorPage", None], "editorCalltipsQScintillaPage": [self.tr("QScintilla"), "qscintilla.png", "EditorCalltipsQScintillaPage", "editorCalltipsPage", None], "editorGeneralPage": [self.tr("General"), "preferences-general.png", "EditorGeneralPage", "0editorPage", None], "editorFilePage": [self.tr("Filehandling"), "preferences-filehandling.png", "EditorFilePage", "0editorPage", None], "editorSearchPage": [self.tr("Searching"), "preferences-search.png", "EditorSearchPage", "0editorPage", None], "editorSpellCheckingPage": [self.tr("Spell checking"), "preferences-spellchecking.png", "EditorSpellCheckingPage", "0editorPage", None], "editorStylesPage": [self.tr("Style"), "preferences-styles.png", "EditorStylesPage", "0editorPage", None], "editorSyntaxPage": [self.tr("Code Checkers"), "preferences-debugger.png", "EditorSyntaxPage", "0editorPage", None], "editorTypingPage": [self.tr("Typing"), "preferences-typing.png", "EditorTypingPage", "0editorPage", None], "editorExportersPage": [self.tr("Exporters"), "preferences-exporters.png", "EditorExportersPage", "0editorPage", None], "1editorLexerPage": [self.tr("Highlighters"), "preferences-highlighting-styles.png", None, "0editorPage", None], "editorHighlightersPage": [self.tr("Filetype Associations"), "preferences-highlighter-association.png", "EditorHighlightersPage", "1editorLexerPage", None], "editorHighlightingStylesPage": [self.tr("Styles"), "preferences-highlighting-styles.png", "EditorHighlightingStylesPage", "1editorLexerPage", None], "editorKeywordsPage": [self.tr("Keywords"), "preferences-keywords.png", "EditorKeywordsPage", "1editorLexerPage", None], "editorPropertiesPage": [self.tr("Properties"), "preferences-properties.png", "EditorPropertiesPage", "1editorLexerPage", None], "1editorMouseClickHandlers": [self.tr("Mouse Click Handlers"), "preferences-mouse-click-handler.png", "EditorMouseClickHandlerPage", "0editorPage", None], "0helpPage": [self.tr("Help"), "preferences-help.png", None, None, None], "helpDocumentationPage": [self.tr("Help Documentation"), "preferences-helpdocumentation.png", "HelpDocumentationPage", "0helpPage", None], "helpViewersPage": [self.tr("Help Viewers"), "preferences-helpviewers.png", "HelpViewersPage", "0helpPage", None], "0projectPage": [self.tr("Project"), "preferences-project.png", None, None, None], "projectBrowserPage": [self.tr("Project Viewer"), "preferences-project.png", "ProjectBrowserPage", "0projectPage", None], "projectPage": [self.tr("Project"), "preferences-project.png", "ProjectPage", "0projectPage", None], "multiProjectPage": [self.tr("Multiproject"), "preferences-multiproject.png", "MultiProjectPage", "0projectPage", None], "0interfacePage": [self.tr("Interface"), "preferences-interface.png", None, None, None], "interfacePage": [self.tr("Interface"), "preferences-interface.png", "InterfacePage", "0interfacePage", None], "viewmanagerPage": [self.tr("Viewmanager"), "preferences-viewmanager.png", "ViewmanagerPage", "0interfacePage", None], } try: from PyQt5 import QtWebKit # __IGNORE_WARNING__ self.configItems.update({ "helpAppearancePage": [self.tr("Appearance"), "preferences-styles.png", "HelpAppearancePage", "0helpPage", None], "helpFlashCookieManagerPage": [self.tr("Flash Cookie Manager"), "flashCookie16.png", "HelpFlashCookieManagerPage", "0helpPage", None], "helpVirusTotalPage": [self.tr("VirusTotal Interface"), "virustotal.png", "HelpVirusTotalPage", "0helpPage", None], "helpWebBrowserPage": [self.tr("eric6 Web Browser"), "ericWeb.png", "HelpWebBrowserPage", "0helpPage", None], }) except ImportError: pass self.configItems.update( e5App().getObject("PluginManager").getPluginConfigData()) elif displayMode == ConfigurationWidget.HelpBrowserMode: self.configItems = { # key : [display string, pixmap name, dialog module name or # page creation function, parent key, # reference to configuration page (must always be last)] # The dialog module must have the module function 'create' to # create the configuration page. This must have the method # 'save' to save the settings. "interfacePage": [self.tr("Interface"), "preferences-interface.png", "HelpInterfacePage", None, None], "networkPage": [self.tr("Network"), "preferences-network.png", "NetworkPage", None, None], "printerPage": [self.tr("Printer"), "preferences-printer.png", "PrinterPage", None, None], "securityPage": [self.tr("Security"), "preferences-security.png", "SecurityPage", None, None], "0helpPage": [self.tr("Help"), "preferences-help.png", None, None, None], "helpDocumentationPage": [self.tr("Help Documentation"), "preferences-helpdocumentation.png", "HelpDocumentationPage", "0helpPage", None], } try: from PyQt5 import QtWebKit # __IGNORE_WARNING__ self.configItems.update({ "helpAppearancePage": [self.tr("Appearance"), "preferences-styles.png", "HelpAppearancePage", "0helpPage", None], "helpFlashCookieManagerPage": [self.tr("Flash Cookie Manager"), "flashCookie16.png", "HelpFlashCookieManagerPage", "0helpPage", None], "helpVirusTotalPage": [self.tr("VirusTotal Interface"), "virustotal.png", "HelpVirusTotalPage", "0helpPage", None], "helpWebBrowserPage": [self.tr("eric6 Web Browser"), "ericWeb.png", "HelpWebBrowserPage", "0helpPage", None], }) except ImportError: pass elif displayMode == ConfigurationWidget.TrayStarterMode: self.configItems = { # key : [display string, pixmap name, dialog module name or # page creation function, parent key, # reference to configuration page (must always be last)] # The dialog module must have the module function 'create' to # create the configuration page. This must have the method # 'save' to save the settings. "trayStarterPage": [self.tr("Tray Starter"), "erict.png", "TrayStarterPage", None, None], } elif displayMode == ConfigurationWidget.HexEditorMode: self.configItems = { # key : [display string, pixmap name, dialog module name or # page creation function, parent key, # reference to configuration page (must always be last)] # The dialog module must have the module function 'create' to # create the configuration page. This must have the method # 'save' to save the settings. "hexEditorPage": [self.tr("Hex Editor"), "hexEditor.png", "HexEditorPage", None, None], } else: raise RuntimeError("Illegal mode value: {0}".format(displayMode)) # generate the list entries self.__expandedEntries = [] for key in sorted(self.configItems.keys()): pageData = self.configItems[key] if pageData[3]: if pageData[3] in self.itmDict: pitm = self.itmDict[pageData[3]] # get the parent item else: continue else: pitm = self.configList self.itmDict[key] = ConfigurationPageItem(pitm, pageData[0], key, pageData[1]) self.itmDict[key].setData(0, Qt.UserRole, key) if (not self.fromEric or displayMode != ConfigurationWidget.DefaultMode or key in expandedEntries): self.itmDict[key].setExpanded(True) self.configList.sortByColumn(0, Qt.AscendingOrder) # set the initial size of the splitter self.configSplitter.setSizes([200, 600]) self.configList.itemActivated.connect(self.__showConfigurationPage) self.configList.itemClicked.connect(self.__showConfigurationPage) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.rejected) if displayMode in [ConfigurationWidget.HelpBrowserMode, ConfigurationWidget.TrayStarterMode, ConfigurationWidget.HexEditorMode]: self.configListSearch.hide() if displayMode not in [ConfigurationWidget.TrayStarterMode, ConfigurationWidget.HexEditorMode]: self.__initLexers() def accept(self): """ Public slot to accept the buttonBox accept signal. """ if not isMacPlatform(): wdg = self.focusWidget() if wdg == self.configList: return self.accepted.emit() def __setupUi(self): """ Private method to perform the general setup of the configuration widget. """ self.setObjectName("ConfigurationDialog") self.resize(900, 650) self.verticalLayout_2 = QVBoxLayout(self) self.verticalLayout_2.setSpacing(6) self.verticalLayout_2.setContentsMargins(6, 6, 6, 6) self.verticalLayout_2.setObjectName("verticalLayout_2") self.configSplitter = QSplitter(self) self.configSplitter.setOrientation(Qt.Horizontal) self.configSplitter.setObjectName("configSplitter") self.configListWidget = QWidget(self.configSplitter) self.leftVBoxLayout = QVBoxLayout(self.configListWidget) self.leftVBoxLayout.setContentsMargins(0, 0, 0, 0) self.leftVBoxLayout.setSpacing(0) self.leftVBoxLayout.setObjectName("leftVBoxLayout") self.configListSearch = E5ClearableLineEdit( self, self.tr("Enter search text...")) self.configListSearch.setObjectName("configListSearch") self.leftVBoxLayout.addWidget(self.configListSearch) self.configList = QTreeWidget() self.configList.setObjectName("configList") self.leftVBoxLayout.addWidget(self.configList) self.configListSearch.textChanged.connect(self.__searchTextChanged) self.scrollArea = QScrollArea(self.configSplitter) self.scrollArea.setFrameShape(QFrame.NoFrame) self.scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOn) self.scrollArea.setWidgetResizable(False) self.scrollArea.setObjectName("scrollArea") self.configStack = QStackedWidget() self.configStack.setFrameShape(QFrame.Box) self.configStack.setFrameShadow(QFrame.Sunken) self.configStack.setObjectName("configStack") self.scrollArea.setWidget(self.configStack) self.emptyPage = QWidget() self.emptyPage.setGeometry(QRect(0, 0, 372, 591)) self.emptyPage.setObjectName("emptyPage") self.vboxlayout = QVBoxLayout(self.emptyPage) self.vboxlayout.setSpacing(6) self.vboxlayout.setContentsMargins(6, 6, 6, 6) self.vboxlayout.setObjectName("vboxlayout") spacerItem = QSpacerItem( 20, 20, QSizePolicy.Minimum, QSizePolicy.Expanding) self.vboxlayout.addItem(spacerItem) self.emptyPagePixmap = QLabel(self.emptyPage) self.emptyPagePixmap.setAlignment(Qt.AlignCenter) self.emptyPagePixmap.setObjectName("emptyPagePixmap") self.emptyPagePixmap.setPixmap( QPixmap(os.path.join(getConfig('ericPixDir'), 'eric.png'))) self.vboxlayout.addWidget(self.emptyPagePixmap) self.textLabel1 = QLabel(self.emptyPage) self.textLabel1.setAlignment(Qt.AlignCenter) self.textLabel1.setObjectName("textLabel1") self.vboxlayout.addWidget(self.textLabel1) spacerItem1 = QSpacerItem( 20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) self.vboxlayout.addItem(spacerItem1) self.configStack.addWidget(self.emptyPage) self.verticalLayout_2.addWidget(self.configSplitter) self.buttonBox = QDialogButtonBox(self) self.buttonBox.setOrientation(Qt.Horizontal) self.buttonBox.setStandardButtons( QDialogButtonBox.Apply | QDialogButtonBox.Cancel | QDialogButtonBox.Ok | QDialogButtonBox.Reset) self.buttonBox.setObjectName("buttonBox") if not self.fromEric and \ self.displayMode == ConfigurationWidget.DefaultMode: self.buttonBox.button(QDialogButtonBox.Apply).hide() self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(False) self.buttonBox.button(QDialogButtonBox.Reset).setEnabled(False) self.verticalLayout_2.addWidget(self.buttonBox) self.setWindowTitle(self.tr("Preferences")) self.configList.header().hide() self.configList.header().setSortIndicator(0, Qt.AscendingOrder) self.configList.setSortingEnabled(True) self.textLabel1.setText( self.tr("Please select an entry of the list \n" "to display the configuration page.")) QMetaObject.connectSlotsByName(self) self.setTabOrder(self.configList, self.configStack) self.configStack.setCurrentWidget(self.emptyPage) self.configList.setFocus() def __searchTextChanged(self, text): """ Private slot to handle a change of the search text. @param text text to search for (string) """ self.__searchChildItems(self.configList.invisibleRootItem(), text) def __searchChildItems(self, parent, text): """ Private method to enable child items based on a search string. @param parent reference to the parent item (QTreeWidgetItem) @param text text to search for (string) @return flag indicating an enabled child item (boolean) """ childEnabled = False text = text.lower() for index in range(parent.childCount()): itm = parent.child(index) if itm.childCount() > 0: enable = self.__searchChildItems(itm, text) or \ text == "" or text in itm.text(0).lower() else: enable = text == "" or text in itm.text(0).lower() if enable: childEnabled = True itm.setDisabled(not enable) return childEnabled def __initLexers(self): """ Private method to initialize the dictionary of preferences lexers. """ import QScintilla.Lexers from .PreferencesLexer import PreferencesLexer, \ PreferencesLexerLanguageError self.lexers = {} for language in QScintilla.Lexers.getSupportedLanguages(): if language not in self.lexers: try: self.lexers[language] = PreferencesLexer(language, self) except PreferencesLexerLanguageError: pass def __importConfigurationPage(self, name): """ Private method to import a configuration page module. @param name name of the configuration page module (string) @return reference to the configuration page module """ modName = "Preferences.ConfigurationPages.{0}".format(name) try: mod = __import__(modName) components = modName.split('.') for comp in components[1:]: mod = getattr(mod, comp) return mod except ImportError: E5MessageBox.critical( self, self.tr("Configuration Page Error"), self.tr("""<p>The configuration page <b>{0}</b>""" """ could not be loaded.</p>""").format(name)) return None def __showConfigurationPage(self, itm, column): """ Private slot to show a selected configuration page. @param itm reference to the selected item (QTreeWidgetItem) @param column column that was selected (integer) (ignored) """ pageName = itm.getPageName() self.showConfigurationPageByName(pageName, setCurrent=False) def __initPage(self, pageData): """ Private method to initialize a configuration page. @param pageData data structure for the page to initialize @return reference to the initialized page """ page = None if isinstance(pageData[2], types.FunctionType): page = pageData[2](self) else: mod = self.__importConfigurationPage(pageData[2]) if mod: page = mod.create(self) if page is not None: self.configStack.addWidget(page) pageData[-1] = page try: page.setMode(self.displayMode) except AttributeError: pass return page def showConfigurationPageByName(self, pageName, setCurrent=True): """ Public slot to show a named configuration page. @param pageName name of the configuration page to show (string) @param setCurrent flag indicating to set the current item (boolean) """ if pageName == "empty" or pageName not in self.configItems: page = self.emptyPage else: pageData = self.configItems[pageName] if pageData[-1] is None and pageData[2] is not None: # the page was not loaded yet, create it page = self.__initPage(pageData) else: page = pageData[-1] if page is None: page = self.emptyPage elif setCurrent: items = self.configList.findItems( pageData[0], Qt.MatchFixedString | Qt.MatchRecursive) for item in items: if item.data(0, Qt.UserRole) == pageName: self.configList.setCurrentItem(item) self.configStack.setCurrentWidget(page) ssize = self.scrollArea.size() if self.scrollArea.horizontalScrollBar(): ssize.setHeight( ssize.height() - self.scrollArea.horizontalScrollBar().height() - 2) if self.scrollArea.verticalScrollBar(): ssize.setWidth( ssize.width() - self.scrollArea.verticalScrollBar().width() - 2) psize = page.minimumSizeHint() self.configStack.resize(max(ssize.width(), psize.width()), max(ssize.height(), psize.height())) if page != self.emptyPage: page.polishPage() self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(True) self.buttonBox.button(QDialogButtonBox.Reset).setEnabled(True) else: self.buttonBox.button(QDialogButtonBox.Apply).setEnabled(False) self.buttonBox.button(QDialogButtonBox.Reset).setEnabled(False) # reset scrollbars for sb in [self.scrollArea.horizontalScrollBar(), self.scrollArea.verticalScrollBar()]: if sb: sb.setValue(0) self.__currentConfigurationPageName = pageName def getConfigurationPageName(self): """ Public method to get the page name of the current page. @return page name of the current page (string) """ return self.__currentConfigurationPageName def calledFromEric(self): """ Public method to check, if invoked from within eric. @return flag indicating invocation from within eric (boolean) """ return self.fromEric def getPage(self, pageName): """ Public method to get a reference to the named page. @param pageName name of the configuration page (string) @return reference to the page or None, indicating page was not loaded yet """ return self.configItems[pageName][-1] def getLexers(self): """ Public method to get a reference to the lexers dictionary. @return reference to the lexers dictionary """ return self.lexers def setPreferences(self): """ Public method called to store the selected values into the preferences storage. """ for key, pageData in list(self.configItems.items()): if pageData[-1]: pageData[-1].save() # page was loaded (and possibly modified) QApplication.processEvents() # ensure HMI is responsive def on_buttonBox_clicked(self, button): """ Private slot called by a button of the button box clicked. @param button button that was clicked (QAbstractButton) """ if button == self.buttonBox.button(QDialogButtonBox.Apply): self.on_applyButton_clicked() elif button == self.buttonBox.button(QDialogButtonBox.Reset): self.on_resetButton_clicked() @pyqtSlot() def on_applyButton_clicked(self): """ Private slot called to apply the settings of the current page. """ if self.configStack.currentWidget() != self.emptyPage: page = self.configStack.currentWidget() savedState = page.saveState() page.save() self.preferencesChanged.emit() if savedState is not None: page.setState(savedState) page.polishPage() @pyqtSlot() def on_resetButton_clicked(self): """ Private slot called to reset the settings of the current page. """ if self.configStack.currentWidget() != self.emptyPage: currentPage = self.configStack.currentWidget() savedState = currentPage.saveState() pageName = self.configList.currentItem().getPageName() self.configStack.removeWidget(currentPage) if pageName == "editorHighlightingStylesPage": self.__initLexers() self.configItems[pageName][-1] = None self.showConfigurationPageByName(pageName) if savedState is not None: self.configStack.currentWidget().setState(savedState) def getExpandedEntries(self): """ Public method to get a list of expanded entries. @return list of expanded entries (list of string) """ return self.__expandedEntries @pyqtSlot(QTreeWidgetItem) def on_configList_itemCollapsed(self, item): """ Private slot handling a list entry being collapsed. @param item reference to the collapsed item (QTreeWidgetItem) """ pageName = item.data(0, Qt.UserRole) if pageName in self.__expandedEntries: self.__expandedEntries.remove(pageName) @pyqtSlot(QTreeWidgetItem) def on_configList_itemExpanded(self, item): """ Private slot handling a list entry being expanded. @param item reference to the expanded item (QTreeWidgetItem) """ pageName = item.data(0, Qt.UserRole) if pageName not in self.__expandedEntries: self.__expandedEntries.append(pageName)