class GanttConfigure(QDialog): def __init__(self, sim, start, end): QDialog.__init__(self) #self.setCaption("Gantt configuration") self.layout = QVBoxLayout(self) # self._slider = QxtSpanSliderWidget( # sim.observe_window[0] // sim.cycles_per_ms, # min(sim.now(), sim.observe_window[1]) // sim.cycles_per_ms, # self) self._slider = QxtSpanSliderWidget( 0, min(sim.now(), sim.duration) // sim.cycles_per_ms, self) self._slider.setSpan(start, end) self.layout.addWidget(self._slider) self._list_elements = QListWidget(self) for processor in sim.processors: item = QListWidgetItem(processor.name, self._list_elements) item.setData(Qt.UserRole, processor) self._list_elements.addItem(item) for task in sim.task_list: item = QListWidgetItem(task.name, self._list_elements) item.setData(Qt.UserRole, task) self._list_elements.addItem(item) #self._list_elements.setDragDropMode(QListWidget.InternalMove) for row in range(0, self._list_elements.count()): self._list_elements.item(row).setCheckState(Qt.Checked) self.layout.addWidget(self._list_elements) buttons = QWidget(self) buttons_layout = QHBoxLayout() buttons.setLayout(buttons_layout) buttons_layout.addStretch() ok_button = QPushButton("Ok") cancel_button = QPushButton("Cancel") ok_button.clicked.connect(self.accept) cancel_button.clicked.connect(self.reject) buttons_layout.addWidget(ok_button) buttons_layout.addWidget(cancel_button) self.layout.addWidget(buttons) def get_start_date(self): return self._slider.lowerValue def get_end_date(self): return self._slider.upperValue def get_selected_items(self): res = [] for row in range(0, self._list_elements.count()): if self._list_elements.item(row).checkState() == Qt.Checked: try: data = self._list_elements.item(row).data(Qt.UserRole).toPyObject() except AttributeError: data = self._list_elements.item(row).data(Qt.UserRole) res.append(data) return res
class SnappingDock(DockWidget): def __init__(self, iface, parent=None): super(SnappingDock, self).__init__(parent) self._iface = iface self.setWindowTitle(u'Snapping Panel') self.setObjectName(u'snappingDock') self._listWidget = QListWidget(self) self._listWidget.setSelectionMode(QAbstractItemView.NoSelection) self._listWidget.setDropIndicatorShown(False) self._dockLayout = QVBoxLayout(self) self._dockLayout.setObjectName(u'dockLayout') self._dockLayout.addWidget(self._listWidget) self._dockContents = QWidget(self) self._dockContents.setObjectName(u'dockContents') self._dockContents.setLayout(self._dockLayout) self.setWidget(self._dockContents) # Keep up-to-date with layers added and removed QgsMapLayerRegistry.instance().layersAdded.connect(self._layersAdded) QgsMapLayerRegistry.instance().layersRemoved.connect( self._layersRemoved) def refresh(self): self._listWidget.clear() layers = QgsMapLayerRegistry.instance().mapLayers() layerIds = layers.keys() sorted(layerIds) for layerId in layerIds: self.addLayer(layers[layerId]) def addLayer(self, layer): if (layer is None or not layer.isValid() or layer.type() != QgsMapLayer.VectorLayer): return newItem = QListWidgetItem() newItem.setData(Qt.UserRole, layer.id()) # newItem.setSizeHint(layerWidget.minimumSizeHint()) self._listWidget.addItem(newItem) self._listWidget.setItemWidget(newItem, LayerSnappingWidget(layer, self)) def removeLayer(self, layerId): for idx in range(0, self._listWidget.count() - 1): if self._listWidget.item(idx).data() == layerId: self._listWidget.takeItem(idx) return def _layersAdded(self, layers): for layer in layers: self.addLayer(layer) def _layersRemoved(self, layerIds): for idx in range(self._listWidget.count() - 1, 0): if self._listWidget.item(idx).data() in layerIds: self._listWidget.takeItem(idx)
class SnappingDock(DockWidget): def __init__(self, iface, parent=None): super(SnappingDock, self).__init__(parent) self._iface = iface self.setWindowTitle(u'Snapping Panel') self.setObjectName(u'snappingDock') self._listWidget = QListWidget(self) self._listWidget.setSelectionMode(QAbstractItemView.NoSelection) self._listWidget.setDropIndicatorShown(False) self._dockLayout = QVBoxLayout(self) self._dockLayout.setObjectName(u'dockLayout') self._dockLayout.addWidget(self._listWidget) self._dockContents = QWidget(self) self._dockContents.setObjectName(u'dockContents') self._dockContents.setLayout(self._dockLayout) self.setWidget(self._dockContents) # Keep up-to-date with layers added and removed QgsMapLayerRegistry.instance().layersAdded.connect(self._layersAdded) QgsMapLayerRegistry.instance().layersRemoved.connect(self._layersRemoved) def refresh(self): self._listWidget.clear() layers = QgsMapLayerRegistry.instance().mapLayers() layerIds = layers.keys() sorted(layerIds) for layerId in layerIds: self.addLayer(layers[layerId]) def addLayer(self, layer): if (layer is None or not layer.isValid() or layer.type() != QgsMapLayer.VectorLayer): return newItem = QListWidgetItem() newItem.setData(Qt.UserRole, layer.id()) # newItem.setSizeHint(layerWidget.minimumSizeHint()) self._listWidget.addItem(newItem) self._listWidget.setItemWidget(newItem, LayerSnappingWidget(layer, self)) def removeLayer(self, layerId): for idx in range(0, self._listWidget.count() - 1): if self._listWidget.item(idx).data() == layerId: self._listWidget.takeItem(idx) return def _layersAdded(self, layers): for layer in layers: self.addLayer(layer) def _layersRemoved(self, layerIds): for idx in range(self._listWidget.count() - 1, 0): if self._listWidget.item(idx).data() in layerIds: self._listWidget.takeItem(idx)
class TagsWidget(QWidget): tagsChanged = pyqtSignal(list) def __init__(self, parent=None): super(TagsWidget, self).__init__(parent) self.lineEdit = TagLineEdit(self) self.lineEdit.returnPressed.connect( lambda: QTimer.singleShot(0, self.addTag)) self.listWidget = QListWidget(self) l = QVBoxLayout(self) l.addWidget(self.lineEdit) l.addWidget(self.listWidget) self.availableTags = [] self.reload() def reload(self): tags = Session.query(Tag.name, Tag.id).all() self.tagsdict = dict(tags) self.availableTags = self.tagsdict.keys() for i in xrange(self.listWidget.count()): tag = self.listWidget.item(i).text() if tag in self.availableTags: self.availableTags.remove(tag) self.lineEdit.completer().model().setStringList(self.availableTags) def addTag(self): text = self.lineEdit.text() if text in self.availableTags: self.availableTags.remove(text) self.lineEdit.completer().model().setStringList(self.availableTags) self.listWidget.addItem(text) self.lineEdit.clear() self.tagsChanged.emit(self.tags()) def tags(self): tags = [ self.tagsdict[self.listWidget.item(i).text()] for i in xrange(self.listWidget.count()) ] return tags def keyPressEvent(self, event): if event.key() == Qt.Key_Delete: self.listWidget.takeItem(self.listWidget.currentRow()) self.tagsChanged.emit(self.tags()) else: super(TagsWidget, self).keyPressEvent(event)
def addPathList(self, key, typeid, predefs, selectednodes): if not self.overwriteKeys(key) and type(key).__name__=='str': layout = QVBoxLayout() listpathcontainer = QListWidget() ##XXX listpathcontainer.setDragDropMode(QAbstractItemView.InternalMove) if len(predefs) > 0: if not self.checkUnifiedTypes(predefs): return -1 for predef in predefs: listpathcontainer.insertItem(listpathcontainer.count() + 1, str(predef)) if selectednodes and len(selectednodes) > 0: for node in selectednodes: if type(node) == Node and typeid == typeId.Node: listpathcontainer.insertItem(listpathcontainer.count() + 1, QString.fromUtf8(node.absolute())) elif type(node) != Node: listpathcontainer.insertItem(listpathcontainer.count() + 1, node) hbox = QHBoxLayout() buttonbox = QDialogButtonBox() if typeid == typeId.Path: combo = QComboBox() self.connect(combo, SIGNAL("editTextChanged(QString)"), self.argumentChanged) self.connect(combo, SIGNAL("currentIndexChanged(QString)"), self.argumentChanged) combo.addItem(self.inputFile) combo.addItem(self.inputDirectory) add = addLocalPathButton(self, key, listpathcontainer, combo) else: add = addLocalPathButton(self, key, listpathcontainer, nodetype=True) buttonbox.addButton(add, QDialogButtonBox.ActionRole) rm = rmLocalPathButton(self, listpathcontainer) buttonbox.addButton(rm, QDialogButtonBox.ActionRole) self.connect(add, SIGNAL("clicked()"), self.argumentChanged) self.connect(rm, SIGNAL("clicked()"), self.argumentChanged) hbox.addWidget(buttonbox, 3, Qt.AlignLeft) if typeid == typeId.Path: hbox.addWidget(combo, 1, Qt.AlignRight) layout.addLayout(hbox, 0) layout.addWidget(listpathcontainer, 2) if not self.displaykey: self.layout.addRow(layout) else: self.layout.addRow(key, layout) self.widgets[key] = listpathcontainer return 1 else: return -1
class TagsWidget(QWidget): tagsChanged = pyqtSignal(list) def __init__(self, parent=None): super(TagsWidget, self).__init__(parent) self.lineEdit = TagLineEdit(self) self.lineEdit.returnPressed.connect( lambda: QTimer.singleShot(0, self.addTag)) self.listWidget = QListWidget(self) l = QVBoxLayout(self) l.addWidget(self.lineEdit) l.addWidget(self.listWidget) self.availableTags = [] self.reload() def reload(self): tags = Session.query(Tag.name, Tag.id).all() self.tagsdict = dict(tags) self.availableTags = self.tagsdict.keys() for i in xrange(self.listWidget.count()): tag = self.listWidget.item(i).text() if tag in self.availableTags: self.availableTags.remove(tag) self.lineEdit.completer().model().setStringList(self.availableTags) def addTag(self): text = self.lineEdit.text() if text in self.availableTags: self.availableTags.remove(text) self.lineEdit.completer().model().setStringList(self.availableTags) self.listWidget.addItem(text) self.lineEdit.clear() self.tagsChanged.emit(self.tags()) def tags(self): tags = [self.tagsdict[self.listWidget.item(i).text()] for i in xrange(self.listWidget.count())] return tags def keyPressEvent(self, event): if event.key() == Qt.Key_Delete: self.listWidget.takeItem(self.listWidget.currentRow()) self.tagsChanged.emit(self.tags()) else: super(TagsWidget, self).keyPressEvent(event)
class InterfacePage(QWizardPage): def __init__(self): super(InterfacePage,self).__init__() self.completed = False self.setTitle('接口设置') self.setSubTitle('设置需要实现的接口') rootLayout = QVBoxLayout() rootLayout.setContentsMargins(20, 30, 20, 30) self.lw_interface = QListWidget() rootLayout.addWidget(self.lw_interface) self.setLayout(rootLayout) def initializePage(self): super(InterfacePage, self).initializePage() exsits = [] for key in app.g_configurations.interfaces: if app.g_configurations.interfaces[key]: exsits.append(key) for interface in app.g_configurations.config['interfaces']: litem = QListWidgetItem(interface['name']) litem.setToolTip(interface['description']) litem.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled) if app.g_configurations.initialized: if interface['name'] in exsits: litem.setCheckState(Qt.Checked) else: litem.setCheckState(Qt.Unchecked) else: isdefault = False if app.g_configurations.component_type == "window": if interface['default'] & 2: isdefault = True else: if interface['default'] & 1: isdefault = True if isdefault: litem.setCheckState(Qt.Checked) else: litem.setCheckState(Qt.Unchecked) self.lw_interface.addItem(litem) def validatePage(self): interfaces = {} for i in range(self.lw_interface.count()): litem = self.lw_interface.item(i) key = app.QString2str(litem.text()) if litem.checkState() == 2: interfaces[key] = True; else: interfaces[key] = False; app.g_configurations.interfaces = interfaces return True
class InterfacePage(QWizardPage): def __init__(self): super(InterfacePage, self).__init__() self.completed = False self.setTitle('接口设置') self.setSubTitle('设置需要实现的接口') rootLayout = QVBoxLayout() rootLayout.setContentsMargins(20, 30, 20, 30) self.lw_interface = QListWidget() rootLayout.addWidget(self.lw_interface) self.setLayout(rootLayout) def initializePage(self): super(InterfacePage, self).initializePage() exsits = [] for key in app.g_configurations.interfaces: if app.g_configurations.interfaces[key]: exsits.append(key) for interface in app.g_configurations.config['interfaces']: litem = QListWidgetItem(interface['name']) litem.setToolTip(interface['description']) litem.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled) if app.g_configurations.initialized: if interface['name'] in exsits: litem.setCheckState(Qt.Checked) else: litem.setCheckState(Qt.Unchecked) else: isdefault = False if app.g_configurations.component_type == "window": if interface['default'] & 2: isdefault = True else: if interface['default'] & 1: isdefault = True if isdefault: litem.setCheckState(Qt.Checked) else: litem.setCheckState(Qt.Unchecked) self.lw_interface.addItem(litem) def validatePage(self): interfaces = {} for i in range(self.lw_interface.count()): litem = self.lw_interface.item(i) key = app.QString2str(litem.text()) if litem.checkState() == 2: interfaces[key] = True else: interfaces[key] = False app.g_configurations.interfaces = interfaces return True
class ChainComposerDialog(QDialog): def __init__(self, parent=None): super(ChainComposerDialog, self).__init__(parent) self.setWindowTitle("Composer Chain") layout = QVBoxLayout() mainLayout = QHBoxLayout() selectionLayout = QVBoxLayout() label = QLabel("Available Filters:") selectionLayout.addWidget(label) self.__selectionList = QListWidget() selectionLayout.addWidget(self.__selectionList) mainLayout.addLayout(selectionLayout) actionsLayout = QVBoxLayout() actionsLayout.addStretch() addButton = QPushButton("Add>>") addButton.clicked.connect(self.__handleAdd) actionsLayout.addWidget(addButton) removeButton = QPushButton("Remove") actionsLayout.addWidget(removeButton) removeAllButton = QPushButton("Remove All") actionsLayout.addWidget(removeAllButton) actionsLayout.addStretch() mainLayout.addLayout(actionsLayout) chainLayout = QVBoxLayout() chainLayout.addWidget(QLabel("Chain:")) self.__chainList = QListWidget() chainLayout.addWidget(self.__chainList) mainLayout.addLayout(chainLayout) layout.addLayout(mainLayout) buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) buttonBox.accepted.connect(self.okClick) buttonBox.rejected.connect(self.cancelClick) layout.addWidget(buttonBox) # buttonLayout = QHBoxLayout() # okButton = QPushButton('OK') # okButton.clicked.connect(self.accept) # buttonLayout.addWidget(okButton) # cancelButton = QPushButton('Cancel') # cancelButton.clicked.connect(self.reject) # buttonLayout.addWidget(cancelButton) # layout.addLayout(buttonLayout) self.setLayout(layout) self.__composer = None def okClick(self): print "OK!" self.accept() def cancelClick(self): print "Cancel" self.reject() def setComposer(self, composer): self.__composer = composer @property def selectionList(self): return self.__getStrings(self.__selectionList) @selectionList.setter def setSelectionList(self, filters): for i in xrange(self.__selectionList.count()): self.__selectionList.takeItem(i) self.__selectionList.addItems(filters) def filterAt(self, row): return self.__selectionList.item(row).text() def addToChain(self, filterName): self.__chainList.addItem(filterName) @property def composedFilter(self): return self.__getStrings(self.__chainList) @staticmethod def __getStrings(listWidget): return tuple(listWidget.item(i) for i in range(listWidget.count())) def __handleAdd(self): if self.__composer is None: return for item in self.__selectionList.selectedItems(): row = self.__selectionList.row(item) self.__composer.add(row)
class SolverGenerator(QWidget): def __init__(self): super().__init__() self._init_info_base() self._init_ui() def _init_info_base(self): f = open('base') lines = [line for line in f.readlines() if line.split()] count = int(lines[0]) self._names = {} for line in lines[1:1 + count]: line = line.split(' ', 1) self._names[line[1].rstrip()] = line[0] model = [Formula(info=line1, code=line2) for line1, line2 in zip(lines[1 + count::2], lines[2 + count::2])] self._info_base = InfoBase(model) def _init_ui(self): main = QVBoxLayout(self) up_label = QLabel('Входные параметры:') up_label.setAlignment(Qt.AlignCenter) main.addWidget(up_label) up = QHBoxLayout(self) self.up_left = QListWidget(self) self.up_left.addItems(list(self._names.keys())) self.up_left.sortItems() up.addWidget(self.up_left) up_buttons = QVBoxLayout(self) up_to_right = QPushButton('>') self.connect(up_to_right, SIGNAL('pressed()'), self._up_to_right) up_buttons.addWidget(up_to_right) up_to_left = QPushButton('<') self.connect(up_to_left, SIGNAL('pressed()'), self._up_to_left) up_buttons.addWidget(up_to_left) up_buttons.setAlignment(Qt.AlignCenter) up.addLayout(up_buttons) self.up_right = QListWidget(self) up.addWidget(self.up_right) self.up_right.sortItems() main.addLayout(up) down_label = QLabel('Выходные параметры:') down_label.setAlignment(Qt.AlignCenter) main.addWidget(down_label) down = QHBoxLayout(self) self.down_left = QListWidget(self) self.down_left.addItems(list(self._names.keys())) self.down_left.sortItems() down.addWidget(self.down_left) down_buttons = QVBoxLayout(self) down_to_right = QPushButton('>') self.connect(down_to_right, SIGNAL('pressed()'), self._down_to_right) down_buttons.addWidget(down_to_right) down_to_left = QPushButton('<') self.connect(down_to_left, SIGNAL('pressed()'), self._down_to_left) down_buttons.addWidget(down_to_left) down_buttons.setAlignment(Qt.AlignCenter) down.addLayout(down_buttons) self.down_right = QListWidget(self) down.addWidget(self.down_right) self.down_right.sortItems() main.addLayout(down) solve = QPushButton('Решить') self.connect(solve, SIGNAL('pressed()'), self._solve) main.addWidget(solve) self.setLayout(main) self.setWindowTitle('SolverGenerator') self.resize(600, 600) self._center() self.show() def _solve(self): input_definition = [self.up_right.item(i).text() for i in range(self.up_right.count())] input_params = [self._names[item] for item in input_definition] output_definition = [self.down_right.item(i).text() for i in range(self.down_right.count())] output_params = [self._names[item] for item in output_definition] algorithm = self._info_base.get_algorithm(input_params, output_params) if algorithm: self._generate_code(input_definition, input_params, output_definition, output_params, algorithm) else: QMessageBox().warning(self, 'Решения нет', 'Для выбранных данных решения нет') def _up_to_right(self): item = self.up_left.takeItem(self.up_left.currentRow()) self.up_right.addItem(item) self.up_right.sortItems() def _up_to_left(self): item = self.up_right.takeItem(self.up_right.currentRow()) self.up_left.addItem(item) self.up_left.sortItems() def _down_to_right(self): item = self.down_left.takeItem(self.down_left.currentRow()) self.down_right.addItem(item) self.down_right.sortItems() def _down_to_left(self): item = self.down_right.takeItem(self.down_right.currentRow()) self.down_left.addItem(item) self.down_left.sortItems() def _center(self): qr = self.frameGeometry() cp = QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) self.move(qr.topLeft()) @staticmethod def _generate_code(input_definition, input_params, output_definition, output_params, algorithm): code = [] if any('math' in formula.code for formula in algorithm): code.append('import math') for name, definition in zip(input_params, input_definition): code.append( '{0} = float(input("Введите {0} ({1}): "))'.format(name, definition.lower())) for formula in algorithm: code.append(formula.code) for name, definition in zip(output_params, output_definition): code.append('print("{0} = %f" % {1})'.format(definition, name)) code.append('input("Нажмите Enter для завершения.")') code.append('') code = '\n'.join(code) file = open('program.py', 'w') file.write(code) file.close() xterm = sh.Command('xterm') xterm('-e', 'python3 program.py')
class CodeCompletionWidget(QFrame): def __init__(self, editor): super(CodeCompletionWidget, self).__init__(None, Qt.FramelessWindowHint | Qt.ToolTip) self._editor = editor self.stack_layout = QStackedLayout(self) self.stack_layout.setContentsMargins(0, 0, 0, 0) self.stack_layout.setSpacing(0) self.completion_list = QListWidget() self.completion_list.setMinimumHeight(200) self.completion_list.setAlternatingRowColors(True) self._list_index = self.stack_layout.addWidget(self.completion_list) self._icons = { "a": resources.IMAGES["attribute"], "f": resources.IMAGES["function"], "c": resources.IMAGES["class"], } self.cc = code_completion.CodeCompletion() self._completion_results = [] self._prefix = u"" self.setVisible(False) self.source = "" self._key_operations = { Qt.Key_Up: self._select_previous_row, Qt.Key_Down: self._select_next_row, Qt.Key_PageUp: (lambda: self._select_previous_row(6)), Qt.Key_PageDown: (lambda: self._select_next_row(6)), Qt.Key_Right: lambda: None, Qt.Key_Left: lambda: None, Qt.Key_Enter: self.pre_key_insert_completion, Qt.Key_Return: self.pre_key_insert_completion, Qt.Key_Tab: self.pre_key_insert_completion, Qt.Key_Space: self.hide_completer, Qt.Key_Escape: self.hide_completer, Qt.Key_Backtab: self.hide_completer, Qt.NoModifier: self.hide_completer, Qt.ShiftModifier: self.hide_completer, } desktop = QApplication.instance().desktop() self._desktop_geometry = desktop.availableGeometry() self.connect(self._editor.document(), SIGNAL("blockCountChanged(int)"), self.update_metadata) def _select_next_row(self, move=1): new_row = self.completion_list.currentRow() + move if new_row < self.completion_list.count(): self.completion_list.setCurrentRow(new_row) else: self.completion_list.setCurrentRow(0) return True def _select_previous_row(self, move=1): new_row = self.completion_list.currentRow() - move if new_row >= 0: self.completion_list.setCurrentRow(new_row) else: self.completion_list.setCurrentRow(self.completion_list.count() - move) return True def update_metadata(self): source = self._editor.get_text() source = source.encode(self._editor.encoding) self.cc.analyze_file("", source) def insert_completion(self, insert): if insert != self._prefix: extra = len(self._prefix) - len(insert) self._editor.textCursor().insertText(insert[extra:]) self.hide_completer() def _get_geometry(self): cr = self._editor.cursorRect() point = self._editor.mapToGlobal(cr.topLeft()) cr.moveTopLeft(point) # Check new position according desktop geometry width = ( self.completion_list.sizeHintForColumn(0) + self.completion_list.verticalScrollBar().sizeHint().width() + 10 ) height = 200 orientation = (point.y() + height) < self._desktop_geometry.height() if orientation: cr.moveTop(cr.bottom()) cr.setWidth(width) cr.setHeight(height) if not orientation: cr.moveBottom(cr.top()) xpos = self._desktop_geometry.width() - (point.x() + width) if xpos < 0: cr.moveLeft(cr.left() + xpos) return cr def complete(self, results): self.add_list_items(results) self.completion_list.setCurrentRow(0) cr = self._get_geometry() self.setGeometry(cr) self.completion_list.updateGeometries() self.show() def add_list_items(self, proposals): self.completion_list.clear() for p in proposals: self.completion_list.addItem( QListWidgetItem(QIcon(self._icons.get(p[0], resources.IMAGES["attribute"])), p[1]) ) def set_completion_prefix(self, prefix): self._prefix = prefix proposals = [] proposals += [("c", item) for item in self.completion_results.get("classes", []) if item.startswith(prefix)] proposals += [("a", item) for item in self.completion_results.get("attributes", []) if item.startswith(prefix)] proposals += [("f", item) for item in self.completion_results.get("functions", []) if item.startswith(prefix)] if proposals: self.complete(proposals) else: self.hide_completer() def fill_completer(self): source = self._editor.get_text() source = source.encode(self._editor.encoding) offset = self._editor.textCursor().position() results = self.cc.get_completion(source, offset) self.completion_results = results prefix = self._editor._text_under_cursor() self.set_completion_prefix(prefix) def hide_completer(self): self._prefix = "" self.hide() def pre_key_insert_completion(self): insert = unicode(self.completion_list.currentItem().text()) self.insert_completion(insert) self.hide_completer() return True def process_pre_key_event(self, event): if not self.isVisible(): return False skip = self._key_operations.get(event.key(), lambda: False)() self._key_operations.get(event.modifiers(), lambda: False)() if skip is None: skip = False return skip def process_post_key_event(self, event): if not settings.CODE_COMPLETION or self._editor.lang != "python": return if self.isVisible(): source = self._editor.get_text() source = source.encode(self._editor.encoding) offset = self._editor.textCursor().position() prefix = self.cc.get_prefix(source, offset) self.set_completion_prefix(prefix) self.completion_list.setCurrentRow(0) if event.key() == Qt.Key_Period or (event.key() == Qt.Key_Space and event.modifiers() == Qt.ControlModifier): self.fill_completer()
class NotebookListDialog(QDialog): """ Funtions to display, create, remove, modify notebookList """ def __init__(self, parent=None): super(NotebookListDialog, self).__init__(parent) self.notebookList = QListWidget() self.moveUp = QPushButton('<<') self.moveDown = QPushButton('>>') self.add = QPushButton('Add') self.remove = QPushButton('Remove') self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False) layout = QGridLayout() layout.addWidget(self.notebookList, 0, 0, 4, 6) layout.addWidget(self.moveUp, 1, 6) layout.addWidget(self.moveDown, 2, 6) layout.addWidget(self.add, 4, 0) layout.addWidget(self.remove, 4, 1) layout.addWidget(self.buttonBox, 4, 5, 1, 2) self.setLayout(layout) self.notebookList.setItemDelegate(ListDelegate(self.notebookList)) self.notebookList.currentRowChanged.connect(self.updateUi) self.add.clicked.connect(self.actionAdd) self.remove.clicked.connect(self.actionRemove) self.moveUp.clicked.connect(self.moveItemUp) self.moveDown.clicked.connect(self.moveItemDown) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) self.initList() def initList(self): self.notebookList.clear() notebooks = Mikibook.read() for nb in notebooks: item = QListWidgetItem() item.setData(Qt.DisplayRole, nb[0]) item.setData(Qt.UserRole, nb[1]) self.notebookList.addItem(item) self.updateUi(len(notebooks) != 0) self.notebookList.setCurrentRow(0) # QListWidgetItem(nb, self.notebookList) def updateUi(self, row): flag = (row != -1) self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(flag) self.remove.setEnabled(flag) self.moveUp.setEnabled(flag) self.moveDown.setEnabled(flag) def actionAdd(self): Mikibook.create() self.initList() count = self.notebookList.count() self.notebookList.setCurrentRow(count-1) def actionRemove(self): item = self.notebookList.currentItem() row = self.notebookList.currentRow() name = item.data(Qt.DisplayRole) path = item.data(Qt.UserRole) self.notebookList.takeItem(row) Mikibook.remove(name, path) def moveItemUp(self): item = self.notebookList.currentItem() row = self.notebookList.currentRow() if row != 0: # self.notebookList.removeItemWidget(item) self.notebookList.takeItem(row) self.notebookList.insertItem(row-1, item) self.notebookList.setCurrentRow(row-1) def moveItemDown(self): item = self.notebookList.currentItem() row = self.notebookList.currentRow() count = self.notebookList.count() if row != count-1: self.notebookList.takeItem(row) self.notebookList.insertItem(row+1, item) self.notebookList.setCurrentRow(row+1) def accept(self): notebookPath = self.notebookList.currentItem().data(Qt.UserRole) notebookName = self.notebookList.currentItem().data(Qt.DisplayRole) settings = Setting([[notebookName, notebookPath]]) window = mikidown.MikiWindow(settings) window.show() count = self.notebookList.count() notebooks = [] for i in range(count): name = self.notebookList.item(i).data(Qt.DisplayRole) path = self.notebookList.item(i).data(Qt.UserRole) notebooks.append([name, path]) Mikibook.write(notebooks) QDialog.accept(self)
class CodeCompletionWidget(QFrame): def __init__(self, editor): super(CodeCompletionWidget, self).__init__(None, Qt.FramelessWindowHint | Qt.ToolTip) self._editor = editor self._revision = 0 self._block = 0 self.stack_layout = QStackedLayout(self) self.stack_layout.setContentsMargins(0, 0, 0, 0) self.stack_layout.setSpacing(0) self.completion_list = QListWidget() self.completion_list.setMinimumHeight(200) self.completion_list.setAlternatingRowColors(True) self._list_index = self.stack_layout.addWidget(self.completion_list) self._icons = { 'a': resources.IMAGES['attribute'], 'f': resources.IMAGES['function'], 'c': resources.IMAGES['class'], 'm': resources.IMAGES['module'] } self.cc = code_completion.CodeCompletion() self._completion_results = {} self._prefix = '' self.setVisible(False) self.source = '' self._key_operations = { Qt.Key_Up: self._select_previous_row, Qt.Key_Down: self._select_next_row, Qt.Key_PageUp: (lambda: self._select_previous_row(6)), Qt.Key_PageDown: (lambda: self._select_next_row(6)), Qt.Key_Right: lambda: None, Qt.Key_Left: lambda: None, Qt.Key_Enter: self.pre_key_insert_completion, Qt.Key_Return: self.pre_key_insert_completion, Qt.Key_Tab: self.pre_key_insert_completion, Qt.Key_Space: self.hide_completer, Qt.Key_Escape: self.hide_completer, Qt.Key_Backtab: self.hide_completer, Qt.NoModifier: self.hide_completer, Qt.ShiftModifier: self.hide_completer, } self.desktop = QApplication.instance().desktop() self.connect(self.completion_list, SIGNAL("itemClicked(QListWidgetItem*)"), self.pre_key_insert_completion) self.connect(self._editor.document(), SIGNAL("cursorPositionChanged(QTextCursor)"), self.update_metadata) def _select_next_row(self, move=1): new_row = self.completion_list.currentRow() + move if new_row < self.completion_list.count(): self.completion_list.setCurrentRow(new_row) else: self.completion_list.setCurrentRow(0) return True def _select_previous_row(self, move=1): new_row = self.completion_list.currentRow() - move if new_row >= 0: self.completion_list.setCurrentRow(new_row) else: self.completion_list.setCurrentRow(self.completion_list.count() - move) return True def update_metadata(self, cursor): if settings.CODE_COMPLETION: if self._editor.document().revision() != self._revision and \ cursor.block().blockNumber() != self._block: source = self._editor.get_text() source = source.encode(self._editor.encoding) self.cc.analyze_file(self._editor.ID, source, self._editor.indent, self._editor.useTabs) self._revision = self._editor.document().revision() self._block = cursor.block().blockNumber() def insert_completion(self, insert, type_=ord('a')): if insert != self._prefix: closing = '' if type_ in (ord('f'), ord('c')): closing = '()' extra = len(self._prefix) - len(insert) insertion = '%s%s' % (insert[extra:], closing) self._editor.textCursor().insertText(insertion) self.hide_completer() def _get_geometry(self): cr = self._editor.cursorRect() desktop_geometry = self.desktop.availableGeometry(self._editor) point = self._editor.mapToGlobal(cr.topLeft()) cr.moveTopLeft(point) #Check new position according desktop geometry width = (self.completion_list.sizeHintForColumn(0) + self.completion_list.verticalScrollBar().sizeHint().width() + 10) height = 200 orientation = (point.y() + height) < desktop_geometry.height() if orientation: cr.moveTop(cr.bottom()) cr.setWidth(width) cr.setHeight(height) if not orientation: cr.moveBottom(cr.top()) xpos = desktop_geometry.width() - (point.x() + width) if xpos < 0: cr.moveLeft(cr.left() + xpos) return cr def complete(self, results): self.add_list_items(results) self.completion_list.setCurrentRow(0) cr = self._get_geometry() self.setGeometry(cr) self.completion_list.updateGeometries() self.show() def add_list_items(self, proposals): self.completion_list.clear() for p in proposals: self.completion_list.addItem( QListWidgetItem(QIcon( self._icons.get(p[0], resources.IMAGES['attribute'])), p[1], type=ord(p[0]))) def set_completion_prefix(self, prefix, valid=True): self._prefix = prefix proposals = [] proposals += [('m', item) for item in self._completion_results.get('modules', []) if item.startswith(prefix)] proposals += [('c', item) for item in self._completion_results.get('classes', []) if item.startswith(prefix)] proposals += [ ('a', item) for item in self._completion_results.get('attributes', []) if item.startswith(prefix) ] proposals += [ ('f', item) for item in self._completion_results.get('functions', []) if item.startswith(prefix) ] if proposals and valid: self.complete(proposals) else: self.hide_completer() def _invalid_completion_position(self): result = False cursor = self._editor.textCursor() cursor.movePosition(QTextCursor.StartOfLine, QTextCursor.KeepAnchor) selection = cursor.selectedText()[:-1].split(' ') if len(selection) == 0 or selection[-1] == '' or \ selection[-1].isdigit(): result = True return result def fill_completer(self, force_completion=False): if not force_completion and (self._editor.cursor_inside_string() or self._editor.cursor_inside_comment() or self._invalid_completion_position()): return source = self._editor.get_text() source = source.encode(self._editor.encoding) offset = self._editor.textCursor().position() results = self.cc.get_completion(source, offset) self._completion_results = results if force_completion: cursor = self._editor.textCursor() cursor.movePosition(QTextCursor.StartOfWord, QTextCursor.KeepAnchor) prefix = cursor.selectedText() else: prefix = self._editor._text_under_cursor() self.set_completion_prefix(prefix) def hide_completer(self): self._prefix = '' self.hide() def pre_key_insert_completion(self): type_ = ord('a') current = self.completion_list.currentItem() insert = current.text() if not insert.endswith(')'): type_ = current.type() self.insert_completion(insert, type_) self.hide_completer() return True def process_pre_key_event(self, event): if not self.isVisible() or self._editor.lang != "python": return False skip = self._key_operations.get(event.key(), lambda: False)() self._key_operations.get(event.modifiers(), lambda: False)() if skip is None: skip = False return skip def process_post_key_event(self, event): if not settings.CODE_COMPLETION or self._editor.lang != "python": return if self.isVisible(): source = self._editor.get_text() source = source.encode(self._editor.encoding) offset = self._editor.textCursor().position() prefix, valid = self.cc.get_prefix(source, offset) self.set_completion_prefix(prefix, valid) self.completion_list.setCurrentRow(0) force_completion = (event.key() == Qt.Key_Space and event.modifiers() == Qt.ControlModifier) if event.key() == Qt.Key_Period or force_completion: self.fill_completer(force_completion)
class AdvancedVisualizationForm(QWidget): def __init__(self, mainwindow, result_manager): QWidget.__init__(self, mainwindow) #mainwindow is an OpusGui self.mainwindow = mainwindow self.result_manager = result_manager self.toolboxBase = self.result_manager.mainwindow.toolboxBase self.inGui = False self.logFileKey = 0 self.xml_helper = ResultsManagerXMLHelper(toolboxBase = self.toolboxBase) self.result_generator = OpusResultGenerator( toolboxBase = self.toolboxBase) self.result_generator.guiElement = self self.tabIcon = QIcon(':/Images/Images/cog.png') self.tabLabel = 'Advanced Visualization' self.widgetLayout = QVBoxLayout(self) self.widgetLayout.setAlignment(Qt.AlignTop) self.resultsGroupBox = QGroupBox(self) self.widgetLayout.addWidget(self.resultsGroupBox) self.dataGroupBox = QGroupBox(self) self.widgetLayout.addWidget(self.dataGroupBox) self.optionsGroupBox = QGroupBox(self) self.widgetLayout.addWidget(self.optionsGroupBox) self._setup_definition_widget() self._setup_buttons() self._setup_tabs() def _setup_buttons(self): # Add Generate button... self.pbn_go = QPushButton(self.resultsGroupBox) self.pbn_go.setObjectName('pbn_go') self.pbn_go.setText(QString('Go!')) QObject.connect(self.pbn_go, SIGNAL('released()'), self.on_pbn_go_released) self.widgetLayout.addWidget(self.pbn_go) self.pbn_set_esri_storage_location = QPushButton(self.optionsGroupBox) self.pbn_set_esri_storage_location.setObjectName('pbn_set_esri_storage_location') self.pbn_set_esri_storage_location.setText(QString('...')) self.pbn_set_esri_storage_location.hide() QObject.connect(self.pbn_set_esri_storage_location, SIGNAL('released()'), self.on_pbn_set_esri_storage_location_released) def _setup_tabs(self): # Add a tab widget and layer in a tree view and log panel self.tabWidget = QTabWidget(self.resultsGroupBox) # Log panel self.logText = QTextEdit(self.resultsGroupBox) self.logText.setReadOnly(True) self.logText.setLineWidth(0) self.tabWidget.addTab(self.logText,'Log') # Finally add the tab to the model page self.widgetLayout.addWidget(self.tabWidget) # def _setup_definition_widget(self): #### setup results group box #### self.gridlayout = QGridLayout(self.resultsGroupBox) self.gridlayout.setObjectName('gridlayout') self.lbl_results = QLabel(self.resultsGroupBox) self.lbl_results.setObjectName('lbl_results') self.lbl_results.setText(QString('Results')) self.gridlayout.addWidget(self.lbl_results,0,0,1,3) self._setup_co_results() self.gridlayout.addWidget(self.co_results,0,3,1,10) self.pbn_add = QPushButton(self.resultsGroupBox) self.pbn_add.setObjectName('pbn_add') self.pbn_add.setText(QString('+')) QObject.connect(self.pbn_add, SIGNAL('released()'), self.on_pbn_add_released) self.gridlayout.addWidget(self.pbn_add, 0, 14, 1, 1) self.lw_indicators = QListWidget(self.resultsGroupBox) self.lw_indicators.setObjectName('lw_indicators') self.gridlayout.addWidget(self.lw_indicators,1,1,1,13) self.pbn_remove = QPushButton(self.resultsGroupBox) self.pbn_remove.setObjectName('pbn_remove') self.pbn_remove.setText(QString('-')) QObject.connect(self.pbn_remove, SIGNAL('released()'), self.on_pbn_remove_released) self.gridlayout.addWidget(self.pbn_remove, 1, 14, 1, 1) #### setup data group box #### self.gridlayout2 = QGridLayout(self.dataGroupBox) self.gridlayout2.setObjectName('gridlayout2') self._setup_co_result_style() self.gridlayout2.addWidget(self.co_result_style,1,0,1,2) self.lbl_result_style_sep = QLabel(self.resultsGroupBox) self.lbl_result_style_sep.setObjectName('lbl_result_style_sep') self.lbl_result_style_sep.setText(QString('<center>as</center>')) self.gridlayout2.addWidget(self.lbl_result_style_sep,1,2,1,1) self._setup_co_result_type() self.gridlayout2.addWidget(self.co_result_type,1,3,1,2) ##### setup options group box #### self.gridlayout3 = QGridLayout(self.optionsGroupBox) self.gridlayout3.setObjectName('gridlayout3') self.le_esri_storage_location = QLineEdit(self.optionsGroupBox) self.le_esri_storage_location.setObjectName('le_esri_storage_location') self.le_esri_storage_location.setText('[set path]') self.le_esri_storage_location.hide() self.optionsGroupBox.hide() QObject.connect(self.co_result_style, SIGNAL('currentIndexChanged(int)'), self.on_co_result_style_changed) QObject.connect(self.co_result_type, SIGNAL('currentIndexChanged(int)'), self.on_co_result_type_changed) def _setup_co_results(self): self.co_results = QComboBox(self.resultsGroupBox) self.co_results.setObjectName('co_results') self.co_results.addItem(QString('[select]')) results = self.xml_helper.get_available_results() for result in results: name = '%i.%s'%(result['run_id'],result['indicator_name']) self.co_results.addItem(QString(name)) def _setup_co_result_style(self): available_styles = [ 'visualize', 'export', ] self.co_result_style = QComboBox(self.dataGroupBox) self.co_result_style.setObjectName('co_result_style') for dataset in available_styles: self.co_result_style.addItem(QString(dataset)) def _setup_co_result_type(self): available_types = [ 'Table (per year, spans indicators)', 'Chart (per indicator, spans years)', 'Map (per indicator per year)', 'Chart (per indicator, spans years)', ] self.co_result_type = QComboBox(self.dataGroupBox) self.co_result_type.setObjectName('co_result_type') for dataset in available_types: self.co_result_type.addItem(QString(dataset)) def on_pbnRemoveModel_released(self): self.result_manager.removeTab(self) self.result_manager.updateGuiElements() def on_pbn_add_released(self): cur_selected = self.co_results.currentText() for i in range(self.lw_indicators.count()): if self.lw_indicators.item(i).text() == cur_selected: return self.lw_indicators.addItem(cur_selected) def on_pbn_remove_released(self): selected_idxs = self.lw_indicators.selectedIndexes() for idx in selected_idxs: self.lw_indicators.takeItem(idx.row()) def on_co_result_style_changed(self, ind): available_viz_types = [ 'Table (per year, spans indicators)', 'Chart (per indicator, spans years)', 'Map (per indicator per year)', 'Chart (per indicator, spans years)', ] available_export_types = [ 'ESRI table (for loading in ArcGIS)' ] txt = self.co_result_style.currentText() if txt == 'visualize': available_types = available_viz_types else: available_types = available_export_types self.co_result_type.clear() for result_type in available_types: r_type = QString(result_type) self.co_result_type.addItem(r_type) def on_co_result_type_changed(self, ind): self.gridlayout3.removeWidget(self.le_esri_storage_location) self.gridlayout3.removeWidget(self.pbn_set_esri_storage_location) self.optionsGroupBox.hide() self.pbn_set_esri_storage_location.hide() self.le_esri_storage_location.hide() txt = self.co_result_type.currentText() print txt if txt == 'ESRI table (for loading in ArcGIS)': self.pbn_set_esri_storage_location.show() self.le_esri_storage_location.show() self.gridlayout3.addWidget(self.le_esri_storage_location,0,1,1,6) self.gridlayout3.addWidget(self.pbn_set_esri_storage_location,0,7,1,1) self.optionsGroupBox.show() def on_pbn_set_esri_storage_location_released(self): print 'pbn_set_esri_storage_location released' from opus_core.misc import directory_path_from_opus_path start_dir = directory_path_from_opus_path('opus_gui.projects') configDialog = QFileDialog() filter_str = QString("*.gdb") fd = configDialog.getExistingDirectory(self,QString("Please select an ESRI geodatabase (*.gdb)..."), #, *.sde, *.mdb)..."), QString(start_dir), QFileDialog.ShowDirsOnly) if len(fd) != 0: fileName = QString(fd) fileNameInfo = QFileInfo(QString(fd)) fileNameBaseName = fileNameInfo.completeBaseName() self.le_esri_storage_location.setText(fileName) def on_pbn_go_released(self): # Fire up a new thread and run the model print 'Go button pressed' # References to the GUI elements for status for this run... #self.statusLabel = self.runStatusLabel #self.statusLabel.setText(QString('Model initializing...')) indicator_names = [] for i in range(self.lw_indicators.count()): indicator_names.append(str(self.lw_indicators.item(i).text())) if indicator_names == []: print 'no indicators selected' return indicator_type = str(self.co_result_type.currentText()) indicator_type = { #'Map (per indicator per year)':'matplotlib_map', 'Map (per indicator per year)':'mapnik_map', 'Chart (per indicator, spans years)':'matplotlib_chart', 'Table (per indicator, spans years)':'table_per_attribute', 'Table (per year, spans indicators)':'table_per_year', 'ESRI table (for loading in ArcGIS)':'table_esri' }[indicator_type] kwargs = {} if indicator_type == 'table_esri': storage_location = str(self.le_esri_storage_location.text()) if not os.path.exists(storage_location): print 'Warning: %s does not exist!!'%storage_location kwargs['storage_location'] = storage_location self.result_manager.addIndicatorForm(indicator_type = indicator_type, indicator_names = indicator_names, kwargs = kwargs) def runUpdateLog(self): self.logFileKey = self.result_generator._get_current_log(self.logFileKey) def runErrorFromThread(self,errorMessage): QMessageBox.warning(self.mainwindow, 'Warning', errorMessage)
class statisticsInfoWidget(infoWidget): __chart = None __mainLayout = None __statistics = None __projectsList = None __buttonsLayout = None __statisticGroupBox = None __statisticLayout = None __modeGroupBox = None __modeLayout = None __colors = [Qt.red, QColor(200, 160, 30), Qt.darkGreen, Qt.blue, Qt.black, Qt.darkRed, Qt.darkBlue] def __init__(self, client, parent = None): infoWidget.__init__(self, client, parent) self.__mainLayout = QHBoxLayout() self.__chart = LineChartFrame() self.__projectsList = QListWidget() self.__projectsList.setFixedWidth(200) self.__statisticGroupBox = QGroupBox(self.tr("Statistics type")) self.__statisticLayout = QVBoxLayout() self.__statisticGroupBox.setLayout(self.__statisticLayout) userTotalRadio = QRadioButton(self.tr("User total"), self.__statisticGroupBox) userAverageRadio = QRadioButton(self.tr("User average"), self.__statisticGroupBox) hostTotalRadio = QRadioButton(self.tr("Host total"), self.__statisticGroupBox) hostAverageRadio = QRadioButton(self.tr("Host average"), self.__statisticGroupBox) self.__statisticLayout.addWidget(userTotalRadio) self.__statisticLayout.addWidget(userAverageRadio) self.__statisticLayout.addWidget(hostTotalRadio) self.__statisticLayout.addWidget(hostAverageRadio) self.__buttonsLayout = QVBoxLayout() self.__buttonsLayout.addWidget(self.__projectsList) self.__buttonsLayout.addWidget(self.__statisticGroupBox) self.__mainLayout.addWidget(self.__chart) self.__mainLayout.addLayout(self.__buttonsLayout) self.setMainLayout(self.__mainLayout) userTotalRadio.setChecked(True) self.connect(userTotalRadio, SIGNAL("toggled(bool)"), self.__setUserTotalGraph) self.connect(userAverageRadio, SIGNAL("toggled(bool)"), self.__setUserAverageGraph) self.connect(hostTotalRadio, SIGNAL("toggled(bool)"), self.__setHostTotalGraph) self.connect(hostAverageRadio, SIGNAL("toggled(bool)"), self.__setHostAverageGraph) self.connect(self.__projectsList, SIGNAL("itemChanged(QListWidgetItem *)"), self.__updateStatisticsGraph) self.connect(client, SIGNAL("getStatisticsRecv(PyQt_PyObject)"), self.__updateStatistics) client.getStatistics() def __setUserTotalGraph(self, checked): if checked: self.__chart.setIndex(0) def __setUserAverageGraph(self, checked): if checked: self.__chart.setIndex(1) def __setHostTotalGraph(self, checked): if checked: self.__chart.setIndex(2) def __setHostAverageGraph(self, checked): if checked: self.__chart.setIndex(3) def __updateStatistics(self, statistics): self.disconnect(self.sender(), SIGNAL("getStatisticsRecv(PyQt_PyObject)"), self.__updateStatistics) self.__statistics = statistics self.__addListItems() self.__updateStatisticsGraph() def __addListItems(self): i = 0 for key in self.__statistics.keys(): name = self.sender().getProjectName(key) if name is None: name = key color = self.__colors[i] item = QListWidgetItem(name) item.setData(Qt.DecorationRole, QVariant(QColor(color))) item.setData(Qt.UserRole, QVariant(key)) item.setFlags(Qt.ItemIsSelectable|Qt.ItemIsUserCheckable|Qt.ItemIsEnabled) item.setCheckState(Qt.Checked) self.__projectsList.addItem(item) i = i + 1 if i >= len(self.__colors): i = 0 def __updateStatisticsGraph(self): self.__chart.removeGraphs() for i in range(self.__projectsList.count()): item = self.__projectsList.item(i) color = item.data(Qt.DecorationRole) name = str(item.data(Qt.DisplayRole).toString()) key = str(item.data(Qt.UserRole).toString()) if item.checkState() == Qt.Checked: self.__chart.addGraph(self.__statistics[key], name, color)
class GroupSelectParameterWidget(GenericParameterWidget): """Widget class for Group Select Parameter.""" def __init__(self, parameter, parent=None): """Constructor. :param parameter: A GroupSelectParameter object. :type parameter: GroupSelectParameter """ QWidget.__init__(self, parent) self._parameter = parameter # Store spin box self.spin_boxes = {} # Create elements # Label (name) self.label = QLabel(self._parameter.name) # Layouts self.main_layout = QVBoxLayout() self.input_layout = QVBoxLayout() # _inner_input_layout must be filled with widget in the child class self.inner_input_layout = QVBoxLayout() self.radio_button_layout = QGridLayout() # Create radio button group self.input_button_group = QButtonGroup() # List widget self.list_widget = QListWidget() self.list_widget.setSelectionMode(QAbstractItemView.ExtendedSelection) self.list_widget.setDragDropMode(QAbstractItemView.DragDrop) self.list_widget.setDefaultDropAction(Qt.MoveAction) self.list_widget.setEnabled(False) self.list_widget.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Expanding) for i, key in enumerate(self._parameter.options): value = self._parameter.options[key] radio_button = QRadioButton(value.get('label')) self.radio_button_layout.addWidget(radio_button, i, 0) if value.get('type') == SINGLE_DYNAMIC: double_spin_box = QDoubleSpinBox() self.radio_button_layout.addWidget(double_spin_box, i, 1) double_spin_box.setValue(value.get('value', 0)) double_spin_box.setMinimum( value.get('constraint', {}).get('min', 0)) double_spin_box.setMaximum( value.get('constraint', {}).get('max', 1)) double_spin_box.setSingleStep( value.get('constraint', {}).get('step', 0.01)) step = double_spin_box.singleStep() if step > 1: precision = 0 else: precision = len(str(step).split('.')[1]) if precision > 3: precision = 3 double_spin_box.setDecimals(precision) self.spin_boxes[key] = double_spin_box # Enable spin box depends on the selected option if self._parameter.selected == key: double_spin_box.setEnabled(True) else: double_spin_box.setEnabled(False) elif value.get('type') == STATIC: static_value = value.get('value', 0) if static_value is not None: self.radio_button_layout.addWidget( QLabel(str(static_value)), i, 1) elif value.get('type') == MULTIPLE_DYNAMIC: selected_fields = value.get('value', []) if self._parameter.selected == key: self.list_widget.setEnabled(True) else: self.list_widget.setEnabled(False) self.input_button_group.addButton(radio_button, i) if self._parameter.selected == key: radio_button.setChecked(True) # Help text self.help_label = QLabel(self._parameter.help_text) self.help_label.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Expanding) self.help_label.setWordWrap(True) self.help_label.setAlignment(Qt.AlignTop) self.inner_input_layout.addLayout(self.radio_button_layout) self.inner_input_layout.addWidget(self.list_widget) # Put elements into layouts self.input_layout.addWidget(self.label) self.input_layout.addLayout(self.inner_input_layout) self.help_layout = QVBoxLayout() self.help_layout.addWidget(self.help_label) self.main_layout.addLayout(self.input_layout) self.main_layout.addLayout(self.help_layout) self.setLayout(self.main_layout) self.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Expanding) # Update list widget self.update_list_widget() # Connect signal self.input_button_group.buttonClicked.connect( self.radio_buttons_clicked) def get_parameter(self): """Obtain list parameter object from the current widget state. :returns: A DefaultValueParameter from the current state of widget :rtype: DefaultValueParameter """ # Set value for each key for key, value in self._parameter.options.items(): if value.get('type') == STATIC: continue elif value.get('type') == SINGLE_DYNAMIC: new_value = self.spin_boxes.get(key).value() self._parameter.set_value_for_key(key, new_value) elif value.get('type') == MULTIPLE_DYNAMIC: # Need to iterate through all items items = [] for index in xrange(self.list_widget.count()): items.append(self.list_widget.item(index)) new_value = [i.text() for i in items] self._parameter.set_value_for_key(key, new_value) # Get selected radio button radio_button_checked_id = self.input_button_group.checkedId() # No radio button checked, then default value = None if radio_button_checked_id == -1: self._parameter.selected = None else: self._parameter.selected = self._parameter.options.keys( )[radio_button_checked_id] return self._parameter def update_list_widget(self): """Update list widget when radio button is clicked.""" # Get selected radio button radio_button_checked_id = self.input_button_group.checkedId() # No radio button checked, then default value = None if radio_button_checked_id > -1: selected_dict = self._parameter.options.values( )[radio_button_checked_id] if selected_dict.get('type') == MULTIPLE_DYNAMIC: for field in selected_dict.get('value'): # Update list widget field_item = QListWidgetItem(self.list_widget) field_item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsDragEnabled) field_item.setData(Qt.UserRole, field) field_item.setText(field) self.list_widget.addItem(field_item) def radio_buttons_clicked(self): """Handler when selected radio button changed.""" # Disable all spin boxes for spin_box in self.spin_boxes.values(): spin_box.setEnabled(False) # Disable list widget self.list_widget.setEnabled(False) # Get selected radio button radio_button_checked_id = self.input_button_group.checkedId() if radio_button_checked_id > -1: selected_value = self._parameter.options.values( )[radio_button_checked_id] if selected_value.get('type') == MULTIPLE_DYNAMIC: # Enable list widget self.list_widget.setEnabled(True) elif selected_value.get('type') == SINGLE_DYNAMIC: selected_key = self._parameter.options.keys( )[radio_button_checked_id] self.spin_boxes[selected_key].setEnabled(True) def select_radio_button(self, key): """Helper to select a radio button with key. :param key: The key of the radio button. :type key: str """ key_index = self._parameter.options.keys().index(key) radio_button = self.input_button_group.button(key_index) radio_button.click()
class StringListDlg(QDialog): acceptedList = Signal(QStringList) def __init__(self, name, stringlist=None, parent=None): super(StringListDlg, self).__init__(parent) self.name = name self.create_widgets(stringlist) self.layout_widgets() self.setWindowTitle("Edit {0} List".format(self.name)) def create_widgets(self, stringlist): self.listWidget = QListWidget() if stringlist is not None: self.listWidget.addItems(stringlist) self.listWidget.setCurrentRow(0) def layout_widgets(self): buttonLayout = QVBoxLayout() for text, slot in (("&Add...", self.add), ("&Edit...", self.edit), ("&Remove...", self.remove), ("&Up", self.up), ("&Down", self.down), ("&Sort", self.listWidget.sortItems), ("Close", self.accept)): button = QPushButton(text) if not MAC: button.setFocusPolicy(Qt.NoFocus) if text == "Close": buttonLayout.addStretch() buttonLayout.addWidget(button) button.clicked.connect(slot) layout = QHBoxLayout() layout.addWidget(self.listWidget) layout.addLayout(buttonLayout) self.setLayout(layout) def add(self): row = self.listWidget.currentRow() title = "Add {0}".format(self.name) string, ok = QInputDialog.getText(self, title, title) if ok and not string.isEmpty(): self.listWidget.insertItem(row, string) def edit(self): row = self.listWidget.currentRow() item = self.listWidget.item(row) if item is not None: title = "Edit {0}".format(self.name) string, ok = QInputDialog.getText(self, title, title, QLineEdit.Normal, item.text()) if ok and not string.isEmpty(): item.setText(string) def remove(self): row = self.listWidget.currentRow() item = self.listWidget.item(row) if item is None: return reply = QMessageBox.question(self, "Remove {0}".format( self.name), "Remove {0} `{1}'?".format( self.name, unicode(item.text())), QMessageBox.Yes|QMessageBox.No) if reply == QMessageBox.Yes: item = self.listWidget.takeItem(row) del item def up(self): 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): 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 reject(self): self.accept() def accept(self): self.stringlist = QStringList() for row in range(self.listWidget.count()): self.stringlist.append(self.listWidget.item(row).text()) self.acceptedList.emit(self.stringlist) QDialog.accept(self)
class GitStatus(QDialog): def __init__(self, plugin, git, path): QDialog.__init__(self) self.git = git self.plugin = plugin self.setWindowTitle('Git status') layout = QGridLayout(self) branches = self.git.branch(unicode(path)) self.s_branches = QListWidget() if len(branches) > 0: self.s_branches.addItems(branches[1:]) self.actual_branch = QLabel("<h2>{0}</h2>".format(branches[0])) else: self.actual_branch = QLabel() branch = QLabel("<h2>Branches</h2>") change_branch = QPushButton("Change to") merge_branches = QPushButton("Merge branch") H = QHBoxLayout() delete_branch = QPushButton("Delete branch") add_branch = QPushButton("Add branch") H.addWidget(add_branch) H.addWidget(delete_branch) self.lists = [] no_staged = QLabel("<h2>No staged</h2>") untracked_files = QLabel("Untracked files") self.untracked_files = QListWidget() self.lists.append(self.untracked_files) modified_files = QLabel("Modified files") self.modified_files = QListWidget() self.lists.append(self.modified_files) deleted_files = QLabel("Deleted files") self.deleted_files = QListWidget() self.lists.append(self.deleted_files) staged = QLabel("<h2>Staged</h2>") added_files = QLabel("Added files") self.added_files = QListWidget() self.lists.append(self.added_files) s_modified_files = QLabel("Modified files") self.s_modified_files = QListWidget() self.lists.append(self.s_modified_files) s_deleted_files = QLabel("Deleted files") self.s_deleted_files = QListWidget() self.lists.append(self.s_deleted_files) layout.addWidget(self.actual_branch, 0, 0, Qt.AlignHCenter) layout.addWidget(change_branch, 1, 0) layout.addWidget(merge_branches, 2, 0) layout.addWidget(no_staged, 3, 0) layout.addWidget(untracked_files, 4, 0) layout.addWidget(self.untracked_files, 5, 0) layout.addWidget(modified_files, 6, 0) layout.addWidget(self.modified_files, 7, 0) layout.addWidget(deleted_files, 8, 0) layout.addWidget(self.deleted_files, 9, 0) layout.addWidget(branch, 0, 1) layout.addWidget(self.s_branches, 1, 1) layout.addLayout(H, 2, 1) layout.addWidget(staged, 3, 1) layout.addWidget(added_files, 4, 1) layout.addWidget(self.added_files, 5, 1) layout.addWidget(s_modified_files, 6, 1) layout.addWidget(self.s_modified_files, 7, 1) layout.addWidget(s_deleted_files, 8, 1) layout.addWidget(self.s_deleted_files, 9, 1) self.fill(self.git.no_staged["?"], self.untracked_files) self.fill(self.git.no_staged["M"], self.modified_files) self.fill(self.git.no_staged["D"], self.deleted_files) self.fill(self.git.staged["A"], self.added_files) self.fill(self.git.staged["M"], self.s_modified_files) self.fill(self.git.staged["D"], self.s_deleted_files) self.staged_b = QPushButton('Stage files', self) self.unstage_b = QPushButton("Unstage files", self) self.commit_b = QPushButton('Commit files', self) self.uncommit_b = QPushButton("Uncommit files", self) layout.addWidget(self.staged_b, 10, 0) layout.addWidget(self.unstage_b, 11, 0) layout.addWidget(self.commit_b, 10, 1) layout.addWidget(self.uncommit_b, 11, 1) self.setLayout(layout) self.connect(self.staged_b, SIGNAL('clicked()'), self.add) self.connect(self.unstage_b, SIGNAL('clicked()'), self.unstage) self.connect(self.commit_b, SIGNAL('clicked()'), self.commit) self.connect(self.uncommit_b, SIGNAL('clicked()'), self.uncommit) self.connect(change_branch, SIGNAL("clicked()"), self.change_branch) self.connect(add_branch, SIGNAL("clicked()"), self.add_branch) self.connect(delete_branch, SIGNAL("clicked()"), self.delete_branch) self.connect(merge_branches, SIGNAL("clicked()"), self.merge_branches) def fill(self, a_list, widget_list): for x in a_list: item = QListWidgetItem() widget_list.addItem(item) check_box = QCheckBox(x) widget_list.setItemWidget(item, check_box) def add(self): path = self.plugin.editor.get_project_owner() for pos in reversed(xrange(self.untracked_files.count())): item = self.untracked_files.item(pos) widget = self.untracked_files.itemWidget(item) text = widget.text() if widget.isChecked(): self.git.add(path, text) self.untracked_files.removeItemWidget(item) self.untracked_files.takeItem(pos) item = QListWidgetItem() self.added_files.addItem(item) check_box = QCheckBox(text) self.added_files.setItemWidget(item, check_box) for pos in reversed(xrange(self.modified_files.count())): item = self.modified_files.item(pos) widget = self.modified_files.itemWidget(item) text = widget.text() if widget.isChecked(): self.git.add(path, widget.text()) self.modified_files.removeItemWidget(item) self.modified_files.takeItem(pos) item = QListWidgetItem() self.s_modified_files.addItem(item) check_box = QCheckBox(text) self.s_modified_files.setItemWidget(item, check_box) for pos in reversed(xrange(self.deleted_files.count())): item = self.deleted_files.item(pos) widget = self.deleted_files.itemWidget(item) text = widget.text() if widget.isChecked(): self.git.add(path, widget.text()) self.deleted_files.removeItemWidget(item) self.deleted_files.takeItem(pos) item = QListWidgetItem() self.s_deleted_files.addItem(item) check_box = QCheckBox(text) self.s_deleted_files.setItemWidget(item, check_box) def unstage(self): path = self.plugin.editor.get_project_owner() for pos in reversed(xrange(self.untracked_files.count())): item = self.untracked_files.item(pos) widget = self.untracked_files.itemWidget(item) if widget.isChecked(): self.git.unstage(path, widget.text()) self.untracked_files.removeItemWidget(item) self.untracked_files.takeItem(pos) for pos in reversed(xrange(self.modified_files.count())): item = self.modified_files.item(pos) widget = self.modified_files.itemWidget(item) if widget.isChecked(): self.git.unstage(path, widget.text()) self.modified_files.removeItemWidget(item) self.modified_files.takeItem(pos) for pos in reversed(xrange(self.deleted_files.count())): item = self.deleted_files.item(pos) widget = self.deleted_files.itemWidget(item) if widget.isChecked(): self.git.unstage(path, widget.text()) self.deleted_files.removeItemWidget(item) self.deleted_files.takeItem(pos) def commit(self): msg = QInputDialog.getText(self, "Commit message", "Commit Message:") if msg[1] == False: return (0) path = self.plugin.editor.get_project_owner() for pos in reversed(xrange(self.added_files.count())): item = self.added_files.item(pos) widget = self.added_files.itemWidget(item) if widget.isChecked(): self.git.commit(path, str(widget.text()), msg[0]) self.added_files.removeItemWidget(item) self.added_files.takeItem(pos) for pos in reversed(xrange(self.s_modified_files.count())): item = self.s_modified_files.item(pos) widget = self.s_modified_files.itemWidget(item) if widget.isChecked(): self.git.commit(path, widget.text(), msg[0]) self.s_modified_files.removeItemWidget(item) self.s_modified_files.takeItem(pos) for pos in reversed(xrange(self.s_deleted_files.count())): item = self.s_deleted_files.item(pos) widget = self.s_deleted_files.itemWidget(item) if widget.isChecked(): self.git.commit(path, widget.text(), msg[0]) self.s_deleted_files.takeItem(pos) self.s_deleted_files.removeItemWidget(item) def uncommit(self): path = self.plugin.editor.get_project_owner() for pos in reversed(xrange(self.added_files.count())): item = self.added_files.item(pos) widget = self.added_files.itemWidget(item) text = widget.text() if widget.isChecked(): self.git.uncommit(path, str(widget.text())) self.added_files.removeItemWidget(item) self.added_files.takeItem(pos) item = QListWidgetItem() self.untracked_files.addItem(item) check_box = QCheckBox(text) self.untracked_files.setItemWidget(item, check_box) for pos in reversed(xrange(self.s_modified_files.count())): item = self.s_modified_files.item(pos) widget = self.s_modified_files.itemWidget(item) text = widget.text() if widget.isChecked(): self.git.uncommit(path, widget.text()) self.s_modified_files.removeItemWidget(item) self.s_modified_files.takeItem(pos) item = QListWidgetItem() self.modified_files.addItem(item) check_box = QCheckBox(text) self.modified_files.setItemWidget(item, check_box) for pos in reversed(xrange(self.s_deleted_files.count())): item = self.s_deleted_files.item(pos) widget = self.s_deleted_files.itemWidget(item) text = widget.text() if widget.isChecked(): self.git.uncommit(path, widget.text()) self.s_deleted_files.removeItemWidget(item) self.s_deleted_files.takeItem(pos) item = QListWidgetItem() self.deleted_files.addItem(item) check_box = QCheckBox(text) self.deleted_files.setItemWidget(item, check_box) def change_branch(self): path = self.plugin.editor.get_project_owner() item = self.s_branches.currentItem() if item and not self.something(): text = item.text() self.git.change_branch(path, text) self.s_branches.clear() self.s_branches.addItems(self.git.branch(unicode(path))[1:]) self.actual_branch.setText("<h2>{0}<h2>".format(text)) if self.something(): v = QMessageBox() v.setText("Error: you have unsaved changes") v.setIcon(v.Warning) v.exec_() def add_branch(self): path = self.plugin.editor.get_project_owner() msg = QInputDialog.getText(self, "New branch", "Branch Name:") if msg[1] == False: return (0) self.git.add_branch(path, msg[0]) self.s_branches.clear() self.s_branches.addItems(self.git.branch(unicode(path))[1:]) def delete_branch(self): path = self.plugin.editor.get_project_owner() item = self.s_branches.currentItem() if item: text = str(item.text()) call = self.git.delete_branch(path, text) if not call: self.s_branches.clear() self.s_branches.addItems(self.git.branch(unicode(path))[1:]) else: m = QMessageBox() m.setText("<h2>" + call + "</h2>") m.setInformativeText("Force deletion?") m.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel) m.setDefaultButton(QMessageBox.Cancel) c = m.exec_() if c == QMessageBox.Ok: self.git.force_delete_branch(path, text) self.s_branches.clear() self.s_branches.addItems( self.git.branch(unicode(path))[1:]) def merge_branches(self): path = self.plugin.editor.get_project_owner() item = self.s_branches.currentItem() if item: text = str(item.text()) call = self.git.merge_branches(path, text) if call: m = QMessageBox() m.setText(call) m.setInformativeText("Unknown") m.setIcon(m.Critical) m.exec_() def something(self): for x in self.lists: if x.count() > 0: return True return False
class ConfigDialog(QDialog): """Spyder configuration ('Preferences') dialog box""" def __init__(self, parent=None): QDialog.__init__(self, parent) # Destroying the C++ object right after closing the dialog box, # otherwise it may be garbage-collected in another QThread # (e.g. the editor's analysis thread in Spyder), thus leading to # a segmentation fault on UNIX or an application crash on Windows self.setAttribute(Qt.WA_DeleteOnClose) self.contents_widget = QListWidget() self.contents_widget.setMovement(QListView.Static) self.contents_widget.setSpacing(1) bbox = QDialogButtonBox(QDialogButtonBox.Ok|QDialogButtonBox.Apply |QDialogButtonBox.Cancel) self.apply_btn = bbox.button(QDialogButtonBox.Apply) self.connect(bbox, SIGNAL("accepted()"), SLOT("accept()")) self.connect(bbox, SIGNAL("rejected()"), SLOT("reject()")) self.connect(bbox, SIGNAL("clicked(QAbstractButton*)"), self.button_clicked) self.pages_widget = QStackedWidget() self.connect(self.pages_widget, SIGNAL("currentChanged(int)"), self.current_page_changed) self.connect(self.contents_widget, SIGNAL("currentRowChanged(int)"), self.pages_widget.setCurrentIndex) self.contents_widget.setCurrentRow(0) hsplitter = QSplitter() hsplitter.addWidget(self.contents_widget) hsplitter.addWidget(self.pages_widget) btnlayout = QHBoxLayout() btnlayout.addStretch(1) btnlayout.addWidget(bbox) vlayout = QVBoxLayout() vlayout.addWidget(hsplitter) vlayout.addLayout(btnlayout) self.setLayout(vlayout) self.setWindowTitle(_("Preferences")) self.setWindowIcon(get_icon("configure.png")) def get_current_index(self): """Return current page index""" return self.contents_widget.currentRow() def set_current_index(self, index): """Set current page index""" self.contents_widget.setCurrentRow(index) def get_page(self, index=None): """Return page widget""" if index is None: widget = self.pages_widget.currentWidget() else: widget = self.pages_widget.widget(index) return widget.widget() def accept(self): """Reimplement Qt method""" for index in range(self.pages_widget.count()): configpage = self.get_page(index) if not configpage.is_valid(): return configpage.apply_changes() QDialog.accept(self) def button_clicked(self, button): if button is self.apply_btn: # Apply button was clicked configpage = self.get_page() if not configpage.is_valid(): return configpage.apply_changes() def current_page_changed(self, index): widget = self.get_page(index) self.apply_btn.setVisible(widget.apply_callback is not None) self.apply_btn.setEnabled(widget.is_modified) def add_page(self, widget): self.connect(self, SIGNAL('check_settings()'), widget.check_settings) self.connect(widget, SIGNAL('show_this_page()'), lambda row=self.contents_widget.count(): self.contents_widget.setCurrentRow(row)) self.connect(widget, SIGNAL("apply_button_enabled(bool)"), self.apply_btn.setEnabled) scrollarea = QScrollArea(self) scrollarea.setWidgetResizable(True) scrollarea.setWidget(widget) self.pages_widget.addWidget(scrollarea) item = QListWidgetItem(self.contents_widget) item.setIcon(widget.get_icon()) item.setText(widget.get_name()) item.setFlags(Qt.ItemIsSelectable|Qt.ItemIsEnabled) item.setSizeHint(QSize(0, 25)) def check_all_settings(self): """This method is called to check all configuration page settings after configuration dialog has been shown""" self.emit(SIGNAL('check_settings()')) def resizeEvent(self, event): """ Reimplement Qt method to be able to save the widget's size from the main application """ QDialog.resizeEvent(self, event) self.emit(SIGNAL("size_change(QSize)"), self.size())
class ListEdit(QWidget): """A widget to edit a list of items (e.g. a list of directories).""" # emitted when anything changed in the listbox. changed = pyqtSignal() def __init__(self, *args, **kwargs): QWidget.__init__(self, *args, **kwargs) layout = QGridLayout(self) self.setLayout(layout) self.addButton = QPushButton(icons.get('list-add'), '') self.editButton = QPushButton(icons.get('document-edit'), '') self.removeButton = QPushButton(icons.get('list-remove'), '') self.listBox = QListWidget() layout.setContentsMargins(1, 1, 1, 1) layout.setSpacing(0) layout.addWidget(self.listBox, 0, 0, 8, 1) layout.addWidget(self.addButton, 0, 1) layout.addWidget(self.editButton, 1, 1) layout.addWidget(self.removeButton, 2, 1) @self.addButton.clicked.connect def addClicked(): item = self.createItem() if self.openEditor(item): self.addItem(item) @self.editButton.clicked.connect def editClicked(): item = self.listBox.currentItem() item and self.editItem(item) @self.removeButton.clicked.connect def removeClicked(): item = self.listBox.currentItem() if item: self.removeItem(item) @self.listBox.itemDoubleClicked.connect def itemDoubleClicked(item): item and self.editItem(item) self.listBox.model().layoutChanged.connect(self.changed) def updateSelection(): selected = bool(self.listBox.currentItem()) self.editButton.setEnabled(selected) self.removeButton.setEnabled(selected) self.changed.connect(updateSelection) self.listBox.itemSelectionChanged.connect(updateSelection) updateSelection() app.translateUI(self) def translateUI(self): self.addButton.setText(_("&Add...")) self.editButton.setText(_("&Edit...")) self.removeButton.setText(_("&Remove")) def createItem(self): return QListWidgetItem() def addItem(self, item): self.listBox.addItem(item) self.itemChanged(item) self.changed.emit() def removeItem(self, item): self.listBox.takeItem(self.listBox.row(item)) self.changed.emit() def editItem(self, item): if self.openEditor(item): self.itemChanged(item) self.changed.emit() def setCurrentItem(self, item): self.listBox.setCurrentItem(item) def setCurrentRow(self, row): self.listBox.setCurrentRow(row) def openEditor(self, item): """Opens an editor (dialog) for the item. Returns True if the dialog was accepted and the item edited. Returns False if the dialog was cancelled (the item must be left unedited). """ pass def itemChanged(self, item): """Called after an item has been added or edited. Re-implement to do something at this moment if needed, e.g. alter the text or display of other items. """ pass def setValue(self, strings): """Sets the listbox to a list of strings.""" self.listBox.clear() self.listBox.addItems(strings) self.changed.emit() def value(self): """Returns the list of paths in the listbox.""" return [self.listBox.item(i).text() for i in range(self.listBox.count())] def setItems(self, items): """Sets the listbox to a list of items.""" self.listBox.clear() for item in items: self.listBox.addItem(item) self.itemChanged(item) self.changed.emit() def items(self): """Returns the list of items in the listbox.""" return [self.listBox.item(i) for i in range(self.listBox.count())] def clear(self): """Clears the listbox.""" self.listBox.clear() self.changed.emit()
class CheckList(HelpedWidget): def __init__(self, model, label="", help_link=""): HelpedWidget.__init__(self, "", help_link) layout = QVBoxLayout() widget = QWidget() widget.setLayout(layout) self.checkAllButton = QToolButton() self.checkAllButton.setIcon(resourceIcon("checked")) self.checkAllButton.setIconSize(QSize(16, 16)) self.checkAllButton.setToolButtonStyle(Qt.ToolButtonIconOnly) self.checkAllButton.setAutoRaise(True) self.checkAllButton.setToolTip("Select all") self.uncheckAllButton = QToolButton() self.uncheckAllButton.setIcon(resourceIcon("notchecked")) self.uncheckAllButton.setIconSize(QSize(16, 16)) self.uncheckAllButton.setToolButtonStyle(Qt.ToolButtonIconOnly) self.uncheckAllButton.setAutoRaise(True) self.uncheckAllButton.setToolTip("Unselect all") self.list = QListWidget() self.list.setContextMenuPolicy(Qt.CustomContextMenu) self.list.setSelectionMode(QAbstractItemView.ExtendedSelection) self.search_box = SearchBox() check_button_layout = QHBoxLayout() check_button_layout.setMargin(0) check_button_layout.setSpacing(0) check_button_layout.addWidget(QLabel(label)) check_button_layout.addStretch(1) check_button_layout.addWidget(self.checkAllButton) check_button_layout.addWidget(self.uncheckAllButton) layout.addLayout(check_button_layout) layout.addWidget(self.list) layout.addWidget(self.search_box) self.addWidget(widget) self.connect(self.checkAllButton, SIGNAL('clicked()'), self.checkAll) self.connect(self.uncheckAllButton, SIGNAL('clicked()'), self.uncheckAll) self.connect(self.list, SIGNAL('itemChanged(QListWidgetItem*)'), self.itemChanged) self.search_box.filterChanged.connect(self.filterList) # self.connect(self.search_box, SIGNAL('filterChanged(str)'), self.filterList) self.connect(self.list, SIGNAL('customContextMenuRequested(QPoint)'), self.showContextMenu) assert isinstance(model, (SelectableModelMixin, ListModelMixin)) self.model = model self.model.observable().attach(SelectableModelMixin.SELECTION_CHANGED_EVENT, self.modelChanged) self.model.observable().attach(ListModelMixin.LIST_CHANGED_EVENT, self.modelChanged) self.modelChanged() def itemChanged(self, item): """@type item: QListWidgetItem""" if item.checkState() == Qt.Checked: self.model.selectValue(str(item.text())) elif item.checkState() == Qt.Unchecked: self.model.unselectValue(str(item.text())) else: raise AssertionError("Unhandled checkstate!") def modelChanged(self): self.list.clear() items = self.model.getList() for item in items: list_item = QListWidgetItem(item) list_item.setFlags(list_item.flags() | Qt.ItemIsUserCheckable) if self.model.isValueSelected(item): list_item.setCheckState(Qt.Checked) else: list_item.setCheckState(Qt.Unchecked) self.list.addItem(list_item) self.filterList(self.search_box.filter()) def setSelectionEnabled(self, enabled): self.setEnabled(enabled) self.checkAllButton.setEnabled(enabled) self.uncheckAllButton.setEnabled(enabled) def filterList(self, filter): filter = filter.lower() for index in range(0, self.list.count()): item = self.list.item(index) text = str(item.text()).lower() if filter == "": item.setHidden(False) elif filter in text: item.setHidden(False) else: item.setHidden(True) def checkAll(self): self.model.selectAll() def uncheckAll(self): self.model.unselectAll() def checkSelected(self): items = [] for item in self.list.selectedItems(): items.append(str(item.text())) for item in items: self.model.selectValue(item) def uncheckSelected(self): items = [] for item in self.list.selectedItems(): items.append(str(item.text())) for item in items: self.model.unselectValue(item) def showContextMenu(self, point): p = self.list.mapToGlobal(point) menu = QMenu() check_selected = menu.addAction("Check selected") uncheck_selected = menu.addAction("Uncheck selected") menu.addSeparator() clear_selection = menu.addAction("Clear selection") selected_item = menu.exec_(p) if selected_item == check_selected: self.checkSelected() elif selected_item == uncheck_selected: self.uncheckSelected() elif selected_item == clear_selection: self.list.clearSelection()
class CheckList(QWidget): def __init__(self, model, label="", help_link="", custom_filter_button=None): """ :param custom_filter_button: if needed, add a button that opens a custom filter menu. Useful when search alone isn't enough to filter the list. :type custom_filter_button: QToolButton """ QWidget.__init__(self) self._model = model if help_link != "": addHelpToWidget(self, help_link) layout = QVBoxLayout() self._createCheckButtons() self._list = QListWidget() self._list.setContextMenuPolicy(Qt.CustomContextMenu) self._list.setSelectionMode(QAbstractItemView.ExtendedSelection) self._search_box = SearchBox() check_button_layout = QHBoxLayout() check_button_layout.setMargin(0) check_button_layout.setSpacing(0) check_button_layout.addWidget(QLabel(label)) check_button_layout.addStretch(1) check_button_layout.addWidget(self._checkAllButton) check_button_layout.addWidget(self._uncheckAllButton) layout.addLayout(check_button_layout) layout.addWidget(self._list) """ Inserts the custom filter button, if provided. The caller is responsible for all related actions. """ if custom_filter_button is not None: search_bar_layout = QHBoxLayout() search_bar_layout.addWidget(self._search_box) search_bar_layout.addWidget(custom_filter_button) layout.addLayout(search_bar_layout) else: layout.addWidget(self._search_box) self.setLayout(layout) self._checkAllButton.clicked.connect(self.checkAll) self._uncheckAllButton.clicked.connect(self.uncheckAll) self._list.itemChanged.connect(self.itemChanged) self._search_box.filterChanged.connect(self.filterList) self._list.customContextMenuRequested.connect(self.showContextMenu) self._model.selectionChanged.connect(self.modelChanged) self._model.modelChanged.connect(self.modelChanged) self.modelChanged() def _createCheckButtons(self): self._checkAllButton = QToolButton() self._checkAllButton.setIcon(resourceIcon("checked")) self._checkAllButton.setIconSize(QSize(16, 16)) self._checkAllButton.setToolButtonStyle(Qt.ToolButtonIconOnly) self._checkAllButton.setAutoRaise(True) self._checkAllButton.setToolTip("Select all") self._uncheckAllButton = QToolButton() self._uncheckAllButton.setIcon(resourceIcon("notchecked")) self._uncheckAllButton.setIconSize(QSize(16, 16)) self._uncheckAllButton.setToolButtonStyle(Qt.ToolButtonIconOnly) self._uncheckAllButton.setAutoRaise(True) self._uncheckAllButton.setToolTip("Unselect all") def itemChanged(self, item): """@type item: QListWidgetItem""" if item.checkState() == Qt.Checked: self._model.selectValue(str(item.text())) elif item.checkState() == Qt.Unchecked: self._model.unselectValue(str(item.text())) else: raise AssertionError("Unhandled checkstate!") def modelChanged(self): self._list.clear() items = self._model.getList() for item in items: list_item = QListWidgetItem(item) list_item.setFlags(list_item.flags() | Qt.ItemIsUserCheckable) if self._model.isValueSelected(item): list_item.setCheckState(Qt.Checked) else: list_item.setCheckState(Qt.Unchecked) self._list.addItem(list_item) self.filterList(self._search_box.filter()) def setSelectionEnabled(self, enabled): self.setEnabled(enabled) self._checkAllButton.setEnabled(enabled) self._uncheckAllButton.setEnabled(enabled) def filterList(self, filter): filter = filter.lower() for index in range(0, self._list.count()): item = self._list.item(index) text = str(item.text()).lower() if filter == "": item.setHidden(False) elif filter in text: item.setHidden(False) else: item.setHidden(True) def checkAll(self): """ Checks all visible items in the list. """ for index in range(0, self._list.count()): item = self._list.item(index) if not item.isHidden(): self._model.selectValue(str(item.text())) def uncheckAll(self): """ Unchecks all items in the list, visible or not """ self._model.unselectAll() def checkSelected(self): items = [] for item in self._list.selectedItems(): items.append(str(item.text())) for item in items: self._model.selectValue(item) def uncheckSelected(self): items = [] for item in self._list.selectedItems(): items.append(str(item.text())) for item in items: self._model.unselectValue(item) def showContextMenu(self, point): p = self._list.mapToGlobal(point) menu = QMenu() check_selected = menu.addAction("Check selected") uncheck_selected = menu.addAction("Uncheck selected") menu.addSeparator() clear_selection = menu.addAction("Clear selection") selected_item = menu.exec_(p) if selected_item == check_selected: self.checkSelected() elif selected_item == uncheck_selected: self.uncheckSelected() elif selected_item == clear_selection: self._list.clearSelection()
class ProjectPropertiesDialog( QDialog, object ): """ project properties dialog implementation """ def __init__( self, project = None, parent = None ): QDialog.__init__( self, parent ) # The dialog caller reads this member if the dialog was finished # successfully. self.absProjectFileName = None self.__createLayout() self.__project = project if project is None: # It a new project creation self.setWindowTitle( "New Project Properties" ) userRecord = pwd.getpwuid( os.getuid() ) if not userRecord[ 5 ].endswith( os.path.sep ): self.dirEdit.setText( userRecord[ 5 ] + os.path.sep ) else: self.dirEdit.setText( userRecord[ 5 ] ) self.initialDirName = self.dirEdit.text() self.lastProjectName = "" if userRecord[ 4 ] != "": self.authorEdit.setText( userRecord[ 4 ].split( ',' )[ 0 ].strip() ) else: self.authorEdit.setText( userRecord[ 0 ] ) try: self.emailEdit.setText( userRecord[ 0 ] + "@" + socket.gethostname() ) except: pass self.versionEdit.setText( "0.0.1" ) self.licenseEdit.setText( "GPL v3" ) self.copyrightEdit.setText( "Copyright (c) " + self.authorEdit.text() + ", " + str( datetime.date.today().year ) ) self.creationDateEdit.setText( getLocaleDate() ) self.nameEdit.setFocus() elif type( project ) == type( "" ): self.setWindowTitle( "Viewing Project Properties" ) # This is viewing properties and the argument is the path to the # project file scriptName, importDirs, creationDate, author, lic, \ copy_right, description, \ version, email, uuid = getProjectProperties( project ) if not os.path.isabs( scriptName ) and scriptName != "": scriptName = os.path.normpath( os.path.dirname( project ) + os.path.sep + scriptName ) self.nameEdit.setText( os.path.basename( project ) ) self.nameEdit.setToolTip( "" ) self.dirEdit.setText( os.path.dirname( project ) ) self.dirEdit.setToolTip( "" ) self.scriptEdit.setText( scriptName ) self.versionEdit.setText( version ) self.authorEdit.setText( author ) self.emailEdit.setText( email ) self.licenseEdit.setText( lic ) self.copyrightEdit.setText( copy_right ) self.descriptionEdit.setText( description ) self.creationDateEdit.setText( creationDate ) self.uuidEdit.setText( str( uuid ) ) self.uuidEdit.setToolTip( settingsDir + str( uuid ) + os.path.sep + " (double click to copy path)" ) for item in importDirs: self.importDirList.addItem( item ) self.disableEditing() else: self.setWindowTitle( "Editing Project Properties" ) # This is editing the loaded project. self.nameEdit.setText( os.path.basename( project.fileName ) ) self.nameEdit.setToolTip( "" ) self.dirEdit.setText( project.getProjectDir() ) self.dirEdit.setToolTip( "" ) self.scriptEdit.setText( project.getProjectScript() ) self.versionEdit.setText( project.version ) self.authorEdit.setText( project.author ) self.emailEdit.setText( project.email ) self.licenseEdit.setText( project.license ) self.copyrightEdit.setText( project.copyright ) self.descriptionEdit.setText( project.description ) self.creationDateEdit.setText( project.creationDate ) self.uuidEdit.setText( str( project.uuid ) ) self.uuidEdit.setToolTip( project.userProjectDir + " (double click to copy path)" ) self.setReadOnly() for item in project.importDirs: self.importDirList.addItem( item ) if self.importDirList.count() > 0: self.importDirList.setCurrentRow( 0 ) self.delImportDirButton.setEnabled( True ) # The project could be the one belonging to another user # so there might be no write permissions. if not os.access( project.fileName, os.W_OK ): # Disable editing self.setWindowTitle( "Viewing Project Properties (no write permissions)" ) self.disableEditing() else: self.scriptEdit.setFocus() return def __createLayout( self ): """ Creates the dialog layout """ self.resize( 600, 400 ) self.setSizeGripEnabled( True ) verticalLayout = QVBoxLayout( self ) gridLayout = QGridLayout() # Project name nameLabel = QLabel( self ) nameLabel.setText( "Project name:" ) gridLayout.addWidget( nameLabel, 0, 0, 1, 1 ) self.nameEdit = QLineEdit( self ) self.nameEdit.setToolTip( "Type a project name without a path" ) self.nameEdit.installEventFilter( self ) gridLayout.addWidget( self.nameEdit, 0, 1, 1, 1 ) # Project dir dirLabel = QLabel( self ) dirLabel.setText( "Project directory:" ) gridLayout.addWidget( dirLabel, 1, 0, 1, 1 ) self.dirEdit = QLineEdit( self ) self.dirEdit.setToolTip( "Not existed directories will be created" ) gridLayout.addWidget( self.dirEdit, 1, 1, 1, 1 ) self.dirButton = QPushButton( self ) self.dirButton.setText( "..." ) gridLayout.addWidget( self.dirButton, 1, 2, 1, 1 ) self.dirCompleter = DirCompleter( self.dirEdit ) # Project script mainScriptLabel = QLabel( "Main script:", self ) gridLayout.addWidget( mainScriptLabel, 2, 0, 1, 1 ) self.scriptEdit = QLineEdit( self ) self.scriptEdit.setToolTip( "Project main script, " "used when the project is run" ) gridLayout.addWidget( self.scriptEdit, 2, 1, 1, 1 ) self.scriptButton = QPushButton( "...", self ) gridLayout.addWidget( self.scriptButton, 2, 2, 1, 1 ) self.fileCompleter = FileCompleter( self.scriptEdit ) # Import dirs importLabel = QLabel( self ) importLabel.setText( "Import directories:" ) importLabel.setAlignment( Qt.AlignTop ) gridLayout.addWidget( importLabel, 3, 0, 1, 1 ) self.importDirList = QListWidget( self ) self.importDirList.setAlternatingRowColors( True ) self.importDirList.setSelectionMode( QAbstractItemView.SingleSelection ) self.importDirList.setSelectionBehavior( QAbstractItemView.SelectRows ) self.importDirList.setItemDelegate( NoOutlineHeightDelegate( 4 ) ) self.importDirList.setToolTip( "Directories where to look for " "project specific imports" ) gridLayout.addWidget( self.importDirList, 3, 1, 1, 1 ) self.addImportDirButton = QPushButton( self ) self.addImportDirButton.setText( "Add dir" ) self.delImportDirButton = QPushButton( self ) self.delImportDirButton.setText( "Delete dir" ) self.delImportDirButton.setEnabled( False ) vLayout = QVBoxLayout() vLayout.addWidget( self.addImportDirButton ) vLayout.addWidget( self.delImportDirButton ) vLayout.addStretch( 0 ) gridLayout.addLayout( vLayout, 3, 2, 1, 1 ) # Version versionLabel = QLabel( self ) versionLabel.setText( "Version:" ) gridLayout.addWidget( versionLabel, 4, 0, 1, 1 ) self.versionEdit = QLineEdit( self ) gridLayout.addWidget( self.versionEdit, 4, 1, 1, 1 ) # Author authorLabel = QLabel( self ) authorLabel.setText( "Author:" ) gridLayout.addWidget( authorLabel, 5, 0, 1, 1 ) self.authorEdit = QLineEdit( self ) gridLayout.addWidget( self.authorEdit, 5, 1, 1, 1 ) # E-mail emailLabel = QLabel( self ) emailLabel.setText( "E-mail:" ) gridLayout.addWidget( emailLabel, 6, 0, 1, 1 ) self.emailEdit = QLineEdit( self ) gridLayout.addWidget( self.emailEdit, 6, 1, 1, 1 ) # License licenseLabel = QLabel( self ) licenseLabel.setText( "License:" ) gridLayout.addWidget( licenseLabel, 7, 0, 1, 1 ) self.licenseEdit = QLineEdit( self ) gridLayout.addWidget( self.licenseEdit, 7, 1, 1, 1 ) # Copyright copyrightLabel = QLabel( self ) copyrightLabel.setText( "Copyright:" ) gridLayout.addWidget( copyrightLabel, 8, 0, 1, 1 ) self.copyrightEdit = QLineEdit( self ) gridLayout.addWidget( self.copyrightEdit, 8, 1, 1, 1 ) # Description descriptionLabel = QLabel( self ) descriptionLabel.setText( "Description:" ) descriptionLabel.setAlignment( Qt.AlignTop ) gridLayout.addWidget( descriptionLabel, 9, 0, 1, 1 ) self.descriptionEdit = QTextEdit( self ) self.descriptionEdit.setTabChangesFocus( True ) self.descriptionEdit.setAcceptRichText( False ) gridLayout.addWidget( self.descriptionEdit, 9, 1, 1, 1 ) # Creation date creationDateLabel = QLabel( self ) creationDateLabel.setText( "Creation date:" ) gridLayout.addWidget( creationDateLabel, 10, 0, 1, 1 ) self.creationDateEdit = FramedLabelWithDoubleClick() self.creationDateEdit.setToolTip( "Double click to copy" ) gridLayout.addWidget( self.creationDateEdit, 10, 1, 1, 1 ) # Project UUID uuidLabel = QLabel( self ) uuidLabel.setText( "UUID:" ) gridLayout.addWidget( uuidLabel, 11, 0, 1, 1 ) self.uuidEdit = FramedLabelWithDoubleClick( "", self.__copyProjectPath ) gridLayout.addWidget( self.uuidEdit, 11, 1, 1, 1 ) verticalLayout.addLayout( gridLayout ) # Buttons at the bottom buttonBox = QDialogButtonBox( self ) buttonBox.setOrientation( Qt.Horizontal ) buttonBox.setStandardButtons( QDialogButtonBox.Cancel | \ QDialogButtonBox.Ok ) verticalLayout.addWidget( buttonBox ) nameLabel.setBuddy( self.nameEdit ) dirLabel.setBuddy( self.dirEdit ) versionLabel.setBuddy( self.versionEdit ) authorLabel.setBuddy( self.authorEdit ) emailLabel.setBuddy( self.emailEdit ) licenseLabel.setBuddy( self.licenseEdit ) copyrightLabel.setBuddy( self.copyrightEdit ) descriptionLabel.setBuddy( self.descriptionEdit ) buttonBox.accepted.connect( self.onOKButton ) buttonBox.rejected.connect( self.reject ) self.dirButton.clicked.connect( self.onDirButton ) self.scriptButton.clicked.connect( self.onScriptButton ) self.importDirList.currentRowChanged.connect( self.onImportDirRowChanged ) self.addImportDirButton.clicked.connect( self.onAddImportDir ) self.delImportDirButton.clicked.connect( self.onDelImportDir ) self.nameEdit.textEdited.connect( self.onProjectNameChanged ) self.setTabOrder( self.nameEdit, self.dirEdit ) self.setTabOrder( self.dirEdit, self.dirButton ) self.setTabOrder( self.dirButton, self.scriptEdit ) self.setTabOrder( self.scriptEdit, self.scriptButton ) self.setTabOrder( self.scriptButton, self.importDirList ) self.setTabOrder( self.importDirList, self.addImportDirButton ) self.setTabOrder( self.addImportDirButton, self.delImportDirButton ) self.setTabOrder( self.delImportDirButton, self.versionEdit ) self.setTabOrder( self.versionEdit, self.authorEdit ) self.setTabOrder( self.authorEdit, self.emailEdit ) self.setTabOrder( self.emailEdit, self.licenseEdit ) self.setTabOrder( self.licenseEdit, self.copyrightEdit ) self.setTabOrder( self.copyrightEdit, self.descriptionEdit ) self.setTabOrder( self.descriptionEdit, buttonBox ) return def eventFilter( self, obj, event ): " Event filter for the project name field " # Do not allow path separators if event.type() == QEvent.KeyPress: if event.key() == ord( os.path.sep ): return True return QObject.eventFilter( self, obj, event ) def onDirButton( self ): " Displays a directory selection dialog " dirName = QFileDialog.getExistingDirectory( self, "Select project directory", self.dirEdit.text(), QFileDialog.Options( QFileDialog.ShowDirsOnly ) ) if dirName: self.dirEdit.setText( os.path.normpath( dirName ) ) return def onScriptButton( self ): " Displays a file selection dialog " scriptName = QFileDialog.getOpenFileName( self, "Select project main script", self.dirEdit.text() ) if scriptName: self.scriptEdit.setText( os.path.normpath( scriptName ) ) return def onImportDirRowChanged( self, row ): " Triggered when a current row in the import dirs is changed " self.delImportDirButton.setEnabled( row != -1 ) return def onAddImportDir( self ): " Displays a directory selection dialog " dirName = QFileDialog.getExistingDirectory( self, "Select import directory", self.dirEdit.text(), QFileDialog.Options( QFileDialog.ShowDirsOnly ) ) if not dirName: return # There are 2 cases: new project or # editing the existed project properties if self.__project is None: # It a new project; the project path could be editedd dirToInsert = dirName else: # This is an existed project; no way the project path is changed # Let's decide it a relative path should be used here if self.__project.isProjectDir( dirName ): dirToInsert = relpath( dirName, self.dirEdit.text() ) else: dirToInsert = dirName index = 0 while index < self.importDirList.count(): if self.importDirList.item( index ).text() == dirToInsert: logging.warning( "The directory '" + dirName + "' is already in the list of " "imported directories and is not added." ) return index += 1 self.importDirList.addItem( dirToInsert ) self.importDirList.setCurrentRow( self.importDirList.count() - 1 ) return def onDelImportDir( self ): " Triggered when an import dir should be deleted " rowToDelete = self.importDirList.currentRow() if rowToDelete == -1: self.delImportDirButton.setEnabled( False ) return self.importDirList.takeItem( rowToDelete ) if self.importDirList.count() == 0: self.delImportDirButton.setEnabled( False ) else: self.importDirList.setCurrentRow( self.importDirList.count() - 1 ) return def onOKButton( self ): " Checks that the mandatory fields are filled properly " # The checks must be done for a new project only if not self.nameEdit.isEnabled(): self.accept() return # Check that the project name does not have path separators and is not # empty if not self.nameEdit.text().strip(): QMessageBox.critical( self, "Error", "The project name must not be empty" ) return if os.path.sep in self.nameEdit.text(): QMessageBox.critical( self, "Error", "The project name must not " "contain path separators" ) return # Check that the project directory is given dirName = self.dirEdit.text().strip() if not dirName: QMessageBox.critical( self, "Error", "The project directory must not be empty" ) return dirName = os.path.abspath( dirName ) self.dirEdit.setText( dirName ) # Check that the project file does not exist projectFileName = dirName if not projectFileName.endswith( os.path.sep ): projectFileName += os.path.sep projectFileName += self.nameEdit.text().strip() if not projectFileName.endswith( ".cdm" ): projectFileName += ".cdm" if os.path.exists( projectFileName ): QMessageBox.critical( self, "Error", "The project file " + projectFileName + " exists. Please provide another " "directory / project name." ) return # Check that the project dir is not a file if os.path.exists( dirName ): # It might be a link, so read it first dirName = os.path.realpath( dirName ) if not os.path.exists( dirName ): QMessageBox.critical( self, "Error", "Broken link: " + dirName ) return if not os.path.isdir( dirName ): QMessageBox.critical( self, "Error", "The project directory " "may not be a file" ) return # Check that the dir is writable if not os.access( dirName, os.W_OK ): QMessageBox.critical( self, "Error", "You don't have write permissions on " + dirName ) return else: # Create the directory try: os.makedirs( dirName ) except OSError: QMessageBox.critical( self, "Error", "Cannot create the project directory" ) return # Save the absolute file name for further reading it by the caller self.absProjectFileName = projectFileName # The minimum is provided so we can accept it self.accept() return def onProjectNameChanged( self, newName ): " Called when the project name changed " if newName.endswith( ".cdm" ): newName = newName[ :-4 ] if self.dirEdit.text().strip() == (self.initialDirName + self.lastProjectName): self.dirEdit.setText( self.initialDirName + newName ) self.lastProjectName = newName return def setReadOnly( self ): """ Disables editing some fields """ self.dirEdit.setReadOnly( True ) self.dirEdit.setFocusPolicy( Qt.NoFocus ) self.dirEdit.setDisabled( True ) self.dirButton.setDisabled( True ) self.dirButton.setFocusPolicy( Qt.NoFocus ) self.nameEdit.setReadOnly( True ) self.nameEdit.setFocusPolicy( Qt.NoFocus ) self.nameEdit.setDisabled( True ) return def disableEditing( self ): " Disables all the editing " self.nameEdit.setDisabled( True ) self.dirEdit.setDisabled( True ) self.dirButton.setDisabled( True ) self.scriptEdit.setDisabled( True ) self.scriptButton.setDisabled( True ) self.importDirList.setDisabled( True ) self.addImportDirButton.setDisabled( True ) self.delImportDirButton.setDisabled( True ) self.versionEdit.setDisabled( True ) self.authorEdit.setDisabled( True ) self.emailEdit.setDisabled( True ) self.licenseEdit.setDisabled( True ) self.copyrightEdit.setDisabled( True ) self.descriptionEdit.setDisabled( True ) return def __copyProjectPath( self ): " Copies the project path when a label is double clicked " text = self.uuidEdit.text().strip() if text: path = settingsDir + text + os.path.sep QApplication.clipboard().setText( path ) return
class AdvancedVisualizationForm(QWidget): def __init__(self, mainwindow, result_manager): QWidget.__init__(self, mainwindow) #mainwindow is an OpusGui self.mainwindow = mainwindow self.result_manager = result_manager self.toolboxBase = self.result_manager.mainwindow.toolboxBase self.inGui = False self.logFileKey = 0 self.xml_helper = ResultsManagerXMLHelper(toolboxBase=self.toolboxBase) self.result_generator = OpusResultGenerator( toolboxBase=self.toolboxBase) self.result_generator.guiElement = self self.tabIcon = QIcon(':/Images/Images/cog.png') self.tabLabel = 'Advanced Visualization' self.widgetLayout = QVBoxLayout(self) self.widgetLayout.setAlignment(Qt.AlignTop) self.resultsGroupBox = QGroupBox(self) self.widgetLayout.addWidget(self.resultsGroupBox) self.dataGroupBox = QGroupBox(self) self.widgetLayout.addWidget(self.dataGroupBox) self.optionsGroupBox = QGroupBox(self) self.widgetLayout.addWidget(self.optionsGroupBox) self._setup_definition_widget() self._setup_buttons() self._setup_tabs() def _setup_buttons(self): # Add Generate button... self.pbn_go = QPushButton(self.resultsGroupBox) self.pbn_go.setObjectName('pbn_go') self.pbn_go.setText(QString('Go!')) QObject.connect(self.pbn_go, SIGNAL('released()'), self.on_pbn_go_released) self.widgetLayout.addWidget(self.pbn_go) self.pbn_set_esri_storage_location = QPushButton(self.optionsGroupBox) self.pbn_set_esri_storage_location.setObjectName( 'pbn_set_esri_storage_location') self.pbn_set_esri_storage_location.setText(QString('...')) self.pbn_set_esri_storage_location.hide() QObject.connect(self.pbn_set_esri_storage_location, SIGNAL('released()'), self.on_pbn_set_esri_storage_location_released) def _setup_tabs(self): # Add a tab widget and layer in a tree view and log panel self.tabWidget = QTabWidget(self.resultsGroupBox) # Log panel self.logText = QTextEdit(self.resultsGroupBox) self.logText.setReadOnly(True) self.logText.setLineWidth(0) self.tabWidget.addTab(self.logText, 'Log') # Finally add the tab to the model page self.widgetLayout.addWidget(self.tabWidget) # def _setup_definition_widget(self): #### setup results group box #### self.gridlayout = QGridLayout(self.resultsGroupBox) self.gridlayout.setObjectName('gridlayout') self.lbl_results = QLabel(self.resultsGroupBox) self.lbl_results.setObjectName('lbl_results') self.lbl_results.setText(QString('Results')) self.gridlayout.addWidget(self.lbl_results, 0, 0, 1, 3) self._setup_co_results() self.gridlayout.addWidget(self.co_results, 0, 3, 1, 10) self.pbn_add = QPushButton(self.resultsGroupBox) self.pbn_add.setObjectName('pbn_add') self.pbn_add.setText(QString('+')) QObject.connect(self.pbn_add, SIGNAL('released()'), self.on_pbn_add_released) self.gridlayout.addWidget(self.pbn_add, 0, 14, 1, 1) self.lw_indicators = QListWidget(self.resultsGroupBox) self.lw_indicators.setObjectName('lw_indicators') self.gridlayout.addWidget(self.lw_indicators, 1, 1, 1, 13) self.pbn_remove = QPushButton(self.resultsGroupBox) self.pbn_remove.setObjectName('pbn_remove') self.pbn_remove.setText(QString('-')) QObject.connect(self.pbn_remove, SIGNAL('released()'), self.on_pbn_remove_released) self.gridlayout.addWidget(self.pbn_remove, 1, 14, 1, 1) #### setup data group box #### self.gridlayout2 = QGridLayout(self.dataGroupBox) self.gridlayout2.setObjectName('gridlayout2') self._setup_co_result_style() self.gridlayout2.addWidget(self.co_result_style, 1, 0, 1, 2) self.lbl_result_style_sep = QLabel(self.resultsGroupBox) self.lbl_result_style_sep.setObjectName('lbl_result_style_sep') self.lbl_result_style_sep.setText(QString('<center>as</center>')) self.gridlayout2.addWidget(self.lbl_result_style_sep, 1, 2, 1, 1) self._setup_co_result_type() self.gridlayout2.addWidget(self.co_result_type, 1, 3, 1, 2) ##### setup options group box #### self.gridlayout3 = QGridLayout(self.optionsGroupBox) self.gridlayout3.setObjectName('gridlayout3') self.le_esri_storage_location = QLineEdit(self.optionsGroupBox) self.le_esri_storage_location.setObjectName('le_esri_storage_location') self.le_esri_storage_location.setText('[set path]') self.le_esri_storage_location.hide() self.optionsGroupBox.hide() QObject.connect(self.co_result_style, SIGNAL('currentIndexChanged(int)'), self.on_co_result_style_changed) QObject.connect(self.co_result_type, SIGNAL('currentIndexChanged(int)'), self.on_co_result_type_changed) def _setup_co_results(self): self.co_results = QComboBox(self.resultsGroupBox) self.co_results.setObjectName('co_results') self.co_results.addItem(QString('[select]')) results = self.xml_helper.get_available_results() for result in results: name = '%i.%s' % (result['run_id'], result['indicator_name']) self.co_results.addItem(QString(name)) def _setup_co_result_style(self): available_styles = [ 'visualize', 'export', ] self.co_result_style = QComboBox(self.dataGroupBox) self.co_result_style.setObjectName('co_result_style') for dataset in available_styles: self.co_result_style.addItem(QString(dataset)) def _setup_co_result_type(self): available_types = [ 'Table (per year, spans indicators)', 'Chart (per indicator, spans years)', 'Map (per indicator per year)', 'Chart (per indicator, spans years)', ] self.co_result_type = QComboBox(self.dataGroupBox) self.co_result_type.setObjectName('co_result_type') for dataset in available_types: self.co_result_type.addItem(QString(dataset)) def on_pbnRemoveModel_released(self): self.result_manager.removeTab(self) self.result_manager.updateGuiElements() def on_pbn_add_released(self): cur_selected = self.co_results.currentText() for i in range(self.lw_indicators.count()): if self.lw_indicators.item(i).text() == cur_selected: return self.lw_indicators.addItem(cur_selected) def on_pbn_remove_released(self): selected_idxs = self.lw_indicators.selectedIndexes() for idx in selected_idxs: self.lw_indicators.takeItem(idx.row()) def on_co_result_style_changed(self, ind): available_viz_types = [ 'Table (per year, spans indicators)', 'Chart (per indicator, spans years)', 'Map (per indicator per year)', 'Chart (per indicator, spans years)', ] available_export_types = ['ESRI table (for loading in ArcGIS)'] txt = self.co_result_style.currentText() if txt == 'visualize': available_types = available_viz_types else: available_types = available_export_types self.co_result_type.clear() for result_type in available_types: r_type = QString(result_type) self.co_result_type.addItem(r_type) def on_co_result_type_changed(self, ind): self.gridlayout3.removeWidget(self.le_esri_storage_location) self.gridlayout3.removeWidget(self.pbn_set_esri_storage_location) self.optionsGroupBox.hide() self.pbn_set_esri_storage_location.hide() self.le_esri_storage_location.hide() txt = self.co_result_type.currentText() print txt if txt == 'ESRI table (for loading in ArcGIS)': self.pbn_set_esri_storage_location.show() self.le_esri_storage_location.show() self.gridlayout3.addWidget(self.le_esri_storage_location, 0, 1, 1, 6) self.gridlayout3.addWidget(self.pbn_set_esri_storage_location, 0, 7, 1, 1) self.optionsGroupBox.show() def on_pbn_set_esri_storage_location_released(self): print 'pbn_set_esri_storage_location released' from opus_core.misc import directory_path_from_opus_path start_dir = directory_path_from_opus_path('opus_gui.projects') configDialog = QFileDialog() filter_str = QString("*.gdb") fd = configDialog.getExistingDirectory( self, QString("Please select an ESRI geodatabase (*.gdb)..." ), #, *.sde, *.mdb)..."), QString(start_dir), QFileDialog.ShowDirsOnly) if len(fd) != 0: fileName = QString(fd) fileNameInfo = QFileInfo(QString(fd)) fileNameBaseName = fileNameInfo.completeBaseName() self.le_esri_storage_location.setText(fileName) def on_pbn_go_released(self): # Fire up a new thread and run the model print 'Go button pressed' # References to the GUI elements for status for this run... #self.statusLabel = self.runStatusLabel #self.statusLabel.setText(QString('Model initializing...')) indicator_names = [] for i in range(self.lw_indicators.count()): indicator_names.append(str(self.lw_indicators.item(i).text())) if indicator_names == []: print 'no indicators selected' return indicator_type = str(self.co_result_type.currentText()) indicator_type = { #'Map (per indicator per year)':'matplotlib_map', 'Map (per indicator per year)': 'mapnik_map', 'Chart (per indicator, spans years)': 'matplotlib_chart', 'Table (per indicator, spans years)': 'table_per_attribute', 'Table (per year, spans indicators)': 'table_per_year', 'ESRI table (for loading in ArcGIS)': 'table_esri' }[indicator_type] kwargs = {} if indicator_type == 'table_esri': storage_location = str(self.le_esri_storage_location.text()) if not os.path.exists(storage_location): print 'Warning: %s does not exist!!' % storage_location kwargs['storage_location'] = storage_location self.result_manager.addIndicatorForm(indicator_type=indicator_type, indicator_names=indicator_names, kwargs=kwargs) def runUpdateLog(self): self.logFileKey = self.result_generator._get_current_log( self.logFileKey) def runErrorFromThread(self, errorMessage): QMessageBox.warning(self.mainwindow, 'Warning', errorMessage)
class VocDialog(QDialog) : """This is the dialog which presents the interface and organise everything.""" MAGICWORD = 'CHANGEME' findDight = reCompile(r'\d+') baseURL = 'http://www.gstatic.com/dictionary/static/sounds/de/0/CHANGEME.mp3' def __init__(self, autoProxy=False, parent=None) : super(VocDialog, self).__init__(parent) self.logger = getLogger('VocVoc.VocDialog') self.info = self.logger.info self.warn = self.logger.warn self.debug = self.logger.debug if autoProxy : self.info('Starting VocDialog with autoProxy.') else : self.info('Starting VocDialog without autoProxy.') self.mediaObeject = Phonon.createPlayer(Phonon.MusicCategory, Phonon.MediaSource('')) self.setupUi() self.connect() self.initCountWord() self.candidates = None self.autoProxy = autoProxy self.spellChecker = SpellChecker() self.correct = self.spellChecker.correct self.corpusDir = self.spellChecker.corpusDir self.info('VocDialog started.') def keyPressEvent(self, event) : self.debug('Key is {}.'.format(event.key())) super(VocDialog, self).keyPressEvent(event) def resizeEvent(self, event) : self.debug("Resized to {}.".format(self.size())) super(VocDialog, self).resizeEvent(event) def initCountWord(self) : """ The first one is a count about how many time the input is wrong. WRONG : Not collected in or can be corrected by the wordModel. The second one is the last time's wrong input. """ self.countWord = [0, ''] def setupUi(self) : "Setup the UI." self.info('Seting up the UI.') self.fileDialog = QFileDialog() self.fileDialog.setFileMode(QFileDialog.AnyFile) self.fileDialog.setViewMode(QFileDialog.Detail) self.loadButton = QPushButton( r'Open/New :', self) self.loadButton.setAutoDefault(False) self.textList = QListWidget(self) self.inputLine = tabEnabledLineEdit(self) self.toggleButton = QPushButton(r'Show/Hide', self) self.toggleButton.setAutoDefault(False) self.toggleButton.setCheckable(True) self.textLabel = QLabel() self.hBox = QHBoxLayout() self.hBox.addWidget(self.inputLine) self.hBox.addWidget(self.toggleButton) self.statusBar = QStatusBar(self) msg = 'Hello World! I love YOU!!!' self.statusBar.showMessage(msg, 5000) vBox = QVBoxLayout() items = [self.loadButton, self.textList, self.hBox, self.statusBar] for item in items : try : vBox.addWidget(item) except : vBox.addLayout(item) self.textViewer = QTextEdit() self.textViewer.setHidden(True) self.textViewer.setReadOnly(True) HBox = QHBoxLayout() items = [vBox, self.textViewer] for item in items : try : HBox.addWidget(item) except : HBox.addLayout(item) self.setLayout(HBox) self.resize(350, 500) self.setWindowTitle("VocVoc -- Your Vocabulary Helper") self.info('UI is set up now.') def connect(self) : "Connect signals and slots in the UI." self.info('Connecting signals and slots.') self.loadButton.clicked.connect(self.loadFile) self.inputLine.returnPressed.connect(self.enteredText) self.inputLine.ctrlN.connect(self.completeHandler) self.inputLine.ctrlP.connect(lambda : self.completeHandler(False)) self.textList.itemActivated.connect(self.itemActivated) self.toggleButton.clicked.connect(self.toggleViewer) if self.logger.isEnabledFor(DEBUG) : self.mediaObeject.stateChanged.connect( self.errorState ) self.info('Signals and slots connected.') def errorState(self, state) : errorStates = { 0: 'Loading', 1: 'Stopped', 2: 'Playing', 3: 'Buffering', 4: 'Paused', 5: 'Error' } msg ='{} state in Phonon!'.format( errorStates[state]) self.info(self.mediaObeject.errorType()) if state == 5 : self.warn(msg) else : self.info(msg) def itemActivated(self, item) : row = self.textList.row(item) text = item.text() if not text.startswith('#') : self.pronounce(item.text()) self.findWord(text) if row+1 != self.textList.count() : self.debug('NOT last row!') self.textList.setCurrentRow(row+1) else : self.debug('Last row!') def toggleViewer(self) : if self.textViewer.isHidden() : self.resize(700, 500) self.textViewer.show() else : self.textViewer.hide() self.resize(350, 500) def backAndForward(self, forward=True) : inputLine = self.inputLine word = inputLine.text() setText = inputLine.setText candidates = self.candidates count = len(candidates) try : position = candidates.index(word) self.debug('Position found.') except : position = None self.debug('Position not found.') if forward : if position is None or position == count - 1 : # At end position = -1 setText( candidates[position+1] ) else : if position is None or position == 0 : position = count setText( candidates[position-1] ) def completeHandler(self, goNext=True) : inputLine = self.inputLine candidates = self.candidates word = inputLine.text() if candidates : self.backAndForward(goNext) def play(self, path) : self.mediaObeject.setCurrentSource(Phonon.MediaSource(path)) self.mediaObeject.play() def pronounce(self, word) : self.info('Preparing the url to pronounce.') url = self.baseURL.replace(self.MAGICWORD, word) if not self.autoProxy : self.debug('Without the autoProxy, play it using the url as the source.') self.play(url) else : self.info('With the autoProxy, play it after downloading the file.') try : # May happen HTTPError. resource = urlopen(url).read() tempFile = NamedTemporaryFile() tempFile.write(resource) self.play(tempFile.name) except HTTPError as error : self.warn(repr(error)) self.warn('Pronounciation FAILED.') self.info('Pronounciation ended.') def findWord(self, word) : self.info('Finding word in the text file.') textViewer = self.textViewer if textViewer.isHidden() : return else : pass limit = 5 contexts = list() textLines = list() corpuses = glob(''.join([self.corpusDir, '/*'])) self.debug('Found corpuses : {}.'.format(corpuses)) textViewer.clear() for corpus in corpuses : textLines.append(locateWord(corpus, word)) for textLine in textLines : text, lines = textLine[0], textLine[1] title = ''.join( ['Title : ', basename(text[-1])] ) if lines : for line in lines : wantedLines = text[line-limit: line+limit] #cleanLines = map(self.replace, wantedLines) context = ''.join(wantedLines) context = context.replace(word, ' '.join(['*', word, '*'])) context = context.replace('\n\n', self.MAGICWORD) context = context.replace('\n', ' ') context = context.replace(self.MAGICWORD, '\n\n') contexts.append(''.join([title, '\n', context, '\n\n'])) if contexts : for context in contexts : textViewer.append(context) else : textViewer.append('Sorry, {} not found.'.format(word)) self.info('Word found and showed in the textViewer.') def wordCount(self, word=None) : """ This function uses self.countWord to decide whether record and pronounce the input or not. RECORD : Add the input into the textList and write it into the file. If the word itself is correct, return True. Or if a wrong input were entered twice, return True. Otherwise with a one-time-entered wrong input, return False. """ if self.countWord[0] == 0 : # The word is correct. self.countWord[1] = '' return True elif self.countWord[0] == 1 : msg = 'Maybe the word is WRONG? Playing beep and saving the word.' self.debug(msg) self.countWord[1] = word self.play('beep.mp3') return False elif self.countWord[0] == 2 : if word != self.countWord[1] : # Different word. self.debug('DIFEFRENT WORD.') self.countWord[0] = 1 # Check again. self.countWord[1] = word # Update it. self.play('beep.mp3') return False else : self.countWord[0] = 0 self.countWord[1] = '' return True else : self.countWord[0] = 0 def checkWord(self, word) : statusBar = self.statusBar showMessage = statusBar.showMessage candidates = self.correct(word) if candidates is None : # Not collected. self.countWord[0] += 1 showMessage('Are you sure?', 3000) elif candidates[0] != word : # Can be corrected. self.countWord[0] += 1 self.candidates = candidates msg = 'Do you mean {} ?'.format(' ,'.join(candidates)) showMessage(msg, 5000) else : # Collected in the wordModel. self.findWord(word) self.countWord[0] = 0 self.debug('Word collected in the wordModel.') return True msg = 'wrongTime = {} with the word {}.'.format(self.countWord[0], word) self.logger.debug(msg) return self.wordCount(word) def addText(self, text) : self.info('Starting to add text.') textList = self.textList if text.startswith('#') : # It is a comment. pass else : # It is a word. if self.checkWord(text) : self.pronounce(text) else : # self.checkWord(text) return False return self.inputLine.clear() textList.addItem(text) self.statusBar.clearMessage() textList.setCurrentRow( textList.count() - 1 ) try : # With the try statement, it can be used as a pronunciation helper. flush(self.filePath, text) except Exception : self.debug('Using this freely without writing to a file as a pronunciation helper.') self.info('Text added.') def enteredText(self) : "Get the text from the input line and add it to the file and the list." self.info('Adding text to textList and the file.') textList = self.textList text = self.inputLine.text().strip().lower() self.debug( 'Input is {}.'.format(text) ) self.addText(text) self.info('Text added.') def loadFile(self) : "Open the file dialog to select the file and try to start." # Open the file dialog. logger = getLogger('VocVoc.VocDialog.loadFile') info = logger.info debug = logger.debug debug('Preparing to load file.') textList = self.textList if ( self.fileDialog.exec() ) : debug('Dialog executed sucessfully.') filePath = self.fileDialog.selectedFiles()[0] fileName = basename(filePath) # Create or read file. try : with open(filePath, 'r+') as textFile : debug('File exists, openning up.') writenText = textFile.read() writenText = writenText.splitlines() textList.clear() textList.addItems( writenText ) if not 'end' in writenText[-1].strip().lower() : textList.setCurrentRow( len(writenText)-1 ) else : textList.setCurrentRow( 0 ) debug('Added items to list and set current row to the last row.') except IOError as error : # File does not exist. We create one. debug('File does not exist. Trying to find the dight in the name.') listNumber = self.findDight.search(fileName) if listNumber is None : # No number found in the text. logger.warn('Dight not found in the filename. Try again.') msg = 'No number found in the file name.\nPlease try again.' QMessageBox.warning(self, 'List number NOT found.', msg, QMessageBox.Ok) return msg else : # No existing file but found the number in the file name. debug('Dight Found. Creating file and adding first line.') with open(filePath, 'x') as textFile : firstLine = ''.join( ['# list ' ,str( listNumber.group() )] ) # Cannot put '\n' here. textFile.write( ''.join([firstLine ,'\n']) ) textList.clear() textList.addItem(firstLine) # Otherwise there would be a new line in the list. debug('Set inputLine to write-enabled.') self.inputLine.setReadOnly(False) debug('Pass textFile to the dialog') self.filePath = filePath info('File loaded.')
class ChainComposerDialog(QDialog): def __init__(self, parent=None): super(ChainComposerDialog, self).__init__(parent) self.setWindowTitle('Composer Chain') layout = QVBoxLayout() mainLayout = QHBoxLayout() selectionLayout = QVBoxLayout() label = QLabel('Available Filters:') selectionLayout.addWidget(label) self.__selectionList = QListWidget() selectionLayout.addWidget(self.__selectionList) mainLayout.addLayout(selectionLayout) actionsLayout = QVBoxLayout() actionsLayout.addStretch() addButton = QPushButton('Add>>') addButton.clicked.connect(self.__handleAdd) actionsLayout.addWidget(addButton) removeButton = QPushButton('Remove') actionsLayout.addWidget(removeButton) removeAllButton = QPushButton('Remove All') actionsLayout.addWidget(removeAllButton) actionsLayout.addStretch() mainLayout.addLayout(actionsLayout) chainLayout = QVBoxLayout() chainLayout.addWidget(QLabel('Chain:')) self.__chainList = QListWidget() chainLayout.addWidget(self.__chainList) mainLayout.addLayout(chainLayout) layout.addLayout(mainLayout) buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) buttonBox.accepted.connect(self.okClick) buttonBox.rejected.connect(self.cancelClick) layout.addWidget(buttonBox) # buttonLayout = QHBoxLayout() # okButton = QPushButton('OK') # okButton.clicked.connect(self.accept) # buttonLayout.addWidget(okButton) # cancelButton = QPushButton('Cancel') # cancelButton.clicked.connect(self.reject) # buttonLayout.addWidget(cancelButton) # layout.addLayout(buttonLayout) self.setLayout(layout) self.__composer = None def okClick(self): print "OK!" self.accept() def cancelClick(self): print "Cancel" self.reject() def setComposer(self, composer): self.__composer = composer @property def selectionList(self): return self.__getStrings(self.__selectionList) @selectionList.setter def setSelectionList(self, filters): for i in xrange(self.__selectionList.count()): self.__selectionList.takeItem(i) self.__selectionList.addItems(filters) def filterAt(self, row): return self.__selectionList.item(row).text() def addToChain(self, filterName): self.__chainList.addItem(filterName) @property def composedFilter(self): return self.__getStrings(self.__chainList) @staticmethod def __getStrings(listWidget): return tuple(listWidget.item(i) for i in range(listWidget.count())) def __handleAdd(self): if self.__composer is None: return for item in self.__selectionList.selectedItems(): row = self.__selectionList.row(item) self.__composer.add(row)
class FileArgs(QtHelper.EnhancedQDialog, Logger.ClassLogger): """ File arguments dialog """ def __init__(self, dataArgs, parent=None): """ Dialog to fill arguments for the file probe @param dataArgs: @type dataArgs: @param parent: @type parent: """ super(FileArgs, self).__init__(parent) self.dataArgs = dataArgs self.createDialog() self.createConnections() self.loadDefaultData() def createDialog(self): """ Create qt dialog """ mainLayout = QHBoxLayout() dataLayout = QVBoxLayout() self.labelHelp = QLabel("Path of the file to retrieve:") self.lineEdit = QLineEdit() self.listBox = QListWidget() dataLayout.addWidget(self.labelHelp) dataLayout.addWidget(self.lineEdit) dataLayout.addWidget(self.listBox) buttonLayout = QVBoxLayout() self.addButton = QPushButton("Add", self) self.delButton = QPushButton("Remove", self) self.delButton.setEnabled(False) self.editButton = QPushButton("Edit", self) self.editButton.setEnabled(False) self.clearButton = QPushButton("Clear", self) self.okButton = QPushButton("Ok", self) self.cancelButton = QPushButton("Cancel", self) buttonLayout.addWidget(self.addButton) buttonLayout.addWidget(self.delButton) buttonLayout.addWidget(self.editButton) buttonLayout.addWidget(self.clearButton) buttonLayout.addWidget(self.okButton) buttonLayout.addWidget(self.cancelButton) mainLayout.addLayout(dataLayout) mainLayout.addLayout(buttonLayout) self.setLayout(mainLayout) self.setWindowTitle("File Probe > Arguments") def createConnections(self): """ Create qt connections """ self.okButton.clicked.connect(self.accept) self.cancelButton.clicked.connect(self.reject) self.addButton.clicked.connect(self.addItem) self.delButton.clicked.connect(self.delItem) self.editButton.clicked.connect(self.editItem) self.clearButton.clicked.connect(self.clearList) self.listBox.itemClicked.connect(self.onItemSelected) def clearList(self): """ Clear the list """ self.listBox.clear() def onItemSelected(self, itm): """ Called when an item is selected """ self.delButton.setEnabled(True) self.editButton.setEnabled(True) def editItem(self): """ Edit the selected item """ self.delButton.setEnabled(False) self.editButton.setEnabled(False) # retrieve value to put it in the line edit and then remove item model = self.listBox.model() for selectedItem in self.listBox.selectedItems(): qIndex = self.listBox.indexFromItem(selectedItem) if sys.version_info > (3, ): self.lineEdit.setText(model.data(qIndex)) else: self.lineEdit.setText(model.data(qIndex).toString()) model.removeRow(qIndex.row()) def delItem(self): """ Delete the selected item """ self.delButton.setEnabled(False) self.editButton.setEnabled(False) # remove item model = self.listBox.model() for selectedItem in self.listBox.selectedItems(): qIndex = self.listBox.indexFromItem(selectedItem) model.removeRow(qIndex.row()) def addItem(self): """ Add item """ txt = self.lineEdit.text() if txt != '': self.listBox.insertItem(0, txt) self.lineEdit.setText('') def loadDefaultData(self): """ Load the default data """ try: if len(self.dataArgs) == 0: return dat = eval(self.dataArgs) if 'files' in dat: list_files = dat['files'] self.listBox.insertItems(0, list_files) except Exception as e: self.error(e) def getArgs(self): """ Returns arguments Examples: {'files': [ '/etc/init.d/ntpd', '/root/wmi-1.3.14-2.el5.art.x86_64.rpm' ] } """ listFiles = [] model = self.listBox.model() # iterate all items in a QListWidget for index in xrange(self.listBox.count()): itm = self.listBox.item(index) qIndex = self.listBox.indexFromItem(itm) if sys.version_info > (3, ): listFiles.append(model.data(qIndex)) else: listFiles.append(str(model.data(qIndex).toString())) ret = {'files': listFiles} if len(listFiles) == 0: ret = '' return str(ret)
class TracklistWidget(QWidget): requestUpload = pyqtSignal(list) def __init__(self, parent=None): super(TracklistWidget, self).__init__(parent) self.tracklist = QListWidget(self) self.tracklist.setSelectionMode(QListWidget.NoSelection) self.upload_button = QPushButton( QIcon(resource_path('images/strava-button.png')), 'Upload to Strava', self) self.upload_button.setMinimumHeight(50) self.upload_button.setIconSize(QSize(40, 40)) self.clear_password = QPushButton( QIcon(resource_path('images/cross.png')), 'Clear password', self) self.clear_password.setMinimumHeight(50) self.clear_password.setIconSize(QSize(20, 20)) self.clear_password.hide() self.upload_button.clicked.connect(self._onUploadClicked) self._createLayout() def setTracks(self, tracks): self.tracklist.clear() self.tracklist.addItems(tracks) for i, name in enumerate(tracks): self.tracklist.item(i).setCheckState(Qt.Unchecked) self.tracklist.item(i).setSizeHint(QSize(200, 25)) if tracks: self.tracklist.item(i).setCheckState(Qt.Checked) self.upload_button.setEnabled(True) else: self.upload_button.setEnabled(False) def _onUploadClicked(self): ids = [] for i in range(self.tracklist.count()): item = self.tracklist.item(i) if item.checkState() == Qt.Checked: ids.append(i) if ids: self.requestUpload.emit(ids) def _createLayout(self): l = QVBoxLayout() l.addWidget(self.tracklist) h = QHBoxLayout() h.addWidget(self.upload_button) h.addWidget(self.clear_password) l.addLayout(h) self.setLayout(l)
class PathManager(QDialog): def __init__(self, parent=None, pathlist=None): QDialog.__init__(self, parent) assert isinstance(pathlist, list) self.pathlist = pathlist self.last_path = os.getcwdu() self.setWindowTitle(self.tr("Path manager")) self.resize(500, 300) self.selection_widgets = [] layout = QVBoxLayout() self.setLayout(layout) top_layout = QHBoxLayout() layout.addLayout(top_layout) self.toolbar_widgets1 = self.setup_top_toolbar(top_layout) self.listwidget = QListWidget(self) self.connect(self.listwidget, SIGNAL("currentRowChanged(int)"), self.refresh) layout.addWidget(self.listwidget) bottom_layout = QHBoxLayout() layout.addLayout(bottom_layout) self.toolbar_widgets2 = self.setup_bottom_toolbar(bottom_layout) # Buttons configuration bbox = QDialogButtonBox(QDialogButtonBox.Close) self.connect(bbox, SIGNAL("rejected()"), SLOT("reject()")) bottom_layout.addWidget(bbox) self.update_list() self.refresh() def _add_widgets_to_layout(self, layout, widgets): layout.setAlignment(Qt.AlignLeft) for widget in widgets: layout.addWidget(widget) def setup_top_toolbar(self, layout): toolbar = [] movetop_button = create_toolbutton(self, text=self.tr("Move to top"), icon=get_icon('2uparrow.png'), triggered=lambda: self.move_to(absolute=0)) toolbar.append(movetop_button) moveup_button = create_toolbutton(self, text=self.tr("Move up"), icon=get_icon('1uparrow.png'), triggered=lambda: self.move_to(relative=-1)) toolbar.append(moveup_button) movedown_button = create_toolbutton(self, text=self.tr("Move down"), icon=get_icon('1downarrow.png'), triggered=lambda: self.move_to(relative=1)) toolbar.append(movedown_button) movebottom_button = create_toolbutton(self, text=self.tr("Move to bottom"), icon=get_icon('2downarrow.png'), triggered=lambda: self.move_to(absolute=1)) toolbar.append(movebottom_button) self.selection_widgets.extend(toolbar) self._add_widgets_to_layout(layout, toolbar) return toolbar def setup_bottom_toolbar(self, layout): toolbar = [] add_button = create_toolbutton(self, text=self.tr("Add path"), icon=get_icon('edit_add.png'), triggered=self.add_path) toolbar.append(add_button) remove_button = create_toolbutton(self, text=self.tr("Remove path"), icon=get_icon('edit_remove.png'), triggered=self.remove_path) toolbar.append(remove_button) self.selection_widgets.append(remove_button) self._add_widgets_to_layout(layout, toolbar) layout.addStretch(1) if os.name == 'nt': self.sync_button = create_toolbutton(self, text=self.tr("Synchronize..."), icon=get_icon('synchronize.png'), triggered=self.synchronize, tip=self.tr("Synchronize Spyder's path list with PYTHONPATH " "environment variable")) layout.addWidget(self.sync_button) return toolbar def synchronize(self): """ Synchronize Spyder's path list with PYTHONPATH environment variable Only apply to: current user, on Windows platforms """ answer = QMessageBox.question(self, self.tr("Synchronize"), self.tr("This will synchronize Spyder's path list with " "<b>PYTHONPATH</b> environment variable for current user, " "allowing you to run your Python modules outside Spyder " "without having to configure sys.path. " "<br>Do you want to clear contents of PYTHONPATH before " "adding Spyder's path list?"), QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel) if answer == QMessageBox.Cancel: return elif answer == QMessageBox.Yes: remove = True else: remove = False from spyderlib.utils.environ import (get_user_env, set_user_env, listdict2envdict) env = get_user_env() if remove: ppath = self.pathlist else: ppath = env.get('PYTHONPATH', []) if not isinstance(ppath, list): ppath = [ppath] ppath = [path for path in ppath if path not in self.pathlist] ppath.extend(self.pathlist) env['PYTHONPATH'] = ppath set_user_env( listdict2envdict(env) ) def get_path_list(self): """Return path list""" return self.pathlist def update_list(self): """Update path list""" self.listwidget.clear() for name in self.pathlist: item = QListWidgetItem(name) item.setIcon(get_std_icon('DirClosedIcon')) self.listwidget.addItem(item) self.refresh() def refresh(self, row=None): """Refresh widget""" for widget in self.selection_widgets: widget.setEnabled(self.listwidget.currentItem() is not None) not_empty = self.listwidget.count() > 0 if os.name == 'nt': self.sync_button.setEnabled(not_empty) def move_to(self, absolute=None, relative=None): index = self.listwidget.currentRow() if absolute is not None: if absolute: new_index = len(self.pathlist)-1 else: new_index = 0 else: new_index = index + relative new_index = max(0, min(len(self.pathlist)-1, new_index)) path = self.pathlist.pop(index) self.pathlist.insert(new_index, path) self.update_list() self.listwidget.setCurrentRow(new_index) def remove_path(self): answer = QMessageBox.warning(self, self.tr("Remove path"), self.tr("Do you really want to remove selected path?"), QMessageBox.Yes | QMessageBox.No) if answer == QMessageBox.Yes: self.pathlist.pop(self.listwidget.currentRow()) self.update_list() def add_path(self): self.emit(SIGNAL('redirect_stdio(bool)'), False) directory = QFileDialog.getExistingDirectory(self, self.tr("Select directory"), self.last_path) self.emit(SIGNAL('redirect_stdio(bool)'), True) if not directory.isEmpty(): directory = osp.abspath(unicode(directory)) self.last_path = directory if directory in self.pathlist: answer = QMessageBox.question(self, self.tr("Add path"), self.tr("This directory is already included in Spyder path " "list.<br>Do you want to move it to the top of " "the list?"), QMessageBox.Yes | QMessageBox.No) if answer == QMessageBox.Yes: self.pathlist.remove(directory) else: return self.pathlist.insert(0, directory) self.update_list()
class NotebookSettingsDialog(QDialog): """GUI for adjusting notebook settings""" def __init__(self, parent=None): super(NotebookSettingsDialog, self).__init__(parent) #widgets for tab 1 self.mdExts = QListWidget() self.mjEdit = QLineEdit() self.moveUp = QPushButton('<<') self.moveDown = QPushButton('>>') self.configureExtension = QPushButton('Edit Settings for this extension') self.tmpdict = deepcopy(self.parent().settings.extcfg) #widgets for tab 2 self.fExtEdit = QLineEdit() self.attImgEdit = QLineEdit() self.attDocEdit = QLineEdit() # mandatory button box self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) #tab panels tabs = QTabWidget() markupTab = QWidget() fileExtsTab = QWidget() tabs.addTab(markupTab, "Markdown") tabs.addTab(fileExtsTab, "File extensions") #initialization functions self.initExtList() self.mdExts.setDragDropMode(QAbstractItemView.InternalMove) self.mjEdit.setText(self.parent().settings.mathjax) self.attImgEdit.setText(', '.join(self.parent().settings.attachmentImage)) self.attDocEdit.setText(', '.join(self.parent().settings.attachmentDocument)) self.fExtEdit.setText(self.parent().settings.fileExt) #set up tab 1 layout=QGridLayout(markupTab) layout.addWidget(QLabel("Markdown extensions"),0,0,1,4) layout.addWidget(self.mdExts,1,0,1,4) layout.addWidget(self.moveUp,2,0,1,1) layout.addWidget(self.moveDown,2,1,1,1) layout.addWidget(self.configureExtension,2,2,1,2) layout.addWidget(QLabel("MathJax Location"),3,0,1,1) layout.addWidget(self.mjEdit,3,1,1,3) #set up tab 2 layout=QGridLayout(fileExtsTab) layout.addWidget(QLabel("Note file extension"),0,0,1,1) layout.addWidget(QLabel("Image file extension"),1,0,1,1) layout.addWidget(QLabel("Document file extension"),2,0,1,1) layout.addWidget(self.fExtEdit,0,1,1,1) layout.addWidget(self.attImgEdit,1,1,1,1) layout.addWidget(self.attDocEdit,2,1,1,1) #put it together vlayout = QVBoxLayout(self) vlayout.addWidget(tabs) vlayout.addWidget(self.buttonBox) #setup signal handlers self.moveUp.clicked.connect(self.moveItemUp) self.configureExtension.clicked.connect(self.configExt) self.moveDown.clicked.connect(self.moveItemDown) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) def configExt(self, checked=False, ext=None): if ext is None: ext = self.mdExts.currentItem().text() cfg = self.tmpdict.get(ext,[]) dialog = NotebookExtSettingsDialog(cfg_list=cfg) done = dialog.exec() if done: self.tmpdict[ext] = dialog.configToList() def initExtList(self): extset=set(self.parent().settings.extensions) #for easier performance in checking for ext in self.parent().settings.extensions: item = QListWidgetItem(ext, self.mdExts) item.setFlags(item.flags() | Qt.ItemIsUserCheckable) item.setCheckState(Qt.Checked) for ext in self.parent().settings.faulty_exts: item = QListWidgetItem(ext, self.mdExts) item.setFlags(item.flags() | Qt.ItemIsUserCheckable) item.setBackground(QBrush(QColor('red'))) item.setForeground(QBrush(QColor('black'))) item.setCheckState(Qt.Checked) for ext in allMDExtensions(): if ext in extset: continue item = QListWidgetItem(ext, self.mdExts) item.setFlags(item.flags() | Qt.ItemIsUserCheckable) item.setCheckState(Qt.Unchecked) #self.mdExts.addItem(item) def moveItemUp(self): item = self.mdExts.currentItem() row = self.mdExts.currentRow() if row != 0: # self.mdExts.removeItemWidget(item) self.mdExts.takeItem(row) self.mdExts.insertItem(row-1, item) self.mdExts.setCurrentRow(row-1) def moveItemDown(self): item = self.mdExts.currentItem() row = self.mdExts.currentRow() count = self.mdExts.count() if row != count-1: self.mdExts.takeItem(row) self.mdExts.insertItem(row+1, item) self.mdExts.setCurrentRow(row+1) def accept(self): #write to settings first msettings = self.parent().settings nbsettings = msettings.qsettings nbsettings.setValue('mathJax', self.mjEdit.text()) extlist = [] for i in range(self.mdExts.count()): item = self.mdExts.item(i) if item.checkState() == Qt.Checked: extlist.append(item.text()) writeListToSettings(nbsettings, 'extensions', extlist) writeListToSettings(nbsettings, 'attachmentImage', self.attImgEdit.text().split(", ")) writeListToSettings(nbsettings, 'attachmentDocument', self.attDocEdit.text().split(", ")) writeDictToSettings(nbsettings, 'extensionsConfig', self.tmpdict) #then to memory msettings.extensions = extlist msettings.mathjax = self.mjEdit.text() msettings.attachmentDocument = readListFromSettings(nbsettings, 'attachmentDocument') msettings.attachmentImage = readListFromSettings(nbsettings, 'attachmentImage') msettings.extcfg.update(self.tmpdict) msettings.md = markdown.Markdown(msettings.extensions, extension_configs=msettings.extcfg) #then make mikidown use these settings NOW curitem=self.parent().notesTree.currentItem() self.parent().currentItemChangedWrapper(curitem, curitem) QDialog.accept(self)
class ConfigDialog(QDialog): def __init__(self, parent=None): QDialog.__init__(self, parent) self.contents_widget = QListWidget() self.contents_widget.setMovement(QListView.Static) self.contents_widget.setMinimumWidth(120) self.contents_widget.setMaximumWidth(120) self.contents_widget.setSpacing(1) bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Apply | QDialogButtonBox.Cancel) self.apply_btn = bbox.button(QDialogButtonBox.Apply) self.connect(bbox, SIGNAL("accepted()"), SLOT("accept()")) self.connect(bbox, SIGNAL("rejected()"), SLOT("reject()")) self.connect(bbox, SIGNAL("clicked(QAbstractButton*)"), self.button_clicked) self.pages_widget = QStackedWidget() self.connect(self.pages_widget, SIGNAL("currentChanged(int)"), self.current_page_changed) self.connect(self.contents_widget, SIGNAL("currentRowChanged(int)"), self.pages_widget.setCurrentIndex) self.contents_widget.setCurrentRow(0) hlayout = QHBoxLayout() hlayout.addWidget(self.contents_widget) hlayout.addWidget(self.pages_widget) hlayout.setStretch(1, 1) btnlayout = QHBoxLayout() btnlayout.addStretch(1) btnlayout.addWidget(bbox) vlayout = QVBoxLayout() vlayout.addLayout(hlayout) vlayout.addLayout(btnlayout) self.setLayout(vlayout) self.setWindowTitle("Preferences") self.setWindowIcon(get_icon("configure.png")) def get_current_index(self): """Return current page index""" return self.contents_widget.currentRow() def set_current_index(self, index): """Set current page index""" self.contents_widget.setCurrentRow(index) def accept(self): """Reimplement Qt method""" for index in range(self.pages_widget.count()): configpage = self.pages_widget.widget(index) if not configpage.is_valid(): return configpage.apply_changes() QDialog.accept(self) def button_clicked(self, button): if button is self.apply_btn: # Apply button was clicked configpage = self.pages_widget.currentWidget() if not configpage.is_valid(): return configpage.apply_changes() def current_page_changed(self, index): widget = self.pages_widget.widget(index) self.apply_btn.setVisible(widget.apply_callback is not None) self.apply_btn.setEnabled(widget.is_modified) def add_page(self, widget): self.connect(self, SIGNAL('check_settings()'), widget.check_settings) self.connect(widget, SIGNAL('show_this_page()'), lambda row=self.contents_widget.count(): self. contents_widget.setCurrentRow(row)) self.connect(widget, SIGNAL("apply_button_enabled(bool)"), self.apply_btn.setEnabled) self.pages_widget.addWidget(widget) item = QListWidgetItem(self.contents_widget) item.setIcon(widget.get_icon()) item.setText(widget.get_name()) item.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) item.setSizeHint(QSize(0, 25)) def check_all_settings(self): """This method is called to check all configuration page settings after configuration dialog has been shown""" self.emit(SIGNAL('check_settings()'))
class CodeCompletionWidget(QFrame): def __init__(self, editor): super(CodeCompletionWidget, self).__init__(None, Qt.FramelessWindowHint | Qt.ToolTip) self._editor = editor self.stack_layout = QStackedLayout(self) self.stack_layout.setContentsMargins(0, 0, 0, 0) self.stack_layout.setSpacing(0) self.completion_list = QListWidget() self.completion_list.setMinimumHeight(200) self.completion_list.setAlternatingRowColors(True) self._list_index = self.stack_layout.addWidget(self.completion_list) self._icons = { 'a': resources.IMAGES['attribute'], 'f': resources.IMAGES['function'], 'c': resources.IMAGES['class'], 'm': resources.IMAGES['module'] } self.cc = code_completion.CodeCompletion() self._completion_results = {} self._prefix = u'' self.setVisible(False) self.source = '' self._key_operations = { Qt.Key_Up: self._select_previous_row, Qt.Key_Down: self._select_next_row, Qt.Key_PageUp: (lambda: self._select_previous_row(6)), Qt.Key_PageDown: (lambda: self._select_next_row(6)), Qt.Key_Right: lambda: None, Qt.Key_Left: lambda: None, Qt.Key_Enter: self.pre_key_insert_completion, Qt.Key_Return: self.pre_key_insert_completion, Qt.Key_Tab: self.pre_key_insert_completion, Qt.Key_Space: self.hide_completer, Qt.Key_Escape: self.hide_completer, Qt.Key_Backtab: self.hide_completer, Qt.NoModifier: self.hide_completer, Qt.ShiftModifier: self.hide_completer, } desktop = QApplication.instance().desktop() self._desktop_geometry = desktop.availableGeometry() self.connect(self._editor.document(), SIGNAL("blockCountChanged(int)"), self.update_metadata) def _select_next_row(self, move=1): new_row = self.completion_list.currentRow() + move if new_row < self.completion_list.count(): self.completion_list.setCurrentRow(new_row) else: self.completion_list.setCurrentRow(0) return True def _select_previous_row(self, move=1): new_row = self.completion_list.currentRow() - move if new_row >= 0: self.completion_list.setCurrentRow(new_row) else: self.completion_list.setCurrentRow(self.completion_list.count() - move) return True def update_metadata(self): source = self._editor.get_text() source = source.encode(self._editor.encoding) self.cc.analyze_file('', source) def insert_completion(self, insert): if insert != self._prefix: extra = len(self._prefix) - len(insert) self._editor.textCursor().insertText(insert[extra:]) self.hide_completer() def _get_geometry(self): cr = self._editor.cursorRect() point = self._editor.mapToGlobal(cr.topLeft()) cr.moveTopLeft(point) #Check new position according desktop geometry width = (self.completion_list.sizeHintForColumn(0) + \ self.completion_list.verticalScrollBar().sizeHint().width() + 10) height = 200 orientation = (point.y() + height) < self._desktop_geometry.height() if orientation: cr.moveTop(cr.bottom()) cr.setWidth(width) cr.setHeight(height) if not orientation: cr.moveBottom(cr.top()) xpos = self._desktop_geometry.width() - (point.x() + width) if xpos < 0: cr.moveLeft(cr.left() + xpos) return cr def complete(self, results): self.add_list_items(results) self.completion_list.setCurrentRow(0) cr = self._get_geometry() self.setGeometry(cr) self.completion_list.updateGeometries() self.show() def add_list_items(self, proposals): self.completion_list.clear() for p in proposals: self.completion_list.addItem( QListWidgetItem( QIcon(self._icons.get(p[0], resources.IMAGES['attribute'])), p[1])) def set_completion_prefix(self, prefix, valid=True): self._prefix = prefix proposals = [] proposals += [('m', item) \ for item in self._completion_results.get('modules', []) \ if item.startswith(prefix)] proposals += [('c', item) \ for item in self._completion_results.get('classes', []) \ if item.startswith(prefix)] proposals += [('a', item) \ for item in self._completion_results.get('attributes', []) \ if item.startswith(prefix)] proposals += [('f', item) \ for item in self._completion_results.get('functions', []) \ if item.startswith(prefix)] if proposals and valid: self.complete(proposals) else: self.hide_completer() def fill_completer(self): source = self._editor.get_text() source = source.encode(self._editor.encoding) offset = self._editor.textCursor().position() results = self.cc.get_completion(source, offset) self._completion_results = results prefix = self._editor._text_under_cursor() self.set_completion_prefix(prefix) def hide_completer(self): self._prefix = '' self.hide() def pre_key_insert_completion(self): insert = unicode(self.completion_list.currentItem().text()) self.insert_completion(insert) self.hide_completer() return True def process_pre_key_event(self, event): if not self.isVisible() or self._editor.lang != "python": return False skip = self._key_operations.get(event.key(), lambda: False)() self._key_operations.get(event.modifiers(), lambda: False)() if skip is None: skip = False return skip def process_post_key_event(self, event): if not settings.CODE_COMPLETION or self._editor.lang != "python": return if self.isVisible(): source = self._editor.get_text() source = source.encode(self._editor.encoding) offset = self._editor.textCursor().position() prefix, valid = self.cc.get_prefix(source, offset) self.set_completion_prefix(prefix, valid) self.completion_list.setCurrentRow(0) if event.key() == Qt.Key_Period or (event.key() == Qt.Key_Space and \ event.modifiers() == Qt.ControlModifier): self.fill_completer()
class ListEdit(QWidget): """A widget to edit a list of items (e.g. a list of directories).""" # emitted when anything changed in the listbox. changed = pyqtSignal() def __init__(self, *args, **kwargs): QWidget.__init__(self, *args, **kwargs) layout = QGridLayout(self) self.setLayout(layout) self.addButton = QPushButton(icons.get('list-add'), '') self.editButton = QPushButton(icons.get('document-edit'), '') self.removeButton = QPushButton(icons.get('list-remove'), '') self.listBox = QListWidget() layout.setContentsMargins(1, 1, 1, 1) layout.setSpacing(0) layout.addWidget(self.listBox, 0, 0, 4, 1) layout.addWidget(self.addButton, 0, 1) layout.addWidget(self.editButton, 1, 1) layout.addWidget(self.removeButton, 2, 1) @self.addButton.clicked.connect def addClicked(): item = self.createItem() if self.openEditor(item): self.addItem(item) @self.editButton.clicked.connect def editClicked(): item = self.listBox.currentItem() item and self.editItem(item) @self.removeButton.clicked.connect def removeClicked(): item = self.listBox.currentItem() if item: self.removeItem(item) @self.listBox.itemDoubleClicked.connect def itemDoubleClicked(item): item and self.editItem(item) self.listBox.model().layoutChanged.connect(self.changed) def updateSelection(): selected = bool(self.listBox.currentItem()) self.editButton.setEnabled(selected) self.removeButton.setEnabled(selected) self.changed.connect(updateSelection) self.listBox.itemSelectionChanged.connect(updateSelection) updateSelection() app.translateUI(self) def translateUI(self): self.addButton.setText(_("&Add...")) self.editButton.setText(_("&Edit...")) self.removeButton.setText(_("&Remove")) def createItem(self): return QListWidgetItem() def addItem(self, item): self.listBox.addItem(item) self.itemChanged(item) self.changed.emit() def removeItem(self, item): self.listBox.takeItem(self.listBox.row(item)) self.changed.emit() def editItem(self, item): if self.openEditor(item): self.itemChanged(item) self.changed.emit() def setCurrentItem(self, item): self.listBox.setCurrentItem(item) def setCurrentRow(self, row): self.listBox.setCurrentRow(row) def openEditor(self, item): """Opens an editor (dialog) for the item. Returns True if the dialog was accepted and the item edited. Returns False if the dialog was cancelled (the item must be left unedited). """ pass def itemChanged(self, item): """Called after an item has been added or edited. Re-implement to do something at this moment if needed, e.g. alter the text or display of other items. """ pass def setValue(self, strings): """Sets the listbox to a list of strings.""" self.listBox.clear() self.listBox.addItems(strings) self.changed.emit() def value(self): """Returns the list of paths in the listbox.""" return [ self.listBox.item(i).text() for i in range(self.listBox.count()) ] def setItems(self, items): """Sets the listbox to a list of items.""" self.listBox.clear() for item in items: self.listBox.addItem(item) self.itemChanged(item) self.changed.emit() def items(self): """Returns the list of items in the listbox.""" return [self.listBox.item(i) for i in range(self.listBox.count())] def clear(self): """Clears the listbox.""" self.listBox.clear() self.changed.emit()
class GraphDialog(QDialog): edit_patterns = 0 edit_curves = 1 titles = {edit_patterns: 'Pattern editor', edit_curves: 'Curve editor'} labels = {edit_patterns: 'Patterns', edit_curves: 'Curves'} def __init__(self, dockwidget, parent, params, edit_type): QDialog.__init__(self, parent) main_lay = QVBoxLayout(self) self.dockwidget = dockwidget self.params = params self.edit_type = edit_type self.x_label = '' self.y_label = '' self.setMinimumWidth(600) self.setMinimumHeight(400) self.setWindowTitle(self.titles[edit_type]) # TODO: softcode self.setWindowModality(QtCore.Qt.ApplicationModal) self.current = None self.current_saved = False # File self.lbl_file = QLabel('File:') self.fra_file = QFrame() self.fra_file.setContentsMargins(0, 0, 0, 0) fra_file_lay = QHBoxLayout(self.fra_file) if edit_type == self.edit_patterns: self.txt_file = QLineEdit(self.params.patterns_file) elif edit_type == self.edit_curves: self.txt_file = QLineEdit(self.params.curves_file) self.txt_file.setReadOnly(True) self.txt_file.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignVCenter) self.txt_file.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Minimum) fra_file_lay.addWidget(self.txt_file) self.btn_file = QPushButton('Change') # TODO: softcode self.btn_file.clicked.connect(self.import_file) fra_file_lay.addWidget(self.btn_file) fra_file_lay.setContentsMargins(0, 0, 0, 0) self.lbl_list = QLabel(self.labels[edit_type]) self.lst_list = QListWidget() self.lst_list.currentItemChanged.connect(self.list_item_changed) # Form self.fra_form = QFrame() fra_form1_lay = QFormLayout(self.fra_form) fra_form1_lay.setContentsMargins(0, 0, 0, 0) fra_form1_lay.addRow(self.lbl_list, self.lst_list) # Buttons self.fra_buttons = QFrame() fra_buttons_lay = QHBoxLayout(self.fra_buttons) fra_buttons_lay.setContentsMargins(0, 0, 0, 0) if self.edit_type == self.edit_patterns: ele_name = 'pattern' elif self.edit_type == self.edit_curves: ele_name = 'curve' self.btn_new = QPushButton('New ' + ele_name) # TODO: softcode self.btn_new.clicked.connect(self.new_element) fra_buttons_lay.addWidget(self.btn_new) self.btn_import = QPushButton('Import ' + ele_name + 's') # TODO: softcode self.btn_import.clicked.connect(self.import_file) fra_buttons_lay.addWidget(self.btn_import) self.btn_save = QPushButton('Save current ' + ele_name) # TODO: softcode self.btn_save.clicked.connect(self.save) fra_buttons_lay.addWidget(self.btn_save) self.btn_del = QPushButton('Delete current ' + ele_name) # TODO: softcode self.btn_del.clicked.connect(self.del_item) fra_buttons_lay.addWidget(self.btn_del) # ID self.lbl_id = QLabel('ID:') self.txt_id = QLineEdit() self.txt_id.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.MinimumExpanding) self.lbl_desc = QLabel('Desc.:') self.txt_desc = QLineEdit() self.fra_id = QFrame() fra_id_lay = QHBoxLayout(self.fra_id) fra_id_lay.addWidget(self.lbl_id) fra_id_lay.addWidget(self.txt_id) fra_id_lay.addWidget(self.lbl_desc) fra_id_lay.addWidget(self.txt_desc) # Table form self.table = QTableWidget(self) self.rows_nr = 24 self.cols_nr = 2 self.table.setRowCount(self.rows_nr) self.table.setColumnCount(self.cols_nr) self.table.verticalHeader().setVisible(False) # Initialize empty table self.clear_table() self.table.itemChanged.connect(self.data_changed) self.fra_table = QFrame() fra_table_lay = QVBoxLayout(self.fra_table) fra_table_lay.setContentsMargins(0, 0, 0, 0) if edit_type == self.edit_curves: self.fra_pump_type = QFrame() fra_pump_type_lay = QFormLayout(self.fra_pump_type) self.lbl_pump_type = QLabel('Curve type:') # TODO: softcode self.cbo_pump_type = QComboBox() for key, name in Curve.type_names.iteritems(): self.cbo_pump_type.addItem(name, key) fra_pump_type_lay.addRow(self.lbl_pump_type, self.cbo_pump_type) fra_table_lay.addWidget(self.fra_pump_type) self.cbo_pump_type.activated.connect(self.cbo_pump_type_activated) fra_table_lay.addWidget(self.table) self.btn_add_row = QPushButton('Add row') self.btn_add_row.clicked.connect(self.add_row) fra_table_lay.addWidget(self.btn_add_row) # Graph canvas self.fra_graph = QFrame() self.static_canvas = StaticMplCanvas(self.fra_graph, width=5, height=4, dpi=100) fra_graph_lay = QVBoxLayout(self.fra_graph) fra_graph_lay.addWidget(self.static_canvas) # Top frame self.fra_top = QFrame() fra_top_lay = QVBoxLayout(self.fra_top) fra_top_lay.addWidget(self.fra_form) fra_top_lay.addWidget(self.fra_id) fra_top_lay.addWidget(self.fra_buttons) # Bottom frame self.fra_bottom = QFrame() fra_bottom_lay = QHBoxLayout(self.fra_bottom) fra_bottom_lay.addWidget(self.fra_table) fra_bottom_lay.addWidget(self.fra_graph) # Main main_lay.addWidget(self.fra_top) main_lay.addWidget(self.fra_bottom) # Get existing patterns/curves self.need_to_update_graph = False if self.edit_type == self.edit_patterns: for pattern_id, pattern in self.params.patterns.iteritems(): self.lst_list.addItem(pattern.id) elif self.edit_type == self.edit_curves: for curve_id, curve in self.params.curves.iteritems(): self.lst_list.addItem(curve.id) if self.lst_list.count() > 0: self.lst_list.setCurrentRow(0) self.txt_id.setEnabled(True) self.txt_desc.setEnabled(True) self.btn_save.setEnabled(True) self.btn_del.setEnabled(True) self.table.setEnabled(True) self.table.setEditTriggers(QAbstractItemView.AllEditTriggers) else: self.txt_id.setEnabled(False) self.txt_desc.setEnabled(False) self.btn_save.setEnabled(False) self.btn_del.setEnabled(False) self.table.setEnabled(False) self.table.setEditTriggers(QAbstractItemView.NoEditTriggers) self.new_dialog = None self.need_to_update_graph = True def cbo_pump_type_activated(self): self.update_table_headers() self.update_graph() def add_row(self): row_pos = self.table.rowCount() self.table.insertRow(row_pos) col = 0 item = QTableWidgetItem(str(row_pos)) if self.edit_type == self.edit_patterns: self.table.setItem(row_pos, col, item) item.setFlags(QtCore.Qt.ItemIsSelectable) def setVisible(self, bool): QDialog.setVisible(self, bool) self.update_table_headers() self.update_graph() def list_item_changed(self): p_index = self.lst_list.currentRow() flags = Qt.ItemFlags() flags != Qt.ItemIsEnabled # Clear table self.clear_table() self.need_to_update_graph = False if p_index >= 0: self.table.setRowCount(0) if self.edit_type == self.edit_patterns: self.current = self.params.patterns[ self.lst_list.currentItem().text()] for v in range(len(self.current.values)): row_pos = self.table.rowCount() self.table.insertRow(row_pos) item = QTableWidgetItem(str(v)) item.setFlags(flags) self.table.setItem(v, 0, item) self.table.setItem( v, 1, QTableWidgetItem(str(self.current.values[v]))) elif self.edit_type == self.edit_curves: self.current = self.params.curves[ self.lst_list.currentItem().text()] for v in range(len(self.current.xs)): row_pos = self.table.rowCount() self.table.insertRow(row_pos) self.table.setItem( v, 0, QTableWidgetItem(str(self.current.xs[v]))) self.table.setItem( v, 1, QTableWidgetItem(str(self.current.ys[v]))) curve_type = self.current.type self.cbo_pump_type.setCurrentIndex(curve_type) # Update GUI self.txt_id.setText(self.current.id) self.txt_desc.setText(self.current.desc) self.update_table_headers() # Update graph self.need_to_update_graph = True self.update_graph() else: # No curves self.txt_id.setText('') self.txt_desc.setText('') # Update table and chart self.need_to_update_graph = False for v in range(self.table.columnCount()): self.table.setItem(v, 1, QTableWidgetItem('')) self.need_to_update_graph = True self.update_graph() def import_file(self): config_file = ConfigFile(Parameters.config_file_path) directory = None if self.edit_type == GraphDialog.edit_curves: directory = self.params.last_curves_dir elif self.edit_type == GraphDialog.edit_patterns: directory = self.params.last_patterns_dir if directory is None: directory = self.params.last_project_dir file_path = QFileDialog.getOpenFileName(self, 'Select file', directory, 'Files (*.txt *.inp)') if file_path is None or file_path == '': return else: if self.edit_type == GraphDialog.edit_patterns: # Save patterns file path in configuration file config_file.set_patterns_file_path(file_path) Parameters.patterns_file = file_path elif self.edit_type == GraphDialog.edit_curves: # Save curve file path in configuration file config_file.set_curves_file_path(file_path) Parameters.curves_file = file_path self.read(file_path) def read(self, file_path): self.lst_list.clear() if self.edit_type == self.edit_patterns: InpFile.read_patterns(self.params, file_path) for pattern_id, pattern in self.params.patterns.iteritems(): # desc = ' (' + pattern.desc + ')' if pattern.desc is not None else '' self.lst_list.addItem(pattern.id) self.params.patterns[pattern.id] = pattern elif self.edit_type == self.edit_curves: InpFile.read_curves(self.params, file_path) for curve_id, curve in self.params.curves.iteritems(): # desc = ' (' + curve.desc + ')' if curve.desc is not None else '' self.lst_list.addItem(curve.id) self.params.curves[curve.id] = curve if self.lst_list.count() > 0: self.lst_list.setCurrentRow(0) def new_element(self): old_ids = [] if self.edit_type == self.edit_patterns: for pattern in self.params.patterns.itervalues(): old_ids.append(pattern.id) elif self.edit_type == self.edit_curves: for curve in self.params.curves.itervalues(): old_ids.append(curve.id) self.new_dialog = NewIdDialog(self, old_ids) self.new_dialog.exec_() new_id = self.new_dialog.get_newid() description = self.new_dialog.get_description() if new_id is None or description is None: return if self.edit_type == self.edit_patterns: new_pattern = Pattern(new_id, description) self.params.patterns[new_pattern.id] = new_pattern self.lst_list.addItem(new_pattern.id) elif self.edit_type == self.edit_curves: curve_type = self.cbo_pump_type.itemData( self.cbo_pump_type.currentIndex()) new_curve = Curve(new_id, curve_type, desc=description) self.params.curves[new_curve.id] = new_curve self.lst_list.addItem(new_curve.id) self.lst_list.setCurrentRow(self.lst_list.count() - 1) self.txt_id.setText(new_id) self.txt_desc.setText(description) # Clear table self.clear_table() self.static_canvas.axes.clear() self.txt_id.setEnabled(True) self.txt_desc.setEnabled(True) self.btn_save.setEnabled(True) self.btn_del.setEnabled(True) self.table.setEnabled(True) self.table.setEditTriggers(QAbstractItemView.AllEditTriggers) def save(self): self.need_to_update_graph = False # Check for ID if not self.txt_id.text(): QMessageBox.warning( self, Parameters.plug_in_name, u'Please specify the ID.', # TODO: softcode QMessageBox.Ok) return if self.edit_type == GraphDialog.edit_patterns: values = [] for row in range(self.table.rowCount()): item = self.table.item(row, 1) if item is not None and item.text() != '': values.append(self.from_item_to_val(item)) else: values.append('0') pattern = Pattern(self.txt_id.text(), self.txt_desc.text(), values) old_patterns = self.params.patterns old_patterns[pattern.id] = pattern self.params.patterns = old_patterns self.lst_list.currentItem().setText(pattern.id) elif self.edit_type == GraphDialog.edit_curves: # Check for ID unique xs = [] ys = [] for row in range(self.table.rowCount()): item_x = self.table.item(row, 0) item_y = self.table.item(row, 1) if item_x.text() != '' and item_y.text() != '': xs.append(self.from_item_to_val(item_x)) ys.append(self.from_item_to_val(item_y)) curve_type = self.cbo_pump_type.itemData( self.cbo_pump_type.currentIndex()) curve = Curve(self.txt_id.text(), curve_type, self.txt_desc.text()) for v in range(len(xs)): curve.append_xy(xs[v], ys[v]) old_curves = self.params.curves old_curves[curve.id] = curve self.params.curves = old_curves self.lst_list.currentItem().setText(curve.id) # Update GUI self.dockwidget.update_curves_combo() # self.read() self.need_to_update_graph = True def clear_table(self): self.need_to_update_graph = False for r in range(self.table.rowCount()): self.table.setItem(r, 0, QTableWidgetItem(None)) self.table.setItem(r, 1, QTableWidgetItem(None)) for row in range(self.rows_nr): for col in range(self.cols_nr): if self.edit_type == self.edit_patterns: if col == 0: item = QTableWidgetItem(str(row)) self.table.setItem(row, col, item) item.setFlags(QtCore.Qt.ItemIsSelectable) # elif col == 1 and row == 0: # item = QTableWidgetItem(str(1)) # self.table.setItem(row, col, item) # item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) # elif self.edit_type == self.edit_curves: # if row == 0: # item = QTableWidgetItem(str(0)) # self.table.setItem(row, 0, item) # item = QTableWidgetItem(str(1)) # self.table.setItem(row, 1, item) # item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEnabled) self.need_to_update_graph = True def del_item(self): selected_row = self.lst_list.currentRow() name = self.lst_list.currentItem().text() if selected_row < 0: return self.lst_list.takeItem(selected_row) if self.lst_list.count() == 0: self.txt_id.setEnabled(False) self.txt_desc.setEnabled(False) self.btn_save.setEnabled(False) self.btn_del.setEnabled(False) self.table.setEnabled(False) self.table.setEditTriggers(QAbstractItemView.NoEditTriggers) if self.edit_type == GraphDialog.edit_curves: del self.params.curves[name] # Update GUI self.dockwidget.update_curves_combo() elif self.edit_type == GraphDialog.edit_patterns: del self.params.patterns[name] # Update GUI self.dockwidget.update_patterns_combo() def data_changed(self): if self.need_to_update_graph: self.update_graph() def update_table_headers(self): if self.edit_type == self.edit_patterns: self.x_label = 'Time period' self.y_label = 'Multiplier' elif self.edit_type == self.edit_curves: cbo_data = self.cbo_pump_type.itemData( self.cbo_pump_type.currentIndex()) if cbo_data == Curve.type_efficiency: self.x_label = 'Flow ' + '[' + self.params.options.flow_units + ']' self.y_label = 'Efficiency ' + '[' + self.params.options.units_deltaz[ self.params.options.units] + ']' if cbo_data == Curve.type_headloss: self.x_label = 'Flow ' + '[' + self.params.options.flow_units + ']' self.y_label = 'Headloss ' + '[' + self.params.options.units_deltaz[ self.params.options.units] + ']' if cbo_data == Curve.type_pump: self.x_label = 'Flow ' + '[' + self.params.options.flow_units + ']' self.y_label = 'Head ' + '[' + self.params.options.units_deltaz[ self.params.options.units] + ']' if cbo_data == Curve.type_volume: self.x_label = 'Height ' + '[' + self.params.options.flow_units + ']' self.y_label = 'Volume ' + '[' + self.params.options.units_deltaz[ self.params.options.units] + ']' self.table.setHorizontalHeaderLabels([self.x_label, self.y_label]) # TODO: softcode def update_graph(self): if not self.need_to_update_graph: return xs = [] ys = [] for row in range(self.table.rowCount()): item = self.table.item(row, 0) x = self.from_item_to_val(item) item = self.table.item(row, 1) y = self.from_item_to_val(item) if x is not None: xs.append(float(x)) if y is not None: ys.append(float(y)) if len(xs) == 0 or len(ys) == 0: self.static_canvas.clear() return xys_t = zip(xs, ys) xys_t.sort() xys = zip(*xys_t) xs = xys[0] ys = xys[1] if self.edit_type == self.edit_patterns: y_axis_label = 'Mult. avg.: ' + '{0:.2f}'.format( (numpy.average(ys))) self.static_canvas.draw_bars_graph( ys, time_period=self.params.times.pattern_timestep, y_axes_label=y_axis_label) elif self.edit_type == self.edit_curves: # Account for different types of curves cbo_data = self.cbo_pump_type.itemData( self.cbo_pump_type.currentIndex()) series_length = min(len(xs), len(ys)) # Need to account for different types of curves if cbo_data == Curve.type_efficiency or cbo_data == Curve.type_headloss or cbo_data == Curve.type_volume: self.static_canvas.draw_line_graph(xs[:series_length], ys[:series_length], self.x_label, self.y_label) elif cbo_data == Curve.type_pump: if series_length == 1 or series_length == 3: if series_length == 1: # 3 curve points curve_xs = [0, xs[0], xs[0] * 2] curve_ys = [ys[0] * 1.33, ys[0], 0] # y = a * x^2 + b * x + c elif series_length == 3: # 3 curve points curve_xs = [xs[0], xs[1], xs[2]] curve_ys = [ys[0], ys[1], ys[2]] (a, b, c) = numpy.polyfit(curve_xs, curve_ys, 2) # Create a few interpolated values interp_xs = [] interp_ys = [] n_vals = 30 for v in range(n_vals + 1): x = (curve_xs[2] - curve_xs[0]) / n_vals * v interp_xs.append(x) y = a * x**2 + b * x + c interp_ys.append(y) self.static_canvas.draw_line_graph(interp_xs, interp_ys, self.x_label, self.y_label) else: self.static_canvas.draw_line_graph(xs[:series_length], ys[:series_length], self.x_label, self.y_label) def from_item_to_val(self, item): if item is None: value = None else: value = item.text() try: value = float(value) value = max(value, 0) except: value = None return value
class NotebookSettingsDialog(QDialog): """GUI for adjusting notebook settings""" def __init__(self, parent=None): super(NotebookSettingsDialog, self).__init__(parent) #widgets for tab 1 self.mdExts = QListWidget() self.mjEdit = QLineEdit() self.moveUp = QPushButton('<<') self.moveDown = QPushButton('>>') self.configureExtension = QPushButton( 'Edit Settings for this extension') self.tmpdict = deepcopy(self.parent().settings.extcfg) #widgets for tab 2 self.fExtEdit = QLineEdit() self.attImgEdit = QLineEdit() self.attDocEdit = QLineEdit() # mandatory button box self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) #tab panels tabs = QTabWidget() markupTab = QWidget() fileExtsTab = QWidget() tabs.addTab(markupTab, "Markdown") tabs.addTab(fileExtsTab, "File extensions") #initialization functions self.initExtList() self.mdExts.setDragDropMode(QAbstractItemView.InternalMove) self.mjEdit.setText(self.parent().settings.mathjax) self.attImgEdit.setText(', '.join( self.parent().settings.attachmentImage)) self.attDocEdit.setText(', '.join( self.parent().settings.attachmentDocument)) self.fExtEdit.setText(self.parent().settings.fileExt) #set up tab 1 layout = QGridLayout(markupTab) layout.addWidget(QLabel("Markdown extensions"), 0, 0, 1, 4) layout.addWidget(self.mdExts, 1, 0, 1, 4) layout.addWidget(self.moveUp, 2, 0, 1, 1) layout.addWidget(self.moveDown, 2, 1, 1, 1) layout.addWidget(self.configureExtension, 2, 2, 1, 2) layout.addWidget(QLabel("MathJax Location"), 3, 0, 1, 1) layout.addWidget(self.mjEdit, 3, 1, 1, 3) #set up tab 2 layout = QGridLayout(fileExtsTab) layout.addWidget(QLabel("Note file extension"), 0, 0, 1, 1) layout.addWidget(QLabel("Image file extension"), 1, 0, 1, 1) layout.addWidget(QLabel("Document file extension"), 2, 0, 1, 1) layout.addWidget(self.fExtEdit, 0, 1, 1, 1) layout.addWidget(self.attImgEdit, 1, 1, 1, 1) layout.addWidget(self.attDocEdit, 2, 1, 1, 1) #put it together vlayout = QVBoxLayout(self) vlayout.addWidget(tabs) vlayout.addWidget(self.buttonBox) #setup signal handlers self.moveUp.clicked.connect(self.moveItemUp) self.configureExtension.clicked.connect(self.configExt) self.moveDown.clicked.connect(self.moveItemDown) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) def configExt(self, checked=False, ext=None): if ext is None: ext = self.mdExts.currentItem().text() cfg = self.tmpdict.get(ext, []) dialog = NotebookExtSettingsDialog(cfg_list=cfg) done = dialog.exec() if done: self.tmpdict[ext] = dialog.configToList() def initExtList(self): extset = set(self.parent().settings.extensions) #for easier performance in checking for ext in self.parent().settings.extensions: item = QListWidgetItem(ext, self.mdExts) item.setFlags(item.flags() | Qt.ItemIsUserCheckable) item.setCheckState(Qt.Checked) for ext in self.parent().settings.faulty_exts: item = QListWidgetItem(ext, self.mdExts) item.setFlags(item.flags() | Qt.ItemIsUserCheckable) item.setBackground(QBrush(QColor('red'))) item.setForeground(QBrush(QColor('black'))) item.setCheckState(Qt.Checked) for ext in allMDExtensions(): if ext in extset: continue item = QListWidgetItem(ext, self.mdExts) item.setFlags(item.flags() | Qt.ItemIsUserCheckable) item.setCheckState(Qt.Unchecked) #self.mdExts.addItem(item) def moveItemUp(self): item = self.mdExts.currentItem() row = self.mdExts.currentRow() if row != 0: # self.mdExts.removeItemWidget(item) self.mdExts.takeItem(row) self.mdExts.insertItem(row - 1, item) self.mdExts.setCurrentRow(row - 1) def moveItemDown(self): item = self.mdExts.currentItem() row = self.mdExts.currentRow() count = self.mdExts.count() if row != count - 1: self.mdExts.takeItem(row) self.mdExts.insertItem(row + 1, item) self.mdExts.setCurrentRow(row + 1) def accept(self): #write to settings first msettings = self.parent().settings nbsettings = msettings.qsettings nbsettings.setValue('mathJax', self.mjEdit.text()) extlist = [] for i in range(self.mdExts.count()): item = self.mdExts.item(i) if item.checkState() == Qt.Checked: extlist.append(item.text()) writeListToSettings(nbsettings, 'extensions', extlist) writeListToSettings(nbsettings, 'attachmentImage', self.attImgEdit.text().split(", ")) writeListToSettings(nbsettings, 'attachmentDocument', self.attDocEdit.text().split(", ")) writeDictToSettings(nbsettings, 'extensionsConfig', self.tmpdict) #then to memory msettings.extensions = extlist msettings.mathjax = self.mjEdit.text() msettings.attachmentDocument = readListFromSettings( nbsettings, 'attachmentDocument') msettings.attachmentImage = readListFromSettings( nbsettings, 'attachmentImage') msettings.extcfg.update(self.tmpdict) msettings.md = markdown.Markdown(msettings.extensions, extension_configs=msettings.extcfg) #then make mikidown use these settings NOW curitem = self.parent().notesTree.currentItem() self.parent().currentItemChangedWrapper(curitem, curitem) QDialog.accept(self)
class WellExportDialog(QDialog): def __init__(self): super(WellExportDialog, self).__init__() self.resize(400, 300) self.initUI() self.export_Button.clicked.connect(self.export_well) self.button_box.rejected.connect(self.close) self.select_Button.clicked.connect(self.select_file) self.well_comboBox.currentIndexChanged.connect( self.populate_log_listWidget) self.update_well_comboBox() def initUI(self): self.setWindowIcon(QIcon(':/icon/export')) self.setWindowTitle("Export Well") self.layout = QGridLayout(self) # add QLabel self.label_0 = QLabel(self) self.label_0.setGeometry(QRect(0, 24, 31, 20)) self.label_0.setAlignment(Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self.label_0.setText("Well to export:") self.layout.addWidget(self.label_0, 0, 0) # add QComboBox self.well_comboBox = QComboBox(self) self.well_comboBox.setGeometry(QRect(10, 10, 101, 24)) self.layout.addWidget(self.well_comboBox, 0, 1, 1, 1) # add QCheckBox self.checkbox = QCheckBox(self) self.checkbox.setText("Full LAS") self.checkbox.setCheckState(Qt.Unchecked) self.layout.addWidget(self.checkbox, 0, 2) # add QListWidget self.logs_listWidget = QListWidget(self) self.logs_listWidget.setGeometry(QRect(0, 0, 101, 201)) # self.well_comboBox.setMaximumHeight(151) self.layout.addWidget(self.logs_listWidget, 1, 1) # add QLabel self.label_1 = QLabel(self) self.label_1.setGeometry(QRect(0, 24, 31, 20)) self.label_1.setAlignment(Qt.AlignRight | Qt.AlignTrailing | Qt.AlignVCenter) self.label_1.setText("Output File:") self.layout.addWidget(self.label_1, 2, 0) # add QLineEdit self.file_path_lineEdit = QLineEdit(self) self.file_path_lineEdit.setGeometry(QRect(50, 24, 81, 20)) self.layout.addWidget(self.file_path_lineEdit, 2, 1) # add Button self.select_Button = QPushButton(self) self.select_Button.setMaximumSize(QSize(61, 24)) self.select_Button.setText("Select") self.layout.addWidget(self.select_Button, 2, 2) # add QDialogButtonBox self.button_box = QDialogButtonBox(self) self.export_Button = self.button_box.addButton( "Export", QDialogButtonBox.ApplyRole) self.button_box.addButton(QDialogButtonBox.Cancel) self.layout.addWidget(self.button_box, 3, 0, 1, 3) def update_well_comboBox(self): survey_file = CONF.survey_dir / '.survey' if survey_file.exists(): dnames = get_data_files(CONF.well_dir) self.well_comboBox.addItems(dnames) def populate_log_listWidget(self): self.logs_listWidget.clear() well = ppp.Well( str(CONF.well_dir / ".{}".format(self.well_comboBox.currentText()))) # self.logs_listWidget.addItems(well.logs) for name in well.logs: new_item = QListWidgetItem(name, self.logs_listWidget) new_item.setFlags(new_item.flags() | Qt.ItemIsUserCheckable) new_item.setCheckState(Qt.Unchecked) def export_well(self): file_name = str(self.file_path_lineEdit.text()) if not file_name: QMessageBox().information(self, "Info", "Please select ouput file.") pass else: well = well = ppp.Well( str(CONF.well_dir / ".{}".format(self.well_comboBox.currentText()))) logs_to_export = [] for i in range(self.logs_listWidget.count()): item = self.logs_listWidget.item(i) if item.checkState() == Qt.Checked: logs_to_export.append(str(item.text())) full = True if self.checkbox.checkState() == Qt.Checked \ else False well.export(file_name, logs_to_export, full) QMessageBox().information(self, "Info", "Succeed!") def select_file(self): fl = QFileDialog.getSaveFileName(self, 'Save File', str(CONF.well_dir)) self.file_path_lineEdit.setText(fl)
class RunsDialog(QtHelper.EnhancedQDialog): """ Runs several dialog """ RefreshRepository = pyqtSignal(str) def __init__(self, dialogName, parent = None, iRepo=None, lRepo=None, rRepo=None): """ Constructor """ QtHelper.EnhancedQDialog.__init__(self, parent) self.name = self.tr("Prepare a group of runs") self.projectReady = False self.iRepo = iRepo self.lRepo = lRepo self.rRepo = rRepo self.createDialog() self.createConnections() def createDialog(self): """ Create qt dialog """ self.setWindowTitle( self.name ) mainLayout = QHBoxLayout() layoutTests = QHBoxLayout() layoutRepoTest = QVBoxLayout() self.prjCombo = QComboBox(self) self.prjCombo.setEnabled(False) self.repoTests = QTreeWidget(self) self.repoTests.setFrameShape(QFrame.NoFrame) if USE_PYQT5: self.repoTests.header().setSectionResizeMode(QHeaderView.Stretch) else: self.repoTests.header().setResizeMode(QHeaderView.Stretch) self.repoTests.setHeaderHidden(True) self.repoTests.setContextMenuPolicy(Qt.CustomContextMenu) self.repoTests.setIndentation(10) layoutRepoTest.addWidget(self.prjCombo) layoutRepoTest.addWidget(self.repoTests) self.testsList = QListWidget(self) layoutTests.addLayout( layoutRepoTest ) layoutTests.addWidget( self.testsList ) mainLayout.addLayout( layoutTests ) buttonLayout = QVBoxLayout() self.okButton = QPushButton(self.tr("Execute All"), self) self.okButton.setEnabled(False) self.cancelButton = QPushButton(self.tr("Cancel"), self) self.upButton = QPushButton(self.tr("UP"), self) self.upButton.setEnabled(False) self.downButton = QPushButton(self.tr("DOWN"), self) self.downButton.setEnabled(False) self.clearButton = QPushButton(self.tr("Remove All"), self) self.delButton = QPushButton(self.tr("Remove"), self) self.delButton.setEnabled(False) self.runSimultaneous = QCheckBox(self.tr("Simultaneous Run")) self.schedImmed = QRadioButton(self.tr("Run Immediately")) self.schedImmed.setChecked(True) self.schedAt = QRadioButton(self.tr("Run At:")) self.schedAtDateTimeEdit = QDateTimeEdit(QDateTime.currentDateTime()) self.schedAtDateTimeEdit.setEnabled(False) buttonLayout.addWidget(self.okButton) buttonLayout.addWidget(self.runSimultaneous) buttonLayout.addWidget(self.schedImmed) buttonLayout.addWidget(self.schedAt) buttonLayout.addWidget(self.schedAtDateTimeEdit) buttonLayout.addWidget( self.upButton ) buttonLayout.addWidget( self.downButton ) buttonLayout.addWidget( self.delButton ) buttonLayout.addWidget( self.clearButton ) buttonLayout.addWidget(self.cancelButton) mainLayout.addLayout(buttonLayout) self.setMinimumHeight(400) self.setMinimumWidth(750) self.setLayout(mainLayout) def initProjects(self, projects=[], defaultProject=1): """ Initialize projects """ # init date and time self.schedAtDateTimeEdit.setDateTime(QDateTime.currentDateTime()) self.projectReady = False self.repoTests.clear() self.prjCombo.clear() self.testsList.clear() self.prjCombo.setEnabled(True) # insert data pname = '' for p in projects: self.prjCombo.addItem ( p['name'] ) if defaultProject == p['project_id']: pname = p['name'] for i in xrange(self.prjCombo.count()): item_text = self.prjCombo.itemText(i) if str(pname) == str(item_text): self.prjCombo.setCurrentIndex(i) self.projectReady = True self.RefreshRepository.emit(pname) def initializeTests(self, listing): """ Initialize tests """ self.repoTests.clear() self.testRoot = self.rRepo.Item(repo = self.iRepo.remote(), parent = self.repoTests, txt = "Root", type = QTreeWidgetItem.UserType+10, isRoot = True ) self.testRoot.setSelected(True) self.createRepository(listing=listing, parent=self.testRoot,fileincluded=True) self.repoTests.sortItems(0, Qt.AscendingOrder) self.hideItems(hideTsx=False, hideTpx=False, hideTcx=True, hideTdx=True, hideTxt=True, hidePy=True, hideTux=False, hidePng=True, hideTgx=False, hideTax=False) def createRepository(self, listing, parent, fileincluded=True): """ Create repository @param listing: @type listing: list @param parent: @type parent: @param fileincluded: @type fileincluded: boolean """ try: for dct in listing: if dct["type"] == "folder": item = self.rRepo.Item(repo = self.iRepo.remote(), parent = parent, txt = dct["name"], propertiesFile=dct ) self.createRepository( dct["content"] , item, fileincluded ) else: if fileincluded: if dct["type"] == "file": pname = self.iRepo.remote().getProjectName(dct["project"]) # {'modification': 1342259500, 'type': 'file', 'name': '__init__.py', 'size': '562 } item = self.rRepo.Item(repo = self.iRepo.remote(), parent = parent, txt = dct["name"] , propertiesFile=dct, type = QTreeWidgetItem.UserType+0, projectId=dct["project"], projectName=pname ) except Exception as e: self.error( "unable to create tree for runs: %s" % e ) def onProjectChanged(self, projectItem): """ Called when the project changed on the combo box """ if self.projectReady: item_text = self.prjCombo.itemText(projectItem) self.RefreshRepository.emit(item_text) def createConnections (self): """ create qt connections * ok * cancel """ self.prjCombo.currentIndexChanged.connect(self.onProjectChanged) self.okButton.clicked.connect( self.acceptClicked ) self.cancelButton.clicked.connect( self.reject ) self.upButton.clicked.connect(self.upTest) self.downButton.clicked.connect(self.downTest) self.clearButton.clicked.connect(self.clearList) self.delButton.clicked.connect(self.delTest) self.testsList.itemClicked.connect(self.onItemSelected) self.testsList.itemSelectionChanged.connect(self.onItemSelectionChanged) self.schedAt.toggled.connect(self.onSchedAtActivated) self.repoTests.itemDoubleClicked.connect( self.onTestDoucleClicked ) def onSchedAtActivated(self, toggled): """ On sched at button activated """ if toggled: self.schedAtDateTimeEdit.setEnabled(True) else: self.schedAtDateTimeEdit.setEnabled(False) def onItemSelectionChanged(self): """ Called on item selection changed """ self.onItemSelected(itm=None) def onItemSelected(self, itm): """ Call on item selected """ selectedItems = self.testsList.selectedItems() if len(selectedItems): self.delButton.setEnabled(True) self.upButton.setEnabled(True) self.downButton.setEnabled(True) else: self.delButton.setEnabled(False) self.upButton.setEnabled(False) self.downButton.setEnabled(False) if not self.testsList.count(): self.okButton.setEnabled(False) def upTest(self): """ Up test """ currentRow = self.testsList.currentRow() currentItem = self.testsList.takeItem(currentRow) self.testsList.insertItem(currentRow - 1, currentItem) def downTest(self): """ Down test """ currentRow = self.testsList.currentRow() currentItem = self.testsList.takeItem(currentRow) self.testsList.insertItem(currentRow + 1, currentItem) def delTest(self): """ Del test """ currentRow = self.testsList.currentRow() currentItem = self.testsList.takeItem(currentRow) def clearList(self): """ Clear test """ self.testsList.clear() self.delButton.setEnabled(False) self.upButton.setEnabled(False) self.downButton.setEnabled(False) self.okButton.setEnabled(False) def iterateTree(self, item, hideTsx, hideTpx, hideTcx, hideTdx, hideTxt, hidePy, hideTux, hidePng, hideTgx, hideTax): """ Iterate tree """ child_count = item.childCount() for i in range(child_count): subitem = item.child(i) subchild_count = subitem.childCount() if subchild_count > 0: self.iterateTree(item=subitem, hideTsx=hideTsx, hideTpx=hideTpx, hideTcx=hideTcx, hideTdx=hideTdx, hideTxt=hideTxt, hidePy=hidePy, hideTux=hideTux, hidePng=hidePng, hideTgx=hideTgx, hideTax=hideTax) else: if hideTux and subitem.getExtension() == self.rRepo.EXTENSION_TUX: subitem.setHidden (True) elif hideTpx and subitem.getExtension() == self.rRepo.EXTENSION_TPX: subitem.setHidden (True) elif hideTgx and subitem.getExtension() == self.rRepo.EXTENSION_TGX: subitem.setHidden (True) elif hideTcx and subitem.getExtension() == self.rRepo.EXTENSION_TCX: subitem.setHidden (True) elif hideTsx and subitem.getExtension() == self.rRepo.EXTENSION_TSX: subitem.setHidden (True) elif hideTdx and subitem.getExtension() == self.rRepo.EXTENSION_TDX: subitem.setHidden (True) elif hideTxt and subitem.getExtension() == self.rRepo.EXTENSION_TXT: subitem.setHidden (True) elif hidePy and subitem.getExtension() == self.rRepo.EXTENSION_PY: subitem.setHidden (True) elif hidePng and subitem.getExtension() == self.rRepo.EXTENSION_PNG: subitem.setHidden (True) elif hideTax and subitem.getExtension() == self.rRepo.EXTENSION_TAx: subitem.setHidden (True) else: subitem.setHidden(False) def hideItems(self, hideTsx=False, hideTpx=False, hideTcx=False, hideTdx=False, hideTxt=False, hidePy=False, hideTux=False, hidePng=False, hideTgx=False, hideTax=False): """ Hide items """ root = self.repoTests.invisibleRootItem() self.iterateTree(item=root, hideTsx=hideTsx, hideTpx=hideTpx, hideTcx=hideTcx, hideTdx=hideTdx, hideTxt=hideTxt, hidePy=hidePy, hideTux=hideTux, hidePng=hidePng, hideTgx=hideTgx, hideTax=hideTax) def onTestDoucleClicked(self, testItem): """ On tests double clicked """ if testItem.type() != QTreeWidgetItem.UserType+0: return self.okButton.setEnabled(True) currentProject = self.prjCombo.currentText() testName = "%s:%s" % (str(currentProject),testItem.getPath(withFileName = True)) testItem = QListWidgetItem(testName ) if testName.endswith(self.rRepo.EXTENSION_TUX): testItem.setIcon(QIcon(":/tux.png")) if testName.endswith(self.rRepo.EXTENSION_TSX): testItem.setIcon(QIcon(":/tsx.png")) if testName.endswith(self.rRepo.EXTENSION_TPX): testItem.setIcon(QIcon(":/tpx.png")) if testName.endswith(self.rRepo.EXTENSION_TGX): testItem.setIcon(QIcon(":/tgx.png")) if testName.endswith(self.rRepo.EXTENSION_TAX): testItem.setIcon(QIcon(":/tax.png")) self.testsList.addItem( testItem ) def acceptClicked (self): """ Called on accept button """ self.accept() def getTests(self): """ Returns all tests in the list """ tests = [] for i in xrange(self.testsList.count()): testItem = self.testsList.item(i) tests.append( str(testItem.text()) ) runSimultaneous = False if self.runSimultaneous.isChecked(): runSimultaneous = True if self.schedImmed.isChecked(): runAt = (0,0,0,0,0,0) return (tests, False, runAt, runSimultaneous) else: pydt = self.schedAtDateTimeEdit.dateTime().toPyDateTime() runAt = (pydt.year, pydt.month, pydt.day, pydt.hour, pydt.minute, pydt.second) return (tests, True, runAt, runSimultaneous)
class multipleListWidget(QWidget): def __init__(self, parent, typeid, predefs, editable): QWidget.__init__(self) self.parent = parent self.typeid = typeid self.editable = editable self.predefs = predefs self.init() def init(self): self.vbox = QVBoxLayout() self.vbox.setSpacing(5) self.vbox.setMargin(0) self.createHeader() self.valuelist = QListWidget() self.vbox.addWidget(self.valuelist) self.setLayout(self.vbox) def createHeader(self): self.whead = QWidget() self.headerlayout = QHBoxLayout() self.headerlayout.setSpacing(0) self.headerlayout.setMargin(0) if self.typeid in (typeId.Node, typeId.Path) and self.editable: self.addPath() else: self.addSingleArgument() self.addButton = QPushButton(QIcon(":add.png"), "") self.rmButton = QPushButton(QIcon(":del_dump.png"), "") self.addButton.setIconSize(QSize(16, 16)) self.rmButton.setIconSize(QSize(16, 16)) self.connect(self.addButton, SIGNAL("clicked()"), self.addParameter) self.connect(self.rmButton, SIGNAL("clicked()"), self.rmParameter) self.connect(self.addButton, SIGNAL("clicked()"), self.parent.argumentChanged) self.connect(self.rmButton, SIGNAL("clicked()"), self.parent.argumentChanged) self.headerlayout.addWidget(self.addButton, 0) self.headerlayout.addWidget(self.rmButton, 0) self.whead.setLayout(self.headerlayout) self.vbox.addWidget(self.whead) def addParameterConfig(self, config): try : if len(config) : for item in config: self.valuelist.insertItem(self.valuelist.count() + 1, item) except TypeError: self.valuelist.insertItem(self.valuelist.count() + 1, config) def addParameter(self): if isinstance(self.container, QComboBox): item = self.container.currentText() else: item = self.container.text() if len(self.valuelist.findItems(item, Qt.MatchExactly)) == 0: self.valuelist.insertItem(self.valuelist.count() + 1, item) def rmParameter(self): selected = self.valuelist.selectedItems() for item in selected: row = self.valuelist.row(item) self.valuelist.takeItem(row) def addSingleArgument(self): if len(self.predefs) > 0: self.container = QComboBox() for value in self.predefs: if self.typeid == typeId.Node: self.container.addItem(value.value().name()) else: self.container.addItem(value.toString()) self.container.setEditable(self.editable) else: self.container = QLineEdit() self.container.setReadOnly(self.editable) self.headerlayout.addWidget(self.container, 2) def addPath(self): if len(self.predefs) > 0: self.container = QComboBox() self.container.setReadOnly(False) for value in self.predefs: self.container.addItem(value.toString()) else: self.container = QLineEdit() self.container.setReadOnly(False) if self.typeid == typeId.Path: browse = addLocalPathButton(self, key, self.container, isdir=False) else: browse = addLocalPathButton(self, key, self.container, isdir=False, nodetype=True) self.headerlayout.addWidget(self.container, 2) self.headerlayout.addWidget(browse, 0) def addPredefValue(self): selected = self.predefs.selectedItems() for item in selected: self.valuelist.insertItem(self.valuelist.count() + 1, item.text())
class TagsDialog(QDialog): def __init__(self, dockwidget, parent, params): QDialog.__init__(self, parent) main_lay = QVBoxLayout(self) self.dockwidget = dockwidget self.params = params self.setWindowTitle('Tags editor') # Top frame self.fra_top = QFrame() fra_top_lay = QVBoxLayout(self.fra_top) self.lst_main = QListWidget(self) self.btn_add = QPushButton('Add tag') self.btn_add.clicked.connect(self.add_tag) self.btn_remove = QPushButton('Remove tag') self.btn_remove.clicked.connect(self.remove_tag) fra_top_lay.addWidget(self.lst_main) fra_top_lay.addWidget(self.btn_add) fra_top_lay.addWidget(self.btn_remove) # Bottom frame self.fra_bottom = QFrame() fra_bottom_lay = QHBoxLayout(self.fra_bottom) btb_main = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) btb_main.accepted.connect(self.ok) btb_main.rejected.connect(self.reject) fra_bottom_lay.addWidget(btb_main) # Main main_lay.addWidget(self.fra_top) main_lay.addWidget(self.fra_bottom) self.initialize() def initialize(self): for tag_name in self.params.tag_names: self.lst_main.insertItem(self.lst_main.count(), QListWidgetItem(tag_name, self.lst_main)) def ok(self): tag_names = [] for r in range(self.lst_main.count()): tag_names.append(self.lst_main.item(r).text()) self.params.tag_names = tag_names self.setVisible(False) def reject(self): self.setVisible(False) def add_tag(self): tag_name_dialog = TagNameDialog(self.dockwidget, self) tag_name_dialog.exec_() tag_name = tag_name_dialog.get_tag_name() if tag_name is not None: current_row = self.lst_main.currentRow() if current_row is None: current_row = self.lst_main.count() self.lst_main.insertItem(current_row, QListWidgetItem(tag_name, self.lst_main)) def remove_tag(self): sel_items = self.lst_main.selectedItems() for sel_item in sel_items: self.lst_main.takeItem(self.lst_main.row(sel_item))
class CheckList(HelpedWidget): def __init__(self, model, label="", help_link=""): HelpedWidget.__init__(self, "", help_link) layout = QVBoxLayout() widget = QWidget() widget.setLayout(layout) self.checkAllButton = QToolButton() self.checkAllButton.setIcon(resourceIcon("checked")) self.checkAllButton.setIconSize(QSize(16, 16)) self.checkAllButton.setToolButtonStyle(Qt.ToolButtonIconOnly) self.checkAllButton.setAutoRaise(True) self.checkAllButton.setToolTip("Select all") self.uncheckAllButton = QToolButton() self.uncheckAllButton.setIcon(resourceIcon("notchecked")) self.uncheckAllButton.setIconSize(QSize(16, 16)) self.uncheckAllButton.setToolButtonStyle(Qt.ToolButtonIconOnly) self.uncheckAllButton.setAutoRaise(True) self.uncheckAllButton.setToolTip("Unselect all") self.list = QListWidget() self.list.setContextMenuPolicy(Qt.CustomContextMenu) self.list.setSelectionMode(QAbstractItemView.ExtendedSelection) self.search_box = SearchBox() check_button_layout = QHBoxLayout() check_button_layout.setMargin(0) check_button_layout.setSpacing(0) check_button_layout.addWidget(QLabel(label)) check_button_layout.addStretch(1) check_button_layout.addWidget(self.checkAllButton) check_button_layout.addWidget(self.uncheckAllButton) layout.addLayout(check_button_layout) layout.addWidget(self.list) layout.addWidget(self.search_box) self.addWidget(widget) self.connect(self.checkAllButton, SIGNAL('clicked()'), self.checkAll) self.connect(self.uncheckAllButton, SIGNAL('clicked()'), self.uncheckAll) self.connect(self.list, SIGNAL('itemChanged(QListWidgetItem*)'), self.itemChanged) self.search_box.filterChanged.connect(self.filterList) # self.connect(self.search_box, SIGNAL('filterChanged(str)'), self.filterList) self.connect(self.list, SIGNAL('customContextMenuRequested(QPoint)'), self.showContextMenu) assert isinstance(model, (SelectableModelMixin, ListModelMixin)) self.model = model self.model.observable().attach( SelectableModelMixin.SELECTION_CHANGED_EVENT, self.modelChanged) self.model.observable().attach(ListModelMixin.LIST_CHANGED_EVENT, self.modelChanged) self.modelChanged() def itemChanged(self, item): """@type item: QListWidgetItem""" if item.checkState() == Qt.Checked: self.model.selectValue(str(item.text())) elif item.checkState() == Qt.Unchecked: self.model.unselectValue(str(item.text())) else: raise AssertionError("Unhandled checkstate!") def modelChanged(self): self.list.clear() items = self.model.getList() for item in items: list_item = QListWidgetItem(item) list_item.setFlags(list_item.flags() | Qt.ItemIsUserCheckable) if self.model.isValueSelected(item): list_item.setCheckState(Qt.Checked) else: list_item.setCheckState(Qt.Unchecked) self.list.addItem(list_item) self.filterList(self.search_box.filter()) def setSelectionEnabled(self, enabled): self.setEnabled(enabled) self.checkAllButton.setEnabled(enabled) self.uncheckAllButton.setEnabled(enabled) def filterList(self, filter): filter = filter.lower() for index in range(0, self.list.count()): item = self.list.item(index) text = str(item.text()).lower() if filter == "": item.setHidden(False) elif filter in text: item.setHidden(False) else: item.setHidden(True) def checkAll(self): self.model.selectAll() def uncheckAll(self): self.model.unselectAll() def checkSelected(self): items = [] for item in self.list.selectedItems(): items.append(str(item.text())) for item in items: self.model.selectValue(item) def uncheckSelected(self): items = [] for item in self.list.selectedItems(): items.append(str(item.text())) for item in items: self.model.unselectValue(item) def showContextMenu(self, point): p = self.list.mapToGlobal(point) menu = QMenu() check_selected = menu.addAction("Check selected") uncheck_selected = menu.addAction("Uncheck selected") menu.addSeparator() clear_selection = menu.addAction("Clear selection") selected_item = menu.exec_(p) if selected_item == check_selected: self.checkSelected() elif selected_item == uncheck_selected: self.uncheckSelected() elif selected_item == clear_selection: self.list.clearSelection()
class ListBox(QWidget): def __init__(self, parent): QWidget.__init__(self, parent) while not isinstance(parent, QDialog): parent = parent.parent() self.setObjectName("ListBox" + str(len(parent.findChildren(ListBox)))) self.hLayoutBoxPanel = QHBoxLayout(self) self.hLayoutBoxPanel.setSpacing(0) self.hLayoutBoxPanel.setContentsMargins(3, 3, 3, 3) self.hLayoutBoxPanel.setObjectName(("hLayoutBoxPanel")) self.frameBoxPanel = QFrame(self) sizePolicy = QSizePolicy(QSizePolicy.Preferred, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.frameBoxPanel.sizePolicy().hasHeightForWidth()) self.frameBoxPanel.setSizePolicy(sizePolicy) self.frameBoxPanel.setFrameShape(QFrame.NoFrame) self.frameBoxPanel.setFrameShadow(QFrame.Raised) self.frameBoxPanel.setObjectName(("frameBoxPanel")) self.hLayoutframeBoxPanel = QHBoxLayout(self.frameBoxPanel) self.hLayoutframeBoxPanel.setSpacing(0) self.hLayoutframeBoxPanel.setMargin(0) self.hLayoutframeBoxPanel.setObjectName(("hLayoutframeBoxPanel")) self.captionLabel = QLabel(self.frameBoxPanel) sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth( self.captionLabel.sizePolicy().hasHeightForWidth()) self.captionLabel.setSizePolicy(sizePolicy) self.captionLabel.setMinimumSize(QSize(200, 0)) self.captionLabel.setMaximumSize(QSize(200, 16777215)) font = QFont() font.setBold(False) font.setWeight(50) self.captionLabel.setFont(font) self.captionLabel.setObjectName(("captionLabel")) self.hLayoutframeBoxPanel.addWidget(self.captionLabel) self.listBox = QListWidget(self.frameBoxPanel) self.listBox.setEnabled(True) font = QFont() font.setBold(False) font.setWeight(50) self.listBox.setFont(font) self.listBox.setObjectName(("listBox")) # self.listBox.setText("0.0") self.hLayoutframeBoxPanel.addWidget(self.listBox) self.imageButton = QToolButton(self.frameBoxPanel) self.imageButton.setText(("")) icon = QIcon() icon.addPixmap(QPixmap(("Resource/convex_hull.png")), QIcon.Normal, QIcon.Off) self.imageButton.setIcon(icon) self.imageButton.setObjectName(("imageButton")) self.imageButton.setVisible(False) self.hLayoutframeBoxPanel.addWidget(self.imageButton) self.hLayoutBoxPanel.addWidget(self.frameBoxPanel) self.listBox.currentRowChanged.connect(self.listBoxChanged) self.imageButton.clicked.connect(self.imageButtonClicked) self.captionUnits = "" self.hasObject = False self.objectList = [] self.captionLabel.setVisible(False) def get_Count(self): return self.listBox.count() Count = property(get_Count, None, None, None) def method_3(self, string_0): return self.listBox.row(self.listBox.findItems(string_0)[0]) def method_11(self, string_0): if (self.IsEmpty): return "%s%s\t" % (string_0, self.Caption) return "%s%s\t%s %s" % (string_0, self.Caption, self.Value, self.CaptionUnits) def listBoxChanged(self, index): i = index self.emit(SIGNAL("Event_0"), self) def IndexOf(self, item): if isinstance(item, str): return self.listBox.row(self.listBox.findItems(item)[0]) else: return self.listBox.row( self.listBox.findItems(item.ToString())[0]) def Contains(self, item): compStr = None if isinstance(item, str): compStr = item elif isinstance(item, float) or isinstance(item, int): compStr = str(item) else: compStr = item.ToString() for i in range(self.listBox.count()): comboItemstr = self.listBox.item(i).text() if compStr == comboItemstr: return True return False def Clear(self): self.listBox.clear() self.objectList = [] self.hasObject = False def Add(self, item): if not isinstance(item, str) and not isinstance(item, QString): self.listBox.addItem(item.ToString()) self.objectList.append(item) self.hasObject = True return self.listBox.addItem(item) self.hasObject = False return self.listBox.count() - 1 def Insert(self, index, item): if not isinstance(item, str): self.listBox.insertItem(index, item.ToString()) self.objectList.insert(index, item) self.hasObject = True return self.listBox.insertItem(index, item) self.hasObject = False def imageButtonClicked(self): self.emit(SIGNAL("Event_3"), self) def get_Caption(self): caption = self.captionLabel.text() findIndex = caption.indexOf("(") if findIndex > 0: val = caption.left(findIndex) return val return caption def set_Caption(self, captionStr): if captionStr == "": self.captionLabel.setText("") self.LabelWidth = 0 return if self.CaptionUnits != "" and self.CaptionUnits != None: self.captionLabel.setText(captionStr + "(" + str(self.CaptionUnits) + ")" + ":") else: self.captionLabel.setText(captionStr + ":") Caption = property(get_Caption, set_Caption, None, None) def get_CaptionUnits(self): return self.captionUnits def set_CaptionUnits(self, captionUnits): self.captionUnits = captionUnits CaptionUnits = property(get_CaptionUnits, set_CaptionUnits, None, None) def set_ButtonVisible(self, bool): self.imageButton.setVisible(bool) ButtonVisible = property(None, set_ButtonVisible, None, None) # def get_Value(self): # return self.listBox.currentIndex() # # def set_Value(self, value): # try: # self.listBox.setCurrentIndex(value) # except: # self.textBox.setText("") # Value = property(get_Value, set_Value, None, None) # def get_IsEmpty(self): # return self.listBox.currentText() == "" or self.listBox.currentIndex() == -1 # IsEmpty = property(get_IsEmpty, None, None, None) # def get_ReadOnly(self): # return self.listBox.isReadOnly() # # def set_ReadOnly(self, bool): # # self.listBox.setR.setReadOnly(bool) # # ReadOnly = property(get_ReadOnly, set_ReadOnly, None, None) def set_LabelWidth(self, width): self.captionLabel.setMinimumSize(QSize(width, 0)) self.captionLabel.setMaximumSize(QSize(width, 16777215)) LabelWidth = property(None, set_LabelWidth, None, None) def set_Width(self, width): self.listBox.setMinimumSize(QSize(width, 0)) self.listBox.setMaximumSize(QSize(width, 16777215)) Width = property(None, set_Width, None, None) def set_Button(self, imageName): if imageName == None or imageName == "": self.imageButton.setVisible(False) return icon = QIcon() icon.addPixmap(QPixmap(("Resource/" + imageName)), QIcon.Normal, QIcon.Off) self.imageButton.setIcon(icon) self.imageButton.setVisible(True) Button = property(None, set_Button, None, None) def get_SelectedIndex(self): try: return self.listBox.currentRow() except: return 0 def set_SelectedIndex(self, index): if self.listBox.count() == 0: return if index > self.listBox.count() - 1: self.listBox.setCurrentRow(0) else: self.listBox.setCurrentRow(index) SelectedIndex = property(get_SelectedIndex, set_SelectedIndex, None, None) # def get_Value(self): # return self.listBox.currentIndex() # def set_Value(self, valueStr): # if self.listBox.count() == 0: # return # self.listBox.setCurrentIndex(self.listBox.findText(valueStr)) # Value = property(get_Value, set_Value, None, None) def get_Items(self): if self.hasObject: return self.objectList itemList = [] if self.listBox.count() > 0: for i in range(self.listBox.count()): itemList.append(self.listBox.item(i).text()) return itemList def set_AddItems(self, strList): if len(strList) != 0 and not isinstance( strList[0], str) and not isinstance(strList[0], QString): for obj in strList: self.listBox.addItem(obj.ToString()) self.objectList.append(obj) self.hasObject = True return self.listBox.addItems(strList) Items = property(get_Items, set_AddItems, None, None) def get_Enabled(self): return self.listBox.isEnabled() def set_Enabled(self, bool): self.listBox.setEnabled(bool) Enabled = property(get_Enabled, set_Enabled, None, None) def get_Visible(self): return self.isVisible() def set_Visible(self, bool): self.setVisible(bool) Visible = property(get_Visible, set_Visible, None, None) def get_SelectedItem(self): if self.listBox.count() == 0: return None if self.hasObject: return self.objectList[self.SelectedIndex] return self.listBox.currentItem().text() # def set_SelectedItem(self, val): # index = self.listBox.findText(val) # self.listBox.setCurrentIndex(index) SelectedItem = property(get_SelectedItem, None, None, None)
class NotebookListDialog(QDialog): """ Functions to display, create, remove, modify notebookList """ def __init__(self, parent=None): super(NotebookListDialog, self).__init__(parent) self.notebookList = QListWidget() self.moveUp = QPushButton('<<') self.moveDown = QPushButton('>>') self.add = QPushButton('Add') self.remove = QPushButton('Remove') self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False) layout = QGridLayout() layout.addWidget(self.notebookList, 0, 0, 4, 6) layout.addWidget(self.moveUp, 1, 6) layout.addWidget(self.moveDown, 2, 6) layout.addWidget(self.add, 4, 0) layout.addWidget(self.remove, 4, 1) layout.addWidget(self.buttonBox, 4, 5, 1, 2) self.setLayout(layout) self.notebookList.setItemDelegate(ListDelegate(self.notebookList)) self.notebookList.currentRowChanged.connect(self.updateUi) self.add.clicked.connect(self.actionAdd) self.remove.clicked.connect(self.actionRemove) self.moveUp.clicked.connect(self.moveItemUp) self.moveDown.clicked.connect(self.moveItemDown) self.buttonBox.accepted.connect(self.accept) self.buttonBox.rejected.connect(self.reject) self.initList() def initList(self): self.notebookList.clear() notebooks = Mikibook.read() for nb in notebooks: item = QListWidgetItem() item.setData(Qt.DisplayRole, nb[0]) item.setData(Qt.UserRole, nb[1]) self.notebookList.addItem(item) self.updateUi(len(notebooks) != 0) self.notebookList.setCurrentRow(0) # QListWidgetItem(nb, self.notebookList) def updateUi(self, row): flag = (row != -1) self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(flag) self.remove.setEnabled(flag) self.moveUp.setEnabled(flag) self.moveDown.setEnabled(flag) def actionAdd(self): Mikibook.create() self.initList() count = self.notebookList.count() self.notebookList.setCurrentRow(count - 1) def actionRemove(self): item = self.notebookList.currentItem() row = self.notebookList.currentRow() name = item.data(Qt.DisplayRole) path = item.data(Qt.UserRole) self.notebookList.takeItem(row) Mikibook.remove(name, path) def moveItemUp(self): item = self.notebookList.currentItem() row = self.notebookList.currentRow() if row != 0: # self.notebookList.removeItemWidget(item) self.notebookList.takeItem(row) self.notebookList.insertItem(row - 1, item) self.notebookList.setCurrentRow(row - 1) def moveItemDown(self): item = self.notebookList.currentItem() row = self.notebookList.currentRow() count = self.notebookList.count() if row != count - 1: self.notebookList.takeItem(row) self.notebookList.insertItem(row + 1, item) self.notebookList.setCurrentRow(row + 1) def accept(self): notebookPath = self.notebookList.currentItem().data(Qt.UserRole) notebookName = self.notebookList.currentItem().data(Qt.DisplayRole) settings = Setting([[notebookName, notebookPath]]) window = mikidown.MikiWindow(settings) window.show() count = self.notebookList.count() notebooks = [] for i in range(count): name = self.notebookList.item(i).data(Qt.DisplayRole) path = self.notebookList.item(i).data(Qt.UserRole) notebooks.append([name, path]) Mikibook.write(notebooks) QDialog.accept(self)
class Img2GifWidget(QDialog): AppName = u"GIF生成工具" def __init__(self, parent=None): super(Img2GifWidget, self).__init__(parent) self.setWindowTitle(Img2GifWidget.AppName) self.listWidget = QListWidget() self.listWidget.setMinimumSize(400, 300) self.btnAdd = QPushButton("&Add") self.btnUp = QPushButton("&Up") self.btnDown = QPushButton("&Down") self.btnDel = QPushButton("&Delete") self.btnClear = QPushButton("&Clear") topLeftLay = QVBoxLayout() topLeftLay.addWidget(self.btnAdd) topLeftLay.addWidget(self.btnUp) topLeftLay.addWidget(self.btnDown) topLeftLay.addWidget(self.btnDel) topLeftLay.addWidget(self.btnClear) topLeftLay.addStretch() topLay = QHBoxLayout() topLay.addWidget(self.listWidget) topLay.addLayout(topLeftLay) label = QLabel(u"Gif文件路径:") self.txtGifPath = QLineEdit() self.btnBrowser = QPushButton('...') midLay = QHBoxLayout() midLay.addWidget(label) midLay.addWidget(self.txtGifPath) midLay.addWidget(self.btnBrowser) timeLabel = QLabel(u"时间间隔:") self.spbTime = QDoubleSpinBox() self.spbTime.setRange(0.001, 10) self.spbTime.setSingleStep(0.001) self.spbTime.setValue(1) self.spbTime.setSuffix('s') loopLabel = QLabel(u"循环:") self.spbLoop = QDoubleSpinBox() self.spbLoop = QSpinBox() self.spbLoop.setRange(0, 1000) self.spbLoop.setSingleStep(1) self.spbLoop.setValue(0) self.spbLoop.setToolTip(u"0次循环表示永久循环") self.spbLoop.setSuffix(u"次") self.btnBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) bottomLay = QHBoxLayout() bottomLay.addWidget(timeLabel) bottomLay.addWidget(self.spbTime) bottomLay.addWidget(loopLabel) bottomLay.addWidget(self.spbLoop) bottomLay.addStretch() bottomLay.addWidget(self.btnBox) mainLay = QVBoxLayout() mainLay.addLayout(topLay) mainLay.addLayout(midLay) mainLay.addLayout(bottomLay) self.setLayout(mainLay) self.btnAdd.clicked.connect(self.itemAdd) self.btnUp.clicked.connect(self.itemUp) self.btnDown.clicked.connect(self.itemDown) self.btnDel.clicked.connect(self.itemDel) self.btnClear.clicked.connect(self.listWidget.clear) self.btnBrowser.clicked.connect(self.setGifPath) self.btnBox.rejected.connect(self.close) self.btnBox.accepted.connect(self.makeGif) self.txtGifPath.returnPressed.connect(self.updateGifPath) def itemAdd(self): fileNames = QFileDialog.getOpenFileNames(None, u"{0} -- {1}".format(qApp.applicationName(), Img2GifWidget.AppName), '.', u'所有文件(*.*);;BMP文件(*.bmp);;PNG文件(*.png);;JPG文件(*.jpg *.jpeg)') for fn in fileNames: f = QFileInfo(fn) if unicode(f.suffix().toLower()) in ['jpg', 'png', 'bmp', 'jpeg']: self.listWidget.addItem(fn) def itemUp(self): row = self.listWidget.currentRow() if row <= 0: return item = self.listWidget.currentItem() self.listWidget.takeItem(row) self.listWidget.insertItem(row - 1, item) self.listWidget.setCurrentRow(row - 1) def itemDown(self): rows = self.listWidget.count() row = self.listWidget.currentRow() if (row < 0) or (row == rows - 1): return item = self.listWidget.currentItem() self.listWidget.takeItem(row) self.listWidget.insertItem(row + 1, item) self.listWidget.setCurrentRow(row + 1) def itemDel(self): row = self.listWidget.currentRow() if row >= 0: self.listWidget.takeItem(row) def setGifPath(self): filename = QFileDialog.getSaveFileName(self, u"{0} -- {1}".format(qApp.applicationName(), Img2GifWidget.AppName), ".", "Gif(*.gif)") self.txtGifPath.setText(filename) def updateGifPath(self): fileName = self.txtGifPath.text() f = QFileInfo(fileName) if f.dir().exists and not f.baseName().isEmpty() and not f.suffix().isEmpty(): self.txtGifPath.setText(fileName) return True else: QMessageBox.warning(self, u"{0} -- warning".format(Img2GifWidget.AppName), u"要生成的GIF存储路径{0}不是有效的GIF文件".format(unicode(fileName))) return False def makeGif(self): imgs = [unicode(self.listWidget.item(i).text()) for i in range(self.listWidget.count())] if len(imgs) <= 1: QMessageBox.warning(self, u"{0} - {1}".format(qApp.applicationName(), Img2GifWidget.AppName), u"GIF动画文件必须要给定大于一张图片。") return if not self.updateGifPath(): return durations = self.spbTime.value() loops = self.spbLoop.value() ok, msg = img2gif.images2gif(imgs, self.txtGifPath.text(), durations=durations, loops=loops) if ok: QMessageBox.about(self, u"{0} - {1}".format(qApp.applicationName(), Img2GifWidget.AppName), u"Succeed!\n{0}".format(msg)) qApp.processEvents() else: QMessageBox.about(u"{0} - {1}".format(qApp.applicationName(), Img2GifWidget.AppName), u"sorry! Failed to generate the {0}".format(unicode(self.txtGifPath)))
class ConfigDialog(QDialog): def __init__(self, parent=None): QDialog.__init__(self, parent) self.contents_widget = QListWidget() self.contents_widget.setMovement(QListView.Static) self.contents_widget.setMinimumWidth(120) self.contents_widget.setMaximumWidth(120) self.contents_widget.setSpacing(1) bbox = QDialogButtonBox(QDialogButtonBox.Ok|QDialogButtonBox.Apply |QDialogButtonBox.Cancel) self.apply_btn = bbox.button(QDialogButtonBox.Apply) self.connect(bbox, SIGNAL("accepted()"), SLOT("accept()")) self.connect(bbox, SIGNAL("rejected()"), SLOT("reject()")) self.connect(bbox, SIGNAL("clicked(QAbstractButton*)"), self.button_clicked) self.pages_widget = QStackedWidget() self.connect(self.pages_widget, SIGNAL("currentChanged(int)"), self.current_page_changed) self.connect(self.contents_widget, SIGNAL("currentRowChanged(int)"), self.pages_widget.setCurrentIndex) self.contents_widget.setCurrentRow(0) hlayout = QHBoxLayout() hlayout.addWidget(self.contents_widget) hlayout.addWidget(self.pages_widget) hlayout.setStretch(1,1) btnlayout = QHBoxLayout() btnlayout.addStretch(1) btnlayout.addWidget(bbox) vlayout = QVBoxLayout() vlayout.addLayout(hlayout) vlayout.addLayout(btnlayout) self.setLayout(vlayout) self.setWindowTitle("Preferences") self.setWindowIcon(get_icon("configure.png")) def get_current_index(self): """Return current page index""" return self.contents_widget.currentRow() def set_current_index(self, index): """Set current page index""" self.contents_widget.setCurrentRow(index) def accept(self): """Reimplement Qt method""" for index in range(self.pages_widget.count()): configpage = self.pages_widget.widget(index) if not configpage.is_valid(): return configpage.apply_changes() QDialog.accept(self) def button_clicked(self, button): if button is self.apply_btn: # Apply button was clicked configpage = self.pages_widget.currentWidget() if not configpage.is_valid(): return configpage.apply_changes() def current_page_changed(self, index): widget = self.pages_widget.widget(index) self.apply_btn.setVisible(widget.apply_callback is not None) self.apply_btn.setEnabled(widget.is_modified) def add_page(self, widget): self.connect(self, SIGNAL('check_settings()'), widget.check_settings) self.connect(widget, SIGNAL('show_this_page()'), lambda row=self.contents_widget.count(): self.contents_widget.setCurrentRow(row)) self.connect(widget, SIGNAL("apply_button_enabled(bool)"), self.apply_btn.setEnabled) self.pages_widget.addWidget(widget) item = QListWidgetItem(self.contents_widget) item.setIcon(widget.get_icon()) item.setText(widget.get_name()) item.setFlags(Qt.ItemIsSelectable|Qt.ItemIsEnabled) item.setSizeHint(QSize(0, 25)) def check_all_settings(self): """This method is called to check all configuration page settings after configuration dialog has been shown""" self.emit(SIGNAL('check_settings()'))
class GitStatus(QDialog): def __init__(self, plugin, git, path): QDialog.__init__(self) self.git = git self.plugin = plugin self.setWindowTitle('Git status') layout = QGridLayout(self) branches = self.git.branch(unicode(path)) self.s_branches = QListWidget() if len(branches) > 0: self.s_branches.addItems(branches[1:]) self.actual_branch = QLabel("<h2>{0}</h2>".format(branches[0])) else: self.actual_branch = QLabel() branch = QLabel("<h2>Branches</h2>") change_branch = QPushButton("Change to") merge_branches = QPushButton("Merge branch") H = QHBoxLayout() delete_branch = QPushButton("Delete branch") add_branch = QPushButton("Add branch") H.addWidget(add_branch) H.addWidget(delete_branch) self.lists = [] no_staged = QLabel("<h2>No staged</h2>") untracked_files = QLabel("Untracked files") self.untracked_files = QListWidget() self.lists.append(self.untracked_files) modified_files = QLabel("Modified files") self.modified_files = QListWidget() self.lists.append(self.modified_files) deleted_files = QLabel("Deleted files") self.deleted_files = QListWidget() self.lists.append(self.deleted_files) staged = QLabel("<h2>Staged</h2>") added_files = QLabel("Added files") self.added_files = QListWidget() self.lists.append(self.added_files) s_modified_files = QLabel("Modified files") self.s_modified_files = QListWidget() self.lists.append(self.s_modified_files) s_deleted_files = QLabel("Deleted files") self.s_deleted_files = QListWidget() self.lists.append(self.s_deleted_files) layout.addWidget(self.actual_branch, 0, 0, Qt.AlignHCenter) layout.addWidget(change_branch, 1, 0) layout.addWidget(merge_branches, 2, 0) layout.addWidget(no_staged, 3, 0) layout.addWidget(untracked_files, 4, 0) layout.addWidget(self.untracked_files, 5, 0) layout.addWidget(modified_files, 6, 0) layout.addWidget(self.modified_files, 7, 0) layout.addWidget(deleted_files, 8, 0) layout.addWidget(self.deleted_files, 9, 0) layout.addWidget(branch, 0, 1) layout.addWidget(self.s_branches, 1, 1) layout.addLayout(H, 2, 1) layout.addWidget(staged, 3, 1) layout.addWidget(added_files, 4, 1) layout.addWidget(self.added_files, 5, 1) layout.addWidget(s_modified_files, 6, 1) layout.addWidget(self.s_modified_files, 7, 1) layout.addWidget(s_deleted_files, 8, 1) layout.addWidget(self.s_deleted_files, 9, 1) self.fill(self.git.no_staged["?"], self.untracked_files) self.fill(self.git.no_staged["M"], self.modified_files) self.fill(self.git.no_staged["D"], self.deleted_files) self.fill(self.git.staged["A"], self.added_files) self.fill(self.git.staged["M"], self.s_modified_files) self.fill(self.git.staged["D"], self.s_deleted_files) self.staged_b = QPushButton('Stage files', self) self.unstage_b = QPushButton("Unstage files", self) self.commit_b = QPushButton('Commit files', self) self.uncommit_b = QPushButton("Uncommit files", self) layout.addWidget(self.staged_b, 10, 0) layout.addWidget(self.unstage_b, 11, 0) layout.addWidget(self.commit_b, 10, 1) layout.addWidget(self.uncommit_b, 11, 1) self.setLayout(layout) self.connect(self.staged_b, SIGNAL('clicked()'), self.add) self.connect(self.unstage_b, SIGNAL('clicked()'), self.unstage) self.connect(self.commit_b, SIGNAL('clicked()'), self.commit) self.connect(self.uncommit_b, SIGNAL('clicked()'), self.uncommit) self.connect(change_branch, SIGNAL("clicked()"), self.change_branch) self.connect(add_branch, SIGNAL("clicked()"), self.add_branch) self.connect(delete_branch, SIGNAL("clicked()"), self.delete_branch) self.connect(merge_branches, SIGNAL("clicked()"), self.merge_branches) def fill(self, a_list, widget_list): for x in a_list: item = QListWidgetItem() widget_list.addItem(item) check_box = QCheckBox(x) widget_list.setItemWidget(item, check_box) def add(self): path = self.plugin.editor.get_project_owner() for pos in reversed(xrange(self.untracked_files.count())): item = self.untracked_files.item(pos) widget = self.untracked_files.itemWidget(item) text = widget.text() if widget.isChecked(): self.git.add(path, text) self.untracked_files.removeItemWidget(item) self.untracked_files.takeItem(pos) item = QListWidgetItem() self.added_files.addItem(item) check_box = QCheckBox(text) self.added_files.setItemWidget(item, check_box) for pos in reversed(xrange(self.modified_files.count())): item = self.modified_files.item(pos) widget = self.modified_files.itemWidget(item) text = widget.text() if widget.isChecked(): self.git.add(path, widget.text()) self.modified_files.removeItemWidget(item) self.modified_files.takeItem(pos) item = QListWidgetItem() self.s_modified_files.addItem(item) check_box = QCheckBox(text) self.s_modified_files.setItemWidget(item, check_box) for pos in reversed(xrange(self.deleted_files.count())): item = self.deleted_files.item(pos) widget = self.deleted_files.itemWidget(item) text = widget.text() if widget.isChecked(): self.git.add(path, widget.text()) self.deleted_files.removeItemWidget(item) self.deleted_files.takeItem(pos) item = QListWidgetItem() self.s_deleted_files.addItem(item) check_box = QCheckBox(text) self.s_deleted_files.setItemWidget(item, check_box) def unstage(self): path = self.plugin.editor.get_project_owner() for pos in reversed(xrange(self.untracked_files.count())): item = self.untracked_files.item(pos) widget = self.untracked_files.itemWidget(item) if widget.isChecked(): self.git.unstage(path, widget.text()) self.untracked_files.removeItemWidget(item) self.untracked_files.takeItem(pos) for pos in reversed(xrange(self.modified_files.count())): item = self.modified_files.item(pos) widget = self.modified_files.itemWidget(item) if widget.isChecked(): self.git.unstage(path, widget.text()) self.modified_files.removeItemWidget(item) self.modified_files.takeItem(pos) for pos in reversed(xrange(self.deleted_files.count())): item = self.deleted_files.item(pos) widget = self.deleted_files.itemWidget(item) if widget.isChecked(): self.git.unstage(path, widget.text()) self.deleted_files.removeItemWidget(item) self.deleted_files.takeItem(pos) def commit(self): msg = QInputDialog.getText(self, "Commit message", "Commit Message:") if msg[1] == False: return(0) path = self.plugin.editor.get_project_owner() for pos in reversed(xrange(self.added_files.count())): item = self.added_files.item(pos) widget = self.added_files.itemWidget(item) if widget.isChecked(): self.git.commit(path, str(widget.text()), msg[0]) self.added_files.removeItemWidget(item) self.added_files.takeItem(pos) for pos in reversed(xrange(self.s_modified_files.count())): item = self.s_modified_files.item(pos) widget = self.s_modified_files.itemWidget(item) if widget.isChecked(): self.git.commit(path, widget.text(), msg[0]) self.s_modified_files.removeItemWidget(item) self.s_modified_files.takeItem(pos) for pos in reversed(xrange(self.s_deleted_files.count())): item = self.s_deleted_files.item(pos) widget = self.s_deleted_files.itemWidget(item) if widget.isChecked(): self.git.commit(path, widget.text(), msg[0]) self.s_deleted_files.takeItem(pos) self.s_deleted_files.removeItemWidget(item) def uncommit(self): path = self.plugin.editor.get_project_owner() for pos in reversed(xrange(self.added_files.count())): item = self.added_files.item(pos) widget = self.added_files.itemWidget(item) text = widget.text() if widget.isChecked(): self.git.uncommit(path, str(widget.text())) self.added_files.removeItemWidget(item) self.added_files.takeItem(pos) item = QListWidgetItem() self.untracked_files.addItem(item) check_box = QCheckBox(text) self.untracked_files.setItemWidget(item, check_box) for pos in reversed(xrange(self.s_modified_files.count())): item = self.s_modified_files.item(pos) widget = self.s_modified_files.itemWidget(item) text = widget.text() if widget.isChecked(): self.git.uncommit(path, widget.text()) self.s_modified_files.removeItemWidget(item) self.s_modified_files.takeItem(pos) item = QListWidgetItem() self.modified_files.addItem(item) check_box = QCheckBox(text) self.modified_files.setItemWidget(item, check_box) for pos in reversed(xrange(self.s_deleted_files.count())): item = self.s_deleted_files.item(pos) widget = self.s_deleted_files.itemWidget(item) text = widget.text() if widget.isChecked(): self.git.uncommit(path, widget.text()) self.s_deleted_files.removeItemWidget(item) self.s_deleted_files.takeItem(pos) item = QListWidgetItem() self.deleted_files.addItem(item) check_box = QCheckBox(text) self.deleted_files.setItemWidget(item, check_box) def change_branch(self): path = self.plugin.editor.get_project_owner() item = self.s_branches.currentItem() if item and not self.something(): text = item.text() self.git.change_branch(path, text) self.s_branches.clear() self.s_branches.addItems(self.git.branch(unicode(path))[1:]) self.actual_branch.setText("<h2>{0}<h2>".format(text)) if self.something(): v = QMessageBox() v.setText("Error: you have unsaved changes") v.setIcon(v.Warning) v.exec_() def add_branch(self): path = self.plugin.editor.get_project_owner() msg = QInputDialog.getText(self, "New branch", "Branch Name:") if msg[1] == False: return(0) self.git.add_branch(path, msg[0]) self.s_branches.clear() self.s_branches.addItems(self.git.branch(unicode(path))[1:]) def delete_branch(self): path = self.plugin.editor.get_project_owner() item = self.s_branches.currentItem() if item: text = str(item.text()) call = self.git.delete_branch(path, text) if not call: self.s_branches.clear() self.s_branches.addItems(self.git.branch(unicode(path))[1:]) else: m = QMessageBox() m.setText("<h2>" + call + "</h2>") m.setInformativeText("Force deletion?") m.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel) m.setDefaultButton(QMessageBox.Cancel) c = m.exec_() if c == QMessageBox.Ok: self.git.force_delete_branch(path, text) self.s_branches.clear() self.s_branches.addItems(self.git.branch(unicode(path))[1:]) def merge_branches(self): path = self.plugin.editor.get_project_owner() item = self.s_branches.currentItem() if item: text = str(item.text()) call = self.git.merge_branches(path, text) if call: m = QMessageBox() m.setText(call) m.setInformativeText("Unknown") m.setIcon(m.Critical) m.exec_() def something(self): for x in self.lists: if x.count() > 0: return True return False
class EkdConfigBox(QDialog) : """ EkdConfigBox permet à l'utilisateur de configurer EkdConfig """ def __init__(self, w=550, h=480, titre=u"Configuration de Ekd", parent=None): super(EkdConfigBox, self).__init__(parent) self.resize(w,h) self.w = w self.h = h self.setWindowTitle(titre) self.layout = QVBoxLayout(self) ## Menu contient l'ensemble des sections à paramétrer self.menu = QListWidget(self) self.layout.addWidget(self.menu) ## Pour chaque section à paramétrer, on utilise un Stack d'objets self.leftpart = QStackedLayout() self.leftpart.setSizeConstraint(QLayout.SetNoConstraint) self.layout.addLayout(self.leftpart) ## propWidget contient l'ensemble des objets propriété de toutes les section ## (il est nécessaire de les stocker pour être capable de les faire interagir) self.propWidget=[] wid = 0 ## On crée les différentes parties de configuration qui ne sont pas inclues dans le tableau SECTION_MASK de EkdConfig for section in EkdConfig.SECTIONS : if not section in EkdConfig.SECTION_MASK : self.menu.addItem(EkdConfig.SECTIONS[section]) allprops = EkdConfig.getAllProperties(EkdConfig.getConfigSection(section)) scroll = QScrollArea() frame = QFrame() frame.setMinimumSize(self.w-50, self.h/2) # Ajouté le 10/12/2009 Pour que la partie réglage prenne toute la place dispo. frame.setMaximumSize(self.w, self.h) linelayout = QGridLayout(frame) linelayout.setSizeConstraint(QLayout.SetMinAndMaxSize) row = 0 ## Insertion des propriété de la section en fonction de son type allkeys = allprops.keys() found = False for prop in allkeys : if not prop in EkdConfig.PROPERTIES_MASK : if prop in EkdConfig.PATH_PROPERTIES : self.propWidget.append( EkdPathPropertie(prop, EkdConfig.PROPERTIES[prop], allprops[prop], section=section) ) linelayout.addWidget(self.propWidget[wid].label, row, 0) linelayout.addWidget(self.propWidget[wid].widget, row, 1) wid += 1 found = True row += 1 for prop in allkeys : if not prop in EkdConfig.PROPERTIES_MASK : if prop in EkdConfig.STYLE_PROPERTIES : self.propWidget.append( EkdStylePropertie(prop, EkdConfig.PROPERTIES[prop], allprops[prop], EkdConfig.STYLE_PROPERTIES[prop], section=section ) ) linelayout.addWidget(self.propWidget[wid].label, row, 0) linelayout.addWidget(self.propWidget[wid].widget, row, 1) wid += 1 found = True row += 1 for prop in allkeys : if not prop in EkdConfig.PROPERTIES_MASK : if prop in EkdConfig.CODEC_PROPERTIES : self.propWidget.append( EkdCodecPropertie(prop, EkdConfig.PROPERTIES[prop], allprops[prop], EkdConfig.CODEC_PROPERTIES[prop], section=section ) ) linelayout.addWidget(self.propWidget[wid].label, row, 0) linelayout.addWidget(self.propWidget[wid].widget, row, 1) wid += 1 found = True row += 1 for prop in allkeys : if not prop in EkdConfig.PROPERTIES_MASK : if prop in EkdConfig.BOOLEAN_PROPERTIES : self.propWidget.append( EkdBoolPropertie(prop, EkdConfig.PROPERTIES[prop], allprops[prop], section=section) ) linelayout.addWidget(self.propWidget[wid].widget, row, 0, 1, 2) wid += 1 found = True row += 1 for prop in allkeys : if not prop in EkdConfig.PROPERTIES_MASK : if prop in EkdConfig.NUM_PROPERTIES : self.propWidget.append( EkdNumPropertie(prop, EkdConfig.PROPERTIES[prop], allprops[prop], section=section) ) linelayout.addWidget(self.propWidget[wid].label, row, 0) linelayout.addWidget(self.propWidget[wid].widget, row, 1) wid += 1 found = True row += 1 for prop in allkeys : if not prop in EkdConfig.PROPERTIES_MASK : if prop in EkdConfig.TIME_PROPERTIES : self.propWidget.append( EkdTimePropertie(prop, EkdConfig.PROPERTIES[prop], allprops[prop], section=section) ) linelayout.addWidget(self.propWidget[wid].label, row, 0) linelayout.addWidget(self.propWidget[wid].widget, row, 1) wid += 1 found = True row += 1 for prop in allkeys : if not prop in EkdConfig.PROPERTIES_MASK : if prop in EkdConfig.COLOR_PROPERTIES : self.propWidget.append( EkdColorPropertie(prop, EkdConfig.PROPERTIES[prop], allprops[prop], section=section) ) linelayout.addWidget(self.propWidget[wid].label, row, 0) linelayout.addWidget(self.propWidget[wid].widget, row, 1) wid += 1 found = True elif not found: line = QLineEdit(allprops[prop]) linelayout.addWidget(QLabel(prop), row, 0) linelayout.addWidget(line, row, 1) row += 1 frame.setLineWidth(0) scroll.setWidget(frame) self.leftpart.addWidget(scroll) self.menu.setAlternatingRowColors(True) # Define the size of the list depending of its content self.menu.setFixedHeight(( self.menu.sizeHintForRow(0) + self.menu.verticalStepsPerItem() + 1)* self.menu.count()) self.menu.updateGeometries() ## Boutton pour fermer la boite de dialogue self.fermer = QPushButton(_(u"Fermer")) self.layout.addWidget(self.fermer) ## Lorsqu'on clique sur fermer, la fenêtre se ferme self.connect(self.fermer, SIGNAL("clicked()"), self.close) ## Lorsqu'on selectionne un élément du menu, on met à jour la partie droite du menu self.connect(self.menu, SIGNAL("currentItemChanged(QListWidgetItem *,QListWidgetItem *)"), self.updateMenu) def updateMenu(self): propriete = self.menu.currentRow() self.leftpart.setCurrentIndex(propriete)
class StringListDlg(QDialog): acceptedList = Signal(QStringList) def __init__(self, name, stringlist=None, parent=None): super(StringListDlg, self).__init__(parent) self.name = name self.create_widgets(stringlist) self.layout_widgets() self.setWindowTitle("Edit {0} List".format(self.name)) def create_widgets(self, stringlist): self.listWidget = QListWidget() if stringlist is not None: self.listWidget.addItems(stringlist) self.listWidget.setCurrentRow(0) def layout_widgets(self): buttonLayout = QVBoxLayout() for text, slot in (("&Add...", self.add), ("&Edit...", self.edit), ("&Remove...", self.remove), ("&Up", self.up), ("&Down", self.down), ("&Sort", self.listWidget.sortItems), ("Close", self.accept)): button = QPushButton(text) if not MAC: button.setFocusPolicy(Qt.NoFocus) if text == "Close": buttonLayout.addStretch() buttonLayout.addWidget(button) button.clicked.connect(slot) layout = QHBoxLayout() layout.addWidget(self.listWidget) layout.addLayout(buttonLayout) self.setLayout(layout) def add(self): row = self.listWidget.currentRow() title = "Add {0}".format(self.name) string, ok = QInputDialog.getText(self, title, title) if ok and not string.isEmpty(): self.listWidget.insertItem(row, string) def edit(self): row = self.listWidget.currentRow() item = self.listWidget.item(row) if item is not None: title = "Edit {0}".format(self.name) string, ok = QInputDialog.getText(self, title, title, QLineEdit.Normal, item.text()) if ok and not string.isEmpty(): item.setText(string) def remove(self): row = self.listWidget.currentRow() item = self.listWidget.item(row) if item is None: return reply = QMessageBox.question( self, "Remove {0}".format(self.name), "Remove {0} `{1}'?".format(self.name, unicode(item.text())), QMessageBox.Yes | QMessageBox.No) if reply == QMessageBox.Yes: item = self.listWidget.takeItem(row) del item def up(self): 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): 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 reject(self): self.accept() def accept(self): self.stringlist = QStringList() for row in range(self.listWidget.count()): self.stringlist.append(self.listWidget.item(row).text()) self.acceptedList.emit(self.stringlist) QDialog.accept(self)
class NewSessionPagePermutations(QWizardPage): def __init__(self): super(NewSessionPagePermutations, self).__init__() self.setTitle(_('Configuration of permutations')) self.setSubTitle( _('Select the position of each question' ' and its choices in every model of the exam.')) layout = QGridLayout() self.question_list = QListWidget() self.permutation_grid = QGridLayout() self.alternatives_rows = {} layout.addWidget(QLabel(_('Questions of model A')), 0, 0, 1, 1) layout.addWidget(self.question_list, 1, 0, 1, 1) layout.addWidget(QLabel(_('Model equivalence')), 0, 1, 1, 5) self.permutation_grid.setVerticalSpacing(20) layout.addLayout(self.permutation_grid, 1, 1, 1, 5) layout.setColumnStretch(0, 1) layout.setColumnStretch(1, 5) self.setLayout(layout) def initializePage(self): paramNAlts = int(self.field("paramNAlts").toString()) paramNPerm = int(self.field("paramNPerm").toString()) self.question_list.clear() # Creation of the list section paramNCols_array = self.field("paramNCols").toString().split(',') total_questions = 1 + (int(paramNCols_array[0]) \ if len(paramNCols_array) == 1 \ else reduce(lambda x, y: int(x) + int(y), paramNCols_array)) for i in range(1, total_questions): questions_list = QListWidgetItem(_('Question ') + str(i)) questions_list.setData(Qt.UserRole, widgets.ItemList( optionName=_('Question ') + str(i), optionNumber=i)) # Custom item list self.question_list.addItem(questions_list) self.question_list.setCurrentRow(0) self.question_list.itemClicked.connect(self._on_item_changed) # Creation of the grid section add_header = True # Header of the columns (Name of alternatives) for j in range(0, paramNPerm): self.permutation_grid.addWidget( \ QLabel(_('Model ') + chr(97 + j).upper()), j, 1) self.alternatives_rows[j] = {} for k in range(0, paramNAlts): if add_header: if k == 0: self.permutation_grid.addWidget(QLabel(''), 0, 1) self.permutation_grid.addWidget( \ QLabel(chr(97 + k).upper()), 0, k + 2) self.alternatives_rows[j][k] = \ widgets.InputComboBox(self, c_type='alternative', form=j, alternative=k) self.alternatives_rows[j][k].addItems( \ [chr(97+x).upper() for x in range(0,paramNAlts)]) self.alternatives_rows[j][k].setCurrentIndex(0) self.permutation_grid.addWidget(self.alternatives_rows[j][k], j, k + 2) add_header = False self.alternatives_rows[j][k + 1] = \ widgets.InputComboBox(self, c_type='question', form=j, alternative=self.question_list.\ currentItem().\ data(Qt.UserRole).toPyObject().\ get_question_number()) self.alternatives_rows[j][k + 1].addItems( \ [str(x) for x in range(1,total_questions)]) self.alternatives_rows[j][k + 1].setCurrentIndex(0) self.permutation_grid.addWidget(QLabel(_('Question Number')), j, k + 3) self.permutation_grid.addWidget(self.alternatives_rows[j][k + 1], j, k + 4) button_save = QPushButton(_('Save values')) self.permutation_grid.addWidget(button_save, j + 1, 1, 1, k + 4) button_save.clicked.connect(self._save_values) def _on_item_changed(self, arg=None): permutation = arg.data(Qt.UserRole).toPyObject().get_permutation() for k, v in self.alternatives_rows.iteritems(): for sk, sv in v.iteritems(): if not permutation: sv.setCurrentIndex(0) else: sv.setCurrentIndex( \ [x for x in permutation \ if (x['altr'] == sv.alternative and x['form'] == sv.form and x['c_type'] == sv.c_type)][0]['perm'] - 1) return True def _save_values(self): localItem = self.question_list.currentItem() formatted_grid = self._get_formatted_permutation_grid() if self._validate_grid(formatted_grid): localItem.setBackgroundColor(QColor(0, 255, 68)) localItem.data(Qt.UserRole).toPyObject()\ .set_permutation(formatted_grid) self._reset_permutation_grid() QMessageBox.information( self, _('Information status'), _('The values for the question have been successfully saved')) return True else: QMessageBox.critical(self, _('Error in grid'), _('There is an inconsistence in the options')) return False def _get_formatted_permutation_grid(self): local_alternatives_rows = [] for k, v in self.alternatives_rows.iteritems(): for sk, sv in v.iteritems(): alternative = { 'c_type': sv.c_type, 'form': sv.form, 'altr': sv.alternative, 'perm': sv.currentIndex() + 1 } local_alternatives_rows.append(alternative) return local_alternatives_rows def _validate_grid(self, grid): #validate current grid and questions number forms = {} for row in grid: if row['c_type'] == 'alternative': if row['form'] not in forms: forms[row['form']] = [] if row['perm'] in forms[row['form']]: return False else: forms[row['form']].append(row['perm']) if row['c_type'] == 'question': for i in xrange(self.question_list.count()): if i == self.question_list.currentRow(): continue perm = self.question_list.item(i).data(Qt.UserRole)\ .toPyObject().get_permutation() for perm_row in perm: if (perm_row['c_type'] == 'question' and perm_row['form'] == row['form'] and perm_row['perm'] == row['perm']): return False return True def _reset_permutation_grid(self): for k, v in self.alternatives_rows.iteritems(): for sk, sv in v.iteritems(): sv.setCurrentIndex(0) def _get_values(self): formated_permutation = {} formated_permutation_m = {} for i in xrange(self.question_list.count()): permutations = self.question_list.item(i).data(Qt.UserRole)\ .toPyObject().get_permutation() a = {} for p in permutations: if p['form'] not in formated_permutation: formated_permutation[p['form']] = [] if p['form'] not in a: a[p['form']] = [] if p['c_type'] == 'alternative': a[p['form']].append(p['perm']) if p['c_type'] == 'question': formated_permutation[p['form']].append( \ "%s{%s}" % (p['perm'], ','.join(str(x) \ for x in a[p['form']]))) for k, v in formated_permutation.iteritems(): formated_permutation_m[chr(97 + k).upper()] = '/'.join(v) return formated_permutation_m def validatePage(self): valid = True msg = '' for i in xrange(self.question_list.count()): if not self.question_list.item(i).data(Qt.UserRole)\ .toPyObject().get_permutation(): valid = False msg = _('You must select all permutations for all questions') break if not valid: QMessageBox.critical(self, _('Error'), msg) else: current_permutations = self._get_values() for k, v in current_permutations.iteritems(): self.wizard().exam_config.set_permutations(k, v) return valid def nextId(self): return WizardNewSession.PageIdFiles
class FiltersDialog(Window): def __init__(self, base): Window.__init__(self, base, i18n.get('filters')) self.setFixedSize(280, 360) self.expression = QLineEdit() self.expression.returnPressed.connect(self.__new_filter) self.new_button = QPushButton(i18n.get('add_filter')) self.new_button.setToolTip(i18n.get('create_a_new_filter')) self.new_button.clicked.connect(self.__new_filter) expression_box = QHBoxLayout() expression_box.addWidget(self.expression) expression_box.addWidget(self.new_button) self.list_ = QListWidget() self.list_.clicked.connect(self.__filter_clicked) self.delete_button = QPushButton(i18n.get('delete')) self.delete_button.setEnabled(False) self.delete_button.setToolTip(i18n.get('delete_selected_filter')) self.delete_button.clicked.connect(self.__delete_filter) self.clear_button = QPushButton(i18n.get('delete_all')) self.clear_button.setEnabled(False) self.clear_button.setToolTip(i18n.get('delete_all_filters')) self.clear_button.clicked.connect(self.__delete_all) button_box = QHBoxLayout() button_box.addStretch(1) button_box.addWidget(self.clear_button) button_box.addWidget(self.delete_button) layout = QVBoxLayout() layout.addLayout(expression_box) layout.addWidget(self.list_, 1) layout.addLayout(button_box) layout.setSpacing(5) layout.setContentsMargins(5, 5, 5, 5) self.setLayout(layout) self.__update() self.show() def __update(self): row = 0 self.expression.setText('') self.list_.clear() for expression in self.base.core.list_filters(): self.list_.addItem(expression) row += 1 self.__enable(True) self.delete_button.setEnabled(False) if row == 0: self.clear_button.setEnabled(False) self.expression.setFocus() def __filter_clicked(self, point): self.delete_button.setEnabled(True) self.clear_button.setEnabled(True) def __new_filter(self): expression = str(self.expression.text()) self.list_.addItem(expression) self.__save_filters() def __delete_filter(self): self.list_.takeItem(self.list_.currentRow()) self.__save_filters() def __delete_all(self): self.__enable(False) message = i18n.get('clear_filters_confirm') confirmation = self.base.show_confirmation_message(i18n.get('confirm_delete'), message) if not confirmation: self.__enable(True) return self.list_.clear() self.__save_filters() def __enable(self, value): self.list_.setEnabled(value) self.delete_button.setEnabled(value) self.clear_button.setEnabled(value) def __save_filters(self): filters = [] for i in range(self.list_.count()): filters.append(str(self.list_.item(i).text())) self.base.save_filters(filters) self.__update()
class Window(QtGui.QWidget): def __init__(self): QtGui.QWidget.__init__(self) self.media = Phonon.MediaObject(self) ### video widget #### self.video = Phonon.VideoWidget(self) self.video.setMinimumSize(320,200) self.videoCuts = [] self.myfilename = "" self.extension = "" self.t1 = "" self.t2 = "" self.t3 = "" self.t4 = "" self.t5 = "" self.t6 = "" ### open button ### self.button = QtGui.QPushButton('Choose Video', self) self.button.setFixedWidth(90) self.button.clicked.connect(self.handleButton) self.button.setStyleSheet(stylesheet(self)) ### context menu #### self.setContextMenuPolicy(Qt.CustomContextMenu) self.customContextMenuRequested.connect(self.popup2) ### play / pause button ### self.playbutton = QtGui.QPushButton('Play', self) self.playbutton.setFixedWidth(70) self.playbutton.clicked.connect(self.handlePlayButton) self.playbutton.setStyleSheet(stylesheet(self)) self.connect(QtGui.QShortcut(QtGui.QKeySequence(QtCore.Qt.Key_Space), self), QtCore.SIGNAL('activated()'), self.handlePlayButton) self.connect(QtGui.QShortcut(QtGui.QKeySequence("Ctrl+o"), self), QtCore.SIGNAL('activated()'), self.handleButton) self.connect(QtGui.QShortcut(QtGui.QKeySequence("Ctrl+s"), self), QtCore.SIGNAL('activated()'), self.handleSaveVideo) self.connect(QtGui.QShortcut(QtGui.QKeySequence("Ctrl+q"), self), QtCore.SIGNAL('activated()'), self.handleQuit) ### save button ### self.savebutton = QtGui.QPushButton('Save Video', self) self.savebutton.setFixedWidth(90) self.savebutton.clicked.connect(self.handleSaveVideo) self.savebutton.setStyleSheet(stylesheet(self)) ### seek slider ### self.slider = Phonon.SeekSlider(self.media) self.slider.setStyleSheet(stylesheet(self)) isize = QSize(16,16) self.slider.setIconSize(isize) self.slider.setFocus() # self.slider.connect(self.handleLabel) ### connection position to label ### self.media.isSeekable() self.media.tick.connect(self.handleLabel) self.media.seekableChanged.connect(self.handleLabel) #self.slider.wheel.connect(self.handleLabel) ### table view ### self.iconList = QListWidget() self.iconList.setAlternatingRowColors(True) self.iconList.setFixedWidth(200) self.iconList.setContextMenuPolicy(Qt.CustomContextMenu) self.iconList.setStyleSheet("QListWidget::item:selected:active { background: #7D8ED9; color:#FFFFFF; } ") self.iconList.setViewMode(0) self.iconList.setSelectionBehavior(1) self.iconList.setIconSize(QSize(80, 80/1.78)) self._hookListActions() self.iconList.customContextMenuRequested.connect(self._openListMenu) ### set start button ### self.startbutton = QtGui.QPushButton('set Start', self) self.startbutton.setFixedWidth(70) self.startbutton.clicked.connect(self.handleStartButton) self.startbutton.setStyleSheet(stylesheet(self)) self.connect(QtGui.QShortcut(QtGui.QKeySequence("s"), self), QtCore.SIGNAL('activated()'), self.handleStartButton) ### set end button ### self.endbutton = QtGui.QPushButton('set End', self) self.endbutton.setFixedWidth(70) self.endbutton.clicked.connect(self.handleEndButton) self.endbutton.setStyleSheet(stylesheet(self)) self.connect(QtGui.QShortcut(QtGui.QKeySequence("e"), self), QtCore.SIGNAL('activated()'), self.handleEndButton) ### label ### self.mlabel = QtGui.QLabel('Frame', self) self.mlabel.setStyleSheet('QLabel \ {background-color: transparent; color: white;}\nQLabel{color: darkcyan; font-size: 12px; background-color: transparent; border-radius: 5px; padding: 6px; text-align: center;}\n QLabel:hover{color: red;}') #self.mlabel.setFixedWidth(80) ### layout ### layout = QtGui.QGridLayout(self) layout.addWidget(self.iconList, 0, 0, 1, 1) layout.addWidget(self.video, 0, 1, 1, 6) layout.addWidget(self.slider, 1, 1, 1, 6) layout.addWidget(self.button, 2, 0, 1, 1) layout.addWidget(self.savebutton, 2, 1, 1, 1) layout.addWidget(self.playbutton, 2, 3, 1, 1) layout.addWidget(self.startbutton, 2, 5, 1, 1) layout.addWidget(self.endbutton, 2, 6, 1, 1) layout.addWidget(self.mlabel, 2, 4, 1, 1) def popup2(self, pos): contextmenu = QMenu() contextmenu.addAction("Play / Pause (SPACE)", self.handlePlayButton) contextmenu.addSeparator() contextmenu.addAction("Load Video (Ctrl-O)", self.handleButton) contextmenu.addAction("Save Video (Ctrl-S)", self.handleSaveVideo) contextmenu.addSeparator() contextmenu.addAction("Info", self.handleInfo) contextmenu.addSeparator() contextmenu.addAction("Exit (q)", self.handleQuit) contextmenu.exec_(QCursor.pos()) def handleInfo(self): msg = QMessageBox() #msg.setFixedSize(500, 300) #msg.setGeometry(100,100, 400, 200) msg.setIcon(QMessageBox.Information) msg.setText("Axel Schneider") msg.setInformativeText(unicode(u"©2016")) msg.setWindowTitle("Cut Video") msg.setDetailedText("Python Qt4") msg.setStandardButtons(QMessageBox.Ok) retval = msg.exec_() print "value of pressed message box button:", retval def handleQuit(self): app.quit() def handleButton(self): if self.media.state() == Phonon.PlayingState: self.media.stop() else: path = QtGui.QFileDialog.getOpenFileName(self, ("Video laden"), '/Axel_1/Filme', "Videos (*.ts *.mp4)") if path: self.myfilename = unicode(path) #.encode("utf-8") window.setWindowTitle(self.myfilename.split("/")[-1]) self.extension = path.split(".")[1] print(self.extension) self.media.setCurrentSource(Phonon.MediaSource(path)) self.video.setScaleMode(1) self.video.setAspectRatio(1) self.audio = Phonon.AudioOutput(Phonon.VideoCategory, self) Phonon.createPath(self.media, self.audio) Phonon.createPath(self.media, self.video) self.media.play() self.playbutton.setText('Pause') def handleSaveVideo(self): result = QFileDialog.getSaveFileName(self, ("Video speichern"), '/tmp/film.' + str(self.extension), "Videos (*.ts *.mp4)") if result: target = unicode(result) self.t1 = float(self.videoCuts[0]) self.t2 = float(self.videoCuts[1]) ffmpeg_extract_subclip(self.myfilename, self.t1, self.t2, targetname=target) window.setWindowTitle("Film gespeichert") self.purgeMarker() def handlePlayButton(self): if self.media.state() == Phonon.PlayingState: self.media.pause() self.playbutton.setText('Play') else: #print(self.iconList.count()) self.media.play() self.playbutton.setText('Pause') def handleStartButton(self): if self.iconList.count() < 2: rm = str(self.media.currentTime() / 100.00 / 10.00) item = QListWidgetItem() img = QImage(self.video.snapshot()) pix = QtGui.QPixmap.fromImage(img) item.setIcon(QIcon(pix)) item.setText("Start: " + rm) self.iconList.addItem(item) self.videoCuts.append(rm) else: return def handleEndButton(self): if self.iconList.count() < 2: rm = str(self.media.currentTime() / 100.00 / 10.00) item = QListWidgetItem() #item.setSizeHint(QSize(150, 40)) img = QImage(self.video.snapshot()) pix = QtGui.QPixmap.fromImage(img) item.setIcon(QIcon(pix)) item.setText("End: " + rm) self.iconList.addItem(item) self.videoCuts.append(rm) self.t3 = float(str(self.media.remainingTime())) print(self.t3) self.media.stop() self.playbutton.setText('Play') else: return def handleLabel(self): ms = self.media.currentTime() seconds=str((ms/1000)%60) minutes=str((ms/(1000*60))%60) hours=str((ms/(1000*60*60))%24) if int(seconds) < 10: seconds = "0" + seconds if int(minutes) < 10: minutes = "0" + minutes if int(hours) < 10: hours = "0" + hours s = hours + ":" + minutes + ":" + seconds self.mlabel.setText(s) def _hookListActions(self): #TOO bad-the list model -should be here... rmAction = QtGui.QAction(QtGui.QIcon('icons/close-x.png'), 'entfernen', self) rmAction.triggered.connect(self._removeMarker) rmAllAction = QtGui.QAction(QtGui.QIcon('icons/clear-all.png'), 'alle entfernen', self) rmAllAction.triggered.connect(self.purgeMarker) self.gotoAction = QtGui.QAction(QtGui.QIcon('icons/go-next.png'), 'zu dieser Position springen', self) self.gotoAction.triggered.connect(self._gotoFromMarker) #menus self._listMenu = QMenu() self._listMenu.addAction(self.gotoAction) self._listMenu.addSeparator() self._listMenu.addAction(rmAction) self._listMenu.addAction(rmAllAction) #---List widget context menu def _removeMarker(self,whatis): selectionList = self.iconList.selectedIndexes() if len(selectionList)==0: return item = selectionList[0] self.iconList.takeItem(item.row()) #self.videoCuts.remove[1]) def clearMarkerList(self): self.iconList.clear() #remove contents, remove file def purgeMarker(self): self.iconList.clear() self.videoCuts = [] def _gotoFromMarker(self,whatis): selectionList = self.iconList.selectedIndexes() if len(selectionList)==0: return item = selectionList[0] pos = item.data().toString().replace("Start: ", "").replace("End: ", "") #frame = pos.ToInt() #self.video.currentTime = 1589 self.setWindowTitle(pos) def _openListMenu(self,position): selectionList = self.iconList.selectedIndexes() if len(selectionList)==0: return self._listMenu.exec_(self.iconList.viewport().mapToGlobal(position))
def add_list_box(self, choicesL, name='isBell', init_val=3, layout=None, advance_n=True, fulldesc='Nozzle Geometry', connect_function=None, text_font=ARIAL_10, col=0, parent=None, fit_size_to_contents=True, width=1, height=1): # if parent is input, add widget to parent if parent is None: parent = self if layout is None: NRow = parent.get_next_row_number(advance_n) # Need to change next row number by length of choicesL #if advance_n: # for i in range(1, len(choicesL)): # parent.get_next_row_number(advance_n) self.selection_textD[name] = '' listWidget = QListWidget() for i,choice in enumerate( choicesL ): item = QListWidgetItem(choice) listWidget.addItem(item) if i == init_val: #item.setChecked(True) listWidget.setItemSelected( item, True ) self.selection_textD[name] = choice if fulldesc: vbox = QtGui.QVBoxLayout() lbl = QLabel(fulldesc, parent) lbl.setFont( text_font ) vbox.addWidget( lbl ) self.objectD['%s_listbox_label'%name] = lbl self.input_widget_by_nameD['%s_listbox_label'%name] = (lbl , 'label') vbox.addWidget( listWidget ) grid_child = QtGui.QWidget() grid_child.setLayout(vbox) vbox.addStretch(1) else: grid_child = listWidget if layout is None: if width==1 and height==1: parent.grid.addWidget(grid_child, NRow, col) else: parent.grid.addWidget(grid_child, NRow, col, height, width) #parent.grid.addWidget(grid_child, NRow, col, len(choicesL), 1) else: layout.addWidget( grid_child ) self.objectD['%s_list_box'%name] = listWidget self.input_widget_by_nameD[name] = (listWidget , 'list_box_list') listWidget.itemClicked.connect( lambda: self.list_box_changed( '%s_list_box'%name ) ) if fit_size_to_contents: listWidget.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) listWidget.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff) listWidget.setFixedSize(listWidget.sizeHintForColumn(0) + 2 * listWidget.frameWidth(), listWidget.sizeHintForRow(0) * listWidget.count() + \ 2 * listWidget.frameWidth())
class GroupSelectParameterWidget(GenericParameterWidget): """Widget class for Group Select Parameter.""" def __init__(self, parameter, parent=None): """Constructor. :param parameter: A GroupSelectParameter object. :type parameter: GroupSelectParameter """ QWidget.__init__(self, parent) self._parameter = parameter # Store spin box self.spin_boxes = {} # Create elements # Label (name) self.label = QLabel(self._parameter.name) # Layouts self.main_layout = QVBoxLayout() self.input_layout = QVBoxLayout() # _inner_input_layout must be filled with widget in the child class self.inner_input_layout = QVBoxLayout() self.radio_button_layout = QGridLayout() # Create radio button group self.input_button_group = QButtonGroup() # List widget self.list_widget = QListWidget() self.list_widget.setSelectionMode(QAbstractItemView.ExtendedSelection) self.list_widget.setDragDropMode(QAbstractItemView.DragDrop) self.list_widget.setDefaultDropAction(Qt.MoveAction) self.list_widget.setEnabled(False) self.list_widget.setSizePolicy( QSizePolicy.Maximum, QSizePolicy.Expanding) for i, key in enumerate(self._parameter.options): value = self._parameter.options[key] radio_button = QRadioButton(value.get('label')) self.radio_button_layout.addWidget(radio_button, i, 0) if value.get('type') == SINGLE_DYNAMIC: double_spin_box = QDoubleSpinBox() self.radio_button_layout.addWidget(double_spin_box, i, 1) double_spin_box.setValue(value.get('value', 0)) double_spin_box.setMinimum( value.get('constraint', {}).get('min', 0)) double_spin_box.setMaximum(value.get( 'constraint', {}).get('max', 1)) double_spin_box.setSingleStep( value.get('constraint', {}).get('step', 0.01)) step = double_spin_box.singleStep() if step > 1: precision = 0 else: precision = len(str(step).split('.')[1]) if precision > 3: precision = 3 double_spin_box.setDecimals(precision) self.spin_boxes[key] = double_spin_box # Enable spin box depends on the selected option if self._parameter.selected == key: double_spin_box.setEnabled(True) else: double_spin_box.setEnabled(False) elif value.get('type') == STATIC: static_value = value.get('value', 0) if static_value is not None: self.radio_button_layout.addWidget( QLabel(str(static_value)), i, 1) elif value.get('type') == MULTIPLE_DYNAMIC: selected_fields = value.get('value', []) if self._parameter.selected == key: self.list_widget.setEnabled(True) else: self.list_widget.setEnabled(False) self.input_button_group.addButton(radio_button, i) if self._parameter.selected == key: radio_button.setChecked(True) # Help text self.help_label = QLabel(self._parameter.help_text) self.help_label.setSizePolicy( QSizePolicy.Maximum, QSizePolicy.Expanding) self.help_label.setWordWrap(True) self.help_label.setAlignment(Qt.AlignTop) self.inner_input_layout.addLayout(self.radio_button_layout) self.inner_input_layout.addWidget(self.list_widget) # Put elements into layouts self.input_layout.addWidget(self.label) self.input_layout.addLayout(self.inner_input_layout) self.help_layout = QVBoxLayout() self.help_layout.addWidget(self.help_label) self.main_layout.addLayout(self.input_layout) self.main_layout.addLayout(self.help_layout) self.setLayout(self.main_layout) self.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Expanding) # Update list widget self.update_list_widget() # Connect signal self.input_button_group.buttonClicked.connect( self.radio_buttons_clicked) def get_parameter(self): """Obtain list parameter object from the current widget state. :returns: A DefaultValueParameter from the current state of widget :rtype: DefaultValueParameter """ # Set value for each key for key, value in self._parameter.options.items(): if value.get('type') == STATIC: continue elif value.get('type') == SINGLE_DYNAMIC: new_value = self.spin_boxes.get(key).value() self._parameter.set_value_for_key(key, new_value) elif value.get('type') == MULTIPLE_DYNAMIC: # Need to iterate through all items items = [] for index in xrange(self.list_widget.count()): items.append(self.list_widget.item(index)) new_value = [i.text() for i in items] self._parameter.set_value_for_key(key, new_value) # Get selected radio button radio_button_checked_id = self.input_button_group.checkedId() # No radio button checked, then default value = None if radio_button_checked_id == -1: self._parameter.selected = None else: self._parameter.selected = self._parameter.options.keys()[ radio_button_checked_id] return self._parameter def update_list_widget(self): """Update list widget when radio button is clicked.""" # Get selected radio button radio_button_checked_id = self.input_button_group.checkedId() # No radio button checked, then default value = None if radio_button_checked_id > -1: selected_dict = self._parameter.options.values()[ radio_button_checked_id] if selected_dict.get('type') == MULTIPLE_DYNAMIC: for field in selected_dict.get('value'): # Update list widget field_item = QListWidgetItem(self.list_widget) field_item.setFlags( Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsDragEnabled) field_item.setData(Qt.UserRole, field) field_item.setText(field) self.list_widget.addItem(field_item) def radio_buttons_clicked(self): """Handler when selected radio button changed.""" # Disable all spin boxes for spin_box in self.spin_boxes.values(): spin_box.setEnabled(False) # Disable list widget self.list_widget.setEnabled(False) # Get selected radio button radio_button_checked_id = self.input_button_group.checkedId() if radio_button_checked_id > -1: selected_value = self._parameter.options.values()[ radio_button_checked_id] if selected_value.get('type') == MULTIPLE_DYNAMIC: # Enable list widget self.list_widget.setEnabled(True) elif selected_value.get('type') == SINGLE_DYNAMIC: selected_key = self._parameter.options.keys()[ radio_button_checked_id] self.spin_boxes[selected_key].setEnabled(True) def select_radio_button(self, key): """Helper to select a radio button with key. :param key: The key of the radio button. :type key: str """ key_index = self._parameter.options.keys().index(key) radio_button = self.input_button_group.button(key_index) radio_button.click()
class MainWindow(QMainWindow): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.setWindowTitle('Address Book') self.resize(704, 459) self.db_file = self.database_file() self.db = database.Database(self.db_file) dialog = dialogs.UserPanelDlg(self) if dialog.exec_(): self.user = dialog.user else: self.close() self.categComboBox = QComboBox() self.cont_numLabel = QLabel() self.contactsListWidget = QListWidget() self.searchLineEdit = QLineEdit() widgets = ((QLabel('Category:'), self.categComboBox), (self.cont_numLabel, None), (self.contactsListWidget,), (QLabel('Search:'), self.searchLineEdit)) vlayout1 = QVBoxLayout() for i in widgets: hlayout = pyqttools.add_to_layout(QHBoxLayout(), i) vlayout1.addLayout(hlayout) addToolButton = QToolButton() addToolButton.setIcon(QIcon(':addcontact.jpeg')) addToolButton.setIconSize(QSize(45, 45)) self.showLabel = QLabel() self.showLabel.setFrameShape(QFrame.StyledPanel) self.showLabel.setAlignment(Qt.AlignLeading|Qt.AlignLeft|Qt.AlignTop) self.editButton = QPushButton('Edit') self.delButton = QPushButton('Delete') widgets = ((None, addToolButton, None), (self.showLabel,), (None, self.editButton, self.delButton)) vlayout2 = QVBoxLayout() for i in widgets: hlayout = pyqttools.add_to_layout(QHBoxLayout(), i) vlayout2.addLayout(hlayout) f_layout = pyqttools.add_to_layout(QHBoxLayout(), (vlayout1, vlayout2)) Widget = QWidget() Widget.setLayout(f_layout) self.setCentralWidget(Widget) self.statusBar = self.statusBar() self.userLabel = QLabel() self.statusBar.addPermanentWidget(self.userLabel) c_action = pyqttools.create_action panelAction = c_action(self, 'User panel', triggered=self.user_panel) quitAction = c_action(self, 'Quit', 'Ctrl+Q',triggered=self.close) add_contactAction = c_action(self, 'Add contact', 'Ctrl+N', triggered=self.add_contact) delete_allAction = c_action(self, 'Delete all contacts', triggered=self.delete_all) delete_categAction = c_action(self, 'Delete categories', triggered=self.delete_categories) backupAction = c_action(self, 'Backup', triggered=self.backup) restoreAction = c_action(self, 'Restore', triggered=self.restore) aboutAction = c_action(self, 'About', 'Ctrl+?', triggered=self.about) fileMenu = self.menuBar().addMenu('File') contactsMenu = self.menuBar().addMenu('Contacts') deleteMenu = self.menuBar().addMenu(self.tr('Delete')) backupMenu = self.menuBar().addMenu(self.tr('Backup')) helpMenu = self.menuBar().addMenu('Help') pyqttools.add_actions(fileMenu, [panelAction, None, quitAction]) pyqttools.add_actions(contactsMenu, [add_contactAction]) pyqttools.add_actions(deleteMenu,[delete_allAction,delete_categAction]) pyqttools.add_actions(backupMenu, [backupAction, restoreAction]) pyqttools.add_actions(helpMenu, [aboutAction]) addToolButton.clicked.connect(self.add_contact) self.editButton.clicked.connect(self.edit_contact) self.delButton.clicked.connect(self.delete_contact) self.categComboBox.currentIndexChanged.connect(self.fill_ListWidget) self.contactsListWidget.currentRowChanged.connect(self.show_contact) self.searchLineEdit.textEdited.connect(self.search) self.fill_categComboBox() self.refresh_userLabel() def fill_categComboBox(self): categories = ['All'] categories.extend([i[1] for i in self.db.get_categories(self.user)]) self.categComboBox.currentIndexChanged.disconnect(self.fill_ListWidget) self.categComboBox.clear() self.categComboBox.addItems(categories) self.categComboBox.currentIndexChanged.connect(self.fill_ListWidget) self.fill_ListWidget() def fill_ListWidget(self): self.showLabel.clear() self.contactsListWidget.clear() if self.categComboBox.currentIndex() != 0: self.searchLineEdit.clear() category = self.categComboBox.currentText() if category == 'All': contacts = self.db.get_all_contacts(self.user) else: categ_id = self.db.get_category_id(category, self.user) if categ_id is None: return contacts = self.db.get_contacts(categ_id) for i in contacts: self.contactsListWidget.addItem(MyListItem(i[1]+' '+i[2], i[0])) self.contactsListWidget.setCurrentRow(0) self.refresh_contacts_number() self.set_buttons_enabled() def refresh_userLabel(self): self.userLabel.setText('User: '******'Contacts Numer: {0}'.format(self.contactsListWidget.count()) self.cont_numLabel.setText(text) def set_buttons_enabled(self): enable = bool(self.contactsListWidget) self.editButton.setEnabled(enable) self.delButton.setEnabled(enable) def user_panel(self): dialog = dialogs.UserPanelDlg(self) if dialog.exec_(): self.user = dialog.user self.fill_categComboBox() self.refresh_userLabel() def show_contact(self): try: _id = self.contactsListWidget.currentItem()._id except AttributeError: return _id, name, surname, mail, address, tel, categ_id = \ self.db.get_contact_from_id(_id)[0] category = self.db.get_category_from_id(categ_id) text = '' data = (name, surname, mail, address, tel, category) labs = ('Name', 'Surname', 'e-mail', 'Address', 'Telephone', 'Category') for i, y in zip(labs, data): text += '''<p style=\' margin-top:0px; margin-bottom:0px; \'> <span style=\' font-weight:600;\'>{0}:</span> {1} </p>\n'''\ .format(i, y) self.showLabel.setText(text) def add_contact(self): categories = [i[1] for i in self.db.get_categories(self.user)] dialog = dialogs.AddorEditContactDlg(categories) if dialog.exec_(): data = dialog.values if data[-1] not in categories: self.db.addto_categories(data[-1], self.user) categ_id = self.db.get_category_id(data[-1], self.user) data[-1] = categ_id self.db.addto_contacts(data) self.fill_categComboBox() def edit_contact(self): _id = self.contactsListWidget.currentItem()._id data = list(self.db.get_contact_from_id(_id)[0]) categ = self.db.get_category_from_id(data[-1]) data[-1] = categ categories = [i[1] for i in self.db.get_categories(self.user)] dialog = dialogs.AddorEditContactDlg(categories, True, data) if dialog.exec_(): new_data = dialog.values if new_data[-1] not in categories: self.db.addto_categories(new_data[-1], self.user) categ_id = self.db.get_category_id(new_data[-1], self.user) new_data[-1] = categ_id self.db.edit_contact(new_data, _id) self.fill_categComboBox() def delete_contact(self): reply = QMessageBox.question(self, 'Address Book - Delete Contact', 'Are you sure that you want to delete this contact?', QMessageBox.Yes|QMessageBox.Cancel) if reply == QMessageBox.Yes: _id = self.contactsListWidget.currentItem()._id self.db.delete_contact(_id) self.fill_ListWidget() def delete_all(self): reply = QMessageBox.question(self, 'Address Book - Delete Contact', 'Are you sure that you want to delete all contacts?', QMessageBox.Yes|QMessageBox.Cancel) if reply == QMessageBox.Yes: self.db.delete_all_contacts() self.fill_ListWidget() def delete_categories(self): categories = [i[1] for i in self.db.get_categories(self.user)] dialogs.DelCategoriesDlg(categories, self).exec_() self.fill_categComboBox() def search(self): self.categComboBox.setCurrentIndex(0) self.showLabel.clear() self.contactsListWidget.clear() txt = self.searchLineEdit.text() if all(i == ' ' for i in txt): self.fill_ListWidget() return must_appear = [] contacts = self.db.get_all_contacts(self.user) if not ' ' in txt: for i in contacts: if txt.lower() in i[1].lower() or txt.lower() in i[2].lower(): must_appear.append(i) else: try: first, last = txt.split() except ValueError: return for i in contacts: _bool = bool(first.lower() in i[1].lower() or first.lower() in i[2].lower() or last.lower() in i[1].lower() or last.lower() in i[2].lower()) if _bool: must_appear.append(i) for i in must_appear: item = MyListItem(i[1] + ' ' + i[2], i[0]) self.contactsListWidget.addItem(item) self.contactsListWidget.setCurrentRow(0) self.refresh_contacts_number() self.set_buttons_enabled() def backup(self): fname = QFileDialog.getSaveFileName(self,'Address Book - Backup','.db') if fname: try: shutil.copy(self.db_file, fname) except IOError: pass def restore(self): reply = QMessageBox.question(self, 'Address Book - Restore', 'All current contacts will be deleted.\nAre you sure that you want' ' to continue?', QMessageBox.Yes|QMessageBox.Cancel) if reply == QMessageBox.Yes: fname = QFileDialog.getOpenFileName(self, 'Address Book - Restore') if fname: msg = 'Succesful restore!' try: os.remove(self.db_file) shutil.copy(fname, self.db_file) except (OSError, IOError): msg = 'Restore failed!' QMessageBox.information(self, 'Addess Book - Restore', msg) self.db = database.Database(self.db_file) self.fill_categComboBox() def database_file(self): _file = 'addressbook.db' if not platform.platform().startswith('Windows'): folder = os.getenv('HOME') + os.sep + '.addressbook' if not os.path.exists(folder): os.mkdir(folder) _file = folder + os.sep + _file return _file def about(self): link = 'http://wiki.ubuntu-gr.org/Address%20Book' QMessageBox.about(self, self.tr('About') + ' FF Multi Converter', '''<b> Address Book {0} </b> <p>Gui application to organize your contacts! <p>Copyright © 2012 Ilias Stamatis <br>License: GNU GPL3 <p><a href='{1}'>http://wiki.ubuntu-gr.org/Address Book</a> <p>Python {2} - Qt {3} - PyQt {4} on {5}''' .format(__version__, link, platform.python_version()[:5], QT_VERSION_STR, PYQT_VERSION_STR, platform.system())) def close(self): self.db.close() sys.exit()
class ImportDataDlg(QDialog): __isJy = False # 数据校验成功的标志 __mlist = [] # 定义一个列表用于保存从excel表中取出的数据 def __init__(self, iface, parent=None, impType=ImpDateType.SITEANDCELL): super(ImportDataDlg, self).__init__() self.iface = iface self.parent = parent self.impType = impType self.initView() def initView(self): if self.impType == ImpDateType.SERVINGCELL: self.setWindowTitle(u'相邻小区数据导入') else: self.setWindowTitle(u'基站和小区数据导入') self.setWindowIcon(QIcon('images/logo.png')) self.resize(620, 480) # 数据表格 self.tableWidget = QTableWidget(self) self.tableWidget.setAlternatingRowColors(True) self.tableWidget.setRowCount(7) # 设置当前Table不能编辑 self.tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers) # 初始化表格上下文菜单 self.initTableContextMenu() # 初始化表头 self.initTableHeader() # 导入出错列表 self.listWidget = QListWidget(self) # 按钮组 impBtn = QPushButton(u"导入EXCEL表", self) yzBtn = QPushButton(u"数据检验", self) impdateBtn = QPushButton(u"导入数据", self) btnVBox = QVBoxLayout() btnVBox.addWidget(impBtn) btnVBox.addWidget(yzBtn) btnVBox.addWidget(impdateBtn) # 错误列表与按钮组 hBox = QHBoxLayout() hBox.setMargin(20) hBox.addWidget(self.listWidget) hBox.addLayout(btnVBox) self.mbar = QStatusBar(self) self.mbar.showMessage(u'准备就绪...') self.maction = QToolBar(self) self.editAction = QAction(u'编辑', self.maction) self.editAction.setCheckable(True) self.combox = QComboBox(self) self.combox.addItems(HeadsConfig.ImpExcelName) self.maction.addWidget(self.combox) self.maction.addAction(self.editAction) vBox = QVBoxLayout() vBox.addWidget(self.maction) vBox.addWidget(self.tableWidget) vBox.addLayout(hBox) vBox.addWidget(self.mbar) vBox.setStretchFactor(self.tableWidget, 9) vBox.setStretchFactor(hBox, 5) vBox.setStretchFactor(self.mbar, 1) self.setLayout(vBox) QObject.connect(impBtn, SIGNAL('clicked()'), self.impClick) QObject.connect(yzBtn, SIGNAL('clicked()'), self.yzClick) QObject.connect(impdateBtn, SIGNAL('clicked()'), self.impdateClick) QObject.connect(self.editAction, SIGNAL('triggered()'), self.editClick) QObject.connect(self.combox, SIGNAL('currentIndexChanged(int)'), self.comboxChange) self.listWidget.doubleClicked.connect(self.mlistClicked) # self.connect(self.listWidget, SIGNAL("itemDoubleClicked (QListWidgetItem)"), self.mlistClicked) def initTableContextMenu(self): self.tableWidget.setContextMenuPolicy(Qt.CustomContextMenu) self.popMenu = QMenu(self.tableWidget) delAction = QAction(u'删除', self) # 删除 self.popMenu.addAction(delAction) # 设置表格可以双击修改数据 def setEditTriggers(self, isTrigger): if isTrigger: self.tableWidget.setEditTriggers(QAbstractItemView.DoubleClicked) else: self.tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers) # 提供给外部修改状态栏消息 def setStatusBarMsg(self, msg): self.mbar.showMessage(msg) # 选框改变时,清空当前表格的全部内容,包括表格头 def updateType(self, mtype): self.impType = mtype self.tableWidget.clear() # 清空表格所有内容 self.initTableHeader() # 初始化表格的每个Item def initTable(self, mlist): self.tableWidget.setRowCount(len(mlist)) for (i, v) in enumerate(mlist): for (j, item) in enumerate(v): if type(item) != str: item = unicode(item) if item == None: item = u"" tabItem = QTableWidgetItem(item) tabItem.setTextAlignment(Qt.AlignCenter) self.tableWidget.setItem(i, j, tabItem) # 初始化错误信息列表 def initListView(self, mlist): for iv in mlist: lisItm = QListWidgetItem(self.listWidget) lisItm.setTextColor(Qt.red) lisItm.setData(Qt.UserRole, iv) if isinstance(iv, basestring): # 如果错误信息是一行字符串 lisItm.setText(iv) else: lisItm.setText(u'第' + unicode(str(iv['row'] + 1)) + u'行,第' + unicode(str(iv['col'] + 1)) + u'列:' + iv['msg']) # 初始化Table的头 def initTableHeader(self): self.heads = [] if self.impType == ImpDateType.SITEANDCELL: # 获取当前项目图层的字段名 cell_layer = getLayerByName(u"小区", self.iface) for head in HeadsConfig.SiteANDCellHead: self.heads.append(head) if len(cell_layer.pendingFields()) > 55: for (index, field) in enumerate(cell_layer.pendingFields()): if index > 54: field_name = field.name().strip() self.heads.append(field_name) else: self.heads = HeadsConfig.ServingCellHead self.tableWidget.setColumnCount(len(self.heads)) # 设置表格的列数 for (i, h) in enumerate(self.heads): tabItem = QTableWidgetItem(h) self.tableWidget.setHorizontalHeaderItem(i, tabItem) # 自定义为Table添加Item def addTableItem(self, row, col, content): tabItem = QTableWidgetItem(content) self.tableWidget.setItem(row, col, tabItem) # 修改Item的内容 def editTableItem(self, row, col, content): tabItem = self.tableWidget.item(row, col) tabItem.setText(content) self.tableWidget.setItem(row, col, tabItem) # 从Excel表读取数据(导入Excel表) def impClick(self): fileName = QFileDialog.getOpenFileName(self, u'基站小区数据导入', '/', 'Excel Files (*.xls *.xlsx)') if fileName.strip() != "": self.setStatusBarMsg(u'选择完毕:' + fileName) importData = GetDataFromExcel(fileName, self.impType, self.heads) self.__mlist = [] self.__mlist.extend(importData.getData()) self.tableWidget.clearContents() self.listWidget.clear() self.initTable(self.__mlist) self.setStatusBarMsg(u'数据导入完成...') self.__isJy = False # 导入完数据后,说明需要重新验证数据的正确性 else: QMessageBox.information(self.parent, u"错误", u"请选中文件") # 数据验证按钮点击事件处理 def yzClick(self): if len(self.__mlist) > 0: self.erlist = [] # 定义一个列表用于保存数据验证错误的数据 # 清楚全部的Item if self.listWidget.count() > 0: self.listWidget.clear() # 根据tableWidget更新self.__mlist for (r, items) in enumerate(self.__mlist): for (v, item) in enumerate(self.__mlist[r]): if self.tableWidget.item(r, v).text() == u"": continue else: # 跟据self.__mlist[r][v]数据类型进行比对 if type(self.__mlist[r][v]) == int: if unicode(self.__mlist[r][v]) != ( self.tableWidget.item(r, v).text()): self.__mlist[r][v] = int( self.tableWidget.item(r, v).text()) elif type(self.__mlist[r][v]) == float: if unicode(self.__mlist[r][v]) != ( self.tableWidget.item(r, v).text()): self.__mlist[r][v] = float( self.tableWidget.item(r, v).text()) elif type(self.__mlist[r][v]) == str: if unicode(self.__mlist[r][v] ) != self.tableWidget.item(r, v).text(): self.__mlist[r][v] = str( self.tableWidget.item(r, v).text()) elif type(self.__mlist[r][v]) == unicode: if (self.__mlist[r][v]) != self.tableWidget.item( r, v).text(): self.__mlist[r][v] = self.tableWidget.item( r, v).text() else: print type(self.__mlist[r][v]) # 执行数据校验函数 self.erlist = checkDataByDataType(self.__mlist, self.impType) if len(self.erlist) > 0: self.initListView(self.erlist) QMessageBox.information(self.parent, u'数据校验', u'数据校验失败,请检查数据正确性后,再导入到地图中') self.__isJy = False else: QMessageBox.information(self.parent, u'数据校验', u'数据校验成功,没有错误数据') self.__isJy = True else: QMessageBox.warning(self.parent, u'数据校验', u'请先导入Excel数据后再操作!') # 导入数据到地图中 def impdateClick(self): if self.__isJy: # 如果数据校验成功 if self.impType == ImpDateType.SITEANDCELL: # 导入基站小区 importDataToLayer = ImportDataToLayer(self.iface, self.__mlist, self.parent) if importDataToLayer.importSiteAndCellData(): QMessageBox.information(self.parent, u"导入数据", u"导入数据成功!") else: QMessageBox.critical(self.parent, u"导入数据", u"导入数据失败!") else: # 导入相邻小区 importDataToLayer = ImportDataToLayer(self.iface, self.__mlist, self.parent) if importDataToLayer.importSCellData(): QMessageBox.information(self.parent, u"导入数据", u"导入数据成功!") else: QMessageBox.critical(self.parent, u"导入数据", u"导入数据失败!") else: QMessageBox.warning(self.parent, u'数据导入', u'请确保校验数据成功后,再导入到地图中') # 编辑Action点击事件 def editClick(self): self.setEditTriggers(self.editAction.isChecked()) # 错误列表双击事件处理 def mlistClicked(self, listItem): itemData = listItem.data(Qt.UserRole) self.tableWidget.setFocus() self.tableWidget.setCurrentCell(itemData['row'], itemData['col']) # 选框改变事件 def comboxChange(self, index): self.updateType(index) # 字段验证是否为空 def __validNull(self, name, col, row, itm, rowitm): if itm is None or itm == '': tmpMap = {} tmpMap['col'] = col tmpMap['row'] = row tmpMap['msg'] = unicode(name) + u'不能为空' tmpMap['item'] = rowitm return tmpMap else: return None # 导入数据线程开始信号 绑定函数 def impStart(self): self.setStatusBarMsg(u'准备导入...') # 导入数据线程发生异常信号 绑定函数 def impError(self, e, exception_string): self.setStatusBarMsg(u'发生错误:' + unicode(e)) QMessageBox.warning(self.parent, u'Excel数据导入', u'发生错误:' + unicode(e)) # 导入数据线程完成信号 绑定函数 def impFinish(self, mylist): self.__mlist = [] self.__mlist.extend(mylist) self.mthread.quit() self.mthread.wait() self.mthread.deleteLater() self.impDateThread.deleteLater() self.tableWidget.clearContents() self.listWidget.clear() self.initTable(self.__mlist) self.setStatusBarMsg(u'数据导入完成...') self.__isJy = False # 导入完数据后,说明需要重新验证数据的正确性 # 导入数据到地图线程发生异常信号 绑定函数 def impError1(self, e, exception_string): self.setStatusBarMsg(u"导入数据发生错误") QMessageBox.critical(self, u'数据导入', u"发生错误:" + unicode(e)) # 导入数据到地图线程完成信号 绑定函数 def impFinish1(self, mylist): self.threadImp.quit() self.threadImp.wait() self.threadImp.deleteLater() self.impFeatureThread.deleteLater() remsg = u'数据导入完成!' layer = None if self.impType == LayerType.SITE: # remsg = u'基站' + remsg layer = getLayerByName(u'基站', self.iface) elif self.impType == LayerType.CELL: # remsg = u'小区' + remsg layer = getLayerByName(u'小区', self.iface) else: remsg = u'相邻小区' + remsg layer = getLayerByName(u'相邻小区', self.iface) self.setStatusBarMsg(remsg) layer.updateExtents() # 更新地图数据 self.iface.actionDraw().trigger() QMessageBox.information(self, u'数据导入', remsg) merlist = [] for eritm in self.erlist: merlist.append(eritm['item']) self.tableWidget.clearContents() # 先清楚表格的内容,再将错误的行显示到表格中 self.initTable(merlist)
class CodeCompletionWidget(QFrame): def __init__(self, editor): super(CodeCompletionWidget, self).__init__( None, Qt.FramelessWindowHint | Qt.ToolTip) self._editor = editor self._revision = 0 self._block = 0 self.stack_layout = QStackedLayout(self) self.stack_layout.setContentsMargins(0, 0, 0, 0) self.stack_layout.setSpacing(0) self.completion_list = QListWidget() self.completion_list.setMinimumHeight(200) self.completion_list.setAlternatingRowColors(True) self._list_index = self.stack_layout.addWidget(self.completion_list) self._icons = {'a': resources.IMAGES['attribute'], 'f': resources.IMAGES['function'], 'c': resources.IMAGES['class'], 'm': resources.IMAGES['module']} self.cc = code_completion.CodeCompletion() self._completion_results = {} self._prefix = u'' self.setVisible(False) self.source = '' self._key_operations = { Qt.Key_Up: self._select_previous_row, Qt.Key_Down: self._select_next_row, Qt.Key_PageUp: (lambda: self._select_previous_row(6)), Qt.Key_PageDown: (lambda: self._select_next_row(6)), Qt.Key_Right: lambda: None, Qt.Key_Left: lambda: None, Qt.Key_Enter: self.pre_key_insert_completion, Qt.Key_Return: self.pre_key_insert_completion, Qt.Key_Tab: self.pre_key_insert_completion, Qt.Key_Space: self.hide_completer, Qt.Key_Escape: self.hide_completer, Qt.Key_Backtab: self.hide_completer, Qt.NoModifier: self.hide_completer, Qt.ShiftModifier: self.hide_completer, } self.desktop = QApplication.instance().desktop() self.connect(self.completion_list, SIGNAL("itemClicked(QListWidgetItem*)"), self.pre_key_insert_completion) self.connect(self._editor.document(), SIGNAL("cursorPositionChanged(QTextCursor)"), self.update_metadata) def _select_next_row(self, move=1): new_row = self.completion_list.currentRow() + move if new_row < self.completion_list.count(): self.completion_list.setCurrentRow(new_row) else: self.completion_list.setCurrentRow(0) return True def _select_previous_row(self, move=1): new_row = self.completion_list.currentRow() - move if new_row >= 0: self.completion_list.setCurrentRow(new_row) else: self.completion_list.setCurrentRow( self.completion_list.count() - move) return True def update_metadata(self, cursor): if settings.CODE_COMPLETION: if self._editor.document().revision() != self._revision and \ cursor.block().blockNumber() != self._block: source = self._editor.get_text() source = source.encode(self._editor.encoding) self.cc.analyze_file(self._editor.ID, source) self._revision = self._editor.document().revision() self._block = cursor.block().blockNumber() def insert_completion(self, insert, type_=ord('a')): if insert != self._prefix: closing = '' if type_ in (ord('f'), ord('c')): closing = '()' extra = len(self._prefix) - len(insert) insertion = '%s%s' % (insert[extra:], closing) self._editor.textCursor().insertText(insertion) self.hide_completer() def _get_geometry(self): cr = self._editor.cursorRect() desktop_geometry = self.desktop.availableGeometry(self._editor) point = self._editor.mapToGlobal(cr.topLeft()) cr.moveTopLeft(point) #Check new position according desktop geometry width = (self.completion_list.sizeHintForColumn(0) + self.completion_list.verticalScrollBar().sizeHint().width() + 10) height = 200 orientation = (point.y() + height) < desktop_geometry.height() if orientation: cr.moveTop(cr.bottom()) cr.setWidth(width) cr.setHeight(height) if not orientation: cr.moveBottom(cr.top()) xpos = desktop_geometry.width() - (point.x() + width) if xpos < 0: cr.moveLeft(cr.left() + xpos) return cr def complete(self, results): self.add_list_items(results) self.completion_list.setCurrentRow(0) cr = self._get_geometry() self.setGeometry(cr) self.completion_list.updateGeometries() self.show() def add_list_items(self, proposals): self.completion_list.clear() for p in proposals: self.completion_list.addItem( QListWidgetItem( QIcon(self._icons.get(p[0], resources.IMAGES['attribute'])), p[1], type=ord(p[0]))) def set_completion_prefix(self, prefix, valid=True): self._prefix = prefix proposals = [] proposals += [('m', item) for item in self._completion_results.get('modules', []) if item.startswith(prefix)] proposals += [('c', item) for item in self._completion_results.get('classes', []) if item.startswith(prefix)] proposals += [('a', item) for item in self._completion_results.get('attributes', []) if item.startswith(prefix)] proposals += [('f', item) for item in self._completion_results.get('functions', []) if item.startswith(prefix)] if proposals and valid: self.complete(proposals) else: self.hide_completer() def _invalid_completion_position(self): result = False cursor = self._editor.textCursor() cursor.movePosition(QTextCursor.StartOfLine, QTextCursor.KeepAnchor) selection = unicode(cursor.selectedText())[:-1].split(' ') if len(selection) == 0 or selection[-1] == '' or \ selection[-1].isdigit(): result = True return result def fill_completer(self, force_completion=False): if not force_completion and (self._editor.cursor_inside_string() or self._editor.cursor_inside_comment() or self._invalid_completion_position()): return source = self._editor.get_text() source = source.encode(self._editor.encoding) offset = self._editor.textCursor().position() results = self.cc.get_completion(source, offset) self._completion_results = results if force_completion: cursor = self._editor.textCursor() cursor.movePosition(QTextCursor.StartOfWord, QTextCursor.KeepAnchor) prefix = cursor.selectedText() else: prefix = self._editor._text_under_cursor() self.set_completion_prefix(prefix) def hide_completer(self): self._prefix = '' self.hide() def pre_key_insert_completion(self): type_ = ord('a') current = self.completion_list.currentItem() insert = unicode(current.text()) if not insert.endswith(')'): type_ = current.type() self.insert_completion(insert, type_) self.hide_completer() return True def process_pre_key_event(self, event): if not self.isVisible() or self._editor.lang != "python": return False skip = self._key_operations.get(event.key(), lambda: False)() self._key_operations.get(event.modifiers(), lambda: False)() if skip is None: skip = False return skip def process_post_key_event(self, event): if not settings.CODE_COMPLETION or self._editor.lang != "python": return if self.isVisible(): source = self._editor.get_text() source = source.encode(self._editor.encoding) offset = self._editor.textCursor().position() prefix, valid = self.cc.get_prefix(source, offset) self.set_completion_prefix(prefix, valid) self.completion_list.setCurrentRow(0) force_completion = (event.key() == Qt.Key_Space and event.modifiers() == Qt.ControlModifier) if event.key() == Qt.Key_Period or force_completion: self.fill_completer(force_completion)
class NewSessionPagePermutations(QWizardPage): def __init__(self): super(NewSessionPagePermutations, self).__init__() self.setTitle(_('Configuration of permutations')) self.setSubTitle(_('Select the position of each question' ' and its choices in every model of the exam.')) layout = QGridLayout() self.question_list = QListWidget() self.permutation_grid = QGridLayout() self.alternatives_rows = {} layout.addWidget(QLabel(_('Questions of model A')), 0, 0, 1, 1) layout.addWidget(self.question_list, 1, 0, 1, 1) layout.addWidget(QLabel(_('Model equivalence')), 0, 1, 1, 5) self.permutation_grid.setVerticalSpacing(20) layout.addLayout(self.permutation_grid, 1, 1, 1, 5) layout.setColumnStretch(0, 1) layout.setColumnStretch(1, 5) self.setLayout(layout) def initializePage(self): paramNAlts = int(self.field("paramNAlts").toString()) paramNPerm = int(self.field("paramNPerm").toString()) self.question_list.clear() # Creation of the list section paramNCols_array = self.field("paramNCols").toString().split(',') total_questions = 1 + (int(paramNCols_array[0]) \ if len(paramNCols_array) == 1 \ else reduce(lambda x, y: int(x) + int(y), paramNCols_array)) for i in range(1,total_questions): questions_list = QListWidgetItem(_('Question ') + str(i)) questions_list.setData(Qt.UserRole, widgets.ItemList(optionName=_('Question ') + str(i), optionNumber=i)) # Custom item list self.question_list.addItem(questions_list) self.question_list.setCurrentRow(0) self.question_list.itemClicked.connect(self._on_item_changed) # Creation of the grid section add_header = True # Header of the columns (Name of alternatives) for j in range(0, paramNPerm): self.permutation_grid.addWidget( \ QLabel(_('Model ') + chr(97 + j).upper()), j, 1) self.alternatives_rows[j] = {} for k in range(0, paramNAlts): if add_header: if k == 0: self.permutation_grid.addWidget(QLabel(''), 0, 1) self.permutation_grid.addWidget( \ QLabel(chr(97 + k).upper()), 0, k + 2) self.alternatives_rows[j][k] = \ widgets.InputComboBox(self, c_type='alternative', form=j, alternative=k) self.alternatives_rows[j][k].addItems( \ [chr(97+x).upper() for x in range(0,paramNAlts)]) self.alternatives_rows[j][k].setCurrentIndex(0) self.permutation_grid.addWidget(self.alternatives_rows[j][k], j, k + 2) add_header = False self.alternatives_rows[j][k + 1] = \ widgets.InputComboBox(self, c_type='question', form=j, alternative=self.question_list.\ currentItem().\ data(Qt.UserRole).toPyObject().\ get_question_number()) self.alternatives_rows[j][k + 1].addItems( \ [str(x) for x in range(1,total_questions)]) self.alternatives_rows[j][k + 1].setCurrentIndex(0) self.permutation_grid.addWidget(QLabel(_('Question Number')), j, k + 3) self.permutation_grid.addWidget(self.alternatives_rows[j][k + 1], j, k + 4) button_save = QPushButton(_('Save values')) self.permutation_grid.addWidget(button_save, j + 1, 1, 1, k + 4) button_save.clicked.connect(self._save_values) def _on_item_changed(self, arg=None): permutation = arg.data(Qt.UserRole).toPyObject().get_permutation() for k, v in self.alternatives_rows.iteritems(): for sk, sv in v.iteritems(): if not permutation: sv.setCurrentIndex(0) else: sv.setCurrentIndex( \ [x for x in permutation \ if (x['altr'] == sv.alternative and x['form'] == sv.form and x['c_type'] == sv.c_type)][0]['perm'] - 1) return True def _save_values(self): localItem = self.question_list.currentItem() formatted_grid = self._get_formatted_permutation_grid() if self._validate_grid(formatted_grid): localItem.setBackgroundColor(QColor(0, 255, 68)) localItem.data(Qt.UserRole).toPyObject()\ .set_permutation(formatted_grid) self._reset_permutation_grid() QMessageBox.information(self, _('Information status'), _('The values for the question have been successfully saved')) return True else: QMessageBox.critical(self, _('Error in grid'), _('There is an inconsistence in the options')) return False def _get_formatted_permutation_grid(self): local_alternatives_rows = [] for k, v in self.alternatives_rows.iteritems(): for sk, sv in v.iteritems(): alternative = { 'c_type': sv.c_type, 'form': sv.form, 'altr': sv.alternative, 'perm': sv.currentIndex() + 1 } local_alternatives_rows.append(alternative) return local_alternatives_rows def _validate_grid(self, grid): #validate current grid and questions number forms = {} for row in grid: if row['c_type'] == 'alternative': if row['form'] not in forms: forms[row['form']] = [] if row['perm'] in forms[row['form']]: return False else: forms[row['form']].append(row['perm']) if row['c_type'] == 'question': for i in xrange(self.question_list.count()): if i == self.question_list.currentRow(): continue perm = self.question_list.item(i).data(Qt.UserRole)\ .toPyObject().get_permutation() for perm_row in perm: if (perm_row['c_type'] == 'question' and perm_row['form'] == row['form'] and perm_row['perm'] == row['perm']): return False return True def _reset_permutation_grid(self): for k,v in self.alternatives_rows.iteritems(): for sk, sv in v.iteritems(): sv.setCurrentIndex(0) def _get_values(self): formated_permutation = {} formated_permutation_m = {} for i in xrange(self.question_list.count()): permutations = self.question_list.item(i).data(Qt.UserRole)\ .toPyObject().get_permutation() a = {} for p in permutations: if p['form'] not in formated_permutation: formated_permutation[p['form']] = [] if p['form'] not in a: a[p['form']] = [] if p['c_type'] == 'alternative': a[p['form']].append(p['perm']) if p['c_type'] == 'question': formated_permutation[p['form']].append( \ "%s{%s}" % (p['perm'], ','.join(str(x) \ for x in a[p['form']]))) for k,v in formated_permutation.iteritems(): formated_permutation_m[chr(97+k).upper()] = '/'.join(v) return formated_permutation_m def validatePage(self): valid = True msg = '' for i in xrange(self.question_list.count()): if not self.question_list.item(i).data(Qt.UserRole)\ .toPyObject().get_permutation(): valid = False msg = _('You must select all permutations for all questions') break if not valid: QMessageBox.critical(self, _('Error'), msg) else: current_permutations = self._get_values() for k, v in current_permutations.iteritems(): self.wizard().exam_config.set_permutations(k, v) return valid def nextId(self): return WizardNewSession.PageIdFiles