class DialogSaveFiles(QDialog): def __init__(self, files, editor_container, parent): QDialog.__init__(self, parent) self.setWindowTitle(self.tr("Archivos no guardados!")) self._event_ignore = False self._editor_container = editor_container vLayout = QVBoxLayout(self) label = QLabel(self.tr("Los siguientes archivos se han modificado. " "Guardarlos?")) vLayout.addWidget(label) self.list_widget = QListWidget() self.list_widget.setSelectionMode(QAbstractItemView.ExtendedSelection) for e, _file in enumerate(files): if not _file: _file = "Untitled" self.list_widget.addItem(_file) self.list_widget.item(e).setSelected(True) vLayout.addWidget(self.list_widget) box_buttons = QHBoxLayout() btn_nothing = QPushButton(self.tr("Ninguno")) btn_save = QPushButton(self.tr("Guardar Selección")) btn_cancel = QPushButton(self.tr("Cancelar")) box_buttons.addWidget(btn_nothing) box_buttons.addWidget(btn_save) box_buttons.addWidget(btn_cancel) vLayout.addLayout(box_buttons) self.key_scape = QShortcut(QKeySequence(Qt.Key_Escape), self) # Conexiones self.connect(self.key_scape, SIGNAL("activated()"), self._ignore) self.connect(btn_nothing, SIGNAL("clicked()"), self.close) self.connect(btn_save, SIGNAL("clicked()"), self._save) self.connect(btn_cancel, SIGNAL("clicked()"), self._ignore) def _ignore(self): self._event_ignore = True self.hide() def ignorado(self): return self._event_ignore def _save(self): selected_files = self.list_widget.selectedItems() for _file in selected_files: filename = _file.text() self._editor_container.save_selected(filename) self.close()
def create_central_widget(self): widget = QWidget() vbox = QHBoxLayout() # widget.setLayout(grid) my_dir_list = QListWidget() my_dir_list.itemClicked.connect(self.select_dir) my_dir_list.addItem(os.path.join(os.environ['HOME'], '.icons')) my_dir_list.addItems([os.path.join(x, 'icons') for x in get_xdr_data_dirs()]) my_dir_list.addItem('/usr/share/pixmaps') vbox.addWidget(my_dir_list) self.theme_list = QListWidget() self.theme_list.itemClicked.connect(self.select_theme) vbox.addWidget(self.theme_list) self.sub_dir_list = QListWidget() self.sub_dir_list.itemClicked.connect(self.select_sub_dir) vbox.addWidget(self.sub_dir_list) self.icon_list = QListWidget() self.icon_list.itemClicked.connect(self.select_icon) vbox.addWidget(self.icon_list) self.image = QLabel() self.image.setFixedWidth(150) vbox.addWidget(self.image) widget.setLayout(vbox) return widget
def createCellWidget(self, qmlDict, attr, count): """ Creates specific widgets for each attribute, which can be a QCombobox, a QLineEdit or a QListWidget. """ if attr in qmlDict.keys(): enableIgnoreOption = False #case the type is dict the cell widget must be a combobox if isinstance(qmlDict[attr],dict): comboItem = DsgCustomComboBox() comboItem.addItems(sorted(qmlDict[attr].keys())) self.attributeTableWidget.setCellWidget(count, 1, comboItem) #case the type is tuple the cell widget must be a listwidget if isinstance(qmlDict[attr],tuple): (table, filterKeys) = qmlDict[attr] #getting the value relation dictionary used to make the listwidget valueRelation = self.makeValueRelationDict(table, filterKeys) list = QListWidget() for key in valueRelation.keys(): listItem = QListWidgetItem(key) listItem.setCheckState(Qt.Unchecked) list.addItem(listItem) self.attributeTableWidget.setCellWidget(count, 1, list) #this is the normal case, a simple lineedit else: textItem = QLineEdit() self.attributeTableWidget.setCellWidget(count, 1, textItem) enableIgnoreOption = True #insert here aditional parameters self.createAditionalParameters(count, enableIgnoreOption)
class MergeDialog(QDialog): def __init__(self, track_panels, parent = None): QDialog.__init__(self, parent) self.track_panels = track_panels self.layout = QVBoxLayout(self) self.list = QListWidget(self) self.list.setSelectionMode(QAbstractItemView.MultiSelection) for tv in track_panels: name = tv.curve_source.name() self.list.addItem(QListWidgetItem(name, self.list)) self.ok_button = QPushButton("ok", self) minimum_size_policy(self.ok_button) QWidget.connect(self.ok_button, SIGNAL("clicked()"), self.accept) self.list.updateGeometry() self.layout.addWidget(self.list) self.layout.addWidget(self.ok_button) self.updateGeometry() self.adjustSize() def selected_track_panels(self): selected = self.list.selectedItems() names = [s.text() for s in selected] return [tv for tv in self.track_panels if tv.curve_source.name() in names]
def __init__(self, cards, parent = None): super(CardDialog, self).__init__(parent) self.combination = None self.setWindowTitle("Cash In Cards") cardList = QListWidget() units = ("Infantry", "Cavalry", "Artillery", "Wild") cardToIndex = {} for i, c in enumerate(cards): label = "%d: %s (%s)" % (i, units[c.unit], c.territoryName) cardList.addItem(label) cardToIndex[c] = i combinationList = QListWidget() combinationList.currentItemChanged.connect(self.__setCombination) combinationList.itemDoubleClicked.connect(self.__setCombination) combinationList.itemDoubleClicked.connect(self.accept) self.combinations = {} for combo in combinations(cards, 3): if [c.unit for c in combo] in Card.validCombinations: indexes = [cardToIndex[c] for c in combo] label = "%d, %d, %d" % tuple(indexes) combinationList.addItem(label) self.combinations[label] = indexes listLayout = QHBoxLayout() listLayout.addWidget(cardList) listLayout.addWidget(combinationList) layout = QVBoxLayout() layout.addLayout(listLayout) layout.addWidget(QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel, accepted=self.accept, rejected=self.reject)) self.setLayout(layout)
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 HyphenDialog(QDialog): def __init__(self, mainwindow): super(HyphenDialog, self).__init__(mainwindow) self.setWindowModality(Qt.WindowModal) layout = QVBoxLayout() self.setLayout(layout) self.topLabel = QLabel() self.listWidget = QListWidget() layout.addWidget(self.topLabel) layout.addWidget(self.listWidget) layout.addWidget(widgets.Separator()) self.buttons = b = QDialogButtonBox() layout.addWidget(b) b.setStandardButtons(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) help.addButton(b, lyrics_help) b.rejected.connect(self.reject) b.accepted.connect(self.accept) self.load() app.translateUI(self) qutil.saveDialogSize(self, "hyphenation/dialog/size") def translateUI(self): self.setWindowTitle(app.caption(_("Hyphenate Lyrics Text"))) self.topLabel.setText(_("Please select a language:")) def load(self): self._langs = [(language_names.languageName(lang, po.setup.current()), lang, dic) for lang, dic in findDicts().iteritems()] self._langs.sort() for name, lang, dic in self._langs: self.listWidget.addItem("{0} ({1})".format(name, lang)) def select(): lastused = settings().value("lastused", "", type("")) if lastused: yield lastused lang = po.setup.preferred()[0] yield lang yield lang.split('_')[0] langs = [item[1] for item in self._langs] for preselect in select(): try: self.listWidget.setCurrentRow(langs.index(preselect)) break except ValueError: continue def hyphenator(self): if self.exec_() and self._langs: lang, dic = self._langs[self.listWidget.currentRow()][1:] result = hyphenator.Hyphenator(dic) settings().setValue("lastused", lang) else: result = None self.deleteLater() return result
def __init__(self, opPixelClassification, parent): super( QDialog, self ).__init__(parent=parent) self._op = opPixelClassification classifier_listwidget = QListWidget(parent=self) classifier_listwidget.setSelectionMode( QListWidget.SingleSelection ) classifier_factories = self._get_available_classifier_factories() for name, classifier_factory in classifier_factories.items(): item = QListWidgetItem( name ) item.setData( Qt.UserRole, QVariant(classifier_factory) ) classifier_listwidget.addItem(item) buttonbox = QDialogButtonBox( Qt.Horizontal, parent=self ) buttonbox.setStandardButtons( QDialogButtonBox.Ok | QDialogButtonBox.Cancel ) buttonbox.accepted.connect( self.accept ) buttonbox.rejected.connect( self.reject ) layout = QVBoxLayout() layout.addWidget( classifier_listwidget ) layout.addWidget( buttonbox ) self.setLayout(layout) self.setWindowTitle( "Select Classifier Type" ) # Save members self._classifier_listwidget = classifier_listwidget
class ErrorsWidget(QWidget): def __init__(self): QWidget.__init__(self) self.pep8 = None self._outRefresh = True vbox = QVBoxLayout(self) self.listErrors = QListWidget() self.listPep8 = QListWidget() self.errorsLabel = QLabel(self.tr(ERRORS_TEXT).arg(0)) vbox.addWidget(self.errorsLabel) vbox.addWidget(self.listErrors) self.pep8Label = QLabel(self.tr(PEP8_TEXT).arg(0)) vbox.addWidget(self.pep8Label) vbox.addWidget(self.listPep8) self.connect(self.listErrors, SIGNAL("itemSelectionChanged()"), self.errors_selected) self.connect(self.listPep8, SIGNAL("itemSelectionChanged()"), self.pep8_selected) def errors_selected(self): editorWidget = main_container.MainContainer().get_actual_editor() if editorWidget and self._outRefresh: lineno = self.listErrors.currentItem().data(Qt.UserRole).toInt()[0] editorWidget.jump_to_line(lineno) editorWidget.setFocus() def pep8_selected(self): editorWidget = main_container.MainContainer().get_actual_editor() if editorWidget and self._outRefresh: lineno = self.listPep8.currentItem().data(Qt.UserRole).toInt()[0] editorWidget.jump_to_line(lineno) editorWidget.setFocus() def refresh_lists(self, errors, pep8): self._outRefresh = False self.listErrors.clear() self.listPep8.clear() for lineno in errors.errorsSummary: linenostr = 'L%s\t' % str(lineno + 1) for data in errors.errorsSummary[lineno]: item = QListWidgetItem(linenostr + data) item.setToolTip(linenostr + data) item.setData(Qt.UserRole, lineno) self.listErrors.addItem(item) self.errorsLabel.setText(self.tr(ERRORS_TEXT).arg( len(errors.errorsSummary))) for lineno in pep8.pep8checks: linenostr = 'L%s\t' % str(lineno + 1) for data in pep8.pep8checks[lineno]: item = QListWidgetItem(linenostr + data.split('\n')[0]) item.setToolTip(linenostr + data.split('\n')[0]) item.setData(Qt.UserRole, lineno) self.listPep8.addItem(item) self.pep8Label.setText(self.tr(PEP8_TEXT).arg( len(pep8.pep8checks))) self._outRefresh = True
class BookView(QSplitter): def __init__(self, parent=None): super(BookView, self).__init__(parent=parent) self.create_layout() self.create_connections() def create_layout(self): self.web_view = QWebView() self.chapter_list = QListWidget() self.next_button = QPushButton("Next chapter") self.previous_button = QPushButton("Previous chapter") hbox = QHBoxLayout() hbox.addStretch() hbox.addWidget(self.previous_button) hbox.addWidget(self.next_button) vbox = QVBoxLayout() vbox.addWidget(QLabel("Chapters")) vbox.addWidget(self.chapter_list) vbox.addLayout(hbox) widget = QWidget() widget.setLayout(vbox) self.addWidget(self.web_view) self.addWidget(widget) def create_connections(self): chlist = self.chapter_list self.connect(self.next_button, SIGNAL("clicked()"), lambda: chlist.setCurrentRow(0 if chlist.currentRow() == chlist.count() - 1 else chlist.currentRow() + 1)) self.connect(self.previous_button, SIGNAL("clicked()"), lambda: chlist.setCurrentRow(chlist.count() - 1 if chlist.currentRow() == 0 else chlist.currentRow() - 1)) self.connect(self.chapter_list, SIGNAL("currentRowChanged(int)"), self.set_chapter) page = self.web_view.page() page.setLinkDelegationPolicy(QWebPage.DelegateAllLinks) def set_chapter(self, num=None): if num is None: num = self.chapter_list.currentRow() if num < 0: num = len(self.book.chapters) - 1 elif num >= len(self.book.chapters): num = 0 self.web_view.setHtml(self.book.get_chapter(num).decode(encoding="utf-8")) def load_book(self, book_id): self.book = Book(book_id) self.chapter_list.clear() for chapter in self.book.chapters: self.chapter_list.addItem(chapter[0]) self.chapter_list.setCurrentRow(0)
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 CaseList(QWidget): def __init__(self): QWidget.__init__(self) addHelpToWidget(self, "init/case_list") layout = QVBoxLayout() self._list = QListWidget(self) self._list.setMinimumHeight(100) self._list.setMaximumHeight(250) self._default_selection_mode = self._list.selectionMode() self.setSelectable(False) layout.addWidget(QLabel("Available Cases:")) layout.addWidget(self._list) self._addRemoveWidget = AddRemoveWidget(self.addItem, self.removeItem, horizontal=True) self._addRemoveWidget.enableRemoveButton(False) layout.addWidget(self._addRemoveWidget) self._title = "New keyword" self._description = "Enter name of keyword:" self.setLayout(layout) ERT.ertChanged.connect(self.updateList) self.updateList() def setSelectable(self, selectable): if selectable: self._list.setSelectionMode(self._default_selection_mode) else: self._list.setSelectionMode(QAbstractItemView.NoSelection) def addItem(self): dialog = ValidatedDialog("New case", "Enter name of new case:", getAllCases()) new_case_name = dialog.showAndTell() if not new_case_name == "": selectOrCreateNewCase(new_case_name) def removeItem(self): message = "Support for removal of items has not been implemented!" QMessageBox.information(self, "Not implemented!", message) def updateList(self): """Retrieves data from the model and inserts it into the list""" case_list = getAllCases() self._list.clear() for case in case_list: self._list.addItem(case)
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 DetailWindow(myWindow): listToParaAndRdnr = {} def __init__(self, parent = None): super(DetailWindow, self).__init__(parent, layoutCls = QHBoxLayout, fixed = False) self._listWidget = QListWidget(self) self._paraAndRdnr = QTableView(self) self.layout().addWidget(self._listWidget) self.layout().addWidget(self._paraAndRdnr) self._listWidget.clicked.connect(self.showParaAndRdnr) def showParaAndRdnr(self, listItem): paraAndRdnr = self.listToParaAndRdnr.get(listItem.row()) model = QStandardItemModel(self) c = 0 for para, rdnrs in paraAndRdnr.iteritems(): l = self._createListItem(para, rdnrs) model.insertRow(c, l) c += 1 model.setHeaderData(0, Qt.Horizontal, "Paragraph") model.setHeaderData(1, Qt.Horizontal, "Randnummern") self._paraAndRdnr.setModel(model) def _createListItem(self, para, rdnrs): rdnrsAsStr = toStr(collect([item for sublist in rdnrs for item in sublist])) item1 = QStandardItem(para.decode("utf-8")) item1.setToolTip(para.decode("utf-8")) item2 = QStandardItem(rdnrsAsStr) item2.setToolTip(rdnrsAsStr) return [item1, item2] def showDetails(self, content, windowTitle = None): if windowTitle: self.setWindowTitle(windowTitle) details = self._map_details(content) self._listWidget.clear() i = 0 for fileName, paraAndRdnrs in details.iteritems(): self._listWidget.addItem(fileName) self.listToParaAndRdnr[i] = paraAndRdnrs i += 1 def _map_details(self, data): def nestedMap(data): res = {} idx = len(data[0])-1 for d in data: old = res.get(d[idx], []) old.append(d[:idx]) res[d[idx]] = old return res res = nestedMap(data) for k, v in res.iteritems(): res[k] = nestedMap(v) return res
def createEditor(self, parent, option, index): # special combobox for field type if index.column() == self.column: list = QListWidget(parent) for item in self.itemsDict: listItem = QListWidgetItem(item) listItem.setCheckState(Qt.Unchecked) list.addItem(listItem) return list return QItemDelegate.createEditor(self, parent, option, index)
class TrackListView(QDockWidget): def __init__(self, parent=None): QDockWidget.__init__(self, parent) self.trackList = QListWidget() self.trackList.addItem("juhu") # layout = QVBoxLayout() # layout.addWidget(trackList) self.setWidget(self.trackList)
class ArrayWidget(QWidget, NodeWidget): data_type = "Array" two_rows = True data_class = ArrayNode def __init__(self, name, data, scheme, parent=None): QWidget.__init__(self, parent) NodeWidget.__init__(self, name, data, scheme) self.layout = QVBoxLayout(self) self.layout.setMargin(0) self.layout.setContentsMargins(0,0,0,0) self._listwidget = QListWidget(self) self.layout.addWidget(self._listwidget) hlayout = QHBoxLayout() self.layout.addLayout(hlayout) self._plus_minus_widget = PlusMinusWidget(self.create_item, self.delete_item, self) hlayout.addWidget(self._plus_minus_widget) self.element_scheme = self.scheme["ElementScheme"] self.new_data = NodeWidget.get_default_data(self.element_scheme, self.data) hlayout.addStretch(1) self.add_widget = NodeWidget.create_node_widget("__not_exist", self.new_data, self.element_scheme) hlayout.addWidget(self.add_widget) def delete_item(self): row = self._listwidget.row(self._listwidget.currentItem()) new_data = list(self.data.get()) del new_data[row] self.data.set(tuple(new_data)) def create_item(self): self.data.set(list(self.data.get())+[Node.create_node(self.new_data.get()),]) def __createItem(self, itemname): item = QListWidgetItem(itemname) # item.setFlags (Qt.ItemIsSelectable | Qt.ItemIsEditable | Qt.ItemIsEnabled ) self._listwidget.addItem(item) def dump(self): pass def load(self): self._listwidget.clear() for item in self.data.get(): self.__createItem(unicode(item)) @classmethod def _get_default_data(cls, scheme, data): return ArrayNode([])
class ResultDialog(QDialog): def __init__(self, result, parent): super(QDialog, self).__init__(parent) self.list = QListWidget(self) self.list.setSelectionMode(QListWidget.NoSelection) self.buttons = QDialogButtonBox(QDialogButtonBox.Ok) self.buttons.accepted.connect(self.accept) self.setWindowTitle('Result') self.resize(380, 200) self._insertResult(result) self._createLayout() def _insertResult(self, result): for track, res in result: item = QListWidgetItem() item.setText('{0} - {1}'.format(track[0]['name'], res['msg'])) if res['status'] == 'OK': # item.setBackground(Qt.green) pass elif res['status'] == 'ERROR': item.setForeground(Qt.red) self.list.addItem(item) def _createLayout(self): l = QVBoxLayout() l.addWidget(self.list) l.addWidget(self.buttons) self.setLayout(l)
def loadThesisesToList(QListWidget, path): ListDir = [] for Bill, ListDir, Bob in os.walk(path): break for dir in ListDir: SubDirs = [] for Bill, SubDirs, Bob in os.walk(path + '/' + dir): break for sdir in SubDirs: tmp = Thesis(path = path + '/' + dir + '/' + sdir) tmp.getDesc(path) QListWidget.addItem(tmp)
def initUI(self, engine): vbox = QVBoxLayout() vbox.addWidget(QLabel('Playlists')) ## make the list view lv = QListWidget() lv.doubleClicked.connect(self.item_select) for playlist in engine.get_user_playlists().values(): lv.addItem(QPlaylistWidgetItem(playlist)) self.lv = lv vbox.addWidget(lv) self.setLayout(vbox)
class FormTabWidget(QWidget): def __init__(self, datalist, comment="", parent=None): QWidget.__init__(self, parent) layout = QHBoxLayout() self.contentsWidget = QListWidget() self.contentsWidget.setViewMode(QListView.ListMode) self.contentsWidget.setMovement(QListView.Static) self.contentsWidget.setMaximumWidth(128) self.pagesWidget = QStackedWidget() layout.addWidget(self.contentsWidget) layout.addWidget(self.pagesWidget) self.setLayout(layout) self.widgetlist = [] for elem in datalist: if len(elem) == 4: data, title, comment, icon = elem else: data, title, comment = elem icon = None if len(data[0]) == 3: widget = FormComboWidget(data, comment=comment, parent=self) else: widget = FormWidget(data, comment=comment, parent=self) #index = self.tabwidget.addTab(widget, title) #self.tabwidget.setTabToolTip(index, comment) self.pagesWidget.addWidget(widget) contentItem = QListWidgetItem(self.contentsWidget) if icon: contentItem.setIcon(icon) contentItem.setText(title) contentItem.setToolTip(comment) contentItem.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled) self.contentsWidget.addItem(contentItem) self.widgetlist.append(widget) self.contentsWidget.currentRowChanged.connect(self.changePage) def changePage(self, current): if current != -1: self.pagesWidget.setCurrentIndex(current) def setup(self): for widget in self.widgetlist: widget.setup() def get(self): return [ widget.get() for widget in self.widgetlist]
class ErrorsWidget(QWidget): def __init__(self): QWidget.__init__(self) self.pep8 = None self._outRefresh = True vbox = QVBoxLayout(self) self.listErrors = QListWidget() self.listPep8 = QListWidget() self.errorsLabel = QLabel(self.tr(ERRORS_TEXT).arg(0)) vbox.addWidget(self.errorsLabel) vbox.addWidget(self.listErrors) self.pep8Label = QLabel(self.tr(PEP8_TEXT).arg(0)) vbox.addWidget(self.pep8Label) vbox.addWidget(self.listPep8) self.connect(self.listErrors, SIGNAL("itemSelectionChanged()"), self.errors_selected) self.connect(self.listPep8, SIGNAL("itemSelectionChanged()"), self.pep8_selected) def errors_selected(self): editorWidget = main_container.MainContainer().get_actual_editor() if editorWidget and self._outRefresh: index = self.listErrors.currentItem().data(Qt.UserRole).toInt()[0] editorWidget.jump_to_line(editorWidget.errors.errorsLines[index] - 1) editorWidget.setFocus() def pep8_selected(self): editorWidget = main_container.MainContainer().get_actual_editor() if editorWidget and self._outRefresh: index = self.listPep8.currentItem().data(Qt.UserRole).toInt()[0] editorWidget.jump_to_line(editorWidget.pep8.pep8lines[index] - 1) editorWidget.setFocus() def refresh_lists(self, errors, pep8): self._outRefresh = False self.listErrors.clear() self.listPep8.clear() for index, data in enumerate(errors.errorsLines): item = QListWidgetItem(errors.errorsSummary[data]) item.setData(Qt.UserRole, index) self.listErrors.addItem(item) self.errorsLabel.setText(self.tr(ERRORS_TEXT).arg(len(errors.errorsLines))) for index, data in enumerate(pep8.pep8checks): item = QListWidgetItem(data.split("\n")[0]) item.setData(Qt.UserRole, index) self.listPep8.addItem(item) self.pep8Label.setText(self.tr(PEP8_TEXT).arg(len(pep8.pep8checks))) self._outRefresh = True
class TabGroup(QWidget, itab_item.ITabItem): def __init__(self, project, name, actions): QWidget.__init__(self) itab_item.ITabItem.__init__(self) vbox = QVBoxLayout(self) self.actions = actions self.project = project self.ID = self.project self.name = name self.tabs = [] self.listWidget = QListWidget() hbox = QHBoxLayout() btnExpand = QPushButton(self.tr("Expand this Files")) btnExpandAll = QPushButton(self.tr("Expand all Groups")) hbox.addWidget(btnExpandAll) hbox.addSpacerItem(QSpacerItem(20, 20, QSizePolicy.Expanding)) hbox.addWidget(btnExpand) vbox.addLayout(hbox) vbox.addWidget(self.listWidget) self.connect(btnExpand, SIGNAL("clicked()"), self.expand_this) self.connect(btnExpandAll, SIGNAL("clicked()"), self.actions.deactivate_tabs_groups) def add_widget(self, widget): self.tabs.append(widget) self.listWidget.addItem(widget.ID) def expand_this(self): self.actions.group_tabs_together() for tab in self.tabs: tabName = file_manager.get_basename(tab.ID) self.actions.ide.mainContainer.add_tab(tab, tabName) index = self.actions.ide.mainContainer._tabMain.indexOf(self) self.actions.ide.mainContainer._tabMain.removeTab(index) self.tabs = [] self.listWidget.clear() def only_expand(self): for tab in self.tabs: tabName = file_manager.get_basename(tab.ID) self.actions.ide.mainContainer.add_tab(tab, tabName) index = self.actions.ide.mainContainer._tabMain.indexOf(self) self.actions.ide.mainContainer._tabMain.removeTab(index) self.tabs = [] self.listWidget.clear()
class FinishPage(QWizardPage): def __init__(self): super(FinishPage, self).__init__() container = QVBoxLayout(self) self.setSubTitle(self.tr("Elige una plantilla")) self.list_template = QListWidget() self.list_template.addItem(self.tr("Proyecto en blanco")) self.list_template.addItem(self.tr("Incluir achivo y función main")) container.addWidget(self.list_template) @property def template(self): selection = self.list_template.selectedItems() if not selection: self.list_template.currentItem().setSelected(True) return self.list_template.row(self.list_template.selectedItems()[0])
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 PopupCompleter(QFrame): def __init__(self, model): QFrame.__init__(self, None, Qt.FramelessWindowHint | Qt.ToolTip) vbox = QVBoxLayout(self) vbox.setContentsMargins(0, 0, 0, 0) vbox.setSpacing(0) self.listWidget = QListWidget() for i, item in enumerate(model): self.listWidget.addItem(item) self.listWidget.setCurrentRow(0) vbox.addWidget(self.listWidget) def refresh(self, model): self.listWidget.clear() for i, item in enumerate(model): self.listWidget.addItem(item) self.listWidget.setCurrentRow(0)
class LateralWidget(QDockWidget): def __init__(self): super(LateralWidget, self).__init__() self._list_widget = QListWidget() self.setWidget(self._list_widget) Pireal.load_service("lateral", self) self._list_widget.setContextMenuPolicy(Qt.CustomContextMenu) self.connect(self._list_widget, SIGNAL("currentRowChanged(int)"), self._change_item) self.connect(self._list_widget, SIGNAL("customContextMenuRequested(const QPoint)"), self.__show_context_menu) def __show_context_menu(self, point): """ Context menu """ menu = QMenu() remove_table_act = menu.addAction(QIcon(":img/remove-rel"), self.tr("Eliminar Relación")) self.connect(remove_table_act, SIGNAL("triggered()"), self.remove_table) menu.exec_(self.mapToGlobal(point)) def _change_item(self, index): table = Pireal.get_service("container").table_widget table.stacked.setCurrentIndex(index) def add_item_list(self, items): for i in items: item = QListWidgetItem(i) item.setTextAlignment(Qt.AlignHCenter) self._list_widget.addItem(item) def remove_table(self): table_widget = Pireal.get_service("container").table_widget current_index = self._list_widget.currentRow() table_widget.remove_table(current_index) self._list_widget.takeItem(current_index)
class PythonDetectDialog(QDialog): def __init__(self, suggested, parent=None): super(PythonDetectDialog, self).__init__(parent, Qt.Dialog) self.setMaximumSize(QSize(0, 0)) self.setWindowTitle("Configure Python Path") vbox = QVBoxLayout(self) lblMessage = QLabel(self.tr("We have detected that you are using " + "Windows,\nplease choose the proper " + "Python application for you:")) vbox.addWidget(lblMessage) self.listPaths = QListWidget() self.listPaths.setSelectionMode(QListWidget.SingleSelection) vbox.addWidget(self.listPaths) hbox = QHBoxLayout() hbox.addSpacerItem(QSpacerItem(1, 0, QSizePolicy.Expanding)) btnCancel = QPushButton(self.tr("Cancel")) btnAccept = QPushButton(self.tr("Accept")) hbox.addWidget(btnCancel) hbox.addWidget(btnAccept) vbox.addLayout(hbox) self.connect(btnAccept, SIGNAL("clicked()"), self._set_python_path) self.connect(btnCancel, SIGNAL("clicked()"), self.close) for path in suggested: self.listPaths.addItem(path) self.listPaths.setCurrentRow(0) def _set_python_path(self): python_path = self.listPaths.currentItem().text() qsettings = QSettings(resources.SETTINGS_PATH, QSettings.IniFormat) settings.PYTHON_PATH = python_path settings.PYTHON_EXEC = python_path settings.PYTHON_EXEC_CONFIGURED_BY_USER = True qsettings.setValue('preferences/execution/pythonPath', python_path) qsettings.setValue('preferences/execution/pythonPathConfigured', True) self.close()
class ListWindow(QWidget): def __init__(self, parent=None): super(ListWindow, self).__init__(parent) self.listWidget = QListWidget() for i in range(1, 11): self.listWidget.addItem("Item {}".format(i)) item1 = QListWidgetItem('Text', self.listWidget) item1.setData(Qt.UserRole, 'chunk-124.xml.bz2') # self.listWidget.addItem(item1) self.listWidget.itemActivated.connect(self.printItemText) mainLayout = QHBoxLayout() mainLayout.addWidget(self.listWidget) self.setLayout(mainLayout) def printItemText(self, item): """These two are equivalent""" w = self.listWidget.currentItem() print(w.text()) print(w.data(Qt.UserRole).toPyObject())
class MultipleChoiceDialog(QDialog): def __init__(self, parent, title, text, items): QDialog.__init__(self, parent) self.setWindowTitle(title) self.layout = QVBoxLayout() label = QLabel(text) self.layout.addWidget(label) self.listwidget = QListWidget(self) self.listwidget.setSelectionMode(QAbstractItemView.ExtendedSelection) for item in items: self.listwidget.addItem(item) self.layout.addWidget(self.listwidget) buttonBox = QDialogButtonBox(QDialogButtonBox.Ok|QDialogButtonBox.Cancel) buttonBox.accepted.connect(self.accept) buttonBox.rejected.connect(self.reject) self.layout.addWidget(buttonBox) self.setLayout(self.layout) def selectedItems(self): return self.listwidget.selectedItems()
class TraceWindow(QMainWindow): def __init__(self, params_pipe, number_pipe, data_pipe, mads_pipe, peaks_pipe, probe_path=None, screen_resolution=None): QMainWindow.__init__(self) # Receive parameters. params = params_pipe[0].recv() self.probe = load_probe(probe_path) self._nb_samples = params['nb_samples'] self._sampling_rate = params['sampling_rate'] self._display_list = list(range(self.probe.nb_channels)) self._params = { 'nb_samples': self._nb_samples, 'sampling_rate': self._sampling_rate, 'time': { 'min': 10.0, # ms 'max': 1000.0, # ms 'init': 100.0, # ms }, 'voltage': { 'min': 10.0, # µV 'max': 10e+3, # µV 'init': 20.0, # µV }, 'mads': { 'min': 0.0, # µV 'max': 100, # µV 'init': 3, # µV }, 'channels': self._display_list } self._canvas = TraceCanvas(probe_path=probe_path, params=self._params) central_widget = self._canvas.native # Create controls widgets. label_time = QLabel() label_time.setText(u"time") label_time_unit = QLabel() label_time_unit.setText(u"ms") self._dsp_time = QDoubleSpinBox() self._dsp_time.setMinimum(self._params['time']['min']) self._dsp_time.setMaximum(self._params['time']['max']) self._dsp_time.setValue(self._params['time']['init']) self._dsp_time.valueChanged.connect(self._on_time_changed) label_display_mads = QLabel() label_display_mads.setText(u"Display Mads") self._display_mads = QCheckBox() self._display_mads.stateChanged.connect(self._on_mads_display) label_display_peaks = QLabel() label_display_peaks.setText(u"Display Peaks") self._display_peaks = QCheckBox() self._display_peaks.stateChanged.connect(self._on_peaks_display) label_mads = QLabel() label_mads.setText(u"Mads") label_mads_unit = QLabel() label_mads_unit.setText(u"unit") self._dsp_mads = QDoubleSpinBox() self._dsp_mads.setMinimum(self._params['mads']['min']) self._dsp_mads.setMaximum(self._params['mads']['max']) self._dsp_mads.setValue(self._params['mads']['init']) self._dsp_mads.valueChanged.connect(self._on_mads_changed) label_voltage = QLabel() label_voltage.setText(u"voltage") label_voltage_unit = QLabel() label_voltage_unit.setText(u"µV") self._dsp_voltage = QDoubleSpinBox() self._dsp_voltage.setMinimum(self._params['voltage']['min']) self._dsp_voltage.setMaximum(self._params['voltage']['max']) self._dsp_voltage.setValue(self._params['voltage']['init']) self._dsp_voltage.valueChanged.connect(self._on_voltage_changed) # Color spikes self._color_spikes = QCheckBox() self._color_spikes.setText('See Spikes color') self._color_spikes.setCheckState(Qt.Checked) self._color_spikes.stateChanged.connect(self.display_spikes_color) # self._selection_channels.setGeometry(QtCore.QRect(10, 10, 211, 291)) spacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) # Create controls grid. grid = QGridLayout() # # Add time row. grid.addWidget(label_time, 0, 0) grid.addWidget(self._dsp_time, 0, 1) grid.addWidget(label_time_unit, 0, 2) # # Add voltage row. grid.addWidget(label_voltage, 1, 0) grid.addWidget(self._dsp_voltage, 1, 1) grid.addWidget(label_voltage_unit, 1, 2) # # Add Mads widgets grid.addWidget(label_display_mads, 3, 0) grid.addWidget(self._display_mads, 3, 1) grid.addWidget(label_mads, 4, 0) grid.addWidget(self._dsp_mads, 4, 1) grid.addWidget(label_mads_unit, 4, 2) grid.addWidget(self._color_spikes, 5, 0) # # Add spacer. grid.addItem(spacer) # # Create info group. controls_group = QGroupBox() controls_group.setLayout(grid) self._selection_channels = QListWidget() self._selection_channels.setSelectionMode( QAbstractItemView.ExtendedSelection ) for i in range(self.probe.nb_channels): item = QListWidgetItem("Channel %i" % i) self._selection_channels.addItem(item) self._selection_channels.item(i).setSelected(True) def add_channel(): items = self._selection_channels.selectedItems() self._display_list = [] for i in range(len(items)): self._display_list.append(i) self._on_channels_changed() # self._selection_channels.itemClicked.connect(add_channel) nb_channel = self.probe.nb_channels self._selection_channels.itemSelectionChanged.connect(lambda: self.selected_channels(nb_channel)) # Create info grid. channels_grid = QGridLayout() # # Add Channel selection # grid.addWidget(label_selection, 3, 0) channels_grid.addWidget(self._selection_channels, 0, 1) # # Add spacer. channels_grid.addItem(spacer) # Create controls group. channels_group = QGroupBox() channels_group.setLayout(channels_grid) # # Create controls dock. channels_dock = QDockWidget() channels_dock.setWidget(channels_group) channels_dock.setWindowTitle("Channels selection") # # Create controls dock. control_dock = QDockWidget() control_dock.setWidget(controls_group) control_dock.setWindowTitle("Controls") # Create info widgets. label_time = QLabel() label_time.setText(u"time") self._label_time_value = QLineEdit() self._label_time_value.setText(u"0") self._label_time_value.setReadOnly(True) self._label_time_value.setAlignment(Qt.AlignRight) label_time_unit = QLabel() label_time_unit.setText(u"s") info_buffer_label = QLabel() info_buffer_label.setText(u"buffer") self._info_buffer_value_label = QLineEdit() self._info_buffer_value_label.setText(u"0") self._info_buffer_value_label.setReadOnly(True) self._info_buffer_value_label.setAlignment(Qt.AlignRight) info_buffer_unit_label = QLabel() info_buffer_unit_label.setText(u"") info_probe_label = QLabel() info_probe_label.setText(u"probe") info_probe_value_label = QLineEdit() info_probe_value_label.setText(u"{}".format(probe_path)) info_probe_value_label.setReadOnly(True) # TODO place the following info in another grid? info_probe_unit_label = QLabel() info_probe_unit_label.setText(u"") info_spacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) # Create info grid. info_grid = QGridLayout() # # Time row. info_grid.addWidget(label_time, 0, 0) info_grid.addWidget(self._label_time_value, 0, 1) info_grid.addWidget(label_time_unit, 0, 2) # # Buffer row. info_grid.addWidget(info_buffer_label, 1, 0) info_grid.addWidget(self._info_buffer_value_label, 1, 1) info_grid.addWidget(info_buffer_unit_label, 1, 2) # # Probe row. info_grid.addWidget(info_probe_label, 2, 0) info_grid.addWidget(info_probe_value_label, 2, 1) info_grid.addWidget(info_probe_unit_label, 2, 2) # # Spacer. info_grid.addItem(info_spacer) # Create info group. info_group = QGroupBox() info_group.setLayout(info_grid) # Create info dock. info_dock = QDockWidget() info_dock.setWidget(info_group) info_dock.setWindowTitle("Info") # Create thread. thread = Thread(number_pipe, data_pipe, mads_pipe, peaks_pipe) thread.number_signal.connect(self._number_callback) thread.reception_signal.connect(self._reception_callback) thread.start() # Add dockable windows. self.addDockWidget(Qt.LeftDockWidgetArea, control_dock) self.addDockWidget(Qt.LeftDockWidgetArea, info_dock) self.addDockWidget(Qt.LeftDockWidgetArea, channels_dock) # Set central widget. self.setCentralWidget(central_widget) # Set window size. if screen_resolution is not None: screen_width = screen_resolution.width() screen_height = screen_resolution.height() self.resize(screen_width, screen_height) # Set window title. self.setWindowTitle("SpyKING Circus ORT - Read 'n' Qt display") print(" ") # TODO remove? def _number_callback(self, number): text = u"{}".format(number) self._info_buffer_value_label.setText(text) text = u"{:8.3f}".format(float(number) * float(self._nb_samples) / self._sampling_rate) self._label_time_value.setText(text) return def _reception_callback(self, data, mads, peaks): self._canvas.on_reception(data, mads, peaks) return def _on_time_changed(self): time = self._dsp_time.value() self._canvas.set_time(time) return def _on_voltage_changed(self): voltage = self._dsp_voltage.value() self._canvas.set_voltage(voltage) return def _on_mads_changed(self): mads = self._dsp_mads.value() self._canvas.set_mads(mads) return def _on_mads_display(self): value = self._display_mads.isChecked() self._canvas.show_mads(value) return def _on_peaks_display(self): value = self._display_peaks.isChecked() self._canvas.show_peaks(value) return def _on_channels_changed(self): self._canvas.set_channels(self._display_list) return def display_spikes_color(self, s): self._canvas.color_spikes(s) def selected_channels(self, max_channel): # print(self._selection_channels.selectedItems()) list_channel = [] for i in range(max_channel): if self._selection_channels.item(i).isSelected(): list_channel.append(i) self._canvas.selected_channels(list_channel) return
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 HDFWidget(QWidget): def __init__(self, parent=None): super(HDFWidget, self).__init__(parent=parent) self.parent = parent self.main_layout = QVBoxLayout() ### Select Dataset and properties ### self.layout = QHBoxLayout() self.list = QListWidget() self.textBox = QTextEdit() self.textBox.resize(200, 200) ### Add button ### self.button = QPushButton("Apply") self.main_layout.addLayout(self.layout) self.main_layout.addWidget(self.button) self.setLayout(self.main_layout) self.layout.addWidget(self.list) self.layout.addWidget(self.textBox) ### Variables ### self.settings = None self.list.itemClicked.connect(self.item_clicked) self.connect(self.button, QtCore.SIGNAL("clicked()"), self.apply_settings) def item_clicked(self, item): """Action triggered when an item is clicked. The content of the metadata is retrieved from its index and not from the file itself, avoiding clashes with the main program. """ i = self.list.currentRow() self.settings = self.all_settings[i] self.textBox.clear() self.textBox.setText(self.settings) # mdd = self.settings.split('\n') # for t in mdd: # self.textBox.append(t) def add_items(self, name): """ Adds the group items to the display. The file is closed after extracting the metadata, to avoid conflicts with the main program. :param name: Name of the HDF file to be opened. :return: Null """ f = h5py.File(name, 'r') self.settings = None self.all_settings = [] self.list.clear() for g in f: self.all_settings.append(f[g + '/metadata'][()].decode('ascii')) self.list.addItem(g) f.close() def apply_settings(self): """ Triggered when the apply button is pressed. The settings are broadcasted as coming from the parent. """ if self.settings is not None: self.parent.emit(QtCore.SIGNAL('settings'), self.settings)
class PopupCompleter(QFrame): def __init__(self): QFrame.__init__(self, None, Qt.FramelessWindowHint | Qt.ToolTip) vbox = QVBoxLayout(self) vbox.setContentsMargins(0, 0, 0, 0) vbox.setSpacing(0) self.listWidget = QListWidget() self.listWidget.setMinimumHeight(350) vbox.addWidget(self.listWidget) self.listWidget.currentItemChanged.connect(self._repaint_items) def _repaint_items(self, current, previous): if current is not None: widget = self.listWidget.itemWidget(current) if widget is not None: widget.set_selected() if previous is not None: widget = self.listWidget.itemWidget(previous) if widget is not None: widget.set_not_selected() def reload(self, model): """Reload the data of the Popup Completer, and restart the state.""" self.listWidget.clear() self.add_help() for item in model: self.listWidget.addItem(item[0]) self.listWidget.setItemWidget(item[0], item[1]) self.listWidget.setCurrentRow(8) def clear(self): """Remove all the items of the list (deleted), and reload the help.""" self.listWidget.clear() def refresh(self, model, has_text=True): """Refresh the list when the user search for some word.""" self.listWidget.clear() if not has_text: self.add_help() for item in model: self.listWidget.addItem(item[0]) self.listWidget.setItemWidget(item[0], item[1]) if model: self.listWidget.setCurrentItem(model[0][0]) else: self.add_no_found() def fetch_more(self, model): """Add more items to the list on user scroll.""" for item in model: self.listWidget.addItem(item[0]) self.listWidget.setItemWidget(item[0], item[1]) def add_no_found(self): """Load no results found message""" noFoundItem = self._create_help_item(resources.IMAGES['delete'], translations.TR_NO_RESULTS) self.listWidget.addItem(noFoundItem) def add_help(self): #Load help fileItem = self._create_help_item(resources.IMAGES['locate-file'], translations.TR_ONLY_FILES) self.listWidget.addItem(fileItem) classItem = self._create_help_item(resources.IMAGES['locate-class'], translations.TR_ONLY_CLASSES) self.listWidget.addItem(classItem) methodItem = self._create_help_item( resources.IMAGES['locate-function'], translations.TR_ONLY_METHODS) self.listWidget.addItem(methodItem) attributeItem = self._create_help_item( resources.IMAGES['locate-attributes'], translations.TR_ONLY_ATRIBUTES) self.listWidget.addItem(attributeItem) thisFileItem = self._create_help_item( resources.IMAGES['locate-on-this-file'], translations.TR_ONLY_CLASSES_METHODS) self.listWidget.addItem(thisFileItem) tabsItem = self._create_help_item(resources.IMAGES['locate-tab'], translations.TR_ONLY_CURRENT_TABS) self.listWidget.addItem(tabsItem) lineItem = self._create_help_item(resources.IMAGES['locate-line'], translations.TR_GO_TO_LINE) self.listWidget.addItem(lineItem) nonPythonItem = self._create_help_item( resources.IMAGES['locate-nonpython'], translations.TR_ONLY_NON_PYTHON) self.listWidget.addItem(nonPythonItem) def _create_help_item(self, image, text): Item = QListWidgetItem(QIcon(image), text) font = Item.font() font.setBold(True) Item.setSizeHint(QSize(20, 30)) Item.setBackground(QBrush(Qt.lightGray)) Item.setForeground(QBrush(Qt.black)) Item.setFont(font) return 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 Consultas(QFrame): def __init__(self, func): super().__init__() self.consulta_actual = 0 self.funciones = [f for f in func] self.initUI() def initUI(self): #self.setFixedSize(830, 120) self.setStyleSheet(""" QWidget{ background-color: #FFFFFF; border:0px; } QLineEdit{ border: 1px solid #000099;} QListWidget{ border: 1px solid #000099;} QPushButton{ border: 1px solid #000099;} QPushButton{background-color: #FFCC33; color: #000099; } QPushButton:pressed { background-color: #FFFF00; } """) self.grid = QGridLayout() self.setLayout(self.grid) self.grid.setSpacing(5) # Botones self.boton = QPushButton("¡Click y descubre!") self.atras = QPushButton("◄") self.adelante = QPushButton("►") # Conexiones self.boton.clicked.connect(self.clicked) self.atras.clicked.connect(self.retroceder) self.adelante.clicked.connect(self.avanzar) # Lista de consultas self.args = [ ("1.Cantidad de ubicaciones por región:", "Ubicación", "Región"), ("2.Regiones sin ubicaciones:", "Ubicaciones:", "Región:"), ("3.Ruta de ubicacion1 a ubicacion2", "Ubicación 1:", "Ubicación 2:"), ("4.Cantidad de un tipo de ubicación a una distancia", "Ubicación", "Cantidad de sub-grillas:"), ("5.Distancia hasta n ubicaciones de un tipo:", "Ubicación", "Cantidad") ] self.consulta(*self.args[self.consulta_actual]) def consulta(self, titulo, label1, label2): label_consulta = QLabel(titulo) label1 = QLabel(label1) label2 = QLabel(label2) label3 = QLabel("Respuesta:") self.arg1 = QLineEdit() self.arg2 = QLineEdit() self.respuesta = QListWidget(self) self.limpiar_grid(self.grid) self.grid.addWidget(label_consulta, 0, 0) self.grid.addWidget(self.boton, 1, 0) self.grid.addWidget(self.atras, 2, 0) self.grid.addWidget(self.adelante, 3, 0) self.grid.addWidget(label1, 0, 1) self.grid.addWidget(self.arg1, 1, 1) self.grid.addWidget(label2, 2, 1) self.grid.addWidget(self.arg2, 3, 1) self.grid.addWidget(label3, 0, 3) self.grid.addWidget(self.respuesta, 1, 3, 3, 1) def clicked(self): tupla = (self.arg1.text(), self.arg2.text()) valor1 = tupla[0].split(sep=",") valor2 = tupla[1].split(sep=",") tupla = (valor1, valor2) if tupla[0] and tupla[1]: lista = (self.funciones[self.consulta_actual])(tupla) self.respuesta.clear() if isinstance(lista, list): for x in lista: item = QListWidgetItem(str(x)) self.respuesta.addItem(item) else: item = QListWidgetItem(str(lista)) self.respuesta.addItem(item) def avanzar(self): self.consulta_actual = (self.consulta_actual + 1) % 5 self.consulta(*self.args[self.consulta_actual]) def retroceder(self): valor = self.consulta_actual - 1 self.consulta_actual = 4 if valor < 0 else valor self.consulta(*self.args[self.consulta_actual]) def limpiar_grid(self, grid): for i in reversed(range(grid.count())): grid.itemAt(i).widget().setParent(None)
class PopupCompleter(QFrame): def __init__(self): QFrame.__init__(self, None, Qt.FramelessWindowHint | Qt.ToolTip) vbox = QVBoxLayout(self) vbox.setContentsMargins(0, 0, 0, 0) vbox.setSpacing(0) self.listWidget = QListWidget() self.listWidget.setMinimumHeight(300) vbox.addWidget(self.listWidget) def reload(self, model): """Reload the data of the Popup Completer, and restart the state.""" self.listWidget.clear() self.add_help() for item in model: self.listWidget.addItem(item[0]) self.listWidget.setItemWidget(item[0], item[1]) self.listWidget.setCurrentRow(6) def clear(self): """Remove all the items of the list (deleted), and reload the help.""" self.listWidget.clear() def refresh(self, model): """Refresh the list when the user search for some word.""" self.listWidget.clear() for item in model: self.listWidget.addItem(item[0]) self.listWidget.setItemWidget(item[0], item[1]) if model: self.listWidget.setCurrentItem(model[0][0]) def fetch_more(self, model): """Add more items to the list on user scroll.""" for item in model: self.listWidget.addItem(item[0]) self.listWidget.setItemWidget(item[0], item[1]) def add_help(self): #Load help fileItem = QListWidgetItem(QIcon(resources.IMAGES['locate-file']), '@\t(Filter only by Files)') font = fileItem.font() font.setBold(True) fileItem.setSizeHint(QSize(20, 30)) fileItem.setBackground(QBrush(Qt.lightGray)) fileItem.setForeground(QBrush(Qt.black)) fileItem.setFont(font) self.listWidget.addItem(fileItem) classItem = QListWidgetItem(QIcon(resources.IMAGES['locate-class']), '<\t(Filter only by Classes)') self.listWidget.addItem(classItem) classItem.setSizeHint(QSize(20, 30)) classItem.setBackground(QBrush(Qt.lightGray)) classItem.setForeground(QBrush(Qt.black)) classItem.setFont(font) methodItem = QListWidgetItem( QIcon(resources.IMAGES['locate-function']), '>\t(Filter only by Methods)') self.listWidget.addItem(methodItem) methodItem.setSizeHint(QSize(20, 30)) methodItem.setBackground(QBrush(Qt.lightGray)) methodItem.setForeground(QBrush(Qt.black)) methodItem.setFont(font) attributeItem = QListWidgetItem( QIcon(resources.IMAGES['locate-attributes']), '-\t(Filter only by Attributes)') self.listWidget.addItem(attributeItem) attributeItem.setSizeHint(QSize(20, 30)) attributeItem.setBackground(QBrush(Qt.lightGray)) attributeItem.setForeground(QBrush(Qt.black)) attributeItem.setFont(font) thisFileItem = QListWidgetItem( QIcon(resources.IMAGES['locate-on-this-file']), '.\t(Filter only by Classes and Methods in this File)') font = thisFileItem.font() font.setBold(True) thisFileItem.setSizeHint(QSize(20, 30)) thisFileItem.setBackground(QBrush(Qt.lightGray)) thisFileItem.setForeground(QBrush(Qt.black)) thisFileItem.setFont(font) self.listWidget.addItem(thisFileItem) nonPythonItem = QListWidgetItem( QIcon(resources.IMAGES['locate-nonpython']), '!\t(Filter only by Non Python Files)') self.listWidget.addItem(nonPythonItem) nonPythonItem.setSizeHint(QSize(20, 30)) nonPythonItem.setBackground(QBrush(Qt.lightGray)) nonPythonItem.setForeground(QBrush(Qt.black)) nonPythonItem.setFont(font)
class NewProjectManager(QDialog): def __init__(self, parent=None): super(NewProjectManager, self).__init__(parent, Qt.Dialog) self.setWindowTitle(translations.TR_NEW_PROJECT) self.setMinimumHeight(500) vbox = QVBoxLayout(self) vbox.addWidget(QLabel(translations.TR_CHOOSE_TEMPLATE)) vbox.addWidget(QLabel(translations.TR_TAB_PROJECTS)) hbox = QHBoxLayout() self.list_projects = QListWidget() self.list_projects.setProperty("wizard", True) hbox.addWidget(self.list_projects) self.list_templates = QListWidget() self.list_templates.setProperty("wizard", True) hbox.addWidget(self.list_templates) self.text_info = QTextBrowser() self.text_info.setProperty("wizard", True) hbox.addWidget(self.text_info) vbox.addLayout(hbox) hbox2 = QHBoxLayout() cancel = QPushButton(translations.TR_CANCEL) choose = QPushButton(translations.TR_CHOOSE) hbox2.addSpacerItem(QSpacerItem(1, 0, QSizePolicy.Expanding, QSizePolicy.Fixed)) hbox2.addWidget(cancel) hbox2.addWidget(choose) vbox.addLayout(hbox2) self.template_registry = IDE.get_service("template_registry") categories = self.template_registry.list_project_categories() for category in categories: self.list_projects.addItem(category) self.connect(cancel, SIGNAL("clicked()"), self.close) self.connect(choose, SIGNAL("clicked()"), self._start_wizard) self.connect(self.list_projects, SIGNAL("itemSelectionChanged()"), self._project_selected) self.connect(self.list_templates, SIGNAL("itemSelectionChanged()"), self._template_selected) def _project_selected(self): self.list_templates.clear() item = self.list_projects.currentItem() category = item.text() for template in self.template_registry.list_templates_for_cateogory( category): item = QListWidgetItem(template.type_name) item.setData(Qt.UserRole, template) item = self.list_templates.addItem(item) def _template_selected(self): item = self.list_templates.currentItem() ptype = item.data(Qt.UserRole) self.text_info.setText(ptype.description) def _start_wizard(self): item = self.list_templates.currentItem() if item is not None: ptype = item.data(Qt.UserRole)
class FieldMappingTab(QWidget, object): """Widget class for field mapping.""" def __init__(self, field_group=None, parent=None, iface=None): """Constructor.""" # Init from parent class QWidget.__init__(self, parent) # Attributes self.layer = None self.metadata = {} self.parent = parent self.iface = iface self.field_group = field_group self.setting = QSettings() # TODO(IS): Make dynamic # Main container self.main_layout = QVBoxLayout() # Inner layout self.header_layout = QHBoxLayout() self.content_layout = QHBoxLayout() self.footer_layout = QHBoxLayout() # Header self.header_label = QLabel() self.header_label.setWordWrap(True) # Content self.field_layout = QVBoxLayout() self.parameter_layout = QHBoxLayout() self.field_description = QLabel(tr('List of fields')) self.field_list = QListWidget() self.field_list.setSelectionMode(QAbstractItemView.ExtendedSelection) self.field_list.setDragDropMode(QAbstractItemView.DragDrop) self.field_list.setDefaultDropAction(Qt.MoveAction) self.field_list.setSizePolicy( QSizePolicy.Maximum, QSizePolicy.Expanding) # noinspection PyUnresolvedReferences self.field_list.itemSelectionChanged.connect(self.update_footer) # Footer self.footer_label = QLabel() # Parameters self.extra_parameters = [ (GroupSelectParameter, GroupSelectParameterWidget) ] self.parameters = [] self.parameter_container = None # Adding to layout self.header_layout.addWidget(self.header_label) self.field_layout.addWidget(self.field_description) self.field_layout.addWidget(self.field_list) self.field_layout.setSizeConstraint(QLayout.SetMaximumSize) self.content_layout.addLayout(self.field_layout) self.content_layout.addLayout(self.parameter_layout) self.footer_layout.addWidget(self.footer_label) self.main_layout.addLayout(self.header_layout) self.main_layout.addLayout(self.content_layout) self.main_layout.addLayout(self.footer_layout) self.setLayout(self.main_layout) def set_layer(self, layer, keywords=None): """Set layer and update UI accordingly. :param layer: A vector layer that has been already patched with metadata. :type layer: QgsVectorLayer :param keywords: Custom keyword for the layer. :type keywords: dict, None """ self.layer = layer if keywords is not None: self.metadata = keywords else: # Check if it has keywords if not hasattr(layer, 'keywords'): message = 'Layer {layer_name} does not have keywords.'.format( layer_name=layer.name()) raise KeywordNotFoundError(message) self.metadata = layer.keywords self.populate_parameter() def populate_field_list(self, excluded_fields=None): """Helper to add field of the layer to the list. :param excluded_fields: List of field that want to be excluded. :type excluded_fields: list """ # Populate fields list if excluded_fields is None: excluded_fields = [] self.field_list.clear() for field in self.layer.dataProvider().fields(): # Skip if it's excluded if field.name() in excluded_fields: continue # Skip if it's not number (float, int, etc) if field.type() not in qvariant_numbers: continue field_item = QListWidgetItem(self.field_list) field_item.setFlags( Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsDragEnabled) field_item.setData(Qt.UserRole, field.name()) field_item.setText(field.name()) self.field_list.addItem(field_item) def populate_parameter(self): """Helper to setup the parameter widget.""" used_fields = [] self.parameters = [] for field in self.field_group.get('fields', []): selected_option = DO_NOT_USE options = OrderedDict([ (DO_NOT_USE, { 'label': tr('Do not use'), 'value': None, 'type': STATIC, 'constraint': {} }), ]) # Example: count if field['absolute']: # Used in field options field_label = tr('Count fields') else: # Example: ratio # Used in field options field_label = tr('Ratio fields') global_default_value = get_inasafe_default_value_qsetting( self.setting, GLOBAL, field['key']) options[GLOBAL_DEFAULT] = { 'label': tr('Global default'), 'value': global_default_value, 'type': STATIC, 'constraint': {} } default_custom_value = get_inasafe_default_value_qsetting( self.setting, RECENT, field['key']) custom_value = self.metadata.get( 'inasafe_default_values', {}).get( field['key'], default_custom_value) if field['key'] in self.metadata.get( 'inasafe_default_values', {}): if custom_value == global_default_value: selected_option = GLOBAL_DEFAULT else: selected_option = CUSTOM_VALUE min_value = field['default_value'].get('min_value', 0) max_value = field['default_value'].get('max_value', 100) default_step = (max_value - min_value) / 100.0 step = field['default_value'].get('increment', default_step) options[CUSTOM_VALUE] = { 'label': tr('Custom'), 'value': custom_value, 'type': SINGLE_DYNAMIC, 'constraint': { 'min': min_value, 'max': max_value, 'step': step } } custom_fields = self.metadata.get('inasafe_fields', {}).get( field['key'], []) if field['key'] in self.metadata.get('inasafe_fields', {}): selected_option = FIELDS if isinstance(custom_fields, basestring): custom_fields = [custom_fields] options[FIELDS] = { 'label': field_label, 'value': custom_fields, 'type': MULTIPLE_DYNAMIC, 'constraint': {} } used_fields.extend(custom_fields) parameter = GroupSelectParameter() parameter.guid = field['key'] parameter.name = field['name'] parameter.options = options parameter.selected = selected_option parameter.help_text = field['help_text'] parameter.description = field['description'] self.parameters.append(parameter) self.parameter_container = ParameterContainer( parameters=self.parameters, extra_parameters=self.extra_parameters, vertical=False ) self.parameter_container.setup_ui() constraints = self.field_group.get('constraints', {}) for key, value in constraints.items(): self.parameter_container.add_validator( validators[key], kwargs=value['kwargs'], validation_message=value['message']) self.parameter_layout.addWidget(self.parameter_container) # Set move or copy if self.field_group.get('exclusive', False): # If exclusive, do not add used field. self.populate_field_list(excluded_fields=used_fields) # Use move action since it's exclusive self.field_list.setDefaultDropAction(Qt.MoveAction) # Just make sure that the signal is disconnected try: # noinspection PyUnresolvedReferences self.field_list.itemChanged.disconnect(self.drop_remove) except TypeError: pass # Set header header_text = self.field_group['description'] header_text += '\n\n' + tr( 'You can only map one field to one concept.') else: # If not exclusive, add all field. self.populate_field_list() # Use copy action since it's not exclusive self.field_list.setDefaultDropAction(Qt.CopyAction) # noinspection PyUnresolvedReferences self.field_list.itemChanged.connect( partial(self.drop_remove, field_list=self.field_list)) self.connect_drop_remove_parameter() # Set header header_text = self.field_group['description'] header_text += '\n\n' + tr( 'You can map one field to more than one concepts.') self.header_label.setText(header_text) def get_parameter_value(self): """Get parameter of the tab. :returns: Dictionary of parameters by type in this format: {'fields': {}, 'values': {}}. :rtype: dict """ try: parameters = self.parameter_container.get_parameters(True) except InvalidValidationException as e: raise OriginalValidationException(e) field_parameters = {} value_parameters = {} for parameter in parameters: if parameter.selected_option_type() in [SINGLE_DYNAMIC, STATIC]: value_parameters[parameter.guid] = parameter.value elif parameter.selected_option_type() == MULTIPLE_DYNAMIC: field_parameters[parameter.guid] = parameter.value return { 'fields': field_parameters, 'values': value_parameters } def update_footer(self): """Update footer when the field list change.""" field_item = self.field_list.currentItem() if not field_item: self.footer_label.setText('') return field_name = field_item.data(Qt.UserRole) field = self.layer.fields().field(field_name) index = self.layer.fieldNameIndex(field_name) unique_values = self.layer.uniqueValues(index) pretty_unique_values = ', '.join([str(v) for v in unique_values[:10]]) footer_text = tr('Field type: {0}\n').format(field.typeName()) footer_text += tr('Unique values: {0}').format(pretty_unique_values) self.footer_label.setText(footer_text) def connect_drop_remove_parameter(self): parameter_widgets = self.parameter_container.get_parameter_widgets() for parameter_widget in parameter_widgets: field_list = parameter_widget.widget().list_widget field_list.itemChanged.connect( partial(self.drop_remove, field_list=field_list)) @staticmethod def drop_remove(*args, **kwargs): """Action when we need to remove dropped item. :param args: Position arguments. :type args: list :param kwargs: Keywords arguments. :type kwargs: dict """ dropped_item = args[0] field_list = kwargs['field_list'] num_duplicate = 0 for i in range(field_list.count()): if dropped_item.text() == field_list.item(i).text(): num_duplicate += 1 if num_duplicate > 1: # Notes(IS): For some reason, removeItemWidget is not working. field_list.takeItem(field_list.row(dropped_item))
class AnnotationManager: def __init__(self, iface): locale = QSettings().value('locale/userLocale')[0:2] locale_path = os.path.join(os.path.dirname(__file__), 'i18n', 'annotationManager_{}.qm'.format(locale)) self.translator = None if os.path.exists(locale_path): self.translator = QTranslator() self.translator.load(locale_path) QCoreApplication.installTranslator(self.translator) self.iface = iface self.iface.projectRead.connect(self.projectOpen) self.dock = QDockWidget(self.tr('Annotations manager')) self.manager = QWidget() toolbar = QToolBar() self.annotationList = QListWidget() self.annotationList.itemClicked.connect(self.selectAnnotation) self.annotationList.itemChanged.connect(self.checkItem) action_refresh = QAction( QIcon(':/plugins/annotationManager/resources/mActionDraw.png'), self.tr('Refresh the annotations list'), self.manager) action_refresh.triggered.connect(self.refreshAnnotations) action_remove = QAction( QIcon( ':/plugins/annotationManager/resources/mActionRemoveAnnotation.png' ), self.tr('Remove the selected annotation'), self.manager) action_remove.triggered.connect(self.removeAnnotation) toolbar.addAction(action_refresh) toolbar.addAction(action_remove) toolbar.setIconSize(QSize(16, 16)) p1_vertical = QVBoxLayout() p1_vertical.setContentsMargins(0, 0, 0, 0) p1_vertical.addWidget(toolbar) p1_vertical.addWidget(self.annotationList) self.manager.setLayout(p1_vertical) self.dock.setWidget(self.manager) self.dock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.iface.addDockWidget(Qt.LeftDockWidgetArea, self.dock) self.rb = QgsRubberBand(self.iface.mapCanvas(), QGis.Polygon) self.annotations = [] self.annotationsName = [] def checkItem(self, item): row = self.annotationList.row(item) self.annotationsName[row] = item.text() if item.checkState() == Qt.Checked: self.annotations[row].show() else: self.annotations[row].hide() if item.isSelected(): item.setSelected(False) self.rb.reset() def selectAnnotation(self): index = self.annotationList.currentRow() self.rb.reset() self.rb.setColor(QColor(0, 0, 255, 128)) mapTool = QgsMapTool(self.iface.mapCanvas()) point = self.annotations[index].pos().toPoint() pt1 = mapTool.toMapCoordinates(QPoint(point.x() - 10, point.y() - 10)) pt2 = mapTool.toMapCoordinates(QPoint(point.x() + 10, point.y() + 10)) rect = QgsRectangle(pt1, pt2) poly = QgsGeometry().fromRect(rect) self.rb.setToGeometry(poly, None) def unload(self): del self.dock def tr(self, message): return QCoreApplication.translate('AnnotationManager', message) def getAnnotations(self): annotations = [] items = self.iface.mapCanvas().items() for item in items: if item.data(0) == 'AnnotationItem': annotations.append(item) return annotations def refreshAnnotations(self): for annotation in self.getAnnotations(): if annotation not in self.annotations: self.annotations.append(annotation) self.annotationsName.append('Annotation') i = 0 to_del = [] for annotation in self.annotations: if annotation not in self.getAnnotations(): to_del.append(i) i += 1 i = 0 for index in to_del: self.annotations.pop(index) self.annotationsName.pop(index) self.annotationList.clearSelection() self.annotationList.clear() # argh for annotation in self.annotations: item = QListWidgetItem(self.annotationsName[i]) if annotation.isVisible(): item.setCheckState(Qt.Checked) else: item.setCheckState(Qt.Unchecked) item.setFlags(item.flags() | Qt.ItemIsEditable) self.annotationList.addItem(item) i += 1 # fin argh def removeAnnotation(self): if len(self.annotationList.selectedItems()) > 0: index = self.annotationList.currentRow() self.annotationList.takeItem(index) self.annotationList.clearSelection() self.annotationList.clearFocus() self.iface.mapCanvas().scene().removeItem(self.annotations[index]) self.annotations.pop(index) self.annotationsName.pop(index) self.rb.reset() def projectOpen(self): del self.annotations[:] del self.annotationsName[:] self.refreshAnnotations() def initGui(self): self.refreshAnnotations()
class Window(QMainWindow): def __init__(self, parent=None): super(Window, self).__init__(parent) self.image = QImage() self.dirty = False self.filename = None self.mirroredvertically = False self.mirroredhorizontally = False self.printer = None self.create_widgets() self.create_actions() self.load_settings() self.setWindowTitle("Image Changer") self.updateFileMenu() QTimer.singleShot(0, self.loadInitialFile) def create_widgets(self): self.imageLabel = QLabel() self.imageLabel.setMinimumSize(200, 200) self.imageLabel.setAlignment(Qt.AlignCenter) self.imageLabel.setContextMenuPolicy(Qt.ActionsContextMenu) self.setCentralWidget(self.imageLabel) logDockWidget = QDockWidget("Log", self) logDockWidget.setObjectName("LogDockWidget") logDockWidget.setAllowedAreas(Qt.LeftDockWidgetArea| Qt.RightDockWidgetArea) self.listWidget = QListWidget() logDockWidget.setWidget(self.listWidget) self.addDockWidget(Qt.RightDockWidgetArea, logDockWidget) self.sizeLabel = QLabel() self.sizeLabel.setFrameStyle(QFrame.StyledPanel|QFrame.Sunken) status = self.statusBar() status.setSizeGripEnabled(False) status.addPermanentWidget(self.sizeLabel) status.showMessage("Ready", 5000) def create_actions(self): fileNewAction = self.createAction("&New...", self.fileNew, QKeySequence.New, "filenew", "Create an image file") fileOpenAction = self.createAction("&Open...", self.fileOpen, QKeySequence.Open, "fileopen", "Open an existing image file") fileSaveAction = self.createAction("&Save", self.fileSave, QKeySequence.Save, "filesave", "Save the image") fileSaveAsAction = self.createAction("Save &As...", self.fileSaveAs, icon="filesaveas", tip="Save the image using a new name") filePrintAction = self.createAction("&Print", self.filePrint, QKeySequence.Print, "fileprint", "Print the image") fileQuitAction = self.createAction("&Quit", self.close, "Ctrl+Q", "filequit", "Close the application") editInvertAction = self.createAction("&Invert", None, "Ctrl+I", "editinvert", "Invert the image's colors", True) editInvertAction.toggled.connect(self.editInvert) editSwapRedAndBlueAction = self.createAction("Sw&ap Red and Blue", None, "Ctrl+A", "editswap", "Swap the image's red and blue color components", True) editSwapRedAndBlueAction.toggled.connect(self.editSwapRedAndBlue) editZoomAction = self.createAction("&Zoom...", self.editZoom, "Alt+Z", "editzoom", "Zoom the image") editResizeAction = self.createAction("&Resize...", self.editResize, "Ctrl+R", "editresize", "Resize the image") mirrorGroup = QActionGroup(self) editUnMirrorAction = self.createAction("&Unmirror", None, "Ctrl+U", "editunmirror", "Unmirror the image", True) editUnMirrorAction.toggled.connect(self.editUnMirror) mirrorGroup.addAction(editUnMirrorAction) editMirrorHorizontalAction = self.createAction( "Mirror &Horizontally", None, "Ctrl+H", "editmirrorhoriz", "Horizontally mirror the image", True) editMirrorHorizontalAction.toggled.connect( self.editMirrorHorizontal) mirrorGroup.addAction(editMirrorHorizontalAction) editMirrorVerticalAction = self.createAction( "Mirror &Vertically", None, "Ctrl+V", "editmirrorvert", "Vertically mirror the image", True) editMirrorVerticalAction.toggled.connect(self.editMirrorVertical) mirrorGroup.addAction(editMirrorVerticalAction) editUnMirrorAction.setChecked(True) helpAboutAction = self.createAction("&About Image Changer", self.helpAbout) helpHelpAction = self.createAction("&Help", self.helpHelp, QKeySequence.HelpContents) self.fileMenu = self.menuBar().addMenu("&File") self.fileMenuActions = (fileNewAction, fileOpenAction, fileSaveAction, fileSaveAsAction, None, filePrintAction, fileQuitAction) self.fileMenu.aboutToShow.connect(self.updateFileMenu) editMenu = self.menuBar().addMenu("&Edit") self.addActions(editMenu, (editInvertAction, editSwapRedAndBlueAction, editZoomAction, editResizeAction)) mirrorMenu = editMenu.addMenu(QIcon(":/editmirror.png"), "&Mirror") self.addActions(mirrorMenu, (editUnMirrorAction, editMirrorHorizontalAction, editMirrorVerticalAction)) helpMenu = self.menuBar().addMenu("&Help") self.addActions(helpMenu, (helpAboutAction, helpHelpAction)) fileToolbar = self.addToolBar("File") fileToolbar.setObjectName("FileToolBar") self.addActions(fileToolbar, (fileNewAction, fileOpenAction, fileSaveAsAction)) editToolbar = self.addToolBar("Edit") editToolbar.setObjectName("EditToolBar") self.addActions(editToolbar, (editInvertAction, editSwapRedAndBlueAction, editUnMirrorAction, editMirrorVerticalAction, editMirrorHorizontalAction)) self.zoomSpinBox = QSpinBox() self.zoomSpinBox.setRange(1, 400) self.zoomSpinBox.setSuffix(" %") self.zoomSpinBox.setValue(100) self.zoomSpinBox.setToolTip("Zoom the image") self.zoomSpinBox.setStatusTip(self.zoomSpinBox.toolTip()) self.zoomSpinBox.setFocusPolicy(Qt.NoFocus) self.zoomSpinBox.valueChanged.connect(self.showImage) editToolbar.addWidget(self.zoomSpinBox) self.addActions(self.imageLabel, (editInvertAction, editSwapRedAndBlueAction, editUnMirrorAction, editMirrorVerticalAction, editMirrorHorizontalAction)) self.resetableActions = ((editInvertAction, False), (editSwapRedAndBlueAction, False), (editUnMirrorAction, True)) def load_settings(self): settings = QSettings() self.recentFiles = settings.value("RecentFiles").toStringList() self.restoreGeometry( settings.value("MainWindow/Geometry").toByteArray()) self.restoreState(settings.value("MainWindow/State").toByteArray()) def createAction(self, text, slot=None, shortcut=None, icon=None, tip=None, checkable=False): action = QAction(text, self) if icon is not None: action.setIcon(QIcon(":/{0}.png".format(icon))) if shortcut is not None: action.setShortcut(shortcut) if tip is not None: action.setToolTip(tip) action.setStatusTip(tip) if slot is not None: action.triggered.connect(slot) if checkable: action.setCheckable(True) return action def addActions(self, target, actions): for action in actions: if action is None: target.addSeparator() else: target.addAction(action) def closeEvent(self, event): if self.okToContinue(): settings = QSettings() filename = (QVariant(QString(self.filename)) if self.filename is not None else QVariant()) settings.setValue("LastFile", filename) recentFiles = (QVariant(self.recentFiles) if self.recentFiles else QVariant()) settings.setValue("RecentFiles", recentFiles) settings.setValue("MainWindow/Geometry", QVariant( self.saveGeometry())) settings.setValue("MainWindow/State", QVariant( self.saveState())) else: event.ignore() def okToContinue(self): if self.dirty: reply = QMessageBox.question(self, "Image Changer - Unsaved Changes", "Save unsaved changes?", QMessageBox.Yes|QMessageBox.No|QMessageBox.Cancel) if reply == QMessageBox.Cancel: return False elif reply == QMessageBox.Yes: return self.fileSave() return True def loadInitialFile(self): settings = QSettings() fname = unicode(settings.value("LastFile").toString()) if fname and QFile.exists(fname): self.loadFile(fname) def updateStatus(self, message): self.statusBar().showMessage(message, 5000) self.listWidget.addItem(message) if self.filename is not None: self.setWindowTitle("Image Changer - {0}[*]".format( os.path.basename(self.filename))) elif not self.image.isNull(): self.setWindowTitle("Image Changer - Unnamed[*]") else: self.setWindowTitle("Image Changer[*]") self.setWindowModified(self.dirty) def updateFileMenu(self): self.fileMenu.clear() self.addActions(self.fileMenu, self.fileMenuActions[:-1]) current = (QString(self.filename) if self.filename is not None else None) recentFiles = [] for fname in self.recentFiles: if fname != current and QFile.exists(fname): recentFiles.append(fname) if recentFiles: self.fileMenu.addSeparator() for i, fname in enumerate(recentFiles): action = QAction(QIcon(":/icon.png"), "&{0} {1}".format(i + 1, QFileInfo( fname).fileName()), self) action.setData(QVariant(fname)) action.triggered.connect(self.loadFile) self.fileMenu.addAction(action) self.fileMenu.addSeparator() self.fileMenu.addAction(self.fileMenuActions[-1]) def fileNew(self): if not self.okToContinue(): return dialog = newimagedlg.NewImageDlg(self) if dialog.exec_(): self.addRecentFile(self.filename) self.image = QImage() for action, check in self.resetableActions: action.setChecked(check) self.image = dialog.image() self.filename = None self.dirty = True self.showImage() self.sizeLabel.setText("{0} x {1}".format(self.image.width(), self.image.height())) self.updateStatus("Created new image") def fileOpen(self): if not self.okToContinue(): return dir = (os.path.dirname(self.filename) if self.filename is not None else ".") formats = (["*.{0}".format(unicode(format).lower()) for format in QImageReader.supportedImageFormats()]) fname = unicode(QFileDialog.getOpenFileName(self, "Image Changer - Choose Image", dir, "Image files ({0})".format(" ".join(formats)))) if fname: self.loadFile(fname) def loadFile(self, fname=None): if fname is None: action = self.sender() if isinstance(action, QAction): fname = unicode(action.data().toString()) if not self.okToContinue(): return else: return if fname: self.filename = None image = QImage(fname) if image.isNull(): message = "Failed to read {0}".format(fname) else: self.addRecentFile(fname) self.image = QImage() for action, check in self.resetableActions: action.setChecked(check) self.image = image self.filename = fname self.showImage() self.dirty = False self.sizeLabel.setText("{0} x {1}".format( image.width(), image.height())) message = "Loaded {0}".format(os.path.basename(fname)) self.updateStatus(message) def addRecentFile(self, fname): if fname is None: return if not self.recentFiles.contains(fname): self.recentFiles.prepend(QString(fname)) while self.recentFiles.count() > 9: self.recentFiles.takeLast() def fileSave(self): if self.image.isNull(): return True if self.filename is None: return self.fileSaveAs() else: if self.image.save(self.filename, None): self.updateStatus("Saved as {0}".format(self.filename)) self.dirty = False return True else: self.updateStatus("Failed to save {0}".format( self.filename)) return False def fileSaveAs(self): if self.image.isNull(): return True fname = self.filename if self.filename is not None else "." formats = (["*.{0}".format(unicode(format).lower()) for format in QImageWriter.supportedImageFormats()]) fname = unicode(QFileDialog.getSaveFileName(self, "Image Changer - Save Image", fname, "Image files ({0})".format(" ".join(formats)))) if fname: if "." not in fname: fname += ".png" self.addRecentFile(fname) self.filename = fname return self.fileSave() return False def filePrint(self): if self.image.isNull(): return if self.printer is None: self.printer = QPrinter(QPrinter.HighResolution) self.printer.setPageSize(QPrinter.Letter) form = QPrintDialog(self.printer, self) if form.exec_(): painter = QPainter(self.printer) rect = painter.viewport() size = self.image.size() size.scale(rect.size(), Qt.KeepAspectRatio) painter.setViewport(rect.x(), rect.y(), size.width(), size.height()) painter.drawImage(0, 0, self.image) def editInvert(self, on): if self.image.isNull(): return self.image.invertPixels() self.showImage() self.dirty = True self.updateStatus("Inverted" if on else "Uninverted") def editSwapRedAndBlue(self, on): if self.image.isNull(): return self.image = self.image.rgbSwapped() self.showImage() self.dirty = True self.updateStatus(("Swapped Red and Blue" if on else "Unswapped Red and Blue")) def editUnMirror(self, on): if self.image.isNull(): return if self.mirroredhorizontally: self.editMirrorHorizontal(False) if self.mirroredvertically: self.editMirrorVertical(False) def editMirrorHorizontal(self, on): if self.image.isNull(): return self.image = self.image.mirrored(True, False) self.showImage() self.mirroredhorizontally = not self.mirroredhorizontally self.dirty = True self.updateStatus(("Mirrored Horizontally" if on else "Unmirrored Horizontally")) def editMirrorVertical(self, on): if self.image.isNull(): return self.image = self.image.mirrored(False, True) self.showImage() self.mirroredvertically = not self.mirroredvertically self.dirty = True self.updateStatus(("Mirrored Vertically" if on else "Unmirrored Vertically")) def editZoom(self): if self.image.isNull(): return percent, ok = QInputDialog.getInteger(self, "Image Changer - Zoom", "Percent:", self.zoomSpinBox.value(), 1, 400) if ok: self.zoomSpinBox.setValue(percent) def editResize(self): if self.image.isNull(): return form = resizedlg.ResizeDlg(self.image.width(), self.image.height(), self) if form.exec_(): width, height = form.result() if (width == self.image.width() and height == self.image.height()): self.statusBar().showMessage("Resized to the same size", 5000) else: self.image = self.image.scaled(width, height) self.showImage() self.dirty = True size = "{0} x {1}".format(self.image.width(), self.image.height()) self.sizeLabel.setText(size) self.updateStatus("Resized to {0}".format(size)) def showImage(self, percent=None): if self.image.isNull(): return if percent is None: percent = self.zoomSpinBox.value() factor = percent / 100.0 width = self.image.width() * factor height = self.image.height() * factor image = self.image.scaled(width, height, Qt.KeepAspectRatio) self.imageLabel.setPixmap(QPixmap.fromImage(image)) def helpAbout(self): QMessageBox.about(self, "About Image Changer", """<b>Image Changer</b> v {0} <p>Copyright © 2008 Qtrac Ltd. All rights reserved. <p>This application can be used to perform simple image manipulations. <p>Python {1} - Qt {2} - PyQt {3} on {4}""".format( __version__, platform.python_version(), QT_VERSION_STR, PYQT_VERSION_STR, platform.system())) def helpHelp(self): form = helpform.HelpForm("index.html", self) form.show()
class AddToProject(QDialog): """Dialog to let the user choose one of the folders from the opened proj""" def __init__(self, projects, parent=None): super(AddToProject, self).__init__(parent) # pathProjects must be a list self._projects = projects self.setWindowTitle("XX") self.pathSelected = '' vbox = QVBoxLayout(self) hbox = QHBoxLayout() self._list = QListWidget() for project in self._projects: self._list.addItem(project['name']) # self._list.setCurrentRow(0) self._tree = QTreeView() # self._tree.header().setHidden(True) # self._tree.setSelectionMode(QTreeView.SingleSelection) # self._tree.setAnimated(True) self.load_tree(self._projects[0]) hbox.addWidget(self._list) hbox.addWidget(self._tree) vbox.addLayout(hbox) hbox2 = QHBoxLayout() btnAdd = QPushButton("XX") btnCancel = QPushButton("XX") hbox2.addWidget(btnCancel) hbox2.addWidget(btnAdd) vbox.addLayout(hbox2) self.connect(btnCancel, SIGNAL("clicked()"), self.close) self.connect(btnAdd, SIGNAL("clicked()"), self._select_path) self.connect( self._list, SIGNAL("currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)"), self._project_changed) def _project_changed(self, item, previous): # FIXME, this is not being called, at least in osx for each_project in self._projects: if each_project.name == item.text(): self.load_tree(each_project) def load_tree(self, project): """Load the tree view on the right based on the project selected.""" qfsm = QFileSystemModel() qfsm.setRootPath(project['path']) load_index = qfsm.index(qfsm.rootPath()) # qfsm.setFilter(QDir.AllDirs | QDir.NoDotAndDotDot) # qfsm.setNameFilterDisables(False) # pext = ["*{0}".format(x) for x in project['extensions']] # qfsm.setNameFilters(pext) self._tree.setModel(qfsm) self._tree.setRootIndex(load_index) t_header = self._tree.header() # t_header.setHorizontalScrollMode(QAbstractItemView.ScrollPerPixel) # t_header.setResizeMode(0, QHeaderView.Stretch) # t_header.setStretchLastSection(False) # t_header.setClickable(True) # # self._tree.hideColumn(1) # Size # self._tree.hideColumn(2) # Type # self._tree.hideColumn(3) # Modification date # FIXME: Changing the name column's title requires some magic # Please look at the project tree def _select_path(self): """Set pathSelected to the folder selected in the tree.""" path = self._tree.model().filePath(self._tree.currentIndex()) if path: self.pathSelected = path self.close()
class CustomizePlotDialog(QDialog): applySettings = pyqtSignal() undoSettings = pyqtSignal() redoSettings = pyqtSignal() resetSettings = pyqtSignal() copySettings = pyqtSignal(str) def __init__(self, title, parent=None): QDialog.__init__(self, parent) self.setWindowTitle(title) self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint) self.setWindowFlags(self.windowFlags() & ~Qt.WindowCloseButtonHint) self.setWindowFlags(self.windowFlags() & ~Qt.WindowCancelButtonHint) self._tab_map = {} self._tab_order = [] layout = QVBoxLayout() self._tabs = QTabWidget() layout.addWidget(self._tabs) layout.setSizeConstraint(QLayout.SetFixedSize) # not resizable!!! self._button_layout = QHBoxLayout() self._reset_button = QToolButton() self._reset_button.setIcon(util.resourceIcon("update.png")) self._reset_button.setToolTip("Reset all settings back to default") self._reset_button.clicked.connect(self.resetSettings) self._undo_button = QToolButton() self._undo_button.setIcon(util.resourceIcon("undo.png")) self._undo_button.setToolTip("Undo") self._undo_button.clicked.connect(self.undoSettings) self._redo_button = QToolButton() self._redo_button.setIcon(util.resourceIcon("redo.png")) self._redo_button.setToolTip("Redo") self._redo_button.clicked.connect(self.redoSettings) self._redo_button.setEnabled(False) self._copy_button = QToolButton() self._copy_button.setIcon(util.resourceIcon("page_copy.png")) self._copy_button.setToolTip("Copy settings from another key") self._copy_button.setPopupMode(QToolButton.InstantPopup) self._copy_button.setEnabled(False) tool_menu = QMenu(self._copy_button) self._popup_list = QListWidget(tool_menu) self._popup_list.setSortingEnabled(True) self._popup_list.itemClicked.connect(self.keySelected) action = QWidgetAction(tool_menu) action.setDefaultWidget(self._popup_list) tool_menu.addAction(action) self._copy_button.setMenu(tool_menu) self._apply_button = QPushButton("Apply") self._apply_button.setToolTip("Apply the new settings") self._apply_button.clicked.connect(self.applySettings) self._apply_button.setDefault(True) self._close_button = QPushButton("Close") self._close_button.setToolTip("Hide this dialog") self._close_button.clicked.connect(self.hide) self._button_layout.addWidget(self._reset_button) self._button_layout.addStretch() self._button_layout.addWidget(self._undo_button) self._button_layout.addWidget(self._redo_button) self._button_layout.addWidget(self._copy_button) self._button_layout.addStretch() self._button_layout.addWidget(self._apply_button) self._button_layout.addWidget(self._close_button) layout.addStretch() layout.addLayout(self._button_layout) self.setLayout(layout) def addCopyableKey(self, key): self._popup_list.addItem(key) def keySelected(self, list_widget_item): self.copySettings.emit(str(list_widget_item.text())) def keyPressEvent(self, q_key_event): if q_key_event.key() == Qt.Key_Escape: self.hide() else: QDialog.keyPressEvent(self, q_key_event) def addTab(self, attribute_name, title, widget): self._tabs.addTab(widget, title) self._tab_map[attribute_name] = widget self._tab_order.append(attribute_name) def __getitem__(self, item): """ @rtype: ert_gui.tools.plot.customize.customization_view.CustomizationView """ return self._tab_map[item] def __iter__(self): for attribute_name in self._tab_order: yield self._tab_map[attribute_name] def setUndoRedoCopyState(self, undo, redo, copy=False): self._undo_button.setEnabled(undo) self._redo_button.setEnabled(redo) self._copy_button.setEnabled(copy)
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 ToolDialog(QDialog): def __init__(self, parent=None): logging.debug(__name__ + ': __init__') QDialog.__init__(self, parent) self.resize(600, 500) self._selectedTool = None self._processCopy = None self._configDataAccessor = None self._toolsDir = standardToolsDir self.setWindowFlags(Qt.Window) self.setWindowTitle("Apply tool...") self.fill() def fill(self): logging.debug(__name__ + ': fill') self.setLayout(QVBoxLayout()) self._splitter = QSplitter() self.layout().addWidget(self._splitter) self._toolList = QListWidget(self._splitter) self.connect(self._toolList, SIGNAL("itemSelectionChanged()"), self.toolSelected) self._properties = PropertyView(self._splitter) bottom = QHBoxLayout() self.layout().addLayout(bottom) changedir = QPushButton("&Change tools directory...") bottom.addWidget(changedir) self.connect(changedir, SIGNAL('clicked()'), self.changedir) help = QPushButton("&Help") bottom.addWidget(help) self.connect(help, SIGNAL('clicked()'), self.help) bottom.addStretch() cancel = QPushButton('&Cancel') bottom.addWidget(cancel) self.connect(cancel, SIGNAL('clicked()'), self.reject) self.ok = QPushButton("&Apply") bottom.addWidget(self.ok) self.ok.setDefault(True) self.connect(self.ok, SIGNAL('clicked()'), self.apply) def updateToolList(self): self._toolList.clear() # import all tools and register them in toolsDict toolsFiles = [ os.path.join(self._toolsDir, f) for f in os.listdir(self._toolsDir) if f.endswith(".py") and not f.startswith("_") ] self._toolsDict = {} for toolsFile in toolsFiles: pythonModule = os.path.splitext(os.path.basename(toolsFile))[0] module = imp.load_source(pythonModule, toolsFile) for name in dir(module): tool = getattr(module, name) if inspect.isclass(tool) and issubclass( tool, ConfigToolBase) and not self._toolDataAccessor.label( tool) in self._toolsDict.keys( ) and not tool == ConfigToolBase: self._toolsDict[self._toolDataAccessor.label(tool)] = tool # Show test tool #from FWCore.GuiBrowsers.editorTools import ChangeSource #self._toolsDict["ChangeSource"]=ChangeSource if len(self._toolsDict) == 0 and self._toolsDir == standardToolsDir: logging.error( __name__ + ": Could not find any PAT tools. These will be available for the ConfigEditor in a future release." ) QCoreApplication.instance().errorMessage( "Could not find any PAT tools. These will be available for the ConfigEditor in a future release." ) return for item in self._toolsDict.keys(): self._toolList.addItem(item) self._toolList.sortItems() def keyPressEvent(self, event): if event.modifiers() == Qt.ControlModifier and event.key() == Qt.Key_W: self.reject() QDialog.keyPressEvent(self, event) def tool(self): return self._selectedTool def toolSelected(self): self._selectedTool = self._toolsDict[str( self._toolList.currentItem().text())]() self._properties.setDataObject(self._selectedTool) self._properties.updateContent() def setDataAccessor(self, accessor): self._properties.setDataAccessor(accessor) self._toolDataAccessor = accessor # save process copy to undo changes during the tool dialog self._processCopy = copy.deepcopy( self._toolDataAccessor.configDataAccessor().process()) self.updateToolList() def apply(self): # allow property view to process parameter changes if not self.ok.hasFocus(): self._properties.clearFocus() self.ok.setFocus() return parameterErrors = self._toolDataAccessor.parameterErrors( self._selectedTool) if len(parameterErrors) > 0: message = "\n".join([error for error in parameterErrors]) QCoreApplication.instance().errorMessage(message) return ok = True if self._selectedTool: try: self._selectedTool.apply( self._toolDataAccessor.configDataAccessor().process()) if not self._toolDataAccessor.configDataAccessor().process( ).checkRecording(): ok = False logging.error( __name__ + ": Could not apply tool " + self._toolDataAccessor.label(self._selectedTool) + " (problem with enable recording flag) Please restart the ConfigEditor." ) QCoreApplication.instance().errorMessage( "Could not apply tool " + self._toolDataAccessor.label(self._selectedTool) + " (problem with enable recording flag) Please restart the ConfigEditor." ) except Exception as e: ok = False logging.error( __name__ + ": Could not apply tool " + self._toolDataAccessor.label(self._selectedTool) + ": " + exception_traceback()) QCoreApplication.instance().errorMessage( "Cannot apply tool " + self._toolDataAccessor.label(self._selectedTool) + " (see log file for details):\n" + str(e)) else: ok = False logging.error(__name__ + ": Could not apply tool: No tool selected.") QCoreApplication.instance().errorMessage( "Cannot apply tool: No tool selected.") # recover process copy to undo changes during the tool dialog self._toolDataAccessor.configDataAccessor().setProcess( self._processCopy) if ok: self.accept() def changedir(self): filename = QFileDialog.getExistingDirectory(self, 'Select a directory', self._toolsDir, QFileDialog.ShowDirsOnly) if not filename.isEmpty(): self._toolsDir = str(filename) self.updateToolList() def help(self): QMessageBox.about( self, 'Info', "This dialog let's you choose and configure a tool.\n 1. Select a tool on the left\n 2. Set the parameters on the right. If you hold the mouse over a parameter name a tooltip with a description of the parameter will show up.\n 3. Apply the tool. In case the tool has wrong parameters set an error message will be displayed." )
class ErrorsWidget(QDialog): ############################################################################### # ERRORS WIDGET SIGNALS ############################################################################### """ pep8Activated(bool) lintActivated(bool) """ ############################################################################### def __init__(self, parent=None): super(ErrorsWidget, self).__init__(parent, Qt.WindowStaysOnTopHint) self.pep8 = None self._outRefresh = True vbox = QVBoxLayout(self) self.listErrors = QListWidget() self.listErrors.setSortingEnabled(True) self.listPep8 = QListWidget() self.listPep8.setSortingEnabled(True) hbox_lint = QHBoxLayout() if settings.FIND_ERRORS: self.btn_lint_activate = QPushButton(self.tr("Lint: ON")) else: self.btn_lint_activate = QPushButton(self.tr("Lint: OFF")) self.errorsLabel = QLabel(self.tr("Static Errors: %s") % 0) hbox_lint.addWidget(self.errorsLabel) hbox_lint.addSpacerItem(QSpacerItem(1, 0, QSizePolicy.Expanding)) hbox_lint.addWidget(self.btn_lint_activate) vbox.addLayout(hbox_lint) vbox.addWidget(self.listErrors) hbox_pep8 = QHBoxLayout() if settings.CHECK_STYLE: self.btn_pep8_activate = QPushButton(self.tr("PEP8: ON")) else: self.btn_pep8_activate = QPushButton(self.tr("PEP8: OFF")) self.pep8Label = QLabel(self.tr("PEP8 Errors: %s") % 0) hbox_pep8.addWidget(self.pep8Label) hbox_pep8.addSpacerItem(QSpacerItem(1, 0, QSizePolicy.Expanding)) hbox_pep8.addWidget(self.btn_pep8_activate) vbox.addLayout(hbox_pep8) vbox.addWidget(self.listPep8) self.connect(self.listErrors, SIGNAL("itemSelectionChanged()"), self.errors_selected) self.connect(self.listPep8, SIGNAL("itemSelectionChanged()"), self.pep8_selected) self.connect(self.btn_lint_activate, SIGNAL("clicked()"), self._turn_on_off_lint) self.connect(self.btn_pep8_activate, SIGNAL("clicked()"), self._turn_on_off_pep8) IDE.register_service('tab_errors', self) ExplorerContainer.register_tab(translations.TR_TAB_ERRORS, self) def install_tab(self): ide = IDE.get_service('ide') self.connect(ide, SIGNAL("goingDown()"), self.close) def _turn_on_off_lint(self): """Change the status of the lint checker state.""" settings.FIND_ERRORS = not settings.FIND_ERRORS if settings.FIND_ERRORS: self.btn_lint_activate.setText(self.tr("Lint: ON")) self.listErrors.show() else: self.btn_lint_activate.setText(self.tr("Lint: OFF")) self.listErrors.hide() self.emit(SIGNAL("lintActivated(bool)"), settings.FIND_ERRORS) def _turn_on_off_pep8(self): """Change the status of the lint checker state.""" settings.CHECK_STYLE = not settings.CHECK_STYLE if settings.CHECK_STYLE: self.btn_pep8_activate.setText(self.tr("PEP8: ON")) self.listPep8.show() else: self.btn_pep8_activate.setText(self.tr("PEP8: OFF")) self.listPep8.hide() self.emit(SIGNAL("pep8Activated(bool)"), settings.CHECK_STYLE) def errors_selected(self): main_container = IDE.get_service('main_container') if main_container: editorWidget = main_container.get_current_editor() if editorWidget and self._outRefresh: lineno = int(self.listErrors.currentItem().data(Qt.UserRole)) editorWidget.jump_to_line(lineno) editorWidget.setFocus() def pep8_selected(self): main_container = IDE.get_service('main_container') if main_container: editorWidget = main_container.get_current_editor() if editorWidget and self._outRefresh: lineno = int(self.listPep8.currentItem().data(Qt.UserRole)) editorWidget.jump_to_line(lineno) editorWidget.setFocus() def refresh_pep8_list(self, pep8): self._outRefresh = False self.listPep8.clear() for lineno in pep8: linenostr = 'L%s\t' % str(lineno + 1) for data in pep8[lineno]: item = QListWidgetItem(linenostr + data.split('\n')[0]) item.setToolTip(linenostr + data.split('\n')[0]) item.setData(Qt.UserRole, lineno) self.listPep8.addItem(item) self.pep8Label.setText(self.tr("PEP8 Errors: %s") % len(pep8)) self._outRefresh = True def refresh_error_list(self, errors): self._outRefresh = False self.listErrors.clear() for lineno in errors: linenostr = 'L%s\t' % str(lineno + 1) for data in errors[lineno]: item = QListWidgetItem(linenostr + data) item.setToolTip(linenostr + data) item.setData(Qt.UserRole, lineno) self.listErrors.addItem(item) self.errorsLabel.setText(self.tr("Static Errors: %s") % len(errors)) self._outRefresh = True def clear(self): """ Clear the widget """ self.listErrors.clear() self.listPep8.clear() def reject(self): if self.parent() is None: self.emit(SIGNAL("dockWidget(PyQt_PyObject)"), self) def closeEvent(self, event): self.emit(SIGNAL("dockWidget(PyQt_PyObject)"), self) event.ignore()
class EditorGeneral(QWidget): """EditorGeneral widget class.""" def __init__(self, parent): super(EditorGeneral, self).__init__() self._preferences, vbox = parent, QVBoxLayout(self) self.original_style = copy.copy(resources.CUSTOM_SCHEME) self.current_scheme, self._modified_editors = 'default', [] self._font = settings.FONT groupBoxMini = QGroupBox( translations.TR_PREFERENCES_EDITOR_GENERAL_MINIMAP) groupBoxTypo = QGroupBox( translations.TR_PREFERENCES_EDITOR_GENERAL_TYPOGRAPHY) groupBoxScheme = QGroupBox( translations.TR_PREFERENCES_EDITOR_GENERAL_SCHEME) #Minimap formMini = QGridLayout(groupBoxMini) formMini.setContentsMargins(5, 15, 5, 5) self._checkShowMinimap = QCheckBox( translations.TR_PREFERENCES_EDITOR_GENERAL_ENABLE_MINIMAP) self._spinMaxOpacity = QSpinBox() self._spinMaxOpacity.setRange(0, 100) self._spinMaxOpacity.setSuffix("% Max.") self._spinMinOpacity = QSpinBox() self._spinMinOpacity.setRange(0, 100) self._spinMinOpacity.setSuffix("% Min.") self._spinSize = QSpinBox() self._spinSize.setMaximum(100) self._spinSize.setMinimum(0) self._spinSize.setSuffix( translations.TR_PREFERENCES_EDITOR_GENERAL_AREA_MINIMAP) formMini.addWidget(self._checkShowMinimap, 0, 1) formMini.addWidget(QLabel( translations.TR_PREFERENCES_EDITOR_GENERAL_SIZE_MINIMAP), 1, 0, Qt.AlignRight) formMini.addWidget(self._spinSize, 1, 1) formMini.addWidget(QLabel( translations.TR_PREFERENCES_EDITOR_GENERAL_OPACITY), 2, 0, Qt.AlignRight) formMini.addWidget(self._spinMinOpacity, 2, 1) formMini.addWidget(self._spinMaxOpacity, 2, 2) #Typo gridTypo = QGridLayout(groupBoxTypo) gridTypo.setContentsMargins(5, 15, 5, 5) self._btnEditorFont = QPushButton('') gridTypo.addWidget(QLabel( translations.TR_PREFERENCES_EDITOR_GENERAL_EDITOR_FONT), 0, 0, Qt.AlignRight) gridTypo.addWidget(self._btnEditorFont, 0, 1) #Scheme vboxScheme = QVBoxLayout(groupBoxScheme) vboxScheme.setContentsMargins(5, 15, 5, 5) self._listScheme = QListWidget() vboxScheme.addWidget(self._listScheme) hbox = QHBoxLayout() btnDownload = QPushButton( translations.TR_PREFERENCES_EDITOR_DOWNLOAD_SCHEME) btnDownload.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self.connect(btnDownload, SIGNAL("clicked()"), self._open_schemes_manager) hbox.addWidget(btnDownload) btnAdd = QPushButton(QIcon(":img/add"), translations.TR_EDITOR_CREATE_SCHEME) btnAdd.setIconSize(QSize(16, 16)) btnAdd.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self.connect(btnAdd, SIGNAL("clicked()"), self._open_schemes_designer) btnRemove = QPushButton(QIcon(":img/delete"), translations.TR_EDITOR_REMOVE_SCHEME) btnRemove.setIconSize(QSize(16, 16)) btnRemove.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self.connect(btnRemove, SIGNAL("clicked()"), self._remove_scheme) hbox.addSpacerItem(QSpacerItem(1, 0, QSizePolicy.Expanding)) hbox.addWidget(btnAdd) hbox.addWidget(btnRemove) vboxScheme.addLayout(hbox) vbox.addWidget(groupBoxMini) vbox.addWidget(groupBoxTypo) vbox.addWidget(groupBoxScheme) #Settings qsettings = IDE.ninja_settings() qsettings.beginGroup('preferences') qsettings.beginGroup('editor') self._checkShowMinimap.setChecked(settings.SHOW_MINIMAP) if settings.IS_MAC_OS: self._spinMinOpacity.setValue(100) self._spinMaxOpacity.setValue(100) self._spinMinOpacity.setDisabled(True) self._spinMaxOpacity.setDisabled(True) else: self._spinMinOpacity.setValue(settings.MINIMAP_MIN_OPACITY * 100) self._spinMaxOpacity.setValue(settings.MINIMAP_MAX_OPACITY * 100) self._spinSize.setValue(settings.SIZE_PROPORTION * 100) btnText = ', '.join(self._font.toString().split(',')[0:2]) self._btnEditorFont.setText(btnText) self._listScheme.clear() self._listScheme.addItem('default') self._schemes = json_manager.load_editor_skins() for item in self._schemes: self._listScheme.addItem(item) items = self._listScheme.findItems( qsettings.value('scheme', defaultValue='', type='QString'), Qt.MatchExactly) if items: self._listScheme.setCurrentItem(items[0]) else: self._listScheme.setCurrentRow(0) qsettings.endGroup() qsettings.endGroup() #Signals self.connect(self._btnEditorFont, SIGNAL("clicked()"), self._load_editor_font) self.connect(self._listScheme, SIGNAL("itemSelectionChanged()"), self._preview_style) self.connect(self._preferences, SIGNAL("savePreferences()"), self.save) def _open_schemes_manager(self): ninjaide = IDE.get_service("ide") ninjaide.show_schemes() # refresh schemes def _open_schemes_designer(self): name = self._listScheme.currentItem().text() scheme = self._schemes.get(name, resources.COLOR_SCHEME) designer = preferences_editor_scheme_designer.EditorSchemeDesigner( scheme, self) designer.exec_() if designer.saved: scheme_name = designer.line_name.text() scheme = designer.original_style self._schemes[scheme_name] = scheme result = self._listScheme.findItems(scheme_name, Qt.MatchExactly) if not result: self._listScheme.addItem(scheme_name) def _remove_scheme(self): name = self._listScheme.currentItem().text() fileName = ('{0}.color'.format( file_manager.create_path(resources.EDITOR_SKINS, name))) file_manager.delete_file(fileName) item = self._listScheme.takeItem(self._listScheme.currentRow()) del item def hideEvent(self, event): super(EditorGeneral, self).hideEvent(event) resources.CUSTOM_SCHEME = self.original_style for editorWidget in self._modified_editors: try: editorWidget.restyle(editorWidget.lang) except RuntimeError: print('the editor has been removed') def _preview_style(self): scheme = self._listScheme.currentItem().text() if scheme == self.current_scheme: return main_container = IDE.get_service('main_container') if not main_container: return editorWidget = main_container.get_current_editor() if editorWidget is not None: resources.CUSTOM_SCHEME = self._schemes.get( scheme, resources.COLOR_SCHEME) editorWidget.restyle(editorWidget.lang) self._modified_editors.append(editorWidget) self.current_scheme = scheme def _load_editor_font(self): try: font, ok = QFontDialog.getFont(self._font, self) if ok: self._font = font btnText = ', '.join(self._font.toString().split(',')[0:2]) self._btnEditorFont.setText(btnText) except: QMessageBox.warning( self, translations.TR_PREFERENCES_EDITOR_GENERAL_FONT_MESSAGE_TITLE, translations.TR_PREFERENCES_EDITOR_GENERAL_FONT_MESSAGE_BODY) def save(self): qsettings = IDE.ninja_settings() settings.FONT = self._font qsettings.setValue('preferences/editor/font', settings.FONT) settings.SHOW_MINIMAP = self._checkShowMinimap.isChecked() settings.MINIMAP_MAX_OPACITY = self._spinMaxOpacity.value() / 100.0 settings.MINIMAP_MIN_OPACITY = self._spinMinOpacity.value() / 100.0 settings.SIZE_PROPORTION = self._spinSize.value() / 100.0 qsettings.setValue('preferences/editor/minimapMaxOpacity', settings.MINIMAP_MAX_OPACITY) qsettings.setValue('preferences/editor/minimapMinOpacity', settings.MINIMAP_MIN_OPACITY) qsettings.setValue('preferences/editor/minimapSizeProportion', settings.SIZE_PROPORTION) qsettings.setValue('preferences/editor/minimapShow', settings.SHOW_MINIMAP) scheme = self._listScheme.currentItem().text() resources.CUSTOM_SCHEME = self._schemes.get(scheme, resources.COLOR_SCHEME) qsettings.setValue('preferences/editor/scheme', scheme)
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 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 ShowPresets(QDialog): def __init__(self, parent=None): super(ShowPresets, self).__init__(parent) self.original_presets_file = '/usr/share/ffmulticonverter/presets.xml' self.config_folder = os.getenv('HOME') + '/.config/ffmulticonverter/' self.current_presets_file = self.config_folder + 'presets.xml' self.presListWidget = QListWidget() labelLabel = QLabel(self.tr('Preset label')) self.labelLineEdit = QLineEdit() self.labelLineEdit.setReadOnly(True) commandLabel = QLabel(self.tr('Preset command line parameters')) self.commandLineEdit = QLineEdit() self.commandLineEdit.setReadOnly(True) extLabel = QLabel(self.tr('Output file extension')) self.extLineEdit = QLineEdit() self.extLineEdit.setReadOnly(True) addButton = QPushButton(self.tr('Add')) self.deleteButton = QPushButton(self.tr('Delete')) self.delete_allButton = QPushButton(self.tr('Delete all')) self.editButton = QPushButton(self.tr('Edit')) searchLabel = QLabel(self.tr('Search')) self.searchLineEdit = QLineEdit() okButton = QPushButton(self.tr('OK')) okButton.setDefault(True) spc1 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) spc2 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) spc3 = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) grid = pyqttools.add_to_grid( QGridLayout(), [self.delete_allButton, addButton, spc1], [self.deleteButton, self.editButton, spc2]) hlayout = pyqttools.add_to_layout(QHBoxLayout(), searchLabel, self.searchLineEdit, None, okButton) final_layout = pyqttools.add_to_layout( QVBoxLayout(), self.presListWidget, labelLabel, self.labelLineEdit, commandLabel, self.commandLineEdit, extLabel, self.extLineEdit, grid, spc3, hlayout) self.setLayout(final_layout) okButton.clicked.connect(self.accept) self.presListWidget.currentRowChanged.connect(self.show_preset) addButton.clicked.connect(self.add_preset) self.deleteButton.clicked.connect(self.delete_preset) self.delete_allButton.clicked.connect(self.delete_all_presets) self.editButton.clicked.connect(self.edit_preset) self.searchLineEdit.textEdited.connect(self.search) del_shortcut = QShortcut(self) del_shortcut.setKey(Qt.Key_Delete) del_shortcut.activated.connect(self.delete_preset) self.resize(430, 480) self.setWindowTitle(self.tr('Edit Presets')) QTimer.singleShot(0, self.load_xml) QTimer.singleShot(0, self.fill_presListWidget) def load_xml(self): """Load xml tree and set xml root.""" try: self.tree = etree.parse(self.current_presets_file) except (etree.ParseError, IOError): try: self.tree = etree.parse(self.original_presets_file) except IOError: # when program is not installed self.tree = etree.parse('../share/presets.xml') if not os.path.exists(self.config_folder): os.makedirs(self.config_folder) self.root = self.tree.getroot() def set_buttons_clear_lineEdits(self): """Enable or disable button's and clear lineEdits.""" enable = bool(self.presListWidget) self.editButton.setEnabled(enable) self.deleteButton.setEnabled(enable) self.delete_allButton.setEnabled(enable) if not enable: self.labelLineEdit.clear() self.commandLineEdit.clear() self.extLineEdit.clear() def fill_presListWidget(self): """Clear self.presListWidget and to it presets' tags.""" self.presListWidget.clear() for i in sorted([y.tag for y in self.root]): elem = self.root.find(i) self.presListWidget.addItem(MyListItem(i, elem)) self.presListWidget.setCurrentRow(0) self.set_buttons_clear_lineEdits() self.searchLineEdit.clear() def show_preset(self): """Fill LineEdits with current xml element's values.""" try: xml_elem = self.presListWidget.currentItem().xml_element except AttributeError: return self.labelLineEdit.setText(xml_elem[0].text) self.commandLineEdit.setText(xml_elem[1].text) self.commandLineEdit.home(False) self.extLineEdit.setText(xml_elem[2].text) def add_preset(self): """Open AddorEditPreset() dialog and add a preset xml root.""" dialog = AddorEditPreset(None, False, self) if dialog.exec_(): element = etree.Element(dialog.name_text) label = etree.Element('label') label.text = dialog.label_text command = etree.Element('params') command.text = dialog.command_text ext = etree.Element('extension') ext.text = dialog.ext_text category = etree.Element('category') category.text = 'Scattered' for num, elem in enumerate([label, command, ext, category]): element.insert(num, elem) index = sorted([i.tag for i in self.root] + [dialog.name_text])\ .index(dialog.name_text) self.root.insert(index, element) self.save_tree() self.fill_presListWidget() def delete_preset(self): """ Ask user wether he wants to delete the selected preset. If so, delete the preset from xml root. """ try: xml_elem = self.presListWidget.currentItem().xml_element except AttributeError: return reply = QMessageBox.question( self, 'FF Multi Converter - ' + self.tr('Delete Preset'), self.tr('Are you sure that you want to delete ' 'the %1 preset?').arg(xml_elem.tag), QMessageBox.Yes | QMessageBox.Cancel) if reply == QMessageBox.Yes: self.root.remove(xml_elem) self.save_tree() self.fill_presListWidget() def delete_all_presets(self): """ Ask user if he wants to delete all presets. If so, clear xml root. """ reply = QMessageBox.question( self, 'FF Multi Converter - ' + self.tr('Delete Preset'), self.tr('Are you sure that you want to delete ' 'all presets?'), QMessageBox.Yes | QMessageBox.Cancel) if reply == QMessageBox.Yes: self.root.clear() self.save_tree() self.fill_presListWidget() def edit_preset(self): """Call the AddorEditPreset() dialog and update xml element's values.""" elem = self.presListWidget.currentItem().xml_element dialog = AddorEditPreset(elem, True) if dialog.exec_(): elem.tag = dialog.name_text elem[0].text = dialog.label_text elem[1].text = dialog.command_text elem[2].text = dialog.ext_text self.save_tree() self.fill_presListWidget() def search(self): """ Search for keywords in presets data. Show a preset only if its tag, label or extension matches any of search string's tokens. """ txt = str(self.searchLineEdit.text()).strip().lower() if not txt: self.fill_presListWidget() return self.presListWidget.clear() for i in txt.split(' '): for p in sorted([y.tag for y in self.root]): elem = self.root.find(p) if (i.strip() and (i in elem.tag.lower() or i in elem[0].text.lower() or i in elem[2].text.lower())): self.presListWidget.addItem(MyListItem(p, elem)) self.presListWidget.setCurrentRow(0) self.set_buttons_clear_lineEdits() def save_tree(self): """Save xml tree.""" with open(self.current_presets_file, 'w') as _file: try: etree.ElementTree(self.root).write(_file) except: pass def import_presets(self): """Import an xml tree.""" title = 'FF Multi Converter - Import' reply = QMessageBox.question( self, title, self.tr('All current ' 'presets will be deleted.\nAre you sure that you want to ' 'continue?'), QMessageBox.Yes | QMessageBox.Cancel) if reply == QMessageBox.Yes: fname = QFileDialog.getOpenFileName(self, title) if fname: msg = self.tr('Succesful import!') try: self.tree = etree.parse(fname) except: msg = self.tr('Import failed!') else: self.root = self.tree.getroot() self.save_tree() QMessageBox.information(self, title, msg) def export_presets(self): """Export the xml tree.""" fname = QFileDialog.getSaveFileName( self, 'FF Multi Converter - Export presets', '.xml') if fname: self.load_xml() with open(fname, 'w') as _file: try: etree.ElementTree(self.root).write(_file) except: pass def reset(self): """Import the default xml tree.""" reply = QMessageBox.question( self, 'FF Multi Converter - ' + self.tr('Delete Preset'), self.tr('Are you sure that you want to restore ' 'the default presets?'), QMessageBox.Yes | QMessageBox.Cancel) if reply == QMessageBox.Yes: if os.path.exists(self.current_presets_file): os.remove(self.current_presets_file) def synchronize(self): """ Synchronize current presets with default presets. For each preset in default presets: - if not contained in current presets, add it to current presets - if has the same name with some preset in current presets but different attributes, then add this preset to current presets and add an '__OLD' suffix to matching preset's name """ reply = QMessageBox.question( self, 'FF Multi Converter - ' + self.tr('Presets Synchronization'), self. tr('Current presets and default ' 'presets will be merged. Are you sure that you want to continue?' ), QMessageBox.Yes | QMessageBox.Cancel) if not reply == QMessageBox.Yes: return def_tree = etree.parse(self.original_presets_file) def_root = def_tree.getroot() self.load_xml() for i in def_root: for n, y in enumerate(self.root): if i.tag == y.tag: if not (i[0].text == y[0].text and i[1].text == y[1].text and i[2].text == y[2].text): # copy element and change its name elem = etree.Element(y.tag) label = etree.Element('label') label.text = i[0].text command = etree.Element('params') command.text = i[1].text ext = etree.Element('extension') ext.text = i[2].text elem.insert(0, label) elem.insert(1, command) elem.insert(2, ext) y.tag = y.tag + '__OLD' self.root.insert(n + 1, elem) break else: # preset not found index = sorted([x.tag for x in self.root] + [i.tag]).index(i.tag) self.root.insert(index, i) self.save_tree() def remove_old(self): """Remove those xml elements which their tags has an __OLD prefix.""" reply = QMessageBox.question( self, 'FF Multi Converter - ' + self.tr('Remove old presets'), self.tr( 'All presets with an __OLD prefix ' 'will be deleted. Are you sure that you want to continue?'), QMessageBox.Yes | QMessageBox.Cancel) if not reply == QMessageBox.Yes: return self.load_xml() for i in self.root: if i.tag.endswith('__OLD'): self.root.remove(i) self.save_tree() def accept(self): """ Save current xml element's values in order to be used from main program and close (accept) dialog. """ self.the_command = None if self.presListWidget: self.the_command = self.presListWidget.currentItem()\ .xml_element[1].text self.the_extension = self.presListWidget.currentItem()\ .xml_element[2].text QDialog.accept(self)
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 Theme(QWidget): """Theme widget class.""" def __init__(self, parent): super(Theme, self).__init__() self._preferences, vbox = parent, QVBoxLayout(self) vbox.addWidget(QLabel(self.tr("<b>Select Theme:</b>"))) self.list_skins = QListWidget() self.list_skins.setSelectionMode(QListWidget.SingleSelection) vbox.addWidget(self.list_skins) self.btn_delete = QPushButton(self.tr("Delete Theme")) self.btn_preview = QPushButton(self.tr("Preview Theme")) self.btn_create = QPushButton(self.tr("Create Theme")) hbox = QHBoxLayout() hbox.addWidget(self.btn_delete) hbox.addSpacerItem( QSpacerItem(10, 0, QSizePolicy.Expanding, QSizePolicy.Fixed)) hbox.addWidget(self.btn_preview) hbox.addWidget(self.btn_create) vbox.addLayout(hbox) self._refresh_list() self.connect(self.btn_preview, SIGNAL("clicked()"), self.preview_theme) self.connect(self.btn_delete, SIGNAL("clicked()"), self.delete_theme) self.connect(self.btn_create, SIGNAL("clicked()"), self.create_theme) self.connect(self._preferences, SIGNAL("savePreferences()"), self.save) def delete_theme(self): if self.list_skins.currentRow() != 0: file_name = ("%s.qss" % self.list_skins.currentItem().text()) qss_file = file_manager.create_path(resources.NINJA_THEME_DOWNLOAD, file_name) file_manager.delete_file(qss_file) self._refresh_list() def create_theme(self): designer = preferences_theme_editor.ThemeEditor(self) designer.exec_() self._refresh_list() def showEvent(self, event): self._refresh_list() super(Theme, self).showEvent(event) def _refresh_list(self): self.list_skins.clear() self.list_skins.addItem("Default") files = sorted([ file_manager.get_file_name(filename) for filename in file_manager.get_files_from_folder( resources.NINJA_THEME_DOWNLOAD, "qss") ]) self.list_skins.addItems(files) if settings.NINJA_SKIN in files: index = files.index(settings.NINJA_SKIN) self.list_skins.setCurrentRow(index + 1) else: self.list_skins.setCurrentRow(0) def save(self): qsettings = IDE.ninja_settings() settings.NINJA_SKIN = self.list_skins.currentItem().text() qsettings.setValue("preferences/theme/skin", settings.NINJA_SKIN) self.preview_theme() def preview_theme(self): if self.list_skins.currentRow() == 0: qss_file = resources.NINJA_THEME else: file_name = ("%s.qss" % self.list_skins.currentItem().text()) qss_file = file_manager.create_path(resources.NINJA_THEME_DOWNLOAD, file_name) with open(qss_file) as f: qss = f.read() QApplication.instance().setStyleSheet(qss)
class MigrationWidget(QWidget): def __init__(self): super(MigrationWidget, self).__init__() self._migration = {} vbox = QVBoxLayout(self) lbl_title = QLabel(self.tr("Current code:")) self.current_list = QListWidget() lbl_suggestion = QLabel(self.tr("Suggested changes:")) self.suggestion = QPlainTextEdit() self.suggestion.setReadOnly(True) self.btn_apply = QPushButton(self.tr("Apply change!")) hbox = QHBoxLayout() hbox.addSpacerItem(QSpacerItem(1, 0, QSizePolicy.Expanding)) hbox.addWidget(self.btn_apply) vbox.addWidget(lbl_title) vbox.addWidget(self.current_list) vbox.addWidget(lbl_suggestion) vbox.addWidget(self.suggestion) vbox.addLayout(hbox) self.connect(self.current_list, SIGNAL("itemClicked(QListWidgetItem*)"), self.load_suggestion) self.connect(self.btn_apply, SIGNAL("clicked()"), self.apply_changes) def apply_changes(self): lineno = int(self.current_list.currentItem().data(Qt.UserRole)) lines = self._migration.migration_data[lineno][0].split('\n') remove = -1 code = '' for line in lines: if line.startswith('-'): remove += 1 elif line.startswith('+'): code += '%s\n' % line[1:] editorWidget = main_container.MainContainer().get_actual_editor() block_start = editorWidget.document().findBlockByLineNumber(lineno) block_end = editorWidget.document().findBlockByLineNumber(lineno + remove) cursor = editorWidget.textCursor() cursor.setPosition(block_start.position()) cursor.setPosition(block_end.position(), QTextCursor.KeepAnchor) cursor.movePosition(QTextCursor.EndOfLine, QTextCursor.KeepAnchor) cursor.insertText(code[:-1]) def load_suggestion(self, item): lineno = int(item.data(Qt.UserRole)) lines = self._migration.migration_data[lineno][0].split('\n') code = '' for line in lines: if line.startswith('+'): code += '%s\n' % line[1:] self.suggestion.setPlainText(code) editorWidget = main_container.MainContainer().get_actual_editor() if editorWidget: editorWidget.jump_to_line(lineno) editorWidget.setFocus() def refresh_lists(self, migration): self._migration = migration self.current_list.clear() base_lineno = -1 for lineno in sorted(migration.migration_data.keys()): linenostr = 'L%s\n' % str(lineno + 1) data = migration.migration_data[lineno] lines = data[0].split('\n') if base_lineno == data[1]: continue base_lineno = data[1] message = '' for line in lines: if line.startswith('-'): message += '%s\n' % line item = QListWidgetItem(linenostr + message) item.setToolTip(linenostr + message) item.setData(Qt.UserRole, lineno) self.current_list.addItem(item) def clear(self): """ Clear the widget """ self.current_list.clear() self.suggestion.clear()
class MigrationWidget(QDialog): def __init__(self, parent=None): super(MigrationWidget, self).__init__(parent, Qt.WindowStaysOnTopHint) self._migration = {} vbox = QVBoxLayout(self) lbl_title = QLabel(self.tr("Current code:")) self.current_list = QListWidget() lbl_suggestion = QLabel(self.tr("Suggested changes:")) self.suggestion = QPlainTextEdit() self.suggestion.setReadOnly(True) self.btn_apply = QPushButton(self.tr("Apply change!")) hbox = QHBoxLayout() hbox.addSpacerItem(QSpacerItem(1, 0, QSizePolicy.Expanding)) hbox.addWidget(self.btn_apply) vbox.addWidget(lbl_title) vbox.addWidget(self.current_list) vbox.addWidget(lbl_suggestion) vbox.addWidget(self.suggestion) vbox.addLayout(hbox) self.connect(self.current_list, SIGNAL("itemClicked(QListWidgetItem*)"), self.load_suggestion) self.connect(self.btn_apply, SIGNAL("clicked()"), self.apply_changes) IDE.register_service('tab_migration', self) ExplorerContainer.register_tab(translations.TR_TAB_MIGRATION, self) def install_tab(self): ide = IDE.get_service('ide') self.connect(ide, SIGNAL("goingDown()"), self.close) def apply_changes(self): lineno = int(self.current_list.currentItem().data(Qt.UserRole)) lines = self._migration[lineno][0].split('\n') remove = -1 code = '' for line in lines: if line.startswith('-'): remove += 1 elif line.startswith('+'): code += '%s\n' % line[1:] main_container = IDE.get_service('main_container') if main_container: editorWidget = main_container.get_current_editor() block_start = editorWidget.document().findBlockByLineNumber(lineno) block_end = editorWidget.document().findBlockByLineNumber(lineno + remove) cursor = editorWidget.textCursor() cursor.setPosition(block_start.position()) cursor.setPosition(block_end.position(), QTextCursor.KeepAnchor) cursor.movePosition(QTextCursor.EndOfLine, QTextCursor.KeepAnchor) cursor.insertText(code[:-1]) def load_suggestion(self, item): lineno = int(item.data(Qt.UserRole)) lines = self._migration[lineno][0].split('\n') code = '' for line in lines: if line.startswith('+'): code += '%s\n' % line[1:] self.suggestion.setPlainText(code) main_container = IDE.get_service('main_container') if main_container: editorWidget = main_container.get_current_editor() if editorWidget: editorWidget.jump_to_line(lineno) editorWidget.setFocus() def refresh_lists(self, migration): self._migration = migration self.current_list.clear() base_lineno = -1 for lineno in sorted(migration.keys()): linenostr = 'L%s\n' % str(lineno + 1) data = migration[lineno] lines = data[0].split('\n') if base_lineno == data[1]: continue base_lineno = data[1] message = '' for line in lines: if line.startswith('-'): message += '%s\n' % line item = QListWidgetItem(linenostr + message) item.setToolTip(linenostr + message) item.setData(Qt.UserRole, lineno) self.current_list.addItem(item) def clear(self): """ Clear the widget """ self.current_list.clear() self.suggestion.clear() def reject(self): if self.parent() is None: self.emit(SIGNAL("dockWidget(PyQt_PyObject)"), self) def closeEvent(self, event): self.emit(SIGNAL("dockWidget(PyQt_PyObject)"), self) event.ignore()
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)
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 LeapFlow (QMainWindow): def __init__ (self): QMainWindow.__init__ (self) self.controller = Controller () self.listener = LeapListener (self) self.controller.add_listener (self.listener) self.mode = "gallery" self.scroll = False self.direction = "" self.direction_x = 0 self.scroll_velocity = 0 self.current_index = 0 # List containing images for the gallery self.list_view = QListWidget () self.list_view.setFlow (0) self.list_view.setHorizontalScrollMode (1) self.list_view.setMouseTracking (True) self.list_view.itemClicked.connect (self.show_image) # Setting the style of the ListView, background, item selected, etc self.list_view.setStyleSheet (""" QListWidget::item:hover {background: transparent;} QListWidget::item:disabled:hover {background: transparent;} QListWidget::item:hover:!active {background: transparent;} QListWidget::item:selected:active {background: transparent;} QListWidget::item:selected:!active {background: transparent;} QListWidget::item:selected:disabled {background: transparent;} QListWidget::item:selected:!disabled {background: transparent;} QListWidget {background: #2C3539} """) # Image viewer self.scene = QGraphicsScene () self.viewer = QGraphicsView (self.scene) self.stackedWidget = QStackedWidget () self.stackedWidget.addWidget (self.list_view) self.stackedWidget.addWidget (self.viewer) self.setCentralWidget (self.stackedWidget) self.resize (500, 400) self.showMaximized () scan = ScanLibrary ("/home/chris/Example") threads.append (scan) self.connect (scan, SIGNAL (scan.signal), self.add_images_to_list) scan.start () self.connect (self, SIGNAL ("scrollChanged(bool)"), self.scroll_view) def setScroll (self, scroll): """Emit signal to scroll the view""" if (self.scroll != scroll): self.scroll = scroll self.emit (SIGNAL("scrollChanged(bool)"), scroll) def scroll_view (self): """Scroll the view based on scroll velocity and direction""" x = self.direction_x * self.scroll_velocity / 100 bar_x = self.list_view.horizontalScrollBar ().value () self.list_view.horizontalScrollBar ().setValue (bar_x + x) def add_images_to_list (self): """To add a widget to the listview you must add a QListWidgetItem and replace with your widget""" for image in library: item = QListWidgetItem () pixmap = QPixmap.fromImage (QImage (library[image])) label = QLabel () label.setPixmap (pixmap.scaled (600, 400)) item.setSizeHint (label.sizeHint ()) item.setData (0, library[image]) self.list_view.addItem (item) self.list_view.setItemWidget (item, label) def show_image (self, item): """"Display the selected image""" self.current_index = self.list_view.indexFromItem (item).row () self.scene.addPixmap ((QPixmap.fromImage (QImage (item.text()))).scaled (self.viewer.size())) self.stackedWidget.setCurrentIndex (1) self.mode = "viewer" def previous_image (self): """Load previous image""" if self.current_index - 1 >= 0: self.current_index -= 1 self.load_image () def next_image (self): """Load next image""" if self.current_index + 1 <= len(library.keys ()) - 1: self.current_index += 1 self.load_image () def load_image (self): """Load the image in self.current_index""" self.scene.addPixmap (QPixmap.fromImage (QImage (library[library.keys()[self.current_index]])))
class Completer(QCompleter): def __init__(self, editor, project): QCompleter.__init__(self) self.icons = { 'function': QIcon(resources.images['function']), 'instance': QIcon(resources.images['attribute']), 'module': QIcon(resources.images['module']), 'class': QIcon(resources.images['class']) } self._editor = editor self._fromProject = False if project is not None: if type(project) is str: project = rope.base.project.Project(project, None, '.ninjaproject') self._project = project self._fromProject = True else: self._project = rope.base.project.get_no_project() self.setWidget(self._editor) self.popupView = QListWidget() self.popupView.setAlternatingRowColors(True) self.popupView.setWordWrap(False) self.setPopup(self.popupView) self.setCompletionMode(QCompleter.PopupCompletion) self.setCaseSensitivity(Qt.CaseInsensitive) self.connect(self, SIGNAL("activated(QString)"), self.insert_completion) def insert_completion(self, insert): extra = insert.length() - self.completionPrefix().length() self._editor.textCursor().insertText(insert.right(extra)) def complete(self, cr): if self._project: try: self.popupView.clear() code = str(self._editor.toPlainText()) start = self._editor.textCursor().position() if self._fromProject: self._project.validate() proposals = codeassist.code_assist(self._project, code, start) proposals = codeassist.sorted_proposals(proposals) model = self.obtain_model_items(proposals) self.setModel(model) self.popup().setCurrentIndex(model.index(0, 0)) cr.setWidth(self.popup().sizeHintForColumn(0) \ + self.popup().verticalScrollBar().sizeHint().width() + 10) self.popupView.updateGeometries() super(Completer, self).complete(cr) except: return def obtain_model_items(self, proposals): for p in proposals: if p.type == 'function': self.popupView.addItem( QListWidgetItem( self.icons[p.type], '%s(%s)' % (p.name, ', '.join([ n for n in p.pyname.get_object().get_param_names() if n != 'self' ])))) else: self.popupView.addItem( QListWidgetItem( self.icons.get(p.type, self.icons['class']), p.name)) return self.popupView.model() def get_path_from_project(self): if self._fromProject: return self._project.root.real_path else: return None
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 Window(QMainWindow): def __init__(self, parent=None): super(Window, self).__init__(parent) self.tabWidget = QTabWidget() self.tabWidget.setTabsClosable(True) self.tabWidget.tabCloseRequested.connect(self.closeTab) self.setCentralWidget(self.tabWidget) self.dirty = False self.filename = None self.dir = None self.fullpath = None self.dump_dir = None self.file_size = 0 self.output_path = "tmp/output.sqlite" self.user_db_path = "" self.volatilityInstance = None self.profile = "Use Imageinfo" self.create_widgets() self.create_actions() self.settings = self.loadAppSettings() self.setWindowTitle("YaVol") # self.updateFileMenu() self.imageinfoShown = False self.path_to_yara_rule = None self.yarascan_queue_size = 0 #used to determine when we finished scanning def create_widgets(self): logDockWidget = QDockWidget("Log", self) logDockWidget.setObjectName("LogDockWidget") logDockWidget.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea) self.listWidget = QListWidget() logDockWidget.setWidget(self.listWidget) self.addDockWidget(Qt.RightDockWidgetArea, logDockWidget) self.sizeLabel = QLabel() self.sizeLabel.setFrameStyle(QFrame.StyledPanel | QFrame.Sunken) self.status = self.statusBar() self.status.setSizeGripEnabled(False) self.status.addPermanentWidget(self.sizeLabel) self.status.showMessage("Ready", 5000) def create_actions(self): fileNewAction = self.createAction("&New Analysis", self.fileOpen, QKeySequence.New, "filenew", "Analyse an image file") fileOpenAction = self.createAction("&Open Analysis", self.analysisOpen, QKeySequence.Open, "fileopen", "Restore previous analysis") fileSaveAction = self.createAction("&Save Analysis", partial(self.fileSave, False), QKeySequence.Save, "filesave", "Save analysis") fileExitAction = self.createAction("&Exit", self.appExit, QKeySequence.Close, None, "Exit YaVol") editSettingsAction = self.createAction("&Settings", self.showSettingsDialog, QKeySequence.Preferences, "settings", "YaVol Settings") volPslistAction = self.createAction("pslist", partial(self.actionModule, 'pslist'), None, "pslist", "List of running processes") volPsscanAction = self.createAction("psscan", partial(self.actionModule, 'psscan'), None, "psscan", "List of running processes") volDlllistAction = self.createAction("dlllist", partial(self.actionModule, 'dlllist'), None, "dlllist", "List of loaded DLLs") volHandlesAction = self.createAction("handles", partial(self.actionModule, 'handles'), None, "handles", "List of open handles") volGetsidsAction = self.createAction("getsids", partial(self.actionModule, 'getsids'), None, "getsids", "View SIDs associated with a process") volPrivsAction = self.createAction("privs", partial(self.actionModule, 'privs'), None, "privs", "Shows which process privileges are present") volVerinfoAction = self.createAction("verinfo", partial(self.actionModule, 'verinfo'), None, "verinfo", "Display the version information embedded in PE files") volEnumfuncAction = self.createAction("enumfunc", partial(self.actionModule, 'enumfunc'), None, "enumfunc", "Enumerates imported&exported functions from processes") volConnectionsAction = self.createAction("connections", partial(self.actionModule, 'connections'), None, "connections", "List of network connections") volConnscanAction = self.createAction("connscan", partial(self.actionModule, 'connscan'), None, "connscan", "List of network connections") volSocketsAction = self.createAction("sockets", partial(self.actionModule, 'sockets'), None, "sockets", "Description missing") volSockscanAction = self.createAction("sockscan", partial(self.actionModule, 'sockscan'), None, "sockscan", "Description missing") volNetscanAction = self.createAction("netscan", partial(self.actionModule, 'netscan'), None, "netscan", "Description missing") volMalfindAction = self.createAction("malfind", partial(self.actionModule, 'malfind'), None, "malfind", "Description missing") volSvcscanAction = self.createAction("svcscan", partial(self.actionModule, 'svcscan'), None, "svcscan", "Description missing") volPsxviewAction = self.createAction("psxview", partial(self.actionModule, 'psxview'), None, "psxview", "Description missing") #yaScanallAction = self.createAction("scan image", partial(self.actionModule, 'yarascan'), # None, None, "Scan whole image with yara") yaScanallAction = self.createAction("scan image", self.showYaraScanDialog, None, None, "Scan whole image with yara") helpAboutAction = self.createAction("about", self.showAboutInfo, None, None, "Who the hell created this crap?") fileMenu = self.menuBar().addMenu("&File") self.addActions(fileMenu, (fileNewAction, fileOpenAction, fileSaveAction, fileExitAction)) editMenu = self.menuBar().addMenu("&Edit") self.addActions(editMenu, (editSettingsAction,)) volMenu = self.menuBar().addMenu("&Volatility") volMenuProcesses = volMenu.addMenu("Proc&DLLs") self.addActions(volMenuProcesses, (volPslistAction, volPsscanAction, volDlllistAction, volHandlesAction, volGetsidsAction, volPrivsAction, volVerinfoAction, volEnumfuncAction)) volMenuNetwork = volMenu.addMenu("Network") self.addActions(volMenuNetwork, (volConnectionsAction, volConnscanAction, volSocketsAction, volSockscanAction, volNetscanAction)) volMenuMalware = volMenu.addMenu("Malware") self.addActions(volMenuMalware, (volMalfindAction, volSvcscanAction, volPsxviewAction)) yaraMenu = self.menuBar().addMenu("&Yara") self.addActions(yaraMenu, (yaScanallAction,)) helpMenu = self.menuBar().addMenu("&Help") self.addActions(helpMenu, (helpAboutAction,)) # toolbar fileToolbar = self.addToolBar("File") fileToolbar.setObjectName("FileToolBar") self.addActions(fileToolbar, (fileNewAction, fileOpenAction, fileSaveAction,)) def createAction(self, text, slot=None, shortcut=None, icon=None, tip=None, checkable=False, signal="triggered()"): ''' helper method for setting up actions ''' action = QAction(text, self) if icon is not None: action.setIcon(QIcon(":/%s.png" % icon)) if shortcut is not None: action.setShortcut(shortcut) if tip is not None: action.setToolTip(tip) action.setStatusTip(tip) if slot is not None: self.connect(action, SIGNAL(signal), slot) if checkable: action.setCheckable(True) return action def addActions(self, target, actions): for action in actions: if action is None: target.addSeparator() else: target.addAction(action) def loadAppSettings(self): settings = QSettings() ''' Since we passed no arguments, the names held by the application object are used to locate the settings information ''' self.recentFiles = settings.value("RecentFiles").toStringList() '''method always returns a QVariant, so we must convert it to the data type we are expecting.''' self.restoreGeometry( settings.value("MainWindow/Geometry").toByteArray()) self.restoreState(settings.value("MainWindow/State").toByteArray()) # First app start only, set the defaults if settings.value('dictionary') == None: settings.setValue('dictionary', {'yara': {'rules_dir': {'path': '~/git/yavol_gt/yara'}}, 'dump_dir': 'dump/', 'bar': 2}) return settings def showSettingsDialog(self): dialog = settingsDlg.settingsDlg(self.settings, self) if dialog.exec_(): pass def getParticularSettingValue(self, keyword): #expects key for searching in settings dict, returns associated value settings_dict = self.settings.value('dictionary').toPyObject() if keyword == 'yara_rules_dir': return str(settings_dict[QString('yara')][QString('rules_dir')][QString('path')]) elif keyword == 'dump_dir': return str(settings_dict[QString('dump_dir')]) else: return False def showYaraScanDialog(self): #check if we got a memory image file opened if self.filename: #TODO: create a method that will return particular values from the QSettings object #settings = QSettings() #settings_dict = self.settings.value('dictionary').toPyObject() #path_to_rules = settings_dict[QString('yara')][QString('rules_dir')][QString('path')] path_to_rules = self.getParticularSettingValue('yara_rules_dir') dialog = yarascanDlg.yarascanDlg(path_to_rules) if dialog.exec_(): #check if the returned array of signatures is empty #and run the scan #DEBUG #pprint.pprint(dialog.selected_rules) if len(dialog.selected_rules) > 0: self.volatilityInstance = None #test self.yarascan_queue_size = len(dialog.selected_rules) for rule in dialog.selected_rules: self.path_to_yara_rule = str(path_to_rules + '/' + rule + '.yar') #pprint.pprint(self.path_to_yara_rule) self.actionModule('yarascan') else: #we dont have a memory image file opened self.showWarningInfo('Cannot process', 'No image file specified\n Open a memory image file first.') def closeEvent(self, event): if self.okToContinue(): #delete temp db file (/tmp/output.sqlite) if path.isfile('tmp/output.sqlite'): remove('tmp/output.sqlite') # self.settings = QSettings() filename = (QVariant(QString(self.filename)) if self.filename is not None else QVariant()) self.settings.setValue("LastFile", filename) recentFiles = (QVariant(self.recentFiles) if self.recentFiles else QVariant()) self.settings.setValue("RecentFiles", recentFiles) self.settings.setValue("MainWindow/Geometry", QVariant( self.saveGeometry())) self.settings.setValue("MainWindow/State", QVariant( self.saveState())) del self.settings else: event.ignore() def okToContinue(self): if self.dirty: reply = QMessageBox.question(self, "yavol - Unsaved Changes", "Save unsaved changes?", QMessageBox.Yes | QMessageBox.No | QMessageBox.Cancel) if reply == QMessageBox.Cancel: return False elif reply == QMessageBox.Yes: return self.fileSave(True) return True def fileOpen(self): if not self.okToContinue(): return wdir = path.dirname(self.filename) if self.filename is not None else "." formats = ["*.img", "*.dmp"] fname = unicode(QFileDialog.getOpenFileName(self, "YaVol - Choose Image", wdir, "Memory files (%s)" % " ".join(formats))) if fname: #check if the tmp dir exists if not path.exists('tmp'): makedirs('tmp') #check if we already got tmp file created (user opened something before) if path.isfile('tmp/output.sqlite'): remove('tmp/output.sqlite') self.displayInLog("temp file deleted!") #get image file size self.file_size = path.getsize(fname) self.filename = path.basename(fname) self.dir = path.dirname(fname) self.fullpath = fname #store image data stored = self.storeImageData() if stored: self.displayInLog("storeImageData success") else: self.displayInLog("storeImageData failed") self.showImageTab() def analysisOpen(self): fname = unicode(QFileDialog.getOpenFileName(self, "YaVol - Choose analysis file", '', "Analysis files (*.sqlite)")) if fname: self.displayInLog("Opening db file: " + unicode(fname)) db = dbmodule.sqlitequery('getProfile', fname) result = db.getProfileInfo() if result: #pprint.pprint(result) #check if the memory file is still in the same location image_full_path = result[3] + '/' + result[1] #print image_full_path if path.isfile(image_full_path): #file is still there, set the variables filename, dir, fullpath self.filename = result[1] self.dir = result[3] self.fullpath = image_full_path # set the last used profile self.profile = result[4] # show image tab self.showImageTab() #copy sqlite file to the tmp folder copyfile(fname,self.output_path) self.dirty = False else: # memory image file is no longer in the same location, show warning #TODO:user should be provided with an option to specify new path self.showWarningInfo('Image file not found', 'Memory image file was not found!') #print image_full_path def fileSave(self, exit): #check the dirty flag if self.dirty == False: #show dialog that there is nothing to be saved self.showWarningInfo("Save analysis", "There is nothing to be saved") else: # show the save dialog filename, filter = QFileDialog.getSaveFileNameAndFilter(self, 'Save file', '', "Database file (*.sqlite)") if filename !="": # copy the /tmp/output.sqlite to the location selected by the user strFileName = str(filename) strFilter = str(filter) dst = "" src = "" if strFilter.endswith('.sqlite)'): src = self.output_path if strFileName.endswith('.sqlite'): dst = strFileName else: dst = strFileName + '.sqlite' try: #print dst copyfile(src, dst) #changes were stored, unset the dirty flag self.dirty = False #write to analysisFile if exit: remove(src) #returning true to the caller (okToContinue) will cause exit return True else: remove(src) self.output_path = dst self.dirty = False except IOError as e: #print "I/O error({0}): {1}".format(e.errno, e.strerror) self.showWarningInfo('File saving failed', e.strerror) except ValueError: print "Could not convert data to an integer." except: print "Unexpected error:", sys.exc_info()[0] raise def appExit(self): #check the status of the dirty flag if self.dirty == False: #clean the temp folder if path.isfile('tmp/output.sqlite'): remove('tmp/output.sqlite') #and quit QCoreApplication.instance().quit() else: if self.okToContinue(): if path.isfile('tmp/output.sqlite'): remove('tmp/output.sqlite') QCoreApplication.instance().quit() def storeProfile(self, profile): # If volatility class was called with a profile value # instance was stored in volatilityInstance. In case that user wants to use another profile, # previous instance must be dropped if self.volatilityInstance: self.volatilityInstance = None self.profile = unicode(profile) self.displayInLog("Profile changed: " + unicode(profile)) db = dbmodule.sqlitequery('updateProfile', self.output_path) db.updateProfileInfo(self.profile) self.dirty = True def storeImageData(self): #get current datetime unix_time = int(time()) db = dbmodule.sqlitequery('fileOpen', self.output_path) status = db.storeImageData(imgName=self.filename, imgSize=self.file_size, imgPath=self.dir, time=unix_time) return status def handle_result(self, result): # this method is a callback which should # process the data from the worker thread moduleName = result.moduleName #if the result comes from yarascan, # 1) check if the value of the yara_scan_queue_size > 1 # 1a) lower its size by one # 1aa) send the result to buffer # 2) if the value of yara_scan_queue_size after the substraction is eq 0 # send the buffer to processing if moduleName == 'yarascan': # yarascan module output will be taken special care if self.yarascan_queue_size > 1: self.yarascan_queue_size -= 1 else: #memory image scan was finished with all selected rules # get the data from db and show it to user in a treeview self.yarascan_queue_size = 0 db = dbmodule.sqlitequery(moduleName, self.output_path) data = db.getData() #if there is no hit then returned dict looks like this: #OrderedDict([('Rule', []), ('Owner', []), ('Address', []), ('Data', [])]) if data['Rule']: self.addToTab(moduleName, 'tree', data) #TODO: maybe we would like to store previous scan results.. # drop the yarascan table db.dropYaraScanTable('YaraScan') else: self.addToTab(moduleName, 'list', 'No hit!') elif moduleName == 'procdump': # we've dumped some content, no db entry made #I should check for the return value of the module and handle error properly self.displayInLog("procdump finished") else: #output of the rest of the modules will be shown right away in a tab # textVal is used only with imageinfo module # (and some others that don't write to sqlite) # If it is defined display it in a new tab if result.retValObj.textVal: self.addToTab(moduleName, 'list', result.retValObj.textVal) else: # textVal is not defined, this means data was stored in DB # we need to get them db = dbmodule.sqlitequery(moduleName, self.output_path) data = db.getData() #TODO: offsets are stored in decimal for pslist,psscan, psxview, dlllist, handles,netscan,svcan, malfind #convert offsets from decimal to hexa modified_data = self.convertOffsets(moduleName, data) self.addToTab(moduleName, 'table', modified_data) def convertOffsets(self, moduleName, data): if moduleName == 'pslist': offsets = data['Offset(V)'] self.listToHex(offsets) elif moduleName == 'psscan': offsets = data['Offset(P)'] self.listToHex(offsets) elif moduleName == 'dlllist': offsets = data['Base'] self.listToHex(offsets) elif moduleName == 'handles': offsets = data['Offset(V)'] self.listToHex(offsets) elif moduleName == 'netscan': offsets = data['Offset(P)'] self.listToHex(offsets) elif moduleName == 'psxview': offsets = data['Offset(P)'] self.listToHex(offsets) elif moduleName == 'svcscan': offsets = data['Offset'] self.listToHex(offsets) #malfind will require some more work elif moduleName == 'malfind': offsets = data['Address'] self.listToHex(offsets) return data def listToHex(self, list): for index, value in enumerate(list): number = hex(int(value)) list[index] = number def thread_process(self, moduleName, filename, profile, yara_rule_path, output_path, pid=None, dump_dir="dump/"): MAX_CORES = 2 self.queue = queue.Queue() self.threads = [] for i in range(MAX_CORES): thread = Worker(self.queue, self.handle_result) self.threads.append(thread) thread.start() query = QueueObj(moduleName, filename, profile, yara_rule_path, output_path, pid, dump_dir) self.queue.put(query) for _ in range(MAX_CORES): # Tell the workers to shut down self.queue.put(None) def actionModule(self, moduleName): #check if we got a memory image file specified first if self.filename: # check if the selected image profile supports this module compatibilityCheck = re.match('Vista|Win2008|Win7', self.profile, flags=0) if moduleName in ['connections', 'connscan', 'sockscan', 'sockets']: if compatibilityCheck: self.displayInLog("Error: This module can't be use with this profile") return False # check if we got an open table with this module output if moduleName != 'yarascan': #print self.tabWidget.count() for i in range(self.tabWidget.count()): if self.tabWidget.tabText(i) == moduleName.lower(): #set focus on the tab self.tabWidget.setCurrentIndex(i) return True #check if our db already contains table with this module output if self.checkForTable(moduleName) and moduleName != 'yarascan': self.displayInLog("Info: We already have this module output in db!") #get the data and display it db = dbmodule.sqlitequery(moduleName, self.output_path) data = db.getData() #convert offsets from dec to hex modified_data = self.convertOffsets(moduleName, data) self.addToTab(moduleName, 'table', modified_data) else: #we dont have this output in our db self.status.showMessage("Creating %s output" % moduleName, 5000) self.displayInLog("%s with a profile called!" % moduleName) # TODO: remove check for volatilityInstance, this is no longer in use!!! #if self.volatilityInstance != None: # self.displayInLog("Info: Volatility instance found") if self.path_to_yara_rule: self.thread_process(moduleName, self.fullpath, self.profile, self.path_to_yara_rule, self.output_path) else: self.thread_process(moduleName, self.fullpath, self.profile, None, self.output_path) self.dirty = True else: # we dont have an image file opened self.showWarningInfo('Cannot process', 'No image file specified\n Open a memory image file first.') def addTabFnc(self, name, layout): self.widget = QWidget() self.widget.setLayout(layout) self.tabWidget.addTab(self.widget, name) self.tabWidget.setCurrentWidget(self.widget) def addToTab(self, tabName, type, content): tabLayout = QHBoxLayout() if type == 'list': textEditWidget = QTextEdit() textEditWidget.insertPlainText(content) textEditWidget.setReadOnly(True) tabLayout.addWidget(textEditWidget) elif type == 'tree': #yarascan yarascanClass= yarascanTreeView.yarascanTreeView(content) tabLayout.addWidget(yarascanClass.treeWidget) elif type == 'table': # number of columns depends on number of keys in dict num_of_columns = len(content) num_of_rows = len(content[content.keys()[0]]) #tableWidget = QTableWidget(num_of_rows, num_of_columns) tableWidget = TableWidget(self, content, tabName, num_of_rows, num_of_columns) tabLayout.addWidget(tableWidget) self.addTabFnc(tabName, tabLayout) # self.dirty = True def closeTab(self, currentIndex): currentQWidget = self.tabWidget.widget(currentIndex) currentQWidget.deleteLater() self.tabWidget.removeTab(currentIndex) def showImageTab(self): items = ['Use Imageinfo', 'VistaSP0x64', 'VistaSP0x86', 'VistaSP1x64', 'VistaSP2x64', \ 'VistaSP2x86', 'Win2003SP0x86', 'Win2003SP1x64', 'Win2003SP1x86', 'Win2003SP2x64', \ 'Win2003SP2x86', 'Win2008R2SP0x64', 'Win2008R2SP1x64', 'Win2008SP1x64', 'Win2008SP1x86', \ 'Win2008SP2x64', 'Win7SP0x64', 'Win7SP0x86', 'Win7SP1x64', 'Win7SP1x86', 'WinXPSP1x64', \ 'WinXPSP2x64', 'WinXPSP2x86', 'WinXPSP3x86'] fileNameLabel = QLabel("Image: ") profileLabel = QLabel("Profile: ") fileName = QLabel(self.filename) self.profileSelector = QComboBox() self.profileSelector.addItems(items) # index = items.index(self.profile) self.profileSelector.setCurrentIndex(index) horizontalLayout = QHBoxLayout() grid = QGridLayout() grid.addWidget(fileNameLabel, 1, 0) grid.addWidget(fileName, 1, 1) grid.addWidget(profileLabel, 2, 0) grid.addWidget(self.profileSelector, 2, 1) spacerItem = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Expanding) grid.addItem(spacerItem) horizontalLayout.addItem(grid) horizontalLayout.addStretch() self.connect(self.profileSelector, SIGNAL("currentIndexChanged(QString)"), self.storeProfile) self.addTabFnc("Image", horizontalLayout) self.dirty = True def checkForTable(self, tableName): # This function will determine if we already got a module output in db # input: tableName # output: true/false db = dbmodule.sqlitequery(tableName, self.output_path) presence = db.checkForTable() return presence def showAboutInfo(self): QMessageBox.about(self, "About yavol", "yavol version %s\n\nCopyright(c) 2015 by %s\n" % (__version__, __author__)) def showWarningInfo(self, warning_title, warning_text): QMessageBox.warning(self, warning_title, warning_text, QMessageBox.Ok) def displayInLog(self, content): self.listWidget.addItem(content) #def hashfile(self, afile, hasher, blocksize=65536): # for block in iter(lambda: afile.read(blocksize), ''): # hasher.update(block) # return hasher.hexdigest() def doNothing(self): self.dirty = True self.displayInLog("Nothing was done, really")