def create_filterable_names_list(names, filter_text=None, parent=None, model=NamesModel): nl = QListView(parent) nl.m = m = model(names, parent=nl) m.filtered.connect(lambda all_items: nl.scrollTo(m.index(0))) nl.setModel(m) if model is NamesModel: nl.d = NamesDelegate(nl) nl.setItemDelegate(nl.d) f = QLineEdit(parent) f.setPlaceholderText(filter_text or '') f.textEdited.connect(m.filter) return nl, f
class PlayerInfoField(QWidget): #Widget for inputting player info. names = ['Alex', 'Clifford', 'Tyrone', 'Ava', 'Ralph', 'Emily', 'Falcon', 'Giselle', 'Jaeger', 'Sally', 'Quentin', 'Lara'] def __init__(self, parent, index): super(PlayerInfoField, self).__init__(parent) self.index = index self.layout = QHBoxLayout() self.auto_button = Button(self, 'Auto') self.auto_button.setFixedWidth(60) self.auto_button.clicked.connect(self.generate_name) self.layout.addWidget(self.auto_button) self.name_field = QLineEdit() self.name_field.setPalette(QPalette(Qt.white)) self.name_field.setPlaceholderText('Name') self.name_field.setClearButtonEnabled(True) self.name_field.setFixedWidth(250) self.layout.addWidget(self.name_field) self.AItoggle = QCheckBox() self.AItoggle.setText('Computer') self.AItoggle.setFixedWidth(100) self.layout.addWidget(self.AItoggle) self.AItoggle.stateChanged.connect(self.AIToggled) self.AIdifficulty = QComboBox() self.AIdifficulty.setPalette(QPalette(Qt.white)) self.AIdifficulty.setFixedWidth(100) self.AIdifficulty.addItems(['Braindead', 'Easy', 'Normal', 'Hard', 'HAL-9000']) self.AIdifficulty.setCurrentIndex(2) self.AIdifficulty.setDisabled(True) self.layout.addWidget(self.AIdifficulty) self.spacer = QSpacerItem(40, 20, QSizePolicy.Expanding, QSizePolicy.Minimum) self.layout.addItem(self.spacer) self.layout.setContentsMargins(0, 0, 0, 0) self.setLayout(self.layout) def generate_name(self): self.name_field.setText(PlayerInfoField.names[self.index]) def AIToggled(self): if self.AItoggle.checkState() == Qt.Checked: self.AIdifficulty.setEnabled(True) else: self.AIdifficulty.setDisabled(True)
class Title(QWidget): def __init__(self, parent): QWidget.__init__(self, parent) self.ll = ll = QGridLayout() self.setLayout(self.ll) self.labell = QLabel('Title:') ll.addWidget(self.labell, 0, 0, 1, 1) self.title_edit = QLineEdit(self) self.title_edit.setPlaceholderText('Enter a title for the ebook ') ll.addWidget(self.title_edit, 0, 1, 1, 1) @property def title(self): return unicode(self.title_edit.text())
class URL(QWidget): def __init__(self, parent): QWidget.__init__(self, parent) self.l = l = QGridLayout() self.setLayout(self.l) self.label = QLabel('URL:') l.addWidget(self.label, 0, 0, 1, 1) self.url_edit = QLineEdit(self) self.url_edit.setPlaceholderText('Enter the URL of the wikipedia ' 'article to download') l.addWidget(self.url_edit, 0, 1, 1, 1) @property def url(self): return unicode(self.url_edit.text())
def select_channel(self, text): # 先初始化数据 self.linedit_list.clear() self.channel.clear() # 排序包体参数,防止参数写入乱排序 self.channel['name'] = '' self.channel['sdk'] = text self.channel['channelId'] = '' self.channel['gameName'] = '' self.channel['package'] = '' self.channel['gameVersionCode'] = '' self.channel['gameVersionName'] = '' self.channel['debug'] = "false" # 获取渠道参数定义 if not Utils.get_channel_config(self.channel): return # 再添加当前选择的渠道参数模板,刷新界面(先清空之前渠道参数表单,再添加) for i in range(self.form_layout2.rowCount()): # 因为formlayout清除一行,会自动上移,所以只需remove第一行 self.form_layout2.removeRow(0) channel_name = QLabel(self.channel['name'] + '\t\t\tVersion:' + self.channel['sdkVersionName'] + '\t\tUpdate:' + self.channel['sdkUpdateTime']) channel_name.setAlignment(Qt.AlignRight) self.form_layout2.addRow(channel_name) if self.default_channel is not None and text == self.default_channel[ 'sdk']: self.channel_id_value.setText(self.default_channel['channelId']) self.game_name_value.setText(self.default_channel['gameName']) self.game_package_value.setText(self.default_channel['package']) self.game_vcode_value.setText( self.default_channel['gameVersionCode']) self.game_vname_value.setText( self.default_channel['gameVersionName']) for param in self.default_channel['sdkParams']: line_edit = QLineEdit() line_edit.setText(param['value']) self.form_layout2.addRow(param['showName'] + ':', line_edit) self.linedit_list.append(line_edit) else: for param in self.channel['sdkParams']: line_edit = QLineEdit() line_edit.setPlaceholderText("渠道参数必填") self.form_layout2.addRow(param['showName'] + ':', line_edit) self.linedit_list.append(line_edit)
def _create_widget(self, value): if isinstance(value, str): widget = QLineEdit() widget.setText(value) widget.setPlaceholderText('String Val') elif isinstance(value, list): return [self._create_widget(v) for v in value] else: if isinstance(value, int): widget = QSpinBox() else: widget = QDoubleSpinBox() decimal = str(value)[::-1].find('.') widget.setDecimals(decimal) widget.setSingleStep(pow(10, -decimal)) widget.setMinimum(-9999999) widget.setMaximum(9999999) widget.setValue(value) widget.setFixedWidth(100) widget.setAlignment(Qt.AlignRight) return widget
class Downloader(QDialog): def __init__(self): QDialog.__init__(self) layout = QVBoxLayout() self.url = QLineEdit() self.url.setPlaceholderText("URL") self.save_location = QLineEdit("File save location") self.progressbar = QProgressBar() download = QPushButton("Download") self.progressbar.setValue(0) self.progressbar.setAlignment(Qt.AlignHCenter) layout.addWidget(self.url) layout.addWidget(self.save_location) layout.addWidget(self.progressbar) layout.addWidget(download) self.setLayout(layout) self.setWindowTitle("Python Downloader using PyQt5") self.setFocus() download.clicked.connect(self.download) def download(self): url = self.url.text() save_location = self.save_location.text() urllib.request.urlretrieve(url, save_location, self.report) def report(self, blocknum, blocksize, totalsize): print(blocknum, blocksize, totalsize) readsofar = blocknum * blocksize if totalsize > 0: percent = readsofar * 100 / totalsize print(percent) self.progressbar.setValue(int(percent))
class PackageWidget(QWidget): def __init__(self, main, channels): super(PackageWidget, self).__init__() self.setObjectName("PackageWidget") self.main_win = main self.game = self.main_win.games[self.main_win.game_index] self.channels = channels self.check_boxs = [] self.indexs = [] self.lbps = {} self.progress = None self.monitor = PackageMonitor() self.monitor.signal.connect(self.complete) v_layout = QVBoxLayout() h_layout1 = QHBoxLayout() cbox_widget = QWidget() v_layout1 = QVBoxLayout() self.all_selected_cbox = QCheckBox("全 选") self.all_selected_cbox.stateChanged.connect(self.select_all) v_layout1.addWidget(self.all_selected_cbox) for channel in self.channels: check_box = QCheckBox(channel['channelId']) check_box.setFixedWidth(100) v_layout1.addSpacing(10) v_layout1.addWidget(check_box) self.check_boxs.append(check_box) cbox_widget.setLayout(v_layout1) channel_list_area = QScrollArea() channel_list_area.setWidget(cbox_widget) h_layout1.addWidget(channel_list_area, 1) self.qpb_list_widget = QListWidget() self.qpb_list_widget.setSelectionMode( QAbstractItemView.SingleSelection) self.qpb_list_widget.itemDoubleClicked.connect(self.select_list) h_layout1.addWidget(self.qpb_list_widget, 5) v_layout.addLayout(h_layout1) h_layout2 = QHBoxLayout() self.back_btn = QPushButton("返 回") self.back_btn.setFixedWidth(100) self.back_btn.clicked.connect(self.back) h_layout2.addWidget(self.back_btn, alignment=Qt.AlignLeft | Qt.AlignBottom) h_layout2.addSpacing(100) select_apk_btn = QPushButton("选择母包:") select_apk_btn.clicked.connect(self.select_apk) h_layout2.addWidget(select_apk_btn) self.apk_path = QLineEdit() self.apk_path.setPlaceholderText("母包路径") h_layout2.addWidget(self.apk_path) h_layout2.addSpacing(100) self.pack_btn = QPushButton("打 包") self.pack_btn.setFixedWidth(100) self.pack_btn.clicked.connect(self.click) h_layout2.addWidget(self.pack_btn, alignment=Qt.AlignRight | Qt.AlignBottom) v_layout.addLayout(h_layout2) self.setLayout(v_layout) def select_list(self): index = self.qpb_list_widget.currentIndex().row() channel_id = self.channels[self.indexs[index]]['channelId'] success = self.lbps[channel_id]['success'] dest_apk_dir = Utils.get_full_path('output/' + self.game['id'] + '/' + channel_id) if success: os.startfile(dest_apk_dir) else: QMessageBox.warning(self, "警告", "打包成功了吗?") def back(self): self.monitor.deleteLater() self.main_win.set_channel_list_widget(self.channels) def select_apk(self): fname = QFileDialog.getOpenFileName( self, '选择母包', os.path.join(os.path.expanduser('~'), "Desktop"), ("Apk (*.apk)")) if fname[0]: self.apk_path.setStyleSheet("font-size:12px") self.apk_path.setText(fname[0]) def select_all(self): if self.all_selected_cbox.isChecked(): for cbox in self.check_boxs: cbox.setChecked(True) else: for cbox in self.check_boxs: cbox.setChecked(False) def click(self): if self.pack_btn.text() == "打 包": self.package() elif self.pack_btn.text() == "取 消": self.cancel() def package(self): # 清空上次打包完成后的进度条显示列表 count = self.qpb_list_widget.count() if count > 0: for i in range(count): item = self.qpb_list_widget.takeItem(0) del item self.indexs = [] for i in range(len(self.channels)): if self.check_boxs[i].isChecked(): self.indexs.append(i) if len(self.indexs) <= 0: QMessageBox.warning(self, "警告", "请选择需要打包的渠道!") return if self.apk_path.text().strip() == "": QMessageBox.warning(self, "警告", "请上传母包!") return apk = self.apk_path.text().strip().replace('\\', '/') for i in self.indexs: lbp = {} lbp['success'] = False self.set_qpb_list_item(self.channels[i], lbp) runnable = PackRunnable(self.game, self.channels[i], apk) runnable.signal.signal.connect(self.set_value) self.monitor.add_runnable(runnable) lbp['runnable'] = runnable self.lbps[self.channels[i]['channelId']] = lbp # 开启监听线程 self.monitor.start() # 开始打包,不可返回,返回按钮禁用;设置打包按钮文本为"取 消" self.back_btn.setDisabled(True) self.pack_btn.setText("取 消") def set_qpb_list_item(self, channel, lbp): item = QListWidgetItem(self.qpb_list_widget) item.setSizeHint(QSize(400, 80)) widget = QWidget(self.qpb_list_widget) v_layout = QVBoxLayout() label = QLabel(channel['channelId'] + "==>>>等待出包...") v_layout.addWidget(label) lbp['label'] = label qpb = QProgressBar(self.qpb_list_widget) v_layout.addWidget(qpb) lbp['qpb'] = qpb widget.setLayout(v_layout) self.qpb_list_widget.addItem(item) self.qpb_list_widget.setItemWidget(item, widget) def set_value(self, channel_id, result, msg, step): lbp = self.lbps[channel_id] if result: # 打包步骤异常,提示异常,关闭进度条 lbp['label'].setText(channel_id + "==>>>" + msg) lbp['qpb'].close() if step == 100: lbp['success'] = True self.lbps[channel_id] = lbp else: # 打包正常,设置进度条进度 lbp['qpb'].setValue(step) if step == 0: lbp['label'].setText(channel_id + "==>>>" + msg) # 取消打包(全部取消) def cancel(self): self.progress = QProgressDialog(self) self.progress.setFixedWidth(500) self.progress.setFixedHeight(80) self.progress.setWindowTitle("正在取消,请稍等...") self.progress.setCancelButtonText("取消") self.progress.setMinimumDuration(1) self.progress.setWindowModality(Qt.ApplicationModal) self.progress.setRange(0, 0) self.progress.show() # 清空进度条显示列表 count = self.qpb_list_widget.count() for i in range(count): item = self.qpb_list_widget.takeItem(0) del item # 清空任务线程池;线程池清空后,会触发监听线程的完成信号,重置返回和打包按钮 # 因为打包任务调用外部程序,并不能立即终止外部程序连接,所以清空过程有延迟 for channel_id in self.lbps: self.lbps[channel_id]['runnable'].is_close = True self.monitor.clear() # 取消打包(清空任务完成),或打包完成, def complete(self): if self.progress is not None: self.progress.cancel() # 清空复选框的选择 self.all_selected_cbox.setChecked(False) for cbox in self.check_boxs: cbox.setChecked(False) # 返回按钮解禁;设置打包按钮文本为"打 包" self.back_btn.setDisabled(False) self.pack_btn.setText("打 包")
class ItemEdit(QWidget): def __init__(self, parent, prefs=None): QWidget.__init__(self, parent) self.prefs = prefs or gprefs self.pending_search = None self.current_frag = None self.setLayout(QVBoxLayout()) self.la = la = QLabel('<b>'+_( 'Select a destination for the Table of Contents entry')) self.layout().addWidget(la) self.splitter = sp = QSplitter(self) self.layout().addWidget(sp) self.layout().setStretch(1, 10) sp.setOpaqueResize(False) sp.setChildrenCollapsible(False) self.dest_list = dl = QListWidget(self) dl.setMinimumWidth(250) dl.currentItemChanged.connect(self.current_changed) sp.addWidget(dl) w = self.w = QWidget(self) l = w.l = QGridLayout() w.setLayout(l) self.view = WebView(self) self.view.elem_clicked.connect(self.elem_clicked) self.view.frag_shown.connect(self.update_dest_label, type=Qt.ConnectionType.QueuedConnection) self.view.loadFinished.connect(self.load_finished, type=Qt.ConnectionType.QueuedConnection) l.addWidget(self.view, 0, 0, 1, 3) sp.addWidget(w) self.search_text = s = QLineEdit(self) s.setPlaceholderText(_('Search for text...')) l.addWidget(s, 1, 0) self.ns_button = b = QPushButton(QIcon(I('arrow-down.png')), _('Find &next'), self) b.clicked.connect(self.find_next) l.addWidget(b, 1, 1) self.ps_button = b = QPushButton(QIcon(I('arrow-up.png')), _('Find &previous'), self) l.addWidget(b, 1, 2) b.clicked.connect(self.find_previous) self.f = f = QFrame() f.setFrameShape(QFrame.Shape.StyledPanel) f.setMinimumWidth(250) l = f.l = QVBoxLayout() f.setLayout(l) sp.addWidget(f) f.la = la = QLabel('<p>'+_( 'Here you can choose a destination for the Table of Contents\' entry' ' to point to. First choose a file from the book in the left-most panel. The' ' file will open in the central panel.<p>' 'Then choose a location inside the file. To do so, simply click on' ' the place in the central panel that you want to use as the' ' destination. As you move the mouse around the central panel, a' ' thick green line appears, indicating the precise location' ' that will be selected when you click.')) la.setStyleSheet('QLabel { margin-bottom: 20px }') la.setWordWrap(True) l.addWidget(la) f.la2 = la = QLabel('<b>'+_('&Name of the ToC entry:')) l.addWidget(la) self.name = QLineEdit(self) self.name.setPlaceholderText(_('(Untitled)')) la.setBuddy(self.name) l.addWidget(self.name) self.base_msg = '<b>'+_('Currently selected destination:')+'</b>' self.dest_label = la = QLabel(self.base_msg) la.setWordWrap(True) la.setStyleSheet('QLabel { margin-top: 20px }') l.addWidget(la) l.addStretch() state = self.prefs.get('toc_edit_splitter_state', None) if state is not None: sp.restoreState(state) def load_finished(self, ok): if self.pending_search: self.pending_search() self.pending_search = None def keyPressEvent(self, ev): if ev.key() in (Qt.Key.Key_Return, Qt.Key.Key_Enter) and self.search_text.hasFocus(): # Prevent pressing enter in the search box from triggering the dialog's accept() method ev.accept() return return super(ItemEdit, self).keyPressEvent(ev) def find(self, forwards=True): text = unicode_type(self.search_text.text()).strip() flags = QWebEnginePage.FindFlags(0) if forwards else QWebEnginePage.FindFlag.FindBackward self.find_data = text, flags, forwards self.view.findText(text, flags, self.find_callback) def find_callback(self, found): d = self.dest_list text, flags, forwards = self.find_data if not found and text: if d.count() == 1: return error_dialog(self, _('No match found'), _('No match found for: %s')%text, show=True) delta = 1 if forwards else -1 current = unicode_type(d.currentItem().data(Qt.ItemDataRole.DisplayRole) or '') next_index = (d.currentRow() + delta)%d.count() next = unicode_type(d.item(next_index).data(Qt.ItemDataRole.DisplayRole) or '') msg = '<p>'+_('No matches for %(text)s found in the current file [%(current)s].' ' Do you want to search in the %(which)s file [%(next)s]?') msg = msg%dict(text=text, current=current, next=next, which=_('next') if forwards else _('previous')) if question_dialog(self, _('No match found'), msg): self.pending_search = self.find_next if forwards else self.find_previous d.setCurrentRow(next_index) def find_next(self): return self.find() def find_previous(self): return self.find(forwards=False) def load(self, container): self.container = container spine_names = [container.abspath_to_name(p) for p in container.spine_items] spine_names = [n for n in spine_names if container.has_name(n)] self.dest_list.addItems(spine_names) def current_changed(self, item): name = self.current_name = unicode_type(item.data(Qt.ItemDataRole.DisplayRole) or '') path = self.container.name_to_abspath(name) # Ensure encoding map is populated root = self.container.parsed(name) nasty = root.xpath('//*[local-name()="head"]/*[local-name()="p"]') if nasty: body = root.xpath('//*[local-name()="body"]') if not body: return error_dialog(self, _('Bad markup'), _('This book has severely broken markup, its ToC cannot be edited.'), show=True) for x in reversed(nasty): body[0].insert(0, x) self.container.commit_item(name, keep_parsed=True) self.view.load_path(path, self.current_frag) self.current_frag = None self.dest_label.setText(self.base_msg + '<br>' + _('File:') + ' ' + name + '<br>' + _('Top of the file')) def __call__(self, item, where): self.current_item, self.current_where = item, where self.current_name = None self.current_frag = None self.name.setText('') dest_index, frag = 0, None if item is not None: if where is None: self.name.setText(item.data(0, Qt.ItemDataRole.DisplayRole) or '') self.name.setCursorPosition(0) toc = item.data(0, Qt.ItemDataRole.UserRole) if toc.dest: for i in range(self.dest_list.count()): litem = self.dest_list.item(i) if unicode_type(litem.data(Qt.ItemDataRole.DisplayRole) or '') == toc.dest: dest_index = i frag = toc.frag break self.dest_list.blockSignals(True) self.dest_list.setCurrentRow(dest_index) self.dest_list.blockSignals(False) item = self.dest_list.item(dest_index) if frag: self.current_frag = frag self.current_changed(item) def get_loctext(self, frac): frac = int(round(frac * 100)) if frac == 0: loctext = _('Top of the file') else: loctext = _('Approximately %d%% from the top')%frac return loctext def elem_clicked(self, tag, frac, elem_id, loc, totals): self.current_frag = elem_id or (loc, totals) base = _('Location: A <%s> tag inside the file')%tag loctext = base + ' [%s]'%self.get_loctext(frac) self.dest_label.setText(self.base_msg + '<br>' + _('File:') + ' ' + self.current_name + '<br>' + loctext) def update_dest_label(self, val): self.dest_label.setText(self.base_msg + '<br>' + _('File:') + ' ' + self.current_name + '<br>' + self.get_loctext(val)) @property def result(self): return (self.current_item, self.current_where, self.current_name, self.current_frag, self.name.text().strip() or _('(Untitled)'))
class FontFamilyDialog(QDialog): def __init__(self, current_family, parent=None): QDialog.__init__(self, parent) self.setWindowTitle(_('Choose font family')) self.setWindowIcon(QIcon(I('font.png'))) from calibre.utils.fonts.scanner import font_scanner self.font_scanner = font_scanner self.m = QStringListModel(self) self.build_font_list() self.l = l = QGridLayout() self.setLayout(l) self.view = FontsView(self) self.view.setModel(self.m) self.view.setCurrentIndex(self.m.index(0)) if current_family: for i, val in enumerate(self.families): if icu_lower(val) == icu_lower(current_family): self.view.setCurrentIndex(self.m.index(i)) break self.view.doubleClicked.connect(self.accept, type=Qt.QueuedConnection) self.view.changed.connect(self.current_changed, type=Qt.QueuedConnection) self.faces = Typefaces(self) self.bb = QDialogButtonBox(QDialogButtonBox.Ok|QDialogButtonBox.Cancel) self.bb.accepted.connect(self.accept) self.bb.rejected.connect(self.reject) self.add_fonts_button = afb = self.bb.addButton(_('Add &fonts'), self.bb.ActionRole) afb.setIcon(QIcon(I('plus.png'))) afb.clicked.connect(self.add_fonts) self.ml = QLabel(_('Choose a font family from the list below:')) self.search = QLineEdit(self) self.search.setPlaceholderText(_('Search')) self.search.returnPressed.connect(self.find) self.nb = QToolButton(self) self.nb.setIcon(QIcon(I('arrow-down.png'))) self.nb.setToolTip(_('Find next')) self.pb = QToolButton(self) self.pb.setIcon(QIcon(I('arrow-up.png'))) self.pb.setToolTip(_('Find previous')) self.nb.clicked.connect(self.find_next) self.pb.clicked.connect(self.find_previous) l.addWidget(self.ml, 0, 0, 1, 4) l.addWidget(self.search, 1, 0, 1, 1) l.addWidget(self.nb, 1, 1, 1, 1) l.addWidget(self.pb, 1, 2, 1, 1) l.addWidget(self.view, 2, 0, 1, 3) l.addWidget(self.faces, 1, 3, 2, 1) l.addWidget(self.bb, 3, 0, 1, 4) l.setAlignment(self.faces, Qt.AlignTop) self.resize(800, 600) def set_current(self, i): self.view.setCurrentIndex(self.m.index(i)) def keyPressEvent(self, e): if e.key() == Qt.Key_Return: return return QDialog.keyPressEvent(self, e) def find(self, backwards=False): i = self.view.currentIndex().row() if i < 0: i = 0 q = icu_lower(unicode(self.search.text())).strip() if not q: return r = (xrange(i-1, -1, -1) if backwards else xrange(i+1, len(self.families))) for j in r: f = self.families[j] if q in icu_lower(f): self.set_current(j) return def find_next(self): self.find() def find_previous(self): self.find(backwards=True) def build_font_list(self): try: self.families = list(self.font_scanner.find_font_families()) except: self.families = [] print ('WARNING: Could not load fonts') import traceback traceback.print_exc() self.families.insert(0, _('None')) self.m.setStringList(self.families) def add_fonts(self): families = add_fonts(self) if not families: return self.font_scanner.do_scan() self.m.beginResetModel() self.build_font_list() self.m.endResetModel() self.view.setCurrentIndex(self.m.index(0)) if families: for i, val in enumerate(self.families): if icu_lower(val) == icu_lower(families[0]): self.view.setCurrentIndex(self.m.index(i)) break info_dialog(self, _('Added fonts'), _('Added font families: %s')%( ', '.join(families)), show=True) @property def font_family(self): idx = self.view.currentIndex().row() if idx == 0: return None return self.families[idx] def current_changed(self): fam = self.font_family self.faces.show_family(fam, self.font_scanner.fonts_for_family(fam) if fam else None)
class ProxyQDialog(QDialog): """ Class who create a Proxy QDialog """ def __init__(self, parent=None): super(ProxyQDialog, self).__init__(parent) self.setWindowTitle(_('Proxy Configuration')) self.setWindowFlags(Qt.FramelessWindowHint) self.setStyleSheet(settings.css_style) self.setWindowIcon(QIcon(settings.get_image('icon'))) self.setObjectName('dialog') self.setFixedSize(320, 380) # Fields self.proxy_address = QLineEdit() self.proxy_user = QLineEdit() self.proxy_password = QLineEdit() self.offset = None def initialize_dialog(self): """ Initialize Proxy QDialog """ main_layout = QVBoxLayout() main_layout.setContentsMargins(0, 0, 0, 0) self.setLayout(main_layout) main_layout.addWidget(get_logo_widget(self, _('Proxy Settings'))) main_layout.addWidget(self.get_proxy_widget()) center_widget(self) def get_proxy_widget(self): """ Return the proxy QWidget :return: proxy QWidget :rtype: QWidget """ proxy_widget = QWidget() proxy_widget.setObjectName('dialog') proxy_layout = QVBoxLayout(proxy_widget) # Title title_lbl = QLabel(_('Proxy Settings')) title_lbl.setObjectName('itemtitle') proxy_layout.addWidget(title_lbl) proxy_layout.setAlignment(title_lbl, Qt.AlignTop) # Description desc_label = QLabel( _('Here you can define your proxy. Be sure to enter a valid address.') ) desc_label.setWordWrap(True) proxy_layout.addWidget(desc_label) # Proxy Settings proxy_lbl = QLabel(_('Proxy Address with Port')) proxy_layout.addWidget(proxy_lbl) proxy = settings.get_config('Alignak', 'proxy') self.proxy_address.setText(proxy) self.proxy_address.setPlaceholderText(_('proxy adress:port...')) self.proxy_address.setFixedHeight(25) proxy_layout.addWidget(self.proxy_address) # Proxy User proxy_user_lbl = QLabel(_('Proxy User (Optional)')) proxy_layout.addWidget(proxy_user_lbl) proxy_user = settings.get_config('Alignak', 'proxy_user') self.proxy_user.setText(proxy_user) self.proxy_user.setPlaceholderText(_('proxy user...')) self.proxy_user.setFixedHeight(25) proxy_layout.addWidget(self.proxy_user) # Proxy Password proxy_password_lbl = QLabel(_('Proxy Password (Optional)')) proxy_layout.addWidget(proxy_password_lbl) if settings.get_config('Alignak', 'proxy_password'): self.proxy_password.setText(settings.get_config('Alignak', 'proxy_password')) self.proxy_password.setPlaceholderText(_('proxy password...')) self.proxy_password.setFixedHeight(25) self.proxy_password.setEchoMode(QLineEdit.Password) proxy_layout.addWidget(self.proxy_password) # Valid Button valid_btn = QPushButton(_('Valid')) valid_btn.setObjectName('valid') valid_btn.setMinimumHeight(30) valid_btn.clicked.connect(self.accept_proxy) proxy_layout.addWidget(valid_btn) return proxy_widget def accept_proxy(self): """ Accept QDialog if proxy is valid """ if self.proxy_address.text() or self.proxy_user.text() or self.proxy_password.text(): try: _, _, _ = self.proxy_address.text().split(':') self.accept() except ValueError: self.proxy_error() else: self.accept() @staticmethod def proxy_error(): # pragma: no cover - not testable """ Display a Message QDialog error """ error_dialog = MessageQDialog() error_dialog.initialize( 'Proxy Error', 'error', 'Wrong proxy setting !', 'You must enter a valid address: "http://proxy:port"' ) error_dialog.exec_() def mousePressEvent(self, event): # pragma: no cover - not testable """ QWidget.mousePressEvent(QMouseEvent) """ self.offset = event.pos() def mouseMoveEvent(self, event): # pragma: no cover - not testable """ QWidget.mousePressEvent(QMouseEvent) """ try: x = event.globalX() y = event.globalY() x_w = self.offset.x() y_w = self.offset.y() self.move(x - x_w, y - y_w) except AttributeError as e: logger.warning('Move Event %s: %s', self.objectName(), str(e))
class ServerQDialog(QDialog): """ Class who create Server QDialog. """ def __init__(self, parent=None): super(ServerQDialog, self).__init__(parent) self.setWindowTitle(_('Alignak Settings')) self.setWindowFlags(Qt.FramelessWindowHint) self.setStyleSheet(settings.css_style) self.setWindowIcon(QIcon(settings.get_image('icon'))) self.setObjectName('dialog') self.setFixedSize(340, 420) # Fields self.server_proc = QLineEdit() self.server_url = QLineEdit() self.server_port = QLineEdit() self.webservice_url = QLineEdit() self.proxy_address = QLineEdit() self.proxy_user = QLineEdit() self.proxy_password = QLineEdit() self.offset = None def initialize_dialog(self): """ Initialize Server QDialog """ main_layout = QVBoxLayout() main_layout.setContentsMargins(0, 0, 0, 0) self.setLayout(main_layout) main_layout.addWidget(get_logo_widget(self, _('Alignak Settings'))) main_layout.addWidget(self.get_settings_widget()) center_widget(self) def get_settings_widget(self): """ Return the alignak settings QWidget :return: settings QWidget :rtype: QWidget """ server_widget = QWidget() server_widget.setObjectName('dialog') server_layout = QVBoxLayout(server_widget) # Title title_lbl = QLabel(_('Alignak Backend')) title_lbl.setObjectName('itemtitle') server_layout.addWidget(title_lbl) server_layout.setAlignment(title_lbl, Qt.AlignTop) # Description desc_label = QLabel( _('Here you can define alignak settings. Be sure to enter a valid address.' )) desc_label.setWordWrap(True) server_layout.addWidget(desc_label) # Server URL server_lbl = QLabel(_('Server')) server_layout.addWidget(server_lbl) self.server_url.setText(settings.get_config('Alignak', 'url')) self.server_url.setPlaceholderText(_('alignak backend url...')) self.server_url.setFixedHeight(25) server_layout.addWidget(self.server_url) # Server Port port_lbl = QLabel(_('Port')) server_layout.addWidget(port_lbl) cur_port = settings.get_config('Alignak', 'backend').split(':')[2] self.server_port.setText(cur_port) self.server_port.setPlaceholderText(_('alignak backend port...')) self.server_port.setFixedHeight(25) server_layout.addWidget(self.server_port) # Server Processes (displayed only for Unix platforms) if 'win32' not in sys.platform: process_lbl = QLabel(_('Processes')) server_layout.addWidget(process_lbl) cur_proc = settings.get_config('Alignak', 'processes') self.server_proc.setText(cur_proc) self.server_proc.setPlaceholderText( _('alignak backend processes...')) self.server_proc.setFixedHeight(25) server_layout.addWidget(self.server_proc) # Web Service description server_layout.addStretch(1) webservice_lbl = QLabel(_('Web Service')) webservice_lbl.setObjectName('itemtitle') server_layout.addWidget(webservice_lbl) ws_desc_lbl = QLabel( _('Here you can define your alignak web service url, with port if needed' )) ws_desc_lbl.setWordWrap(True) server_layout.addWidget(ws_desc_lbl) # Web Service URL self.webservice_url.setText( settings.get_config('Alignak', 'webservice')) self.webservice_url.setPlaceholderText(_('alignak webservice url...')) self.webservice_url.setFixedHeight(25) server_layout.addWidget(self.webservice_url) # Valid Button valid_btn = QPushButton(_('Valid')) valid_btn.setObjectName('valid') valid_btn.setMinimumHeight(30) valid_btn.clicked.connect(self.accept) server_layout.addWidget(valid_btn) return server_widget def mousePressEvent(self, event): # pragma: no cover - not testable """ QWidget.mousePressEvent(QMouseEvent) """ self.offset = event.pos() def mouseMoveEvent(self, event): # pragma: no cover - not testable """ QWidget.mousePressEvent(QMouseEvent) """ try: x = event.globalX() y = event.globalY() x_w = self.offset.x() y_w = self.offset.y() self.move(x - x_w, y - y_w) except AttributeError as e: logger.warning('Move Event %s: %s', self.objectName(), str(e))
class ConnectionWidget(QWidget): title_changed = pyqtSignal(QWidget, str, name='title_changed') def __init__(self, parent): super().__init__(parent) self.title = 'Untitled' self.model = ConnectionModel(self) self.model.connected.connect(self.on_connection_changed) self.init_ui() def init_ui(self): layout = QVBoxLayout(self) layout.setContentsMargins(0, 0, 0, 0) control_bar = self.init_control_bar() layout.addWidget(control_bar) workspace = self.init_workspace() layout.addWidget(workspace) self.setLayout(layout) def init_control_bar(self): control_row_layout = QHBoxLayout(self) control_row_layout.setContentsMargins(0, 0, 0, 0) db_combo_box = QComboBox(self) db_combo_box.addItem('SQLite') # db_combo_box.addItem('PostgreSQL') control_row_layout.addWidget(db_combo_box) self.connection_line = QLineEdit(self) self.connection_line.setPlaceholderText(DEFAULT_CONNECTION_LINE) self.connection_line.setText('') control_row_layout.addWidget(self.connection_line) connection_button = QPushButton(self) connection_button.setText('Connect') connection_button.clicked.connect(self.on_connect_click) control_row_layout.addWidget(connection_button) control_row = QWidget(self) control_row.setLayout(control_row_layout) return control_row def init_workspace(self): splitter = QSplitter(self) splitter.setOrientation(Qt.Vertical) splitter.sizePolicy().setVerticalPolicy(QSizePolicy.Maximum) query_edit = self.init_query_text_edit() self.on_disconnected() splitter.addWidget(query_edit) results_widget = self.init_results_widget() splitter.addWidget(results_widget) splitter.setSizes([100, 900]) return splitter def init_query_text_edit(self): query_edit_layout = QVBoxLayout(self) query_edit_layout.setContentsMargins(0, 0, 0, 0) query_control_layout = QHBoxLayout(self) query_control_layout.setContentsMargins(0, 0, 0, 0) self.query_execute_button = QPushButton('Execute', self) self.query_execute_button.clicked.connect(self.on_execute_click) query_control_layout.addWidget(self.query_execute_button) self.query_fetch_button = QPushButton('Fetch', self) self.query_fetch_button.clicked.connect(self.on_fetch_click) self.model.fetch_changed.connect(self.on_fetch_changed) query_control_layout.addWidget(self.query_fetch_button) self.query_commit_button = QPushButton('Commit', self) self.query_commit_button.clicked.connect(self.on_connect_click) query_control_layout.addWidget(self.query_commit_button) self.query_rollback_button = QPushButton('Rollback', self) self.query_rollback_button.clicked.connect(self.on_rollback_click) query_control_layout.addWidget(self.query_rollback_button) query_control = QWidget(self) query_control.setLayout(query_control_layout) query_edit_layout.addWidget(query_control) self.query_text_edit = QTextEdit(self) self.query_text_edit.setText( "SELECT name FROM sqlite_master WHERE type='table'", ) query_edit_layout.addWidget(self.query_text_edit) self.model.connected.connect(self.on_connected) self.model.disconnected.connect(self.on_disconnected) query_edit = QWidget(self) query_edit.setLayout(query_edit_layout) query_edit.sizePolicy().setVerticalPolicy(QSizePolicy.Minimum) return query_edit def init_results_widget(self): results_widget = QTabWidget(self) results_widget.setTabsClosable(False) table_view = QTableView(self) table_view.setModel(self.model) table_view.sizePolicy().setVerticalPolicy( QSizePolicy.MinimumExpanding) results_widget.addTab(table_view, 'Data') log = QTextEdit(self) log.setReadOnly(True) self.model.executed.connect(log.append) results_widget.addTab(log, 'Events') return results_widget def on_connect_click(self): with ErrorHandler(): connection_string = ( self.connection_line.text() or DEFAULT_CONNECTION_LINE ) self.model.connect(connection_string) def on_execute_click(self): with ErrorHandler(): query = self.query_text_edit.toPlainText() self.model.execute(query) def on_fetch_click(self): with ErrorHandler(): self.model.fetch_more() def on_rollback_click(self): with ErrorHandler(): self.model.rollback() def on_connected(self): self.query_commit_button.setEnabled(True) self.query_execute_button.setEnabled(True) self.query_fetch_button.setEnabled(False) self.query_rollback_button.setEnabled(True) self.query_text_edit.setEnabled(True) def on_disconnected(self): self.query_commit_button.setEnabled(False) self.query_execute_button.setEnabled(False) self.query_fetch_button.setEnabled(False) self.query_rollback_button.setEnabled(False) self.query_text_edit.setEnabled(False) def on_fetch_changed(self, state): self.query_fetch_button.setEnabled(state) def on_connection_changed(self, name): self.title_changed.emit(self, name)
class ProblemsQWidget(QWidget): """ Class who create Problems QWidget """ def __init__(self, parent=None): super(ProblemsQWidget, self).__init__(parent) self.setWindowIcon(QIcon(settings.get_image('icon'))) # Fields self.line_search = QLineEdit() self.problems_table = ProblemsQTableView() self.problems_title = QLabel() self.actions_widget = ActionsQWidget() self.spy_widget = None self.filter_hosts_btn = ToggleQWidgetButton() self.filter_services_btn = ToggleQWidgetButton() self.spy_btn = QPushButton() self.host_btn = QPushButton() self.refresh_timer = QTimer() def initialize(self, spy_widget): """ Initialize QWidget and set SpyQWidget :param spy_widget: instance of SpyQWidget to manage spy events :type spy_widget: alignak_app.qobjects.events.spy.SpyQWidget """ problem_layout = QVBoxLayout() problem_layout.setContentsMargins(5, 20, 5, 5) self.setLayout(problem_layout) self.spy_widget = spy_widget self.problems_title.setObjectName('title') problem_layout.addWidget(self.problems_title) problem_layout.addWidget(self.get_search_widget()) problem_layout.addWidget(self.get_btn_widget()) problem_layout.addWidget(self.problems_table) self.update_problems_data() update_problems = int(settings.get_config('Alignak-app', 'update_problems')) * 1000 self.refresh_timer.setInterval(update_problems) self.refresh_timer.start() self.refresh_timer.timeout.connect(self.update_problems_data) def get_current_user_role_item(self): """ Return current selected item by ``Qt.UserRole`` :return: current selected item or None :rtype: alignak_app.items.item.Item """ item = self.problems_table.model().data( self.problems_table.selectionModel().currentIndex(), Qt.UserRole ) return item def update_action_buttons(self): """ Update status of action buttons and set current item for ActionsQWidget """ # Get item by UserRole item = self.get_current_user_role_item() if item: # If the elements had been ack or downtimed, they would not be present self.actions_widget.acknowledge_btn.setEnabled(True) self.actions_widget.downtime_btn.setEnabled(True) self.actions_widget.item = item if 'service' in item.item_type: host_id = item.data['host'] else: host_id = item.item_id self.spy_btn.setEnabled( bool(host_id not in self.spy_widget.spy_list_widget.spied_hosts) ) self.host_btn.setEnabled(True) else: self.actions_widget.acknowledge_btn.setEnabled(False) self.actions_widget.downtime_btn.setEnabled(False) self.host_btn.setEnabled(False) self.spy_btn.setEnabled(False) def get_search_widget(self): """ Create and return the search QWidget :return: search QWidget :rtype: QWidget """ widget = QWidget() layout = QHBoxLayout() layout.setSpacing(0) layout.setContentsMargins(5, 20, 5, 10) widget.setLayout(layout) # Search label search_lbl = QLabel(_('Search Problems')) search_lbl.setObjectName('bordertitle') search_lbl.setFixedHeight(25) search_lbl.setToolTip(_('Search Problems')) layout.addWidget(search_lbl) # QLineEdit self.line_search.setFixedHeight(search_lbl.height()) self.line_search.setPlaceholderText(_('Type text to filter problems...')) layout.addWidget(self.line_search) # Refresh button refresh_btn = QPushButton(_('Refresh')) refresh_btn.setObjectName('ok') refresh_btn.setFixedSize(120, search_lbl.height()) refresh_btn.setToolTip(_('Refresh problems')) refresh_btn.clicked.connect(self.update_problems_data) layout.addWidget(refresh_btn) return widget def get_btn_widget(self): """ Return QWidget with spy and host synthesis QPushButtons :return: widget with spy and host button :rtype: QWidget """ widget_btn = QWidget() layout_btn = QHBoxLayout() layout_btn.setContentsMargins(0, 0, 0, 5) widget_btn.setLayout(layout_btn) host_filter = QLabel(_('Filter hosts')) host_filter.setObjectName('subtitle') layout_btn.addWidget(host_filter) self.filter_hosts_btn.initialize() self.filter_hosts_btn.update_btn_state(False) self.filter_hosts_btn.toggle_btn.clicked.connect(lambda: self.update_problems_data('host')) layout_btn.addWidget(self.filter_hosts_btn) service_filter = QLabel(_('Filter services')) service_filter.setObjectName('subtitle') layout_btn.addWidget(service_filter) self.filter_services_btn.initialize() self.filter_services_btn.update_btn_state(False) self.filter_services_btn.toggle_btn.clicked.connect( lambda: self.update_problems_data('service') ) layout_btn.addWidget(self.filter_services_btn) layout_btn.addStretch() self.host_btn.setIcon(QIcon(settings.get_image('host'))) self.host_btn.setFixedSize(80, 20) self.host_btn.setEnabled(False) self.host_btn.setToolTip(_('See current item in synthesis view')) layout_btn.addWidget(self.host_btn) self.spy_btn.setIcon(QIcon(settings.get_image('spy'))) self.spy_btn.setFixedSize(80, 20) self.spy_btn.setEnabled(False) self.spy_btn.setToolTip(_('Spy current host')) self.spy_btn.clicked.connect(self.add_spied_host) layout_btn.addWidget(self.spy_btn) self.actions_widget.initialize(None) self.actions_widget.acknowledge_btn.setEnabled(False) self.actions_widget.downtime_btn.setEnabled(False) layout_btn.addWidget(self.actions_widget) layout_btn.setAlignment(Qt.AlignCenter) return widget_btn def add_spied_host(self): """ Add a host to spied hosts """ # Get item by UserRole item = self.get_current_user_role_item() if item: if 'service' in item.item_type: item_id = item.data['host'] else: item_id = item.item_id app_backend.query_services(item_id) self.spy_widget.spy_list_widget.add_spy_host(item_id) self.spy_widget.update_parent_spytab() self.update_action_buttons() def update_problems_data(self, item_type=''): """ Update data of Problems QTableWidget and problems title :param item_type: type of item to filter :type item_type: str """ problems_data = data_manager.get_problems() old_research = self.line_search.text() if self.parent(): self.parent().parent().setTabText( self.parent().parent().indexOf(self), _("Problems (%d)") % len(problems_data['problems']) ) self.problems_title.setText( _('There are %d problems to manage (hosts: %d, services: %d)') % ( len(problems_data['problems']), problems_data['hosts_nb'], problems_data['services_nb'] ) ) if self.filter_hosts_btn.is_checked() and not self.filter_services_btn.is_checked(): item_type = 'host' if self.filter_services_btn.is_checked() and not self.filter_hosts_btn.is_checked(): item_type = 'service' if not self.filter_services_btn.is_checked() and not self.filter_hosts_btn.is_checked(): item_type = '' if isinstance(item_type, str): if 'host' in item_type and self.filter_hosts_btn.is_checked(): if self.filter_services_btn.is_checked(): self.filter_services_btn.update_btn_state(False) if 'service' in item_type and self.filter_services_btn.is_checked(): if self.filter_hosts_btn.is_checked(): self.filter_hosts_btn.update_btn_state(False) problems_data['problems'] = [ item for item in problems_data['problems'] if item_type in item.item_type ] proxy_filter = self.problems_table.update_view(problems_data) if problems_data['problems']: self.line_search.textChanged.connect(proxy_filter.setFilterRegExp) else: self.problems_title.setText(_('If problems are found, they will be displayed here.')) self.problems_table.selectionModel().selectionChanged.connect(self.update_action_buttons) self.update_action_buttons() if old_research: self.line_search.setText(old_research) self.line_search.textChanged.emit(old_research)
class LoginQDialog(QDialog): """ Class who create login QDialog. """ def __init__(self, parent=None): super(LoginQDialog, self).__init__(parent) self.setWindowTitle('Login to Alignak') self.setWindowFlags(Qt.FramelessWindowHint) self.setStyleSheet(settings.css_style) self.setWindowIcon(QIcon(settings.get_image('icon'))) self.setObjectName('dialog') self.setFixedSize(310, 360) # Fields self.username_line = QLineEdit() self.password_line = QLineEdit() self.proxies = {} self.offset = None def create_widget(self): """ Create widget login """ # Main status_layout main_layout = QVBoxLayout(self) main_layout.setContentsMargins(0, 0, 0, 0) main_layout.addWidget(get_logo_widget(self, _('Login'), exitapp=True)) # Login QWidget login_widget = QWidget(self) login_widget.setObjectName('dialog') login_layout = QGridLayout() login_widget.setLayout(login_layout) # _ = init_localization() title = QLabel(_('Welcome to Alignak-app')) title.setObjectName('itemtitle') title.setContentsMargins(1, 1, 1, 1) login_layout.addWidget(title, 0, 0, 1, 2) login_layout.setAlignment(title, Qt.AlignCenter) version = QLabel(_('Version %s') % __version__) version.setObjectName('subtitle') login_layout.addWidget(version, 1, 0, 1, 2) login_layout.setAlignment(version, Qt.AlignCenter | Qt.AlignTop) # Alignak server login_label = QLabel(_('Configure Alignak server')) login_layout.addWidget(login_label, 2, 0, 1, 1) login_layout.setAlignment(login_label, Qt.AlignRight) server_btn = QPushButton() server_btn.clicked.connect(self.handle_server) server_btn.setFixedSize(35, 35) server_btn.setIcon(QIcon(settings.get_image('server_settings'))) server_btn.setToolTip(_('Configure Alignak Server')) login_layout.addWidget(server_btn, 2, 1, 1, 1) # Proxy settings proxy_lbl = QLabel(_('Configure Proxy')) login_layout.addWidget(proxy_lbl, 3, 0, 1, 1) login_layout.setAlignment(proxy_lbl, Qt.AlignRight) proxy_btn = QPushButton() proxy_btn.setIcon(QIcon(settings.get_image('password'))) proxy_btn.setToolTip(_('Configure your Proxy')) proxy_btn.setFixedSize(35, 35) proxy_btn.clicked.connect(self.handle_proxy) login_layout.addWidget(proxy_btn, 3, 1, 1, 1) # Connection label connection_lbl = QLabel() connection_lbl.setText(_('<b>Log-in</b> to use the application')) connection_lbl.setWordWrap(True) login_layout.addWidget(connection_lbl, 4, 0, 1, 2) # Username field self.username_line.setFixedHeight(25) self.username_line.setPlaceholderText(_('username...')) login_layout.addWidget(self.username_line, 5, 0, 1, 2) # Password field self.password_line.setFixedHeight(25) self.password_line.setPlaceholderText(_('password...')) self.password_line.setEchoMode(QLineEdit.Password) login_layout.addWidget(self.password_line, 6, 0, 1, 2) # Login button login_button = QPushButton(_('LOGIN'), self) login_button.clicked.connect(self.accept_login) login_button.setObjectName('valid') login_button.setMinimumHeight(30) login_button.setDefault(True) login_layout.addWidget(login_button, 7, 0, 1, 2) main_layout.addWidget(login_widget) self.setLayout(main_layout) center_widget(self) if settings.get_config('Alignak', 'proxy_user'): self.handle_proxy() def accept_login(self): """ Accept Login or not if backend is connected """ username = str(self.username_line.text()) password = str(self.password_line.text()) # Set proxy only if in config if not self.proxies and settings.get_config('Alignak', 'proxy'): self.set_proxy_settings() if app_backend.login(username, password, proxies=self.proxies): self.accept() else: self.reject() def set_proxy_settings(self, proxy_password=None): """ Set the proxy settings, with password if given :param proxy_password: the pasword of proxy :type proxy_password: str """ if settings.get_config('Alignak', 'proxy_user'): # Model is: {'http': 'http://*****:*****@proxy:port'} protocol, address, port = settings.get_config('Alignak', 'proxy').split(':') proxy_user = settings.get_config('Alignak', 'proxy_user') address = address.replace('//', '') proxy = { protocol: '%s://%s:%s@%s:%s' % (protocol, proxy_user, proxy_password, address, port) } self.proxies = proxy elif settings.get_config('Alignak', 'proxy'): protocol = settings.get_config('Alignak', 'proxy').split(':')[0] self.proxies = {protocol: settings.get_config('Alignak', 'proxy')} else: self.proxies = {} def handle_proxy(self): # pragma: no cover - not testable """ Handle Proxy QDialog display and set proxies for login """ proxy_dialog = ProxyQDialog() proxy_dialog.initialize_dialog() self.proxies = None if proxy_dialog.exec_() == ProxyQDialog.Accepted: proxy_address = proxy_dialog.proxy_address.text().rstrip() proxy_user = proxy_dialog.proxy_user.text().rstrip() proxy_password = proxy_dialog.proxy_password.text().rstrip() # Save proxy and user proxy for next login settings.set_config('Alignak', 'proxy', proxy_address) settings.set_config('Alignak', 'proxy_user', proxy_user) self.set_proxy_settings(proxy_password) @staticmethod def handle_server(): # pragma: no cover - not testable """ Handle for Server QDialog and set alignak backend server settings """ server_dialog = ServerQDialog() server_dialog.initialize_dialog() if server_dialog.exec_() == QDialog.Accepted: if server_dialog.server_port.text().rstrip(): backend_url = '%(url)s:' + str( server_dialog.server_port.text()).rstrip() else: backend_url = '%(url)s' settings.set_config('Alignak', 'backend', backend_url) settings.set_config('Alignak', 'url', str(server_dialog.server_url.text()).rstrip()) settings.set_config('Alignak', 'processes', str(server_dialog.server_proc.text()).rstrip()) settings.set_config( 'Alignak', 'webservice', str(server_dialog.webservice_url.text()).rstrip()) def showEvent(self, _): """ QDialog.showEvent(QShowEvent) """ self.username_line.setFocus() def mousePressEvent(self, event): # pragma: no cover - not testable """ QWidget.mousePressEvent(QMouseEvent) """ self.offset = event.pos() def mouseMoveEvent(self, event): # pragma: no cover - not testable """ QWidget.mousePressEvent(QMouseEvent) """ try: x = event.globalX() y = event.globalY() x_w = self.offset.x() y_w = self.offset.y() self.move(x - x_w, y - y_w) except AttributeError as e: logger.warning('Move Event %s: %s', self.objectName(), str(e))
class ValidatorQDialog(QDialog): """ Class who create Validator QDialog to edit text in Alignak-app with regexp to validate """ def __init__(self, parent=None): super(ValidatorQDialog, self).__init__(parent) self.setWindowTitle('Edit Dialog') self.setWindowFlags(Qt.FramelessWindowHint) self.setStyleSheet(settings.css_style) self.setWindowIcon(QIcon(settings.get_image('icon'))) self.setObjectName('dialog') self.setFixedSize(250, 200) # Fields self.line_edit = QLineEdit() self.valid_text = QLabel() self.validator = QRegExpValidator() self.old_text = '' def initialize(self, title, text, regexp): """ Initialize QDialog for ValidatorQDialog :param title: title of the QDialog :type title: str :param text: text to edit :type text: str :param regexp: regular expression to validate :type regexp: str """ self.old_text = text center_widget(self) # Main status_layout main_layout = QVBoxLayout(self) main_layout.setContentsMargins(0, 0, 0, 0) self.setLayout(main_layout) main_layout.addWidget(get_logo_widget(self, title)) text_title = QLabel(_("Edit your text:")) text_title.setObjectName('subtitle') main_layout.addWidget(text_title) main_layout.setAlignment(text_title, Qt.AlignCenter) main_layout.addWidget(self.get_text_widget(regexp)) def get_text_widget(self, regexp): """ Return text QWidget with QTextEdit :return: text QWidget :rtype: QWidget """ text_widget = QWidget() text_widget.setObjectName('dialog') text_layout = QVBoxLayout() text_widget.setLayout(text_layout) text_layout.addWidget(self.valid_text) qreg_exp = QRegExp(regexp) self.validator.setRegExp(qreg_exp) self.line_edit.setPlaceholderText(_('type your text...')) self.line_edit.setText(self.old_text) self.line_edit.setValidator(self.validator) self.line_edit.setFixedHeight(25) self.line_edit.textChanged.connect(self.check_text) text_layout.addWidget(self.line_edit) # Accept button accept_btn = QPushButton(_('Confirm'), self) accept_btn.clicked.connect(self.accept_text) accept_btn.setObjectName('valid') accept_btn.setMinimumHeight(30) text_layout.addWidget(accept_btn) return text_widget def check_text(self): """ Valid email with ``QRegExpValidator`` and inform user """ state = self.validator.validate(self.line_edit.text(), 0)[0] if state == QRegExpValidator.Acceptable: text = 'Valid email' color = '#27ae60' # green else: text = 'Invalid email !' color = '#e67e22' # orange self.valid_text.setStyleSheet('QLabel { color: %s; }' % color) self.valid_text.setText(text) def accept_text(self): # pragma: no cover """ Set Edit QDialog to Rejected or Accepted (prevent to patch for nothing) """ state = self.validator.validate(self.line_edit.text(), 0)[0] if self.old_text == self.line_edit.text(): self.reject() elif not self.old_text or self.old_text.isspace(): if not self.line_edit.text() or self.line_edit.text().isspace(): self.reject() else: if state == QRegExpValidator.Acceptable: self.accept() else: self.reject() elif not self.line_edit.text() or self.line_edit.text().isspace(): self.line_edit.setText('') self.accept() else: if state == QRegExpValidator.Acceptable: self.accept() else: self.reject()
class Index(QWidget): show_mainindex_sg = pyqtSignal(int, str) show_register_sg = pyqtSignal() def __init__(self, parent=None): super(Index, self).__init__(parent) self.desktop = QApplication.desktop() self.screenRect = self.desktop.screenGeometry() self.h = self.screenRect.height() self.w = self.screenRect.width() self.xr = self.w / 930 self.yr = self.h / 640 self.zr = min(self.xr, self.yr) self.top_wi = QWidget(self) self.logo_la = QLabel(self.top_wi) self.ind_wi = QWidget(self) self.login_but = QPushButton(self.ind_wi) self.joke_but = QPushButton(self.ind_wi) self.register_but = QPushButton(self.ind_wi) self.imp_la = QLabel(self.ind_wi) self.account_le = QLineEdit(self.ind_wi) self.psw_le = QLineEdit(self.ind_wi) self.loading = QLabel(self) self.gif = QMovie('./resource/image/load.gif') self.set_ui() with open('index.qss', 'r') as f: self.setStyleSheet(f.read()) def set_ui(self): self.setWindowTitle('Login') self.setObjectName('index') self.resize(self.w, self.h) self.top_wi.setObjectName('top') self.top_wi.resize(930 * self.xr, 95 * self.yr) self.logo_la.setObjectName('logo') self.logo_la.resize(65 * self.xr, 65 * self.zr) self.logo_la.move(29 * self.xr, 16 * self.yr) effect = QGraphicsDropShadowEffect() effect.setOffset(10, 10) effect.setColor(QColor(0, 0, 0, 80)) effect.setBlurRadius(20) self.ind_wi.setObjectName('login') self.ind_wi.resize(327 * self.xr, 388 * self.yr) self.ind_wi.move(300 * self.xr, 150 * self.yr) self.ind_wi.setGraphicsEffect(effect) self.joke_but.setObjectName('joke') self.joke_but.resize(130 * self.xr, 30 * self.yr) self.joke_but.move(76 * self.xr, 234 * self.yr) self.joke_but.setFlat(True) self.joke_but.setText('忘记密码?我也没办法') self.login_but.setObjectName('button') self.login_but.move(64 * self.xr, 260 * self.yr) self.login_but.resize(202 * self.xr, 45 * self.yr) self.login_but.setText('登陆') self.login_but.clicked.connect(self.login) self.register_but.setObjectName('button') self.register_but.move(64 * self.xr, 315 * self.yr) self.register_but.resize(202 * self.xr, 45 * self.yr) self.register_but.setText('注册') self.register_but.clicked.connect(self.show_register) self.imp_la.setObjectName('imp_label') self.imp_la.resize(100 * self.zr, 100 * self.zr) self.imp_la.move(115 * self.xr + 100 * (self.xr - self.zr) / 2, 15 * self.yr) self.imp_la.setStyleSheet('border-radius:{}px;'.format(self.zr * 49)) self.account_le.setObjectName('input') self.account_le.setTextMargins(20, 0, 0, 0) self.account_le.resize(213 * self.xr, 45 * self.yr) self.account_le.move(59 * self.xr, 126 * self.yr) self.account_le.setPlaceholderText('账号') self.psw_le.setObjectName('input') self.psw_le.setTextMargins(20, 0, 0, 0) self.psw_le.resize(213 * self.xr, 45 * self.yr) self.psw_le.move(59 * self.xr, 181 * self.yr) self.psw_le.setPlaceholderText('密码') self.psw_le.setEchoMode(QLineEdit.Password) self.loading.setObjectName('load') self.loading.resize(self.xr * 150, self.yr * 150) self.loading.move(self.xr * 760, self.yr * 500) self.loading.setScaledContents(True) self.loading.setMovie(self.gif) self.gif.start() self.ind_wi.setStyleSheet('#input{border-radius:' + str(self.zr * 20) + 'px;}' + '#button{border-radius:' + str( self.zr * 20) + 'px;' + 'font-size:' + str(int(self.zr * 18)) + 'px;}') def login(self): account_p = self.account_le.text() psw_p = self.psw_le.text() dic = login(account_p, psw_p) if dic['status'] == 0: self.show_mainindex_sg.emit(dic['data']['user_id'], dic['data']['token']) elif dic['status'] == 1: self.account_le.clear() self.psw_le.clear() self.account_le.setStyleSheet('border:4px solid;border-color:red;') self.account_le.setPlaceholderText('网络超时') else: self.account_le.clear() self.psw_le.clear() self.account_le.setStyleSheet('border:4px solid;border-color:red;') self.account_le.setPlaceholderText('账号不存在或密码错误') def show_register(self): self.show_register_sg.emit()
class SynthesisQWidget(QWidget): """ Class who manage Synthesis view with Host and Services QWidgets """ def __init__(self, parent=None): super(SynthesisQWidget, self).__init__(parent) # Fields self.host_widget = HostQWidget() self.services_widget = ServicesQWidget() self.line_search = QLineEdit() self.completer = QCompleter() self.hint_widget = QWidget() def initialize_synthesis(self): """ Initialize Synthesis QWidget """ synthesis_layout = QVBoxLayout() synthesis_layout.setContentsMargins(0, 0, 0, 0) self.setLayout(synthesis_layout) # Search widget search_widget = self.get_search_widget() synthesis_layout.addWidget(search_widget) # Host widget self.host_widget.initialize() self.host_widget.setMaximumHeight(self.width() * 0.5) synthesis_layout.addWidget(self.host_widget) # Hint Widget hint_text = _( '<h4>Dahsboard</h4>' '<ul><li>At the top of App, ' 'you have a dashboard that summarizes the number of items per state.</li></ul>' '<h4>Tabs</h4>' '<ul><li><h4>Host Synthesis</h4></li>' 'Tap in the search bar to view a host and its services.' '<li><h4>Problems</h4></li>' 'The "Problems" tab will show you all problems detected in your backend.' '<li><h4>Spy Hosts</h4></li>' 'A "Spy Host" will keep you regularly informed of his condition. ' 'You will also see problems detected for this host, in the "Spy Hosts" panel.</ul>' '<h4>Alignak</h4>' '<ul><li>You can see your backend status and daemons if available, ' 'as well as your profile.</li></ul>' '<h4>Livestate</h4>' '<ul><li>In the livestate, you can see global state of your monitored items.</li></ul>' '<h4>Events</h4>' '<ul><li>Events will show you informative messages your actions inside App.</li></ul>' ) hint_layout = QVBoxLayout(self.hint_widget) hint_label = QLabel(hint_text) hint_label.setObjectName('subtitle') hint_layout.addWidget(hint_label) synthesis_layout.addWidget(self.hint_widget) # Services widget self.services_widget.initialize() synthesis_layout.addWidget(self.services_widget) # Align all widgets to Top synthesis_layout.setAlignment(Qt.AlignTop) def get_search_widget(self): """ Create and return the search QWidget :return: search QWidget :rtype: QWidget """ widget = QWidget() layout = QHBoxLayout() layout.setSpacing(0) widget.setLayout(layout) # Search label search_lbl = QLabel(_('Search Host')) search_lbl.setObjectName('bordertitle') search_lbl.setFixedHeight(25) search_lbl.setToolTip(_('Search Host')) layout.addWidget(search_lbl) # QLineEdit self.line_search.setFixedHeight(search_lbl.height()) layout.addWidget(self.line_search) self.create_line_search([]) return widget def create_line_search(self, hostnames_list): """ Add all hosts to QLineEdit and set QCompleter :param hostnames_list: list of host names :type hostnames_list: list """ # Get QStringListModel model = self.completer.model() if not model: model = QStringListModel() model.setStringList(hostnames_list) # Configure QCompleter from model self.completer.setFilterMode(Qt.MatchContains) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.completer.setModel(model) self.completer.popup().setObjectName('popup') # Add completer to QLineEdit self.line_search.setCompleter(self.completer) self.line_search.setPlaceholderText( _('Type a host name to display its data')) self.line_search.setToolTip(_('Type a host name to display its data')) def update_synthesis(self, host, services, not_spied): """ Update Synthesis QWidget with given host and services :param host: host item :type host: alignak_app.items.host.Host :param services: list of services attached to host :type services: list :param not_spied: define if host is spied or not :type not_spied: bool """ self.host_widget.spy_btn.setEnabled(not_spied) if host: logger.info('Display %s in synthesis view', host.name) # Update Qwidgets self.host_widget.update_host(host) self.services_widget.update_widget(services) self.hint_widget.hide() self.host_widget.show() self.services_widget.show() # If the service element does not have the same ID as the host, reset to None if self.services_widget.service_data_widget.service_item: if self.services_widget.service_data_widget.service_item.data['host'] != \ self.host_widget.host_item.item_id: self.services_widget.service_data_widget.service_item = None else: self.host_widget.hide() self.services_widget.hide() self.hint_widget.show()
class Search(QWidget): search_sg = pyqtSignal(dict) back_sg = pyqtSignal() def __init__(self, parent=None): super(Search, self).__init__(parent) self.desktop = QApplication.desktop() self.screenRect = self.desktop.screenGeometry() self.h = self.screenRect.height() self.w = self.screenRect.width() self.xr = self.w / 930 self.yr = self.h / 640 self.zr = min(self.xr, self.yr) self.token = '' self.head = QLabel(self) self.search = QLineEdit(self) self.butt = QPushButton(self) self.but = QPushButton(self) self.set_ui() def set_ui(self): self.search.setObjectName('search') self.search.resize(self.xr * 520, self.yr * 40) self.search.move(self.xr * 205, self.yr * 300) self.search.setPlaceholderText('请输入战局ID') self.search.setTextMargins(20, 0, 0, 0) self.search.setStyleSheet('font-size:{}px;border-radius:{}px;'.format(int(self.zr * 16), self.zr * 15)) self.head.setObjectName('head') self.head.resize(self.xr * 200, self.yr * 50) self.head.move(self.xr * 360, self.yr * 240) self.head.setText('搜索战局') self.head.setAlignment(Qt.AlignCenter) self.head.setStyleSheet('font-size:{}px;'.format(int(self.zr * 25))) self.but.setObjectName('button') self.but.resize(self.xr * 130, self.yr * 40) self.but.move(self.xr * 480, self.yr * 380) self.but.setText('返回') self.but.clicked.connect(self.back_for) self.butt.setObjectName('button') self.butt.resize(self.xr * 130, self.yr * 40) self.butt.move(self.xr * 320, self.yr * 380) self.butt.setText('搜索') self.butt.clicked.connect(self.search_for) self.setStyleSheet('#button{font-size:' + str(int(self.zr * 18)) + 'px;border-radius:' + str( self.zr * 15) + 'px;background-color:#333643;color:#ffffff;}#button:hover{background-color:#575B6E;}#button:pressed{background-color:#202129;}') def search_for(self): id_p = self.search.text() self.search.clear() dic = find_info(id_p, self.token) # print(dic) if dic['status'] == 0: self.search_sg.emit(dic) else: self.search.setStyleSheet( 'font-size:{}px;border-radius:{}px;border:4px solid;border-color:red'.format(int(self.zr * 16), self.zr * 15)) self.search.clear() self.search.setPlaceholderText('ID不存在') def back_for(self): self.back_sg.emit() def get_token(self, t): self.token = t
class TableTab(TraceDocks): ## The constructor # initialize the super-class, assign a name and first configItems def __init__(self,parent): super(TableTab, self).__init__(parent,'TableTab') self.tabName = 'TableTab' self.parent = parent self.logger.logEvent('Creating Tab now: '+ self.tabName) # Set a couple of default-values, in case the configParser does not work self.snifferConfig.configAutoClearCheck = 1 self.snifferConfig.configFilterState = 'Local' self.snifferConfig.configFilterList = self.snifferFilter.filteredIdList # By parsing the config now, we assure that we re-load everything # the way we left it self.snifferConfig.parseConfigFromFile() self.lastSearchedText = 'nullthiswillneverbefound' self.lastMatch = 'purge' self.lastIndex = 0 ## Create the visible UI def setTableTabLayout(self): # Create Table Tab --------------------### # Create Layouts self.Vlayout = QVBoxLayout() self.H1layout = QHBoxLayout() self.H11layout = QHBoxLayout() self.H12layout = QHBoxLayout() self.H21layout = QHBoxLayout() self.V11layout = QVBoxLayout() self.V21layout = QVBoxLayout() # Create Widgets for H1layout # First buttons self.clearTableButt = QPushButton('Clear Table') self.clearTableButt.clicked.connect(self.clearTable) self.autoClearCheck = QCheckBox('Auto Clear') self.autoClearCheck.stateChanged.connect(self.checkAutoClearChanged) self.searchInputField = QLineEdit() self.searchInputField.setPlaceholderText('Enter search term, then click search') self.searchButt = QPushButton('Search Table') self.searchButt.clicked.connect(lambda: self.searchInTable(self.searchInputField.text(),2)) self.showSummaryButt = QPushButton('Show Summary') self.showSummaryButt.clicked.connect(self.showSummary) self.filterGroup = QButtonGroup() self.localFilterRadio = QRadioButton('Local',self) self.globalFilterRadio = QRadioButton('Global', self) self.configureFilterButt = QPushButton('Configure Filter') self.configureFilterButt.clicked.connect(self.configureFilter) self.localFilterRadio.clicked.connect(self.localRadioSelected) self.globalFilterRadio.clicked.connect(self.globalRadioSelected) self.H21layout.addWidget(self.localFilterRadio) self.H21layout.addWidget(self.globalFilterRadio) self.H21layout.addWidget(self.showSummaryButt) self.V21layout.addLayout(self.H21layout) self.V21layout.addWidget(self.configureFilterButt) # Add Widgets to H11layout self.H11layout.addWidget(self.clearTableButt) self.H11layout.addWidget(self.autoClearCheck) # Add Widgets to H12layout self.H12layout.addWidget(self.searchInputField) self.H12layout.addWidget(self.searchButt) self.H12layout.addStretch() self.V11layout.addLayout(self.H11layout) self.V11layout.addLayout(self.H12layout) self.H1layout.addLayout(self.V11layout) self.H1layout.addLayout(self.V21layout) self.syncUiToConfig() #------------------------------------ # Create Table self.detailTableIndex = 0 self.detailTable = QTableWidget() self.detailTableItem = QTableWidgetItem() self.detailTable.setRowCount(0) self.detailTable.setColumnCount(6) self.detailTable.setHorizontalHeaderLabels('packID;Tick;Timer;Type;Message;Length'.split(';')) self.detailTable.resizeColumnsToContents() self.detailTableHeader = self.detailTable.horizontalHeader() self.detailTableHeader.setSectionResizeMode(0, QHeaderView.ResizeToContents) self.detailTableHeader.setSectionResizeMode(1, QHeaderView.ResizeToContents) self.detailTableHeader.setSectionResizeMode(2, QHeaderView.ResizeToContents) self.detailTableHeader.setSectionResizeMode(3, QHeaderView.ResizeToContents) self.detailTableHeader.setSectionResizeMode(4, QHeaderView.Stretch) self.detailTableHeader.setSectionResizeMode(5, QHeaderView.ResizeToContents) #------------------------------------ self.Vlayout.addLayout(self.H1layout) self.Vlayout.addWidget(self.detailTable) self.dockContents.setLayout(self.Vlayout) ## Fill the main table with the entries from the given list # @param fillTableList the list which is to be parsed into the table def fillTable(self,fillTableList): print('Filling Table with all items in PayloadList') self.detailTable.scrollToTop() # Scrolls to the top of the table self.configAutoClearCheck = True if self.configAutoClearCheck == True: self.detailTable.setRowCount(0) self.detailTableIndex = 0 Globals.dockDict['dockStart'].progressShotBar.setMaximum(len(Globals.payloadList)) for self.tablePayload in fillTableList: self.detailTable.insertRow(self.detailTableIndex) self.detailTable.setItem(self.detailTableIndex,0,QTableWidgetItem(str(self.tablePayload.payloadHead.packetID))) self.detailTable.setItem(self.detailTableIndex,1,QTableWidgetItem(str(self.tablePayload.payloadHead.tickCountHigh << 8 | self.tablePayload.payloadHead.tickCountLow))) self.detailTable.setItem(self.detailTableIndex,2,QTableWidgetItem(str(self.tablePayload.payloadHead.timerByteHigh << 8 | self.tablePayload.payloadHead.timerByteLow))) self.detailTable.setItem(self.detailTableIndex,3,QTableWidgetItem(Globals.tspDict[self.tablePayload.payloadHead.informationID][0])) testPayload = self.tablePayload.toDict() # This a little messy: We check whether an objectDict is available, and if it is # we check for the different DataTypes there might be, since the message section is unified. # Basically, we need to handle all the different cases there can be, payload0-payload3 and the actual objectType if Globals.objectDict: if getDataType(self.tablePayload) == 1: if getObjectType(self.tablePayload) == 5: try: self.detailTable.setItem(self.detailTableIndex,4,QTableWidgetItem(str(self.tablePayload.data1)+': '+Globals.objectDict['TASK'][str(self.tablePayload.data1)])) except: self.detailTable.setItem(self.detailTableIndex,4,QTableWidgetItem('FAILED WITH KEYERROR - see printOutput')) print('KEYERROR DETAILS:') print(testPayload) elif getDataType(self.tablePayload) == 2: try: self.detailTable.setItem(self.detailTableIndex,4,QTableWidgetItem(str(self.tablePayload.data1)+': '+Globals.objectDict[Globals.objectTypeDict[self.tablePayload.data1]][str(self.tablePayload.data2)])) except: self.detailTable.setItem(self.detailTableIndex,4,QTableWidgetItem('FAILED WITH KEYERROR - see printOutput')) print('KEYERROR DETAILS:') print(testPayload) # If the objectDict does not exist, we can just dump the raw information into the message-section -> no lookup will be happening # and it is up to the user to interpret the data else: if getDataType(self.tablePayload) == 1: self.detailTable.setItem(self.detailTableIndex,4,QTableWidgetItem(str(self.tablePayload.data1))) elif getDataType(self.tablePayload) == 2: self.detailTable.setItem(self.detailTableIndex,4,QTableWidgetItem(str(self.tablePayload.data1)+';'+str(self.tablePayload.data2))) elif getDataType(self.tablePayload) == 3: self.detailTable.setItem(self.detailTableIndex,4,QTableWidgetItem(str(self.tablePayload.data1)+';'+str(self.tablePayload.data2)+';'+str(self.tablePayload.data3))) self.detailTable.setItem(self.detailTableIndex,5,QTableWidgetItem('payload'+str(getDataType(self.tablePayload)))) self.detailTableIndex+=1 Globals.dockDict['dockStart'].progressShotBar.setValue(self.detailTableIndex) Globals.dockDict['dockStart'].progressShotBar.setValue(len(Globals.payloadList)) Globals.dockDict['dockStart'].displayStatusMessage('Table filled completely, check the tab') self.lastSearchedText = 'thisisAWorkAround' # No idea why this is there... # --- DOCK-SPECIFIC UI FUNCTIONS --- # # -----------------------------------# ## Disable all UI-buttons belonging to the tab. This is implementation specific def disableButtons(self): self.clearTableButt.setEnabled(False) self.autoClearCheck.setEnabled(False) print('Disable TabTable Buttons') ## CB: clearTableButton // Clear the main table def clearTable(self): self.logger.logEvent('clear Table clicked') self.detailTable.setRowCount(0) self.detailTableIndex = 0 ## CB: autoClearCheckbox // set the configAutoClearCheck state according to the checkbox def checkAutoClearChanged(self): self.snifferConfig.configAutoClearCheck ^= 1 self.logger.logEvent('changed Auto Clear Checkbox to - '+ str(self.snifferConfig.configAutoClearCheck)) ## CB: localRadioButt // set the configFilterState to 'Local' def localRadioSelected(self): self.snifferConfig.configFilterState = 'Local' self.logger.logEvent('changed Filter Radio to - '+ str(self.snifferConfig.configFilterState)) ## CB: globalRadioButt // set the configFilterState to 'Global' def globalRadioSelected(self): self.snifferConfig.configFilterState = 'Global' self.logger.logEvent('changed Filter Radio to - '+ str(self.snifferConfig.configFilterState)) ## CB: Show Stats // opens the Stat-Dialog to show misc. information about the measurement def showSummary(self): self.snifferStats.show() self.snifferStats.showStats() ## Searches the table for a string and scrolls to the found item. # @param textToSearch the string that needs to be found in the table # @param column the column where the search needs to take place def searchInTable(self, textToSearch, column): if textToSearch not in Globals.IDList: QMessageBox.about(self,'Not Found','SearchText not Found!') return if self.lastSearchedText == textToSearch: self.detailTable.setCurrentItem(self.lastFound[self.lastIndex]) self.detailTable.scrollToItem(self.lastFound[self.lastIndex]) self.lastIndex = self.lastIndex + 1 if self.lastIndex == len(self.lastFound): self.lastIndex = 0 else: foundItems = self.detailTable.findItems(textToSearch, Qt.MatchExactly) self.lastSearchedText = textToSearch if len(foundItems) != 0: self.lastFound = foundItems self.lastIndex = 1 self.detailTable.setCurrentItem(foundItems[0]) self.detailTable.scrollToItem(self.lastFound[self.lastIndex]) # --- MANDATORY UI FUNCTIONS --- # # -------------------------------# ## Read out all components of snifferConfig and set the UI elements according to # the saved values. def syncUiToConfig(self): self.autoClearCheck.setChecked(self.snifferConfig.configAutoClearCheck) if self.snifferConfig.configFilterState == 'Local': self.localFilterRadio.click() elif self.snifferConfig.configFilterState == 'Global': self.globalFilterRadio.click() else: print('Error, neither local nor global in config') ## Open the correct filter based on the radioButton. If the Global-filter is checked # we assign its calledby variable in order to execute the right callback after the filter is saved. def configureFilter(self): if self.localFilterRadio.isChecked(): self.snifferFilter.show() elif self.globalFilterRadio.isChecked(): Globals.globalFilter.show() Globals.globalFilter.calledBy = 'dockTable' else: print('neither radios checked. Error!') ## CB: // Updates the UI-contents with after filtering has taken place. # This function should not be called by the tab itself, but by the filter # @param filteredIDs the IDs that are to be kept in the payloadList (obsolete) # @param filteredPayloads the new payloadList, which only contains the payloads filtered by the SnifferFilter def filterUpdated(self, filteredIDs, filteredPayloads): print('we arrive from SnifferFilter') self.clearTable() self.fillTable(filteredPayloads)
class SynthesisQWidget(QWidget): """ Class who manage Synthesis view with Host and Services QWidgets """ def __init__(self, parent=None): super(SynthesisQWidget, self).__init__(parent) # Fields self.host_widget = HostQWidget() self.services_widget = ServicesQWidget() self.line_search = QLineEdit() self.completer = QCompleter() self.hint_widget = QWidget() def initialize_synthesis(self): """ Initialize Synthesis QWidget """ synthesis_layout = QVBoxLayout() synthesis_layout.setContentsMargins(0, 0, 0, 0) self.setLayout(synthesis_layout) # Search widget search_widget = self.get_search_widget() synthesis_layout.addWidget(search_widget) # Host widget self.host_widget.initialize() self.host_widget.setMaximumHeight(self.width() * 0.5) synthesis_layout.addWidget(self.host_widget) # Hint Widget hint_text = _( '<h4>Dahsboard</h4>' '<ul><li>At the top of App, ' 'you have a dashboard that summarizes the number of items per state.</li></ul>' '<h4>Tabs</h4>' '<ul><li><h4>Host Synthesis</h4></li>' 'Tap in the search bar to view a host and its services.' '<li><h4>Problems</h4></li>' 'The "Problems" tab will show you all problems detected in your backend.' '<li><h4>Spy Hosts</h4></li>' 'A "Spy Host" will keep you regularly informed of his condition. ' 'You will also see problems detected for this host, in the "Spy Hosts" panel.</ul>' '<h4>Alignak</h4>' '<ul><li>You can see your backend status and daemons if available, ' 'as well as your profile.</li></ul>' '<h4>Livestate</h4>' '<ul><li>In the livestate, you can see global state of your monitored items.</li></ul>' '<h4>Events</h4>' '<ul><li>Events will show you informative messages your actions inside App.</li></ul>' ) hint_layout = QVBoxLayout(self.hint_widget) hint_label = QLabel(hint_text) hint_label.setObjectName('subtitle') hint_layout.addWidget(hint_label) synthesis_layout.addWidget(self.hint_widget) # Services widget self.services_widget.initialize() synthesis_layout.addWidget(self.services_widget) # Align all widgets to Top synthesis_layout.setAlignment(Qt.AlignTop) def get_search_widget(self): """ Create and return the search QWidget :return: search QWidget :rtype: QWidget """ widget = QWidget() layout = QHBoxLayout() layout.setSpacing(0) widget.setLayout(layout) # Search label search_lbl = QLabel(_('Search Host')) search_lbl.setObjectName('bordertitle') search_lbl.setFixedHeight(25) search_lbl.setToolTip(_('Search Host')) layout.addWidget(search_lbl) # QLineEdit self.line_search.setFixedHeight(search_lbl.height()) layout.addWidget(self.line_search) self.create_line_search([]) return widget def create_line_search(self, hostnames_list): """ Add all hosts to QLineEdit and set QCompleter :param hostnames_list: list of host names :type hostnames_list: list """ # Get QStringListModel model = self.completer.model() if not model: model = QStringListModel() model.setStringList(hostnames_list) # Configure QCompleter from model self.completer.setFilterMode(Qt.MatchContains) self.completer.setCaseSensitivity(Qt.CaseInsensitive) self.completer.setModel(model) self.completer.popup().setObjectName('popup') # Add completer to QLineEdit self.line_search.setCompleter(self.completer) self.line_search.setPlaceholderText(_('Type a host name to display its data')) self.line_search.setToolTip(_('Type a host name to display its data')) def update_synthesis(self, host, services, not_spied): """ Update Synthesis QWidget with given host and services :param host: host item :type host: alignak_app.items.host.Host :param services: list of services attached to host :type services: list :param not_spied: define if host is spied or not :type not_spied: bool """ self.host_widget.spy_btn.setEnabled(not_spied) if host: logger.info('Display %s in synthesis view', host.name) # Update Qwidgets self.host_widget.update_host(host) self.services_widget.update_widget(services) self.hint_widget.hide() self.host_widget.show() self.services_widget.show() # If the service element does not have the same ID as the host, reset to None if self.services_widget.service_data_widget.service_item: if self.services_widget.service_data_widget.service_item.data['host'] != \ self.host_widget.host_item.item_id: self.services_widget.service_data_widget.service_item = None else: self.host_widget.hide() self.services_widget.hide() self.hint_widget.show()
class ServerQDialog(QDialog): """ Class who create Server QDialog. """ def __init__(self, parent=None): super(ServerQDialog, self).__init__(parent) self.setWindowTitle(_('Alignak Settings')) self.setWindowFlags(Qt.FramelessWindowHint) self.setStyleSheet(settings.css_style) self.setWindowIcon(QIcon(settings.get_image('icon'))) self.setObjectName('dialog') self.setFixedSize(340, 420) # Fields self.server_proc = QLineEdit() self.server_url = QLineEdit() self.server_port = QLineEdit() self.webservice_url = QLineEdit() self.proxy_address = QLineEdit() self.proxy_user = QLineEdit() self.proxy_password = QLineEdit() self.offset = None def initialize_dialog(self): """ Initialize Server QDialog """ main_layout = QVBoxLayout() main_layout.setContentsMargins(0, 0, 0, 0) self.setLayout(main_layout) main_layout.addWidget(get_logo_widget(self, _('Alignak Settings'))) main_layout.addWidget(self.get_settings_widget()) center_widget(self) def get_settings_widget(self): """ Return the alignak settings QWidget :return: settings QWidget :rtype: QWidget """ server_widget = QWidget() server_widget.setObjectName('dialog') server_layout = QVBoxLayout(server_widget) # Title title_lbl = QLabel(_('Alignak Backend')) title_lbl.setObjectName('itemtitle') server_layout.addWidget(title_lbl) server_layout.setAlignment(title_lbl, Qt.AlignTop) # Description desc_label = QLabel( _('Here you can define alignak settings. Be sure to enter a valid address.') ) desc_label.setWordWrap(True) server_layout.addWidget(desc_label) # Server URL server_lbl = QLabel(_('Server')) server_layout.addWidget(server_lbl) self.server_url.setText(settings.get_config('Alignak', 'url')) self.server_url.setPlaceholderText(_('alignak backend url...')) self.server_url.setFixedHeight(25) server_layout.addWidget(self.server_url) # Server Port port_lbl = QLabel(_('Port')) server_layout.addWidget(port_lbl) cur_port = settings.get_config('Alignak', 'backend').split(':')[2] self.server_port.setText(cur_port) self.server_port.setPlaceholderText(_('alignak backend port...')) self.server_port.setFixedHeight(25) server_layout.addWidget(self.server_port) # Server Processes (displayed only for Unix platforms) if 'win32' not in sys.platform: process_lbl = QLabel(_('Processes')) server_layout.addWidget(process_lbl) cur_proc = settings.get_config('Alignak', 'processes') self.server_proc.setText(cur_proc) self.server_proc.setPlaceholderText(_('alignak backend processes...')) self.server_proc.setFixedHeight(25) server_layout.addWidget(self.server_proc) # Web Service description server_layout.addStretch(1) webservice_lbl = QLabel(_('Web Service')) webservice_lbl.setObjectName('itemtitle') server_layout.addWidget(webservice_lbl) ws_desc_lbl = QLabel( _('Here you can define your alignak web service url, with port if needed') ) ws_desc_lbl.setWordWrap(True) server_layout.addWidget(ws_desc_lbl) # Web Service URL self.webservice_url.setText(settings.get_config('Alignak', 'webservice')) self.webservice_url.setPlaceholderText(_('alignak webservice url...')) self.webservice_url.setFixedHeight(25) server_layout.addWidget(self.webservice_url) # Valid Button valid_btn = QPushButton(_('Valid')) valid_btn.setObjectName('valid') valid_btn.setMinimumHeight(30) valid_btn.clicked.connect(self.accept) server_layout.addWidget(valid_btn) return server_widget def mousePressEvent(self, event): # pragma: no cover - not testable """ QWidget.mousePressEvent(QMouseEvent) """ self.offset = event.pos() def mouseMoveEvent(self, event): # pragma: no cover - not testable """ QWidget.mousePressEvent(QMouseEvent) """ try: x = event.globalX() y = event.globalY() x_w = self.offset.x() y_w = self.offset.y() self.move(x - x_w, y - y_w) except AttributeError as e: logger.warning('Move Event %s: %s', self.objectName(), str(e))
class ConnectionWidget(QWidget): title_changed = pyqtSignal(QWidget, str, name='title_changed') def __init__(self, parent): super().__init__(parent) # Initial widget title self.title = 'Untitled' # Initialize data model self.model = ConnectionModel(self) self.model.connected.connect(self.on_connection_changed) # Initialize UI self.init_ui() def init_ui(self): # Declare main vertical layout layout = QVBoxLayout(self) layout.setContentsMargins(0, 0, 0, 0) # Initialize control toolbar control_bar = self.init_control_bar() layout.addWidget(control_bar) # Initialize workspace workspace = self.init_workspace() layout.addWidget(workspace) # Apply configured UI layout to the widget self.setLayout(layout) def init_control_bar(self): # Add control bar control_row_layout = QHBoxLayout(self) control_row_layout.setContentsMargins(0, 0, 0, 0) # DB type combo box db_combo_box = QComboBox(self) db_combo_box.addItem('SQLite') db_combo_box.addItem('PostgreSQL') control_row_layout.addWidget(db_combo_box) # Connection string self.connection_line = QLineEdit(self) self.connection_line.setPlaceholderText('Enter...') self.connection_line.setText('demo.db') control_row_layout.addWidget(self.connection_line) # Connection button connection_button = QPushButton(self) connection_button.setText('Connect') connection_button.clicked.connect(self.on_connect_click) control_row_layout.addWidget(connection_button) # Add contol row as a first widget in a column control_row = QWidget(self) control_row.setLayout(control_row_layout) return control_row def init_workspace(self): # Create a splitter consisting of query edit and table view splitter = QSplitter(self) splitter.setOrientation(Qt.Vertical) splitter.sizePolicy().setVerticalPolicy(QSizePolicy.Maximum) # Initialize query edit file query_edit = self.init_query_text_edit() # Disable query control buttons by default self.on_disconnected() splitter.addWidget(query_edit) # Initialize result desiplaying widgets results_widget = self.init_results_widget() splitter.addWidget(results_widget) splitter.setSizes([100, 900]) return splitter def init_query_text_edit(self): # Add query edit widget query_edit_layout = QVBoxLayout(self) query_edit_layout.setContentsMargins(0, 0, 0, 0) query_control_layout = QHBoxLayout(self) query_control_layout.setContentsMargins(0, 0, 0, 0) self.query_execute_button = QPushButton('Execute', self) self.query_execute_button.clicked.connect(self.on_execute_click) query_control_layout.addWidget(self.query_execute_button) self.query_fetch_button = QPushButton('Fetch', self) self.query_fetch_button.clicked.connect(self.on_fetch_click) self.model.fetch_changed.connect(self.on_fetch_changed) query_control_layout.addWidget(self.query_fetch_button) self.query_commit_button = QPushButton('Commit', self) self.query_commit_button.clicked.connect(self.on_connect_click) query_control_layout.addWidget(self.query_commit_button) self.query_rollback_button = QPushButton('Rollback', self) self.query_rollback_button.clicked.connect(self.on_rollback_click) query_control_layout.addWidget(self.query_rollback_button) query_control = QWidget(self) query_control.setLayout(query_control_layout) query_edit_layout.addWidget(query_control) self.query_text_edit = QTextEdit(self) self.query_text_edit.setText( "SELECT name FROM sqlite_master WHERE type='table'") query_edit_layout.addWidget(self.query_text_edit) # Connect model's connected/disconnected signals self.model.connected.connect(self.on_connected) self.model.disconnected.connect(self.on_disconnected) query_edit = QWidget(self) query_edit.setLayout(query_edit_layout) query_edit.sizePolicy().setVerticalPolicy(QSizePolicy.Minimum) return query_edit def init_results_widget(self): # Initialize QTabWidget to display table view and log # in differnt unclosable tabs results_widget = QTabWidget(self) results_widget.setTabsClosable(False) # Add table view table_view = QTableView(self) table_view.setModel(self.model) table_view.sizePolicy().setVerticalPolicy( QSizePolicy.MinimumExpanding) results_widget.addTab(table_view, 'Data') # Att log view log = QTextEdit(self) log.setReadOnly(True) self.model.executed.connect(log.append) results_widget.addTab(log, 'Events') return results_widget def on_connect_click(self): with handle_error(): connection_string = self.connection_line.text() self.model.connect(connection_string) print('Connected', connection_string) def on_execute_click(self): with handle_error(): query = self.query_text_edit.toPlainText() self.model.execute(query) print('Executed:', query) def on_fetch_click(self): with handle_error(): self.model.fetch_more() print('Fetch more') def on_rollback_click(self): with handle_error(): self.model.rollback() print('Rollback') def on_connected(self): self.query_commit_button.setEnabled(True) self.query_execute_button.setEnabled(True) self.query_fetch_button.setEnabled(False) self.query_rollback_button.setEnabled(True) self.query_text_edit.setEnabled(True) def on_disconnected(self): self.query_commit_button.setEnabled(False) self.query_execute_button.setEnabled(False) self.query_fetch_button.setEnabled(False) self.query_rollback_button.setEnabled(False) self.query_text_edit.setEnabled(False) def on_fetch_changed(self, state): self.query_fetch_button.setEnabled(state) def on_connection_changed(self, name): self.title_changed.emit(self, name)
class SnifferFilter(QDialog): ## The constructor. # Initialize lists to be filled with filtered payloads and # create the dialog. def __init__(self, parent): super(SnifferFilter, self).__init__() self.parent = parent self.setWindowTitle('SnifferFilter') self.filteredPayloadList = [] self.filteredIdList = [] self.layoutingComplete = False self.calledBy = 'NONE' # We store here which tab the filter belongs to, if there is no parent.(Like when the filter is global!) self.objectTabDict = {} self.filteredObjectDict = {} self.resize(670, 700) ## Filters the global payloadList by ID by iterating through it and # appending to a new list by filter-criteria # @param filterList a list of IDs that are to be transferred to the new list def filterPayloadsByID(self, filterList): for payload in Globals.payloadList: if hasattr(payload, 'payloadHead'): if Globals.tspDict[ payload.payloadHead.informationID][0] in filterList: self.filteredPayloadList.append(payload) else: #print('informationID is in filteredIdList, skipping packet') pass ## Filters the global payloadList by Message by iterating through it and # appending to a new list by filter-criteria # @param filterDict a dictionary of Key: ObjectType and Value: ObjectsToKeep as a template # of which items are to be kept in the filteredList def filterPayloadsByMessage(self, filterDict): localFilteredList = [] for payload in self.filteredPayloadList: print('payloadID:' + str(payload.payloadHead.informationID)) # If the ID has nothing to do with the object, we can safely add it. if payload.payloadHead.informationID is 23: x = 0 pass if isRelatedToObject(payload): for objType, messageID in filterDict.items(): print(Globals.objectTypeDict[getObjectType(payload)]) if Globals.objectTypeDict[getObjectType( payload )] == objType: # If the objectType matches the one in the dictionary if objType == 0: x = 0 pass if getDataType(payload) == 2: if payload.data2 not in messageID: # and the message does not match the dictionary print( 'Passing data with msgid: ' + str(payload.data2) ) # don't append, but print that we skipped this one else: localFilteredList.append( payload ) # the message does match the dictionary -> we want to keep it, so we add it to the list elif getDataType(payload) == 1: if payload.data1 not in messageID: print('Passing data with msgid: ' + str(payload.data1)) else: localFilteredList.append(payload) else: localFilteredList.append(payload) else: # If the ID has nothing to do with the object, we can safely add it. # Also, is the object is not even in the filterDict, we can add it too (this should not happen, but # it's there for safety purposes if getDataType(payload) == 0 or Globals.objectTypeDict[ getObjectType(payload)] not in filterDict: localFilteredList.append(payload) else: localFilteredList.append(payload) # In every other case, append it to the list, since we only want to filter out specific objects self.filteredPayloadList = list(localFilteredList) ## Create the visible UI # like the different tables, the searchbar etc. def setSnifferFilterUi(self): self.filterTabs = QTabWidget() self.H1layout = QHBoxLayout() self.Vlayout = QVBoxLayout() self.searchInputField = QLineEdit() self.searchInputField.setPlaceholderText( 'Enter search term, then click search') self.searchButt = QPushButton('Search Table') self.saveFilterButt = QPushButton('Save Filter') self.filterTable = QTableWidget() self.saveFilterButt.clicked.connect(self.saveFilterList) self.searchButt.clicked.connect( lambda: self.searchInTable(self.searchInputField.text(), 0)) # Create Table self.filterTableIndex = 0 self.filterTable = QTableWidget() self.filterTableItem = QTableWidgetItem() self.filterTable.setRowCount(0) self.filterTable.setColumnCount(2) self.filterTable.setHorizontalHeaderLabels( 'informationID;Enable'.split(';')) self.filterTable.resizeColumnsToContents() self.filterTableHeader = self.filterTable.horizontalHeader() self.filterTableHeader.setSectionResizeMode(0, QHeaderView.Stretch) self.filterTableHeader.setSectionResizeMode( 1, QHeaderView.ResizeToContents) font = self.getFont() self.checkBoxAllIds = self.createCheckBox() self.filterTable.itemChanged.connect(self.filterAllIDs) self.checkBoxAllMessages = self.createCheckBox() # -- Add first Row for all -- # self.filterTable.insertRow(self.filterTableIndex) idFilterItem = QTableWidgetItem('FILTER ALL IDs') idFilterItem.setFont(font) messageFilterItem = QTableWidgetItem('FILTER ALL Messages') messageFilterItem.setFont(font) self.filterTable.setItem(self.filterTableIndex, 0, idFilterItem) self.filterTable.setItem(self.filterTableIndex, 1, self.checkBoxAllIds) self.filterTableIndex = self.filterTableIndex + 1 # -- Add informationID filter rows -- # for keys, values in Globals.tspDict.items(): if values[0].startswith('ID'): checkBoxFilter = self.createCheckBox() self.filterTable.insertRow(self.filterTableIndex) self.filterTable.setItem(self.filterTableIndex, 0, QTableWidgetItem(values[0])) self.filterTable.setItem(self.filterTableIndex, 1, checkBoxFilter) self.filterTableIndex = self.filterTableIndex + 1 self.filterTabs.addTab(self.filterTable, 'Information ID') self.H1layout.addWidget(self.searchInputField) self.H1layout.addWidget(self.searchButt) self.Vlayout.addLayout(self.H1layout) self.Vlayout.addWidget(self.filterTabs) self.Vlayout.addWidget(self.saveFilterButt) #------------------------------------ self.setLayout(self.Vlayout) self.layoutingComplete = True ## Updates the visible filter UI to the new objectList # This function is called, when either a new measurement was executed or an old measurement was loaded. # Since the objects shown in the Filter need to be updated. def updateObjectFilter(self): # -- Add message filter rows -- # font = self.getFont() self.filterTabs.clear() self.filterTabs.addTab(self.filterTable, 'Information ID') # For each object in objectList, create a new Table and add it to the tabs. for keys, values in Globals.objectDict.items(): objectFilterTable = QTableWidget() objectFilterTable.setRowCount(0) objectFilterTable.setColumnCount(2) strSplit = keys + ';Enable' objectFilterTable.setHorizontalHeaderLabels(strSplit.split(';')) objectFilterTable.resizeColumnsToContents() filterTableHeader = objectFilterTable.horizontalHeader() filterTableHeader.setSectionResizeMode(0, QHeaderView.Stretch) filterTableHeader.setSectionResizeMode( 1, QHeaderView.ResizeToContents) checkBoxFilter = self.createCheckBox() objectFilterTable.itemChanged.connect( lambda *a, table=objectFilterTable: self.filterAllObjectIDs( *a, table=table)) objectTableIndex = 0 objectFilterTable.insertRow(objectTableIndex) objCat = QTableWidgetItem('FILTER ALL') objCat.setFont(font) objectFilterTable.setItem(objectTableIndex, 0, objCat) objectFilterTable.setItem(objectTableIndex, 1, checkBoxFilter) objectTableIndex = objectTableIndex + 1 for keys2, values2 in values.items(): objectFilterTable.insertRow(objectTableIndex) checkBoxFilter = self.createCheckBox() objectFilterTable.setItem( objectTableIndex, 0, QTableWidgetItem('ID: ' + str(keys2) + ' Name: ' + str(values2))) objectFilterTable.setItem(objectTableIndex, 1, checkBoxFilter) objectTableIndex = objectTableIndex + 1 # Add the newly create table to the tabs. self.filterTabs.addTab(objectFilterTable, keys) self.objectTabDict[keys] = objectFilterTable ## Searches the table for a string and scrolls to the found item. # @param textToSearch the string that needs to be found in the table # @param column the column where the search needs to take place def searchInTable(self, textToSearch, column): # Create a model of the table, so we can match a text tableModel = self.filterTable.model() start = tableModel.index(0, column) matches = tableModel.match(start, Qt.DisplayRole, textToSearch, 1, Qt.MatchContains) # If there are multiple matches, we take the first one, select it and scroll to it if matches: index = matches[0] self.filterTable.selectionModel().select( index, QItemSelectionModel.Select) self.filterTable.scrollToItem( self.filterTable.itemFromIndex(index)) ## CB: SaveFilterButton // Call the filterFunctions -> Filter the unfiltered list by ID and Object and call the update # function of the executing tab in order to update their UI. def saveFilterList(self): self.filteredPayloadList.clear() #--Save by ID--# rowCnt = self.filterTable.rowCount() self.filteredIdList.clear() for rows in range(0, rowCnt): if self.filterTable.item(rows, 1).checkState() == Qt.Checked: #print(self.filterTable.item(rows,0).text()) self.filteredIdList.append( self.filterTable.item(rows, 0).text()) self.filterPayloadsByID(self.filteredIdList) print(len(self.filteredPayloadList)) print(len(Globals.payloadList)) #--Save By Objects--# self.filteredObjectDict.clear() for objType, objectTable in self.objectTabDict.items(): rowCnt = objectTable.rowCount() objectsToFilter = [] for rows in range(0, rowCnt): if objectTable.item(rows, 1).checkState() == Qt.Checked: #print(objectTable.item(rows,0).text()) try: objectsToFilter.append( int( re.search('ID: (.*) Name:.*', objectTable.item( rows, 0).text()).group(1))) self.filteredObjectDict[objType] = objectsToFilter #print('Found Regex: '+re.search('ID: (.*) Name:.*',objectTable.item(rows,0).text()).group(1)) except: print('Error when parsing TableRegex...this is okay') self.filterPayloadsByMessage(self.filteredObjectDict) # We filtered the list, now we hide the windows and call the update-function # If the maintainer of the tab did not follow the implementation guide, there is no update-function to call. # We still save the filtered list, so we print a message to show where to find it. self.hide() try: self.parent.filterUpdated(self.filteredIdList, self.filteredPayloadList) except AttributeError: print( 'No corresponding callable function filterUpdated was found, you can access the most recent filteredList via self.snifferFilter.filteredIdList' ) try: Globals.dockDict[self.calledBy].filterUpdated( self.filteredIdList, self.filteredPayloadList) except: print('not global!') ## Check whether the first checkbox was checked and then update the entire ID table to either checked or unchecked state # @param checkBox a checkBox we perform the query on def filterAllIDs(self, checkBox): if self.layoutingComplete == True: if checkBox.column() == 1 and checkBox.row( ) == 0: # We clicked the toggle ID checkbox if checkBox.checkState() == Qt.Checked: rowCnt = self.filterTable.rowCount() for rows in range(0, rowCnt): try: self.filterTable.item(rows, 1).setCheckState(Qt.Checked) except AttributeError: print( 'no items after' + str(rows) + 'found...Maybe this column has less items than' + str(rowCnt) + '?') elif checkBox.checkState() == Qt.Unchecked: rowCnt = self.filterTable.rowCount() for rows in range(0, rowCnt): try: self.filterTable.item(rows, 1).setCheckState( Qt.Unchecked) except AttributeError: print( 'no items after' + str(rows) + 'found...Maybe this column has less items than' + str(rowCnt) + '?') else: print( 'neither checked nor unchecked...should never be here..' ) ## Check whether the first checkbox was checked and then update the entire ObjectIDtable to either checked or unchecked state # @param checkBox a checkBox we perform the query on # @param table the table that is to be updated def filterAllObjectIDs(self, checkBox, table): if (self.objectTabDict): if checkBox.column() == 1 and checkBox.row( ) == 0: # We clicked the toggle ID checkbox if checkBox.checkState() == Qt.Checked: rowCnt = table.rowCount() for rows in range(0, rowCnt): try: table.item(rows, 1).setCheckState(Qt.Checked) except AttributeError: print( 'no items after' + str(rows) + 'found...Maybe this column has less items than' + str(rowCnt) + '?') elif checkBox.checkState() == Qt.Unchecked: rowCnt = table.rowCount() for rows in range(0, rowCnt): try: table.item(rows, 1).setCheckState(Qt.Unchecked) except AttributeError: print( 'no items after' + str(rows) + 'found...Maybe this column has less items than' + str(rowCnt) + '?') else: print( 'neither checked nor unchecked...should never be here..' ) # --- HELPER FUNCTIONS --- # ## Create a defined checkbox within a tableWidgetItem to facilitate filling the table # @return the created checkbox def createCheckBox(self): myCheck = QTableWidgetItem() myCheck.setFlags(Qt.ItemIsUserCheckable | Qt.ItemIsEnabled) myCheck.setCheckState(Qt.Checked) return myCheck ## Create a defined font (bold,underlined) to facilitate filling the table # @return the created font def getFont(self): font = QFont() font.setBold(True) font.setUnderline(True) return font
class ConnectionWidget(QWidget): title_changed = pyqtSignal(QWidget, str, name="title_changed") def __init__(self, parent): super().__init__(parent) # Initialize anti-recursion flag during highlighting self.is_processing_highlighting = False # Initial widget title self.title = UI.CONNECTION_TAB_DEFAULT_TITLE # Initialize data model self.model = ConnectionModel(self) self.model.connected.connect(self.on_connection_changed) # Initialize UI self.init_ui() def init_ui(self): # Declare main vertical layout layout = QVBoxLayout(self) layout.setContentsMargins(0, 0, 0, 0) # Initialize control toolbar control_bar = self.build_control_bar() layout.addWidget(control_bar) # Initialize workspace workspace = self.build_workspace() layout.addWidget(workspace) # Apply configured UI layout to the widget self.setLayout(layout) def build_control_bar(self): # Add control bar control_row_layout = QHBoxLayout(self) control_row_layout.setContentsMargins(0, 0, 0, 0) # DB type combo box db_combo_box = QComboBox(self) for dbname in UI.CONNECTION_STRING_SUPPORTED_DB_NAMES: db_combo_box.addItem(dbname) control_row_layout.addWidget(db_combo_box) # Connection string self.connection_line = QLineEdit(self) self.connection_line.setPlaceholderText( UI.CONNECTION_STRING_PLACEHOLDER) self.connection_line.setText(UI.CONNECTION_STRING_DEFAULT) control_row_layout.addWidget(self.connection_line) # Connection button connection_button = QPushButton(self) connection_button.setText(UI.QUERY_CONTROL_CONNECT_BUTTON_TEXT) connection_button.clicked.connect(self.on_connect_click) control_row_layout.addWidget(connection_button) # Add contol row as a first widget in a column control_row = QWidget(self) control_row.setLayout(control_row_layout) return control_row def build_workspace(self): # Create a splitter consisting of query edit and table view splitter = QSplitter(self) splitter.setOrientation(Qt.Vertical) splitter.sizePolicy().setVerticalPolicy(QSizePolicy.Maximum) # Initialize query edit query_edit = self.build_query_text_edit() # Disable query control buttons by default self.on_disconnected() splitter.addWidget(query_edit) # Initialize result desiplaying widgets results_widget = self.build_results_widget() splitter.addWidget(results_widget) splitter.setSizes([100, 900]) return splitter def build_query_text_edit(self): # Add layouts query_edit_layout = QVBoxLayout(self) query_edit_layout.setContentsMargins(0, 0, 0, 0) query_control_layout = QHBoxLayout(self) query_control_layout.setContentsMargins(0, 0, 0, 0) # Execute query button self.query_execute_button = QPushButton( UI.QUERY_CONTROL_EXECUTE_BUTTON_TEXT, self) self.query_execute_button.clicked.connect(self.on_execute_click) query_control_layout.addWidget(self.query_execute_button) # Fetch data button self.query_fetch_button = QPushButton( UI.QUERY_CONTROL_FETCH_BUTTON_TEXT, self) self.query_fetch_button.clicked.connect(self.on_fetch_click) self.model.fetch_changed.connect(self.on_fetch_changed) query_control_layout.addWidget(self.query_fetch_button) # Commit button self.query_commit_button = QPushButton( UI.QUERY_CONTROL_COMMIT_BUTTON_TEXT, self) self.query_commit_button.clicked.connect(self.on_connect_click) query_control_layout.addWidget(self.query_commit_button) # Rollback button self.query_rollback_button = QPushButton( UI.QUERY_CONTROL_ROLLBACK_BUTTON_TEXT, self) self.query_rollback_button.clicked.connect(self.on_rollback_click) query_control_layout.addWidget(self.query_rollback_button) # Build control strip widget query_control = QWidget(self) query_control.setLayout(query_control_layout) query_edit_layout.addWidget(query_control) # Initialize query edit document for text editor # and use SQL Highlighter CSS styles for it. self.query_text_edit_document = QTextDocument(self) self.query_text_edit_document.setDefaultStyleSheet( SQLHighlighter.style()) # Initialize query text editor using previously built # text edutir document. self.query_text_edit = QTextEdit(self) self.query_text_edit.setDocument(self.query_text_edit_document) self.query_text_edit.textChanged.connect(self.on_query_changed) self.query_text_edit.setText(UI.QUERY_EDITOR_DEFAULT_TEXT) query_edit_layout.addWidget(self.query_text_edit) # Connect model's connected/disconnected signals self.model.connected.connect(self.on_connected) self.model.disconnected.connect(self.on_disconnected) query_edit = QWidget(self) query_edit.setLayout(query_edit_layout) query_edit.sizePolicy().setVerticalPolicy(QSizePolicy.Minimum) return query_edit def build_results_widget(self): # Initialize QTabWidget to display table view and log # in differnt unclosable tabs results_widget = QTabWidget(self) results_widget.setTabsClosable(False) # Add table view table_view = QTableView(self) table_view.setModel(self.model) table_view.sizePolicy().setVerticalPolicy(QSizePolicy.MinimumExpanding) results_widget.addTab(table_view, UI.QUERY_RESULTS_DATA_TAB_TEXT) # Att log view log = QTextEdit(self) log.setReadOnly(True) self.model.executed.connect(log.append) results_widget.addTab(log, UI.QUERY_RESULTS_EVENTS_TAB_TEXT) return results_widget def on_query_changed(self): """Process query edits by user""" if self.is_processing_highlighting: # If we caused the invokation of this slot by set highlighted # HTML text into query editor, then ignore this call and # mark highlighting processing as finished. self.is_processing_highlighting = False else: # If changes to text were made by user, mark beginning of # highlighting process self.is_processing_highlighting = True # Get plain text query and highlight it query_text = self.query_text_edit.toPlainText() highlighted_query_text = SQLHighlighter.highlight(query_text) # After we set highlighted HTML back to QTextEdit form # the cursor will jump to the end of the text. # To avoid that we remember the current position of the cursor. current_cursor = self.query_text_edit.textCursor() current_cursor_position = current_cursor.position() # Set highlighted text back to editor which will cause the # cursor to jump to the end of the text. self.query_text_edit_document.setHtml(highlighted_query_text) # Return cursor back to the old position current_cursor.setPosition(current_cursor_position) self.query_text_edit.setTextCursor(current_cursor) def on_connect_click(self): with ErrorHandler(): connection_string = self.connection_line.text() self.model.connect(connection_string) logging.info(f"Connected: {connection_string}") def on_execute_click(self): with ErrorHandler(): query = self.query_text_edit.toPlainText() self.model.execute(query) logging.info(f"Executed: {query}") def on_fetch_click(self): with ErrorHandler(): self.model.fetch_more() logging.info("Fetch more") def on_rollback_click(self): with ErrorHandler(): self.model.rollback() logging.info("Rollback") def on_connected(self): self.query_commit_button.setEnabled(True) self.query_execute_button.setEnabled(True) self.query_fetch_button.setEnabled(False) self.query_rollback_button.setEnabled(True) self.query_text_edit.setEnabled(True) def on_disconnected(self): self.query_commit_button.setEnabled(False) self.query_execute_button.setEnabled(False) self.query_fetch_button.setEnabled(False) self.query_rollback_button.setEnabled(False) self.query_text_edit.setEnabled(False) def on_fetch_changed(self, state): self.query_fetch_button.setEnabled(state) def on_connection_changed(self, name): self.title_changed.emit(self, name)
def handle_server(self): """ Handle for server button """ server_dialog = QDialog() server_dialog.setWindowTitle('Server Configuration') server_dialog.setWindowFlags(Qt.FramelessWindowHint) server_dialog.setStyleSheet(get_css()) server_dialog.setFixedSize(300, 300) main_layout = QVBoxLayout(server_dialog) main_layout.setContentsMargins(0, 0, 0, 0) main_layout.addWidget(self.get_logo_widget(server_dialog)) server_widget = QWidget(self) server_widget.setObjectName('login') server_layout = QGridLayout(server_widget) # Description desc_label = QLabel( '<h3>Alignak Backend</h3><p>Here you can define alignak settings.</p>' '<b>Be sure to enter a valid address</b>') desc_label.setWordWrap(True) server_layout.addWidget(desc_label, 0, 0, 1, 3) # Server URL server_layout.addWidget(QLabel('Server'), 1, 0, 1, 1) server_url = QLineEdit() server_url.setPlaceholderText('alignak backend url') server_url.setText(get_app_config('Alignak', 'url')) server_layout.addWidget(server_url, 1, 1, 1, 2) # Server Port server_layout.addWidget(QLabel('Port'), 2, 0, 1, 1) server_port = QLineEdit() server_port.setPlaceholderText('alignak backend port') cur_port = get_app_config('Alignak', 'backend').split(':')[2] server_port.setText(cur_port) server_layout.addWidget(server_port, 2, 1, 1, 2) # Server Processes server_layout.addWidget(QLabel('Processes'), 3, 0, 1, 1) server_proc = QLineEdit() if 'win32' in sys.platform: server_proc.setEnabled(False) server_proc.setPlaceholderText('alignak backend processes') cur_proc = get_app_config('Alignak', 'processes') server_proc.setText(cur_proc) server_layout.addWidget(server_proc, 3, 1, 1, 2) # Valid Button valid_btn = QPushButton('Valid') valid_btn.clicked.connect(server_dialog.accept) server_layout.addWidget(valid_btn, 4, 0, 1, 3) main_layout.addWidget(server_widget) self.center(server_widget) if server_dialog.exec_() == QDialog.Accepted: backend_url = '%(url)s:' + str(server_port.text()).rstrip() set_app_config('Alignak', 'backend', backend_url) set_app_config('Alignak', 'url', str(server_url.text()).rstrip()) set_app_config('Alignak', 'processes', str(server_proc.text()).rstrip())
class ProblemsQWidget(QWidget): """ Class who create Problems QWidget """ def __init__(self, parent=None): super(ProblemsQWidget, self).__init__(parent) self.setWindowIcon(QIcon(settings.get_image('icon'))) # Fields self.line_search = QLineEdit() self.problems_table = ProblemsQTableView() self.problems_title = QLabel() self.actions_widget = ActionsQWidget() self.spy_widget = None self.filter_hosts_btn = ToggleQWidgetButton() self.filter_services_btn = ToggleQWidgetButton() self.spy_btn = QPushButton() self.host_btn = QPushButton() self.refresh_timer = QTimer() def initialize(self, spy_widget): """ Initialize QWidget and set SpyQWidget :param spy_widget: instance of SpyQWidget to manage spy events :type spy_widget: alignak_app.qobjects.events.spy.SpyQWidget """ problem_layout = QVBoxLayout() problem_layout.setContentsMargins(5, 20, 5, 5) self.setLayout(problem_layout) self.spy_widget = spy_widget self.problems_title.setObjectName('title') problem_layout.addWidget(self.problems_title) problem_layout.addWidget(self.get_search_widget()) problem_layout.addWidget(self.get_btn_widget()) problem_layout.addWidget(self.problems_table) self.update_problems_data() update_problems = int( settings.get_config('Alignak-app', 'update_problems')) * 1000 self.refresh_timer.setInterval(update_problems) self.refresh_timer.start() self.refresh_timer.timeout.connect(self.update_problems_data) def get_current_user_role_item(self): """ Return current selected item by ``Qt.UserRole`` :return: current selected item or None :rtype: alignak_app.items.item.Item """ item = self.problems_table.model().data( self.problems_table.selectionModel().currentIndex(), Qt.UserRole) return item def update_action_buttons(self): """ Update status of action buttons and set current item for ActionsQWidget """ # Get item by UserRole item = self.get_current_user_role_item() if item: # If the elements had been ack or downtimed, they would not be present self.actions_widget.acknowledge_btn.setEnabled(True) self.actions_widget.downtime_btn.setEnabled(True) self.actions_widget.item = item if 'service' in item.item_type: host_id = item.data['host'] else: host_id = item.item_id self.spy_btn.setEnabled( bool(host_id not in self.spy_widget.spy_list_widget.spied_hosts)) self.host_btn.setEnabled(True) else: self.actions_widget.acknowledge_btn.setEnabled(False) self.actions_widget.downtime_btn.setEnabled(False) self.host_btn.setEnabled(False) self.spy_btn.setEnabled(False) def get_search_widget(self): """ Create and return the search QWidget :return: search QWidget :rtype: QWidget """ widget = QWidget() layout = QHBoxLayout() layout.setSpacing(0) layout.setContentsMargins(5, 20, 5, 10) widget.setLayout(layout) # Search label search_lbl = QLabel(_('Search Problems')) search_lbl.setObjectName('bordertitle') search_lbl.setFixedHeight(25) search_lbl.setToolTip(_('Search Problems')) layout.addWidget(search_lbl) # QLineEdit self.line_search.setFixedHeight(search_lbl.height()) self.line_search.setPlaceholderText( _('Type text to filter problems...')) layout.addWidget(self.line_search) # Refresh button refresh_btn = QPushButton(_('Refresh')) refresh_btn.setObjectName('ok') refresh_btn.setFixedSize(120, search_lbl.height()) refresh_btn.setToolTip(_('Refresh problems')) refresh_btn.clicked.connect(self.update_problems_data) layout.addWidget(refresh_btn) return widget def get_btn_widget(self): """ Return QWidget with spy and host synthesis QPushButtons :return: widget with spy and host button :rtype: QWidget """ widget_btn = QWidget() layout_btn = QHBoxLayout() layout_btn.setContentsMargins(0, 0, 0, 5) widget_btn.setLayout(layout_btn) host_filter = QLabel(_('Filter hosts')) host_filter.setObjectName('subtitle') layout_btn.addWidget(host_filter) self.filter_hosts_btn.initialize() self.filter_hosts_btn.update_btn_state(False) self.filter_hosts_btn.toggle_btn.clicked.connect( lambda: self.update_problems_data('host')) layout_btn.addWidget(self.filter_hosts_btn) service_filter = QLabel(_('Filter services')) service_filter.setObjectName('subtitle') layout_btn.addWidget(service_filter) self.filter_services_btn.initialize() self.filter_services_btn.update_btn_state(False) self.filter_services_btn.toggle_btn.clicked.connect( lambda: self.update_problems_data('service')) layout_btn.addWidget(self.filter_services_btn) layout_btn.addStretch() self.host_btn.setIcon(QIcon(settings.get_image('host'))) self.host_btn.setFixedSize(80, 20) self.host_btn.setEnabled(False) self.host_btn.setToolTip(_('See current item in synthesis view')) layout_btn.addWidget(self.host_btn) self.spy_btn.setIcon(QIcon(settings.get_image('spy'))) self.spy_btn.setFixedSize(80, 20) self.spy_btn.setEnabled(False) self.spy_btn.setToolTip(_('Spy current host')) self.spy_btn.clicked.connect(self.add_spied_host) layout_btn.addWidget(self.spy_btn) self.actions_widget.initialize(None) self.actions_widget.acknowledge_btn.setEnabled(False) self.actions_widget.downtime_btn.setEnabled(False) layout_btn.addWidget(self.actions_widget) layout_btn.setAlignment(Qt.AlignCenter) return widget_btn def add_spied_host(self): """ Add a host to spied hosts """ # Get item by UserRole item = self.get_current_user_role_item() if item: if 'service' in item.item_type: item_id = item.data['host'] else: item_id = item.item_id app_backend.query_services(item_id) self.spy_widget.spy_list_widget.add_spy_host(item_id) self.spy_widget.update_parent_spytab() self.update_action_buttons() def update_problems_data(self, item_type=''): """ Update data of Problems QTableWidget and problems title :param item_type: type of item to filter :type item_type: str """ problems_data = data_manager.get_problems() old_research = self.line_search.text() if self.parent(): self.parent().parent().setTabText( self.parent().parent().indexOf(self), _("Problems (%d)") % len(problems_data['problems'])) self.problems_title.setText( _('There are %d problems to manage (hosts: %d, services: %d)') % (len(problems_data['problems']), problems_data['hosts_nb'], problems_data['services_nb'])) if self.filter_hosts_btn.is_checked( ) and not self.filter_services_btn.is_checked(): item_type = 'host' if self.filter_services_btn.is_checked( ) and not self.filter_hosts_btn.is_checked(): item_type = 'service' if not self.filter_services_btn.is_checked( ) and not self.filter_hosts_btn.is_checked(): item_type = '' if isinstance(item_type, str): if 'host' in item_type and self.filter_hosts_btn.is_checked(): if self.filter_services_btn.is_checked(): self.filter_services_btn.update_btn_state(False) if 'service' in item_type and self.filter_services_btn.is_checked( ): if self.filter_hosts_btn.is_checked(): self.filter_hosts_btn.update_btn_state(False) problems_data['problems'] = [ item for item in problems_data['problems'] if item_type in item.item_type ] proxy_filter = self.problems_table.update_view(problems_data) if problems_data['problems']: self.line_search.textChanged.connect(proxy_filter.setFilterRegExp) else: self.problems_title.setText( _('If problems are found, they will be displayed here.')) self.problems_table.selectionModel().selectionChanged.connect( self.update_action_buttons) self.update_action_buttons() if old_research: self.line_search.setText(old_research) self.line_search.textChanged.emit(old_research)
class PasswordQDialog(QDialog): """ Class who create PasswordDialog QDialog """ def __init__(self, parent=None): super(PasswordQDialog, self).__init__(parent) self.setWindowTitle('User Password') self.setWindowFlags(Qt.FramelessWindowHint) self.setStyleSheet(settings.css_style) self.setWindowIcon(QIcon(settings.get_image('icon'))) self.setObjectName('dialog') self.setFixedSize(300, 300) # Fields self.pass_edit = QLineEdit() self.confirm_edit = QLineEdit() self.help_label = QLabel() def initialize(self): """ Initialize QDialog for PasswordDialog """ center_widget(self) # Main status_layout main_layout = QVBoxLayout(self) main_layout.setContentsMargins(0, 0, 0, 0) self.setLayout(main_layout) main_layout.addWidget(get_logo_widget(self, _('Edit Password'))) pass_title = QLabel(_("Please type a new PASSWORD:"******"Your password must contain at least 5 characters.")) self.help_label.setWordWrap(True) pass_layout.addWidget(self.help_label) # Accept button accept_btn = QPushButton('Confirm', self) accept_btn.clicked.connect(self.handle_confirm) accept_btn.setObjectName('valid') accept_btn.setMinimumHeight(30) pass_layout.addWidget(accept_btn) main_layout.addWidget(pass_widget) def handle_confirm(self): """ Handle accept_btn for password """ if bool(self.pass_edit.text() == self.confirm_edit.text()) and \ len(self.pass_edit.text()) > 4 and len(self.confirm_edit.text()) > 4: self.accept() else: if bool(self.pass_edit.text() != self.confirm_edit.text()): self.help_label.setText(_("Passwords do not match !")) self.help_label.setStyleSheet("color: red;") if len(self.pass_edit.text()) < 5 or len(self.confirm_edit.text()) < 5: self.help_label.setText(_("Your password must contain at least 5 characters.")) self.help_label.setStyleSheet("color: orange;")
class FontFamilyDialog(QDialog): def __init__(self, current_family, parent=None): QDialog.__init__(self, parent) self.setWindowTitle(_('Choose font family')) self.setWindowIcon(QIcon(I('font.png'))) from calibre.utils.fonts.scanner import font_scanner self.font_scanner = font_scanner self.m = QStringListModel(self) self.build_font_list() self.l = l = QGridLayout() self.setLayout(l) self.view = FontsView(self) self.view.setModel(self.m) self.view.setCurrentIndex(self.m.index(0)) if current_family: for i, val in enumerate(self.families): if icu_lower(val) == icu_lower(current_family): self.view.setCurrentIndex(self.m.index(i)) break self.view.doubleClicked.connect(self.accept, type=Qt.QueuedConnection) self.view.changed.connect(self.current_changed, type=Qt.QueuedConnection) self.faces = Typefaces(self) self.bb = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.bb.accepted.connect(self.accept) self.bb.rejected.connect(self.reject) self.add_fonts_button = afb = self.bb.addButton( _('Add &fonts'), self.bb.ActionRole) afb.setIcon(QIcon(I('plus.png'))) afb.clicked.connect(self.add_fonts) self.ml = QLabel(_('Choose a font family from the list below:')) self.search = QLineEdit(self) self.search.setPlaceholderText(_('Search')) self.search.returnPressed.connect(self.find) self.nb = QToolButton(self) self.nb.setIcon(QIcon(I('arrow-down.png'))) self.nb.setToolTip(_('Find Next')) self.pb = QToolButton(self) self.pb.setIcon(QIcon(I('arrow-up.png'))) self.pb.setToolTip(_('Find Previous')) self.nb.clicked.connect(self.find_next) self.pb.clicked.connect(self.find_previous) l.addWidget(self.ml, 0, 0, 1, 4) l.addWidget(self.search, 1, 0, 1, 1) l.addWidget(self.nb, 1, 1, 1, 1) l.addWidget(self.pb, 1, 2, 1, 1) l.addWidget(self.view, 2, 0, 1, 3) l.addWidget(self.faces, 1, 3, 2, 1) l.addWidget(self.bb, 3, 0, 1, 4) l.setAlignment(self.faces, Qt.AlignTop) self.resize(800, 600) def set_current(self, i): self.view.setCurrentIndex(self.m.index(i)) def keyPressEvent(self, e): if e.key() == Qt.Key_Return: return return QDialog.keyPressEvent(self, e) def find(self, backwards=False): i = self.view.currentIndex().row() if i < 0: i = 0 q = icu_lower(unicode(self.search.text())).strip() if not q: return r = (xrange(i - 1, -1, -1) if backwards else xrange( i + 1, len(self.families))) for j in r: f = self.families[j] if q in icu_lower(f): self.set_current(j) return def find_next(self): self.find() def find_previous(self): self.find(backwards=True) def build_font_list(self): try: self.families = list(self.font_scanner.find_font_families()) except: self.families = [] print('WARNING: Could not load fonts') import traceback traceback.print_exc() self.families.insert(0, _('None')) self.m.setStringList(self.families) def add_fonts(self): families = add_fonts(self) if not families: return self.font_scanner.do_scan() self.m.beginResetModel() self.build_font_list() self.m.endResetModel() self.view.setCurrentIndex(self.m.index(0)) if families: for i, val in enumerate(self.families): if icu_lower(val) == icu_lower(families[0]): self.view.setCurrentIndex(self.m.index(i)) break info_dialog(self, _('Added fonts'), _('Added font families: %s') % (', '.join(families)), show=True) @property def font_family(self): idx = self.view.currentIndex().row() if idx == 0: return None return self.families[idx] def current_changed(self): fam = self.font_family self.faces.show_family( fam, self.font_scanner.fonts_for_family(fam) if fam else None)
class Register(QWidget): register_ok_sg = pyqtSignal() def __init__(self, parent=None): super(Register, self).__init__(parent) self.desktop = QApplication.desktop() self.screenRect = self.desktop.screenGeometry() self.h = self.screenRect.height() self.w = self.screenRect.width() self.xr = self.w / 930 self.yr = self.h / 640 self.zr = min(self.xr, self.yr) self.top_wi = QWidget(self) self.logo_la = QLabel(self.top_wi) self.ind_wi = QWidget(self) self.register_but = QPushButton(self.ind_wi) self.imp_la = QLabel(self.ind_wi) self.account_le = QLineEdit(self.ind_wi) self.psw_le = QLineEdit(self.ind_wi) self.name_le = QLineEdit(self.ind_wi) self.set_ui() with open('index.qss', 'r') as f: self.setStyleSheet(f.read()) def set_ui(self): self.setWindowTitle('Register') self.setObjectName('register') self.resize(self.w, self.h) self.top_wi.setObjectName('top') self.top_wi.resize(930 * self.xr, 95 * self.yr) self.logo_la.setObjectName('logo') self.logo_la.resize(65 * self.xr, 65 * self.zr) self.logo_la.move(29 * self.xr, 16 * self.yr) effect = QGraphicsDropShadowEffect() effect.setOffset(10, 10) effect.setColor(QColor(0, 0, 0, 80)) effect.setBlurRadius(20) self.ind_wi.setObjectName('login') self.ind_wi.resize(327 * self.xr, 388 * self.yr) self.ind_wi.move(300 * self.xr, 150 * self.yr) self.ind_wi.setGraphicsEffect(effect) self.register_but.setObjectName('button') self.register_but.move(64 * self.xr, 315 * self.yr) self.register_but.resize(202 * self.xr, 45 * self.yr) self.register_but.setText('注册新用户') self.register_but.clicked.connect(self.register) self.imp_la.setObjectName('imp_label') self.imp_la.resize(100 * self.zr, 100 * self.zr) self.imp_la.move(115 * self.xr + 100 * (self.xr - self.zr) / 2, 15 * self.yr) self.imp_la.setStyleSheet('border-radius:{}px;'.format(self.zr * 49)) self.account_le.setObjectName('input') self.account_le.setTextMargins(20, 0, 0, 0) self.account_le.resize(213 * self.xr, 45 * self.yr) self.account_le.move(59 * self.xr, 126 * self.yr) self.account_le.setPlaceholderText('账号') self.psw_le.setObjectName('input') self.psw_le.setTextMargins(20, 0, 0, 0) self.psw_le.resize(213 * self.xr, 45 * self.yr) self.psw_le.move(59 * self.xr, 181 * self.yr) self.psw_le.setPlaceholderText('密码') self.psw_le.setEchoMode(QLineEdit.Password) self.name_le.setObjectName('input') self.name_le.setTextMargins(20, 0, 0, 0) self.name_le.resize(213 * self.xr, 45 * self.yr) self.name_le.move(59 * self.xr, 236 * self.yr) self.name_le.setPlaceholderText('昵称') self.ind_wi.setStyleSheet('#input{border-radius:' + str(self.zr * 20) + 'px;}' + '#button{border-radius:' + str(self.zr * 20) + 'px;' + 'font-size:' + str(int(self.zr * 18)) + 'px;}') def register(self): account_p = self.account_le.text() psw_p = self.psw_le.text() # name_p = self.name_le.text() dic = register(account_p, psw_p) if dic['status'] == 1001: self.account_le.clear() self.psw_le.clear() self.account_le.setStyleSheet('border:4px solid;border-color:red;') self.account_le.setPlaceholderText('账号已存在') elif dic['status'] == 0: self.register_ok_sg.emit() else: self.account_le.clear() self.psw_le.clear() self.account_le.setStyleSheet('border:4px solid;border-color:red;') self.account_le.setPlaceholderText('未知错误')
class OperationsPanel(QScrollArea): def __init__(self): super().__init__() self.app_state = AppState() self.setWidgetResizable(True) self.initUI() def initUI(self): self.container = QToolBox() self.setWidget(self.container) self.b_save_edit = QPushButton("Save current edit") self.b_save_edit.clicked.connect(self._applySaveEdit) self.container.addItem(OptionBox([self.b_save_edit]), "Save") self.tf_importance_point_count = QLineEdit() self.tf_importance_point_count.setPlaceholderText( "Number of Points to Sample") self.tf_importance_point_count.setValidator( QIntValidator(1, 1000000, self)) self.b_importance_apply = QPushButton("Apply Sampling") self.b_importance_apply.clicked.connect( self._applyFaceImportanceSampling) self.container.addItem( OptionBox( [self.tf_importance_point_count, self.b_importance_apply]), "Importance Sampling (Mesh)") self.tf_poisson_point_count = QLineEdit() self.tf_poisson_point_count.setPlaceholderText( "Number of Points to Sample") self.tf_poisson_point_count.setValidator( QIntValidator(1, 1000000, self)) self.tf_poisson_radius = QLineEdit() self.tf_poisson_radius.setPlaceholderText( "Radius of the poisson disks") self.tf_poisson_radius.setValidator(QDoubleValidator( 0.0, 2.0, 5, self)) self.b_poisson_apply = QPushButton("Apply Sampling") self.b_poisson_apply.clicked.connect(self._applyPoissonDiskSampling) self.container.addItem( OptionBox([ self.tf_poisson_point_count, self.tf_poisson_radius, self.b_poisson_apply ]), "Poisson Sampling (Mesh)") self.tf_montecarlo_point_count = QLineEdit() self.tf_montecarlo_point_count.setPlaceholderText( "Number of Points to Sample") self.tf_montecarlo_point_count.setValidator( QIntValidator(1, 1000000, self)) self.b_montecarlo_apply = QPushButton("Apply Sampling") self.b_montecarlo_apply.clicked.connect(self._applyMontecarloSampling) self.container.addItem( OptionBox( [self.tf_montecarlo_point_count, self.b_montecarlo_apply]), "Montecarlo Sampling (Mesh)") self.tf_centroid_count = QLineEdit() self.tf_centroid_count.setPlaceholderText("Centroid Count") self.tf_centroid_count.setValidator(QIntValidator(1, 1000000, self)) self.b_show_centroids = QPushButton("Apply FPS") self.b_show_centroids.clicked.connect(self._applyFPS) self.container.addItem( OptionBox([self.tf_centroid_count, self.b_show_centroids]), "FPS Sampling (Point)") self.tf_show_pp2_centroids = QLineEdit() self.tf_show_pp2_centroids.setPlaceholderText("Number of Centroids") self.tf_show_pp2_centroids.setValidator(QIntValidator( 1, 1000000, self)) self.tf_show_pp2_centroids_with_ball = QLineEdit() self.tf_show_pp2_centroids_with_ball.setPlaceholderText( "Number of Centroids with plotted radius") self.tf_show_pp2_centroids_with_ball.setValidator( QIntValidator(1, 1000000, self)) self.tf_show_pp2_radius = QLineEdit() self.tf_show_pp2_radius.setPlaceholderText( "Radius of the neighbour area") self.tf_show_pp2_radius.setValidator( QDoubleValidator(0.0, 2.0, 5, self)) self.b_show_pp2_step = QPushButton("Apply Sampling") self.b_show_pp2_step.clicked.connect(self._show_pp2_step) self.container.addItem( OptionBox([ self.tf_show_pp2_centroids, self.tf_show_pp2_centroids_with_ball, self.tf_show_pp2_radius, self.b_show_pp2_step ]), "Show PointNet2 sampling") #Event Handlers def _applyFPS(self, event): item = self.app_state.current_item if (item is None or item.data is None): return if (item.type != item.TypePointCloud): self.app_state.showError( 'This operation can only be applyed to a Point Clouds.') return if (len(self.tf_centroid_count.text()) <= 0): return count = int(self.tf_centroid_count.text()) rateo = count / item.data.pos.size(0) if (rateo >= 1): self.app_state.showError( 'The number of point to select with FPS({}) have to be less than the total number of points({}).' .format(count, item.data.pos.size(0))) return item.data.pos = item.data.pos.double() idx = FPS(item.data.pos, torch.zeros(item.data.pos.size(0)).long(), rateo) new_item = Item(name='{}-FPS'.format(item.name), data=Data(pos=item.data.pos[idx]), type=Item.TypePointCloud) self.app_state.setNewItem(new_item) def _applyPoissonDiskSampling(self, event): item = self.app_state.current_item if (item is None or item.data is None): return if (item.type != item.TypeMesh): self.app_state.showError( 'This operation can only be applyed to be a Mesh object.') return if (len(self.tf_poisson_point_count.text()) <= 0 or len(self.tf_poisson_radius.text()) <= 0): return count = int(self.tf_poisson_point_count.text()) radio = float(self.tf_poisson_radius.text()) item.data.pos = item.data.pos.float() new_data = PoissonDiskSampling(count, radio)(item.data) new_item = Item(name='{}-Poisson'.format(item.name), data=new_data, type=Item.TypePointCloud) self.app_state.setNewItem(new_item) def _applyMontecarloSampling(self, event): item = self.app_state.current_item if (item is None or item.data is None): return if (item.type != item.TypeMesh): self.app_state.showError( 'This operation can only be applyed to be a Mesh object.') return if (len(self.tf_montecarlo_point_count.text()) <= 0): return count = int(self.tf_montecarlo_point_count.text()) item.data.pos = item.data.pos.float() new_data = MontecarloSampling(count)(item.data) new_item = Item(name='{}-Montecarlo'.format(item.name), data=new_data, type=Item.TypePointCloud) self.app_state.setNewItem(new_item) def _applyFaceImportanceSampling(self, event): item = self.app_state.current_item if (item is None or item.data is None): return if (item.type != item.TypeMesh): self.app_state.showError( 'This operation can only be applyed to be a Mesh object.') return if (len(self.tf_importance_point_count.text()) <= 0): return count = int(self.tf_importance_point_count.text()) item.data.pos = item.data.pos.float() new_data = SamplePoints(count)(item.data) new_item = Item(name='{}-ImportanceSamped'.format(item.name), data=new_data, type=Item.TypePointCloud) self.app_state.setNewItem(new_item) def _show_pp2_step(self, event): item = self.app_state.current_item if (item is None or item.data is None): return if (item.type != item.TypePointCloud): self.app_state.showError( 'This operation can only be applyed to a Point Clouds.') return if (len(self.tf_show_pp2_centroids.text()) <= 0 or len(self.tf_show_pp2_centroids_with_ball.text()) <= 0): return count = int(self.tf_show_pp2_centroids.text()) rateo = count / item.data.pos.size(0) if (rateo >= 1): self.app_state.showError( 'The number of point to select with FPS({}) have to be less than the total number of points({}).' .format(count, item.data.pos.size(0))) return with_ball = int(self.tf_show_pp2_centroids_with_ball.text()) if (with_ball > count): self.app_state.showError( 'The number of point for which plot the radius({}), have to be less than the sampled ammount({}).' .format(with_ball, count)) return item.data.pos = item.data.pos.double() idx = FPS(item.data.pos, torch.zeros(item.data.pos.size(0)).long(), rateo) radius = 0.0 if len(self.tf_show_pp2_radius.text()) <=0 \ else float(self.tf_show_pp2_radius.text()) render = CenterAndRadious(item.data.pos.size(0), centroids_idx=idx, centroid_to_draw=with_ball, radius=radius) self.app_state.setNewItem(item, render) def _applySaveEdit(self, event): sourceItem = self.app_state.current_item item = Item(data=sourceItem.data, name=sourceItem.name, type=sourceItem.type) self.app_state.addItem(item)
class MessageBox(QDialog): _default = ''' MessageBox { min-width: 280px; } QLabel { font-size: 14px; } QLineEdit { font-size: 18px; min-height: 30px; padding: 4px 16px; } QDialogButtonBox { min-height: 30px; } ''' def __init__(self, parent, title, message, field, confirm): super().__init__(parent) self.setWindowTitle(title) self._buttons = None self._edit_text = None self._setup_ui(message, field, confirm) def _setup_ui(self, message, field, confirm): self.setStyleSheet(self._default) layout = make_layout(horizon=False, margin=24, spacing=24) if message != '': label = QLabel(message) label.setAlignment(Qt.AlignCenter) layout.addWidget(label) if field != '': self._edit_text = QLineEdit() if ':' in field: field, default_text = field.split(':') self._edit_text.setText(default_text) self._edit_text.setPlaceholderText(field) layout.addWidget(self._edit_text) buttons = QDialogButtonBox.Ok | QDialogButtonBox.Cancel elif confirm: buttons = QDialogButtonBox.Ok else: buttons = QDialogButtonBox.Yes | QDialogButtonBox.No self._buttons = QDialogButtonBox(buttons) self._buttons.accepted.connect(self.accept) self._buttons.rejected.connect(self.reject) layout.addWidget(self._buttons) self.setLayout(layout) move_center(self) def get_result(self): if self._edit_text is not None: return self._edit_text.text().strip() return True
class ChannelAddWidget(QWidget): def __init__(self, main, channels, default_channel=None): super(ChannelAddWidget, self).__init__() self.setObjectName("ChannelAddWidget") self.main_win = main self.channels = channels self.default_channel = default_channel self.channel = {} self.linedit_list = [] self.game = self.main_win.games[self.main_win.game_index] combox_items = os.listdir(Utils.get_full_path('channelsdk')) v_layout = QVBoxLayout() v_layout.addSpacing(30) select_channel_combox = QComboBox() select_channel_combox.addItems(combox_items) select_channel_combox.activated[str].connect(self.select_channel) v_layout.addWidget(select_channel_combox, alignment=Qt.AlignHCenter) v_layout.addSpacing(30) h_layout1 = QHBoxLayout() form_layout1 = QFormLayout() form_layout1.setContentsMargins(10, 10, 10, 0) game_appid_value = QLabel(self.game['id']) form_layout1.addRow("游戏ID:", game_appid_value) game_appid_value.setTextInteractionFlags(Qt.TextSelectableByMouse) self.channel_id_value = QLineEdit() self.channel_id_value.setPlaceholderText("必填参数") form_layout1.addRow("渠道ID:", self.channel_id_value) self.game_name_value = QLineEdit() self.game_name_value.setText(self.game['name']) form_layout1.addRow("游戏名称:", self.game_name_value) self.game_package_value = QLineEdit() form_layout1.addRow("游戏包名:", self.game_package_value) self.game_vcode_value = QLineEdit() form_layout1.addRow("游戏版本号:", self.game_vcode_value) self.game_vname_value = QLineEdit() form_layout1.addRow("游戏版本名:", self.game_vname_value) self.debug_value = QLineEdit("false") form_layout1.addRow("打印日志:", self.debug_value) h_layout1.addLayout(form_layout1) self.form_layout2 = QFormLayout() self.form_layout2.setContentsMargins(10, 10, 10, 0) h_layout1.addLayout(self.form_layout2) v_layout.addLayout(h_layout1) h_layout2 = QHBoxLayout() back_btn = QPushButton("返 回") back_btn.setFixedWidth(100) back_btn.clicked.connect(self.back) h_layout2.addWidget(back_btn, alignment=Qt.AlignLeft) add_btn = QPushButton("添 加") add_btn.setFixedWidth(100) add_btn.clicked.connect(self.add) h_layout2.addWidget(add_btn, alignment=Qt.AlignRight) v_layout.addSpacing(50) v_layout.addLayout(h_layout2) self.setLayout(v_layout) # 默认松鼠SDK select_channel_combox.setCurrentText("songshu") self.select_channel("songshu") def select_channel(self, text): # 先初始化数据 self.linedit_list.clear() self.channel.clear() # 排序包体参数,防止参数写入乱排序 self.channel['name'] = '' self.channel['sdk'] = text self.channel['channelId'] = '' self.channel['gameName'] = '' self.channel['package'] = '' self.channel['gameVersionCode'] = '' self.channel['gameVersionName'] = '' self.channel['debug'] = "false" # 获取渠道参数定义 if not Utils.get_channel_config(self.channel): return # 再添加当前选择的渠道参数模板,刷新界面(先清空之前渠道参数表单,再添加) for i in range(self.form_layout2.rowCount()): # 因为formlayout清除一行,会自动上移,所以只需remove第一行 self.form_layout2.removeRow(0) channel_name = QLabel(self.channel['name'] + '\t\t\tVersion:' + self.channel['sdkVersionName'] + '\t\tUpdate:' + self.channel['sdkUpdateTime']) channel_name.setAlignment(Qt.AlignRight) self.form_layout2.addRow(channel_name) if self.default_channel is not None and text == self.default_channel[ 'sdk']: self.channel_id_value.setText(self.default_channel['channelId']) self.game_name_value.setText(self.default_channel['gameName']) self.game_package_value.setText(self.default_channel['package']) self.game_vcode_value.setText( self.default_channel['gameVersionCode']) self.game_vname_value.setText( self.default_channel['gameVersionName']) for param in self.default_channel['sdkParams']: line_edit = QLineEdit() line_edit.setText(param['value']) self.form_layout2.addRow(param['showName'] + ':', line_edit) self.linedit_list.append(line_edit) else: for param in self.channel['sdkParams']: line_edit = QLineEdit() line_edit.setPlaceholderText("渠道参数必填") self.form_layout2.addRow(param['showName'] + ':', line_edit) self.linedit_list.append(line_edit) def back(self): if len(self.channels) <= 0: self.main_win.set_game_list_widget(self.main_win.games) else: self.main_win.set_channel_list_widget(self.channels) def add(self): if self.channel_id_value.text().strip() == "": QMessageBox.warning(self, "警告", "渠道ID不能为空!") return self.channel['channelId'] = self.channel_id_value.text().strip() for channel in self.channels: if self.channel['channelId'] == channel['channelId']: QMessageBox.warning(self, "警告", "渠道已存在!") return self.channel['gameName'] = self.game_name_value.text().strip() self.channel['package'] = self.game_package_value.text().strip() self.channel['gameVersionCode'] = self.game_vcode_value.text().strip() self.channel['gameVersionName'] = self.game_vname_value.text().strip() self.channel['debug'] = self.debug_value.text().strip() for i in range(len(self.linedit_list)): if self.linedit_list[i].text().strip() == "": QMessageBox.warning(self, "警告", "渠道参数不能为空!") return self.channel['sdkParams'][i]['value'] = self.linedit_list[i].text( ).strip() self.channels.append(self.channel) Utils.add_channel( Utils.get_full_path('games/' + self.game['id'] + '/config.xml'), self.channel) self.main_win.set_channel_list_widget(self.channels)
def init_ui(self): # Create main layout main_layout = QVBoxLayout() label_1 = QLabel('Current Products') self.dropdown = QComboBox() self.dropdown.setEditText('Please select a Product') # Create buttons add_button = QPushButton("Add") delete_button = QPushButton("Delete") update_button = QPushButton('Update') button_layout = QHBoxLayout() button_layout.addWidget(add_button) button_layout.addWidget(delete_button) button_layout.addWidget(update_button) # Create main product layout product_layout = QHBoxLayout() # Layout for product labels p_labels_layout = QVBoxLayout() p_name_label = QLabel('Name:') p_price_label = QLabel('Price:') p_id_label = QLabel('Id:') p_quantity_label = QLabel('Quantity:') p_labels_layout.addWidget(p_name_label) p_labels_layout.addWidget(p_price_label) p_labels_layout.addWidget(p_id_label) p_labels_layout.addWidget(p_quantity_label) # Layout for product line edits p_edit_layout = QVBoxLayout() p_price = QLineEdit() p_id = QLineEdit() p_quantity = QLineEdit() p_name = QLineEdit() p_name.setPlaceholderText('Enter an String') p_price.setPlaceholderText('Enter an Integer') p_id.setPlaceholderText('Enter an Integer') p_quantity.setPlaceholderText('Enter an Integer') p_edit_layout.addWidget(p_name) p_edit_layout.addWidget(p_price) p_edit_layout.addWidget(p_id) p_edit_layout.addWidget(p_quantity) # Add product label and edit to main product layout product_layout.addLayout(p_labels_layout) product_layout.addLayout(p_edit_layout) # Check if labels are correct type check_inputs = lambda: self.correct_inputs(p_name.text(), p_price.text( ), p_id.text(), p_quantity.text()) update_inputs = lambda: self.update_product(p_name.text( ), p_price.text(), p_id.text(), p_quantity.text()) # Set button functions add_button.released.connect(check_inputs) update_button.released.connect(update_inputs) delete_button.released.connect(self.delete_product) main_layout.addWidget(label_1) main_layout.addWidget(self.dropdown) main_layout.addLayout(product_layout) main_layout.addLayout(button_layout) main_layout.addStretch() self.setLayout(main_layout)
class AppLogin(QDialog): """ Class who create login QDialog. """ def __init__(self, parent=None): super(AppLogin, self).__init__(parent) self.setWindowTitle('Login to Alignak') self.setWindowFlags(Qt.FramelessWindowHint) self.setStyleSheet(get_css()) self.setWindowIcon(QIcon(get_image_path('icon'))) self.setFixedSize(300, 330) # Fields self.app_backend = AppBackend() self.backend_url = None self.username_line = None self.password_line = None self.offset = None def showEvent(self, _): """ QDialog.showEvent(QShowEvent) """ self.username_line.setFocus() def create_widget(self): """ Create widget login """ # Main layout main_layout = QVBoxLayout(self) main_layout.setContentsMargins(0, 0, 0, 0) main_layout.addWidget(self.get_logo_widget(self)) title = QLabel('Welcome to <b>Alignak-app</b>') title.setObjectName('title_login') main_layout.addWidget(title) main_layout.setAlignment(title, Qt.AlignCenter) version = QLabel('Version %s' % __version__) version.setObjectName('version_login') main_layout.addWidget(version) main_layout.setAlignment(version, Qt.AlignCenter | Qt.AlignTop) # Login QWidget login_widget = QWidget(self) login_widget.setObjectName('login') login_layout = QGridLayout(login_widget) # Configuration button refresh_conf_btn = QPushButton() refresh_conf_btn.clicked.connect(init_config) refresh_conf_btn.setFixedSize(25, 25) refresh_conf_btn.setIcon(QIcon(get_image_path('refresh'))) refresh_conf_btn.setToolTip('Reload configuration') login_layout.addWidget(refresh_conf_btn, 2, 1, 1, 1) # Server button server_btn = QPushButton() server_btn.clicked.connect(self.handle_server) server_btn.setFixedSize(25, 25) server_btn.setIcon(QIcon(get_image_path('host'))) server_btn.setToolTip('Modify Alignak Server') login_layout.addWidget(server_btn, 2, 2, 1, 1) # Welcome text login_label = QLabel('<b>Log-in</b> to use the application') login_layout.addWidget(login_label, 2, 0, 1, 1) login_layout.setAlignment(login_label, Qt.AlignCenter) # Username field self.username_line = QLineEdit(self) self.username_line.setPlaceholderText('Username') login_layout.addWidget(self.username_line, 3, 0, 1, 3) # Password field self.password_line = QLineEdit(self) self.password_line.setPlaceholderText('Password') self.password_line.setEchoMode(QLineEdit.Password) login_layout.addWidget(self.password_line, 4, 0, 1, 3) # Login button login_button = QPushButton('LOGIN', self) login_button.clicked.connect(self.handle_login) login_button.setObjectName('valid') login_button.setMinimumHeight(30) login_button.setDefault(True) login_layout.addWidget(login_button, 5, 0, 1, 3) main_layout.addWidget(login_widget) self.setLayout(main_layout) self.center(self) @staticmethod def center(widget): """ Center QWidget """ screen = QApplication.desktop().screenNumber( QApplication.desktop().cursor().pos()) center = QApplication.desktop().screenGeometry(screen).center() widget.move(center.x() - (widget.width() / 2), center.y() - (widget.height() / 2)) @staticmethod def get_logo_widget(widget): """ Return the logo QWidget :param widget: widget parent, needed for action button :type widget: QWidget :return: logo QWidget :rtype: QWidget """ logo_widget = QWidget() logo_widget.setFixedHeight(45) logo_widget.setObjectName('title') logo_layout = QHBoxLayout() logo_widget.setLayout(logo_layout) logo_label = QLabel() logo_label.setPixmap(QPixmap(get_image_path('alignak'))) logo_label.setFixedSize(121, 35) logo_label.setScaledContents(True) logo_layout.addWidget(logo_label, 0) minimize_btn = QPushButton() minimize_btn.setIcon(QIcon(get_image_path('minimize'))) minimize_btn.setFixedSize(24, 24) minimize_btn.setObjectName('app_widget') minimize_btn.clicked.connect(widget.showMinimized) logo_layout.addStretch(widget.width()) logo_layout.addWidget(minimize_btn, 1) maximize_btn = QPushButton() maximize_btn.setIcon(QIcon(get_image_path('maximize'))) maximize_btn.setFixedSize(24, 24) maximize_btn.setObjectName('app_widget') maximize_btn.clicked.connect(widget.showMaximized) logo_layout.addWidget(maximize_btn, 2) close_btn = QPushButton() close_btn.setIcon(QIcon(get_image_path('exit'))) close_btn.setObjectName('app_widget') close_btn.setFixedSize(24, 24) close_btn.clicked.connect(widget.close) logo_layout.addWidget(close_btn, 3) return logo_widget def handle_login(self): """ Handle for login button """ username = self.username_line.text() password = self.password_line.text() self.app_backend.backend = Backend(get_app_config( 'Alignak', 'backend')) resp = self.app_backend.login(str(username), str(password)) if resp: send_banner( 'OK', 'Welcome %s, you are connected to Alignak Backend' % username) self.app_backend.user['username'] = str(username) self.app_backend.user['token'] = str( self.app_backend.backend.token) self.accept() else: send_banner('WARN', 'Backend connection refused...', duration=10000) logger.warning('Connection informations are not accepted !') def handle_server(self): """ Handle for server button """ server_dialog = QDialog() server_dialog.setWindowTitle('Server Configuration') server_dialog.setWindowFlags(Qt.FramelessWindowHint) server_dialog.setStyleSheet(get_css()) server_dialog.setFixedSize(300, 300) main_layout = QVBoxLayout(server_dialog) main_layout.setContentsMargins(0, 0, 0, 0) main_layout.addWidget(self.get_logo_widget(server_dialog)) server_widget = QWidget(self) server_widget.setObjectName('login') server_layout = QGridLayout(server_widget) # Description desc_label = QLabel( '<h3>Alignak Backend</h3><p>Here you can define alignak settings.</p>' '<b>Be sure to enter a valid address</b>') desc_label.setWordWrap(True) server_layout.addWidget(desc_label, 0, 0, 1, 3) # Server URL server_layout.addWidget(QLabel('Server'), 1, 0, 1, 1) server_url = QLineEdit() server_url.setPlaceholderText('alignak backend url') server_url.setText(get_app_config('Alignak', 'url')) server_layout.addWidget(server_url, 1, 1, 1, 2) # Server Port server_layout.addWidget(QLabel('Port'), 2, 0, 1, 1) server_port = QLineEdit() server_port.setPlaceholderText('alignak backend port') cur_port = get_app_config('Alignak', 'backend').split(':')[2] server_port.setText(cur_port) server_layout.addWidget(server_port, 2, 1, 1, 2) # Server Processes server_layout.addWidget(QLabel('Processes'), 3, 0, 1, 1) server_proc = QLineEdit() if 'win32' in sys.platform: server_proc.setEnabled(False) server_proc.setPlaceholderText('alignak backend processes') cur_proc = get_app_config('Alignak', 'processes') server_proc.setText(cur_proc) server_layout.addWidget(server_proc, 3, 1, 1, 2) # Valid Button valid_btn = QPushButton('Valid') valid_btn.clicked.connect(server_dialog.accept) server_layout.addWidget(valid_btn, 4, 0, 1, 3) main_layout.addWidget(server_widget) self.center(server_widget) if server_dialog.exec_() == QDialog.Accepted: backend_url = '%(url)s:' + str(server_port.text()).rstrip() set_app_config('Alignak', 'backend', backend_url) set_app_config('Alignak', 'url', str(server_url.text()).rstrip()) set_app_config('Alignak', 'processes', str(server_proc.text()).rstrip()) def mousePressEvent(self, event): """ QWidget.mousePressEvent(QMouseEvent) """ self.offset = event.pos() def mouseMoveEvent(self, event): """ QWidget.mousePressEvent(QMouseEvent) """ try: x = event.globalX() y = event.globalY() x_w = self.offset.x() y_w = self.offset.y() self.move(x - x_w, y - y_w) except AttributeError as e: logger.warning('Move Event %s: %s', self.objectName(), str(e))
class LLT_EditWord(QMainWindow): def __init__(self): super(LLT_EditWord, self).__init__() self.w = QWidget() self.setCentralWidget(self.w) self.verbDic = [] self.nounDic = [] self.adjDic = [] self.phraseDic = [] self.wordList = [] self.verbList = [] self.nounList = [] self.adjList = [] self.phraseList = [] self.index = int(0) self.w.setWindowTitle("Edit Word") self.w.setGeometry(0,0,500, 500) self.vRad = QRadioButton("Verb") self.vRad.setChecked(True) self.nRad = QRadioButton("Noun") self.aRad = QRadioButton("Adjective") self.pRad = QRadioButton("Phrase") self.okBut = QPushButton("OK") self.okBut.clicked.connect(self.OK) self.lookLab = QLabel("Lookup: ") self.lookEntry = QLineEdit() self.lookEntry.setEnabled(False) self.lookBut = QPushButton("Search") self.lookBut.clicked.connect(self.search) self.lookBut.setEnabled(False) self.entryLab = QLabel("Word: ") self.wordEntry = QLineEdit() self.wordEntry.setEnabled(False) self.tranLab = QLabel("Translation: ") self.tranEntry = QLineEdit() self.tranEntry.setEnabled(False) self.saveBut = QPushButton("Save") self.saveBut.clicked.connect(self.save) self.clearBut = QPushButton("Reset") self.clearBut.clicked.connect(self.reset) self.newBut = QPushButton("New word") self.newBut.clicked.connect(self.new) self.exitBut = QPushButton("Exit") self.exitBut.clicked.connect(self.exit) grid = QGridLayout() grid.addWidget(self.vRad, 0, 0) grid.addWidget(self.nRad, 0, 1) grid.addWidget(self.aRad, 0, 2) grid.addWidget(self.pRad, 0, 3) grid.addWidget(self.okBut, 0, 4) grid.addWidget(self.lookLab, 1, 0) grid.addWidget(self.lookEntry, 1, 1, 1, 2) grid.addWidget(self.lookBut, 1, 4) grid.addWidget(self.entryLab, 2, 0) grid.addWidget(self.wordEntry, 2, 1, 1, 3) grid.addWidget(self.tranLab, 3, 0) grid.addWidget(self.tranEntry, 3, 1, 1, 3) grid.addWidget(self.saveBut, 4, 0) grid.addWidget(self.clearBut, 4, 1) grid.addWidget(self.newBut, 4, 2) grid.addWidget(self.exitBut, 4, 3) self.getDics() self.setLists() self.w.setLayout(grid) self.w.show() def search(self): searchWord = self.lookEntry.text().upper() currentDic = [] currentList = [] if self.vRad.isChecked(): currentDic = self.verbDic currentList = self.verbList elif self.nRad.isChecked(): currentDic = self.nounDic currentList = self.nounList elif self.aRad.isChecked(): currentDic = self.adjDic currentList = self.adjList elif self.pRad.isChecked(): currentDic = self.phraseDic currentList = self.phraseList else: msgBox = QMessageBox() msgBox.setText("You must select a dictionary before continuing.") msgBox.exec_() self.vRad.setEnabled(True) self.nRad.setEnabled(True) self.aRad.setEnabled(True) self.pRad.setEnabled(True) self.lookEntry.setEnabled(False) self.lookBut.setEnabled(False) self.wordEntry.setEnabled(False) self.tranEntry.setEnabled(False) if searchWord in self.wordList: self.lookEntry.setEnabled(False) self.lookBut.setEnabled(False) self.wordEntry.setEnabled(True) self.tranEntry.setEnabled(True) self.index = currentList.index(searchWord) oldWord = currentDic[self.index] self.wordEntry.setPlaceholderText(oldWord[0]) self.tranEntry.setPlaceholderText(oldWord[1]) else: msgBox = QMessageBox() msgBox.setText("Word not currently saved in dictionary.") msgBox.exec_(); def OK(self): self.vRad.setEnabled(False) self.nRad.setEnabled(False) self.aRad.setEnabled(False) self.pRad.setEnabled(False) self.lookEntry.setEnabled(True) self.lookBut.setEnabled(True) def save(self): spanWord = self.wordEntry.text().upper() tranWord = self.tranEntry.text().upper() if spanWord in self.wordList: msgBox = QMessageBox() msgBox.setText(spanWord + ' already in dictionary') msgBox.exec_(); else: self.wordList.append(spanWord) newWord = [spanWord,tranWord] self.wordEntry.setEnabled(False) self.tranEntry.setEnabled(False) if self.vRad.isChecked(): self.verbDic[self.index]= newWord v = open('verb.txt','w') json.dump(self.verbDic, v) v.close() elif self.nRad.isChecked(): self.nounDic[self.index]= newWord n = open('noun.txt','w') json.dump(self.nounDic, n) n.close() elif self.aRad.isChecked(): self.adjDic[self.index]= newWord a = open('adj.txt','w') json.dump(self.adjDic, a) a.close() elif self.pRad.isChecked(): self.phraseDic[self.index]= newWord p = open('phrase.txt','w') json.dump(self.phraseDic, p) p.close() else: msgBox = QMessageBox() msgBox.setText("You must select a dictionary before saving word.") msgBox.exec_(); def reset(self): self.vRad.setEnabled(True) self.nRad.setEnabled(True) self.aRad.setEnabled(True) self.pRad.setEnabled(True) self.lookEntry.setEnabled(False) self.lookBut.setEnabled(False) self.wordEntry.setEnabled(False) self.tranEntry.setEnabled(False) self.wordEntry.clear() self.tranEntry.clear() self.lookEntry.setPlaceholderText('') self.wordEntry.setPlaceholderText('') self.tranEntry.setPlaceholderText('') def new(self): self.vRad.setEnabled(True) self.nRad.setEnabled(True) self.aRad.setEnabled(True) self.pRad.setEnabled(True) self.wordEntry.setEnabled(False) self.tranEntry.setEnabled(False) self.wordEntry.clear() self.tranEntry.clear() self.lookEntry.setPlaceholderText('') self.wordEntry.setPlaceholderText('') self.tranEntry.setPlaceholderText('') def exit(self): confirm = QMessageBox.question(self.w, 'Quit', 'Are you sure you want to exit?', QMessageBox.Yes | QMessageBox.No) if confirm == QMessageBox.Yes: self.close() else: pass def getDics(self): try: v=open('verb.txt','r') self.verbDic=json.load(v) v.close() except: self.verbDic = [] try: n=open('noun.txt','r') self.nounDic=json.load(n) n.close() except: self.nounDic = [] try: p=open('phrase.txt','r') self.phraseDic=json.load(p) p.close() except: self.phraseDic = [] try: a=open('adj.txt','r') self.adjDic=json.load(a) a.close() except: self.phraseDic = [] def setLists(self): for item in self.verbDic: self.wordList.append(item[0]) self.verbList.append(item[0]) for item in self.nounDic: self.wordList.append(item[0]) self.nounList.append(item[0]) for item in self.adjDic: self.wordList.append(item[0]) self.adjList.append(item[0]) for item in self.phraseDic: self.wordList.append(item[0]) self.phraseList.append(item[0])