class AboutNinja(QDialog): def __init__(self, parent=None): QDialog.__init__(self, parent, Qt.Dialog) self.setWindowTitle(self.tr("About NINJA-IDE")) self.setMaximumSize(QSize(0, 0)) vbox = QVBoxLayout(self) #Create an icon for the Dialog pixmap = QPixmap(resources.IMAGES['icon']) self.lblIcon = QLabel() self.lblIcon.setPixmap(pixmap) hbox = QHBoxLayout() hbox.addWidget(self.lblIcon) lblTitle = QLabel( '<h1>NINJA-IDE</h1>\n<i>Ninja-IDE Is Not Just Another IDE<i>') lblTitle.setTextFormat(Qt.RichText) lblTitle.setAlignment(Qt.AlignLeft) hbox.addWidget(lblTitle) vbox.addLayout(hbox) #Add description vbox.addWidget(QLabel( self.tr("""NINJA-IDE (from: "Ninja Is Not Just Another IDE"), is a cross-platform integrated development environment specially design to build Python Applications. NINJA-IDE provides tools to simplify the Python-software development and handles all kinds of situations thanks to its rich extensibility."""))) vbox.addWidget(QLabel(self.tr("Version: %1").arg( ninja_ide.__version__))) link_ninja = QLabel( self.tr("Website: <a href='%1'>%1</a>").arg(ninja_ide.__url__)) vbox.addWidget(link_ninja) link_source = QLabel( self.tr("Source Code: <a href='%1'>%1</a>").arg( ninja_ide.__source__)) vbox.addWidget(link_source) self.connect(link_ninja, SIGNAL("linkActivated(QString)"), self.link_activated) self.connect(link_source, SIGNAL("linkActivated(QString)"), self.link_activated) self.lblIcon.installEventFilter(self) def link_activated(self, link): webbrowser.open(str(link)) def eventFilter(self, obj, event): if obj == self.lblIcon and event.type() == QEvent.MouseButtonPress: self.show_retsae() return False def show_retsae(self): height = main_container.MainContainer().size().height() width = main_container.MainContainer().size().width() tetris = TetrisMainWindow(width, height) main_container.MainContainer().add_tab(tetris, 'Tetris') self.close()
class AboutNinja(QDialog): def __init__(self, parent=None): QDialog.__init__(self, parent, Qt.Dialog) self.setModal(True) self.setWindowTitle(self.tr("About NINJA-IDE")) self.setMaximumSize(QSize(0, 0)) vbox = QVBoxLayout(self) #Create an icon for the Dialog pixmap = QPixmap(resources.IMAGES['icon']) self.lblIcon = QLabel() self.lblIcon.setPixmap(pixmap) hbox = QHBoxLayout() hbox.addWidget(self.lblIcon) lblTitle = QLabel( '<h1>NINJA-IDE</h1>\n<i>Ninja-IDE Is Not Just Another IDE<i>') lblTitle.setTextFormat(Qt.RichText) lblTitle.setAlignment(Qt.AlignLeft) hbox.addWidget(lblTitle) vbox.addLayout(hbox) #Add description vbox.addWidget( QLabel( self.tr( """NINJA-IDE (from: "Ninja Is Not Just Another IDE"), is a cross-platform integrated development environment specially design to build Python Applications. NINJA-IDE provides tools to simplify the Python-software development and handles all kinds of situations thanks to its rich extensibility."""))) vbox.addWidget( QLabel(self.tr("Version: %1").arg(ninja_ide.__version__))) vbox.addWidget(QLabel(self.tr("Website: %1").arg(ninja_ide.__url__))) vbox.addWidget( QLabel(self.tr("Source Code: %1").arg(ninja_ide.__source__))) self.lblIcon.installEventFilter(self) def eventFilter(self, obj, event): if obj == self.lblIcon and event.type() == QEvent.MouseButtonPress: self.show_retsae() return False def show_retsae(self): height = main_container.MainContainer().size().height() width = main_container.MainContainer().size().width() tetris = TetrisMainWindow(width, height) main_container.MainContainer().add_tab(tetris, 'Tetris') self.close()
class MobileWidget(QWidget): """ Mobile widget """ RefreshScreen = pyqtSignal() RefreshAutomatic = pyqtSignal(bool) TapOn = pyqtSignal(int, int) def __init__(self, parent=None): """ Constructor """ super(MobileWidget, self).__init__(parent) self.origWidth = 0 self.origHeight = 0 self.imagePath = None self.createActions() self.createWidget() self.createToolbar() self.center() def createActions(self): """ Create qt actions """ self.refreshAction = QtHelper.createAction(self, self.tr("&Refresh"), self.refreshScreen, icon=None) self.refreshAction.setEnabled(False) self.copyAction = QtHelper.createAction(self, self.tr("&Copy"), self.copyItem, icon=None) def createWidget(self): """ Create qt widget """ self.screenResolutionLabel = QLabel(self) self.screenTapLabel = QLabel(self) mobileLayout = QVBoxLayout() self.mobileDockToolbar = QToolBar(self) self.mobileDockToolbar.setStyleSheet("QToolBar { border: 0px }") self.mobileDockToolbar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon) self.mobileImageLabel = QLabel(self) self.mobileImageLabel.setMouseTracking(True) self.mobileImageLabel.installEventFilter(self) self.mobileImageLabel.setScaledContents(True) self.mobileImageLabel.mousePressEvent = self.pixelSelect self.refreshCheckbox = QCheckBox("Automatic Refresh", self) self.refreshCheckbox.setEnabled(False) self.refreshCheckbox.stateChanged.connect(self.onRefreshChanged) self.clickCheckbox = QCheckBox("Enable Tap", self) self.clickCheckbox.setEnabled(False) self.model = DomModel(QDomDocument(), self) self.mobileTreeView = QTreeView(self) self.mobileTreeView.setMinimumWidth(300) self.mobileTreeView.setModel(self.model) self.mobileTreeView.clicked.connect(self.onTreeViewClicked) header = ["Attribute", "Value"] self.tableModel = MyTableModel(self, [], header) self.mobileTableView = QTableView(self) self.mobileTableView.setSelectionMode( QAbstractItemView.SingleSelection) self.mobileTableView.setModel(self.tableModel) self.mobileTableView.setContextMenuPolicy(Qt.CustomContextMenu) self.mobileTableView.customContextMenuRequested.connect( self.onContextMenuEvent) self.mobileTableView.setMinimumWidth(300) mobileViewLayout = QHBoxLayout() mobileViewLayout.addWidget(self.mobileImageLabel) mobileViewLayout.addWidget(self.mobileTreeView) mobileViewLayout.addWidget(self.mobileTableView) mobileLayout.addWidget(self.mobileDockToolbar) mobileLayout.addLayout(mobileViewLayout) self.setLayout(mobileLayout) def createToolbar(self): """ Create qt toolbar """ self.mobileDockToolbar.setObjectName("Toolbar") self.mobileDockToolbar.addWidget(self.refreshCheckbox) self.mobileDockToolbar.addWidget(self.clickCheckbox) self.mobileDockToolbar.addSeparator() self.mobileDockToolbar.addAction(self.refreshAction) self.mobileDockToolbar.addSeparator() self.mobileDockToolbar.addWidget(self.screenResolutionLabel) self.mobileDockToolbar.addSeparator() self.mobileDockToolbar.addWidget(self.screenTapLabel) self.mobileDockToolbar.addSeparator() self.mobileDockToolbar.setIconSize(QSize(16, 16)) def center(self): """ Center the dialog """ qr = self.frameGeometry() cp = QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) self.move(qr.topLeft()) def eventFilter(self, srcEvent, event): """ On event filtering """ if srcEvent == self.mobileImageLabel: if event.type() == QEvent.MouseMove: x = event.pos().x() y = event.pos().y() pixmap = self.mobileImageLabel.pixmap() if pixmap is not None: x_scaled = int((self.origWidth * x) / pixmap.width()) y_scaled = int((self.origHeight * y) / pixmap.height()) self.mobileImageLabel.setToolTip("%sx%s" % (x_scaled, y_scaled)) return False def onContextMenuEvent(self, event): """ On context menu event """ menu = QMenu(self) menu.addAction(self.copyAction) menu.popup(QCursor.pos()) def copyItem(self): """ Copy the item """ indexes = self.mobileTableView.selectedIndexes() if len(indexes): data = self.tableModel.mylist[indexes[0].row()][ indexes[0].column()] clipboard = QApplication.clipboard() clipboard.setText(data) def onTreeViewClicked(self, qindex): """ On click in the treeview """ item = qindex.internalPointer() attributes = [] node = item.node() attributeMap = node.attributes() nodeName = node.nodeName() bounds_str = None for i in range(0, attributeMap.count()): attribute = attributeMap.item(i) attributes.append((attribute.nodeName(), attribute.nodeValue())) if attribute.nodeName() == 'bounds': bounds_str = attribute.nodeValue() self.tableModel.mylist = attributes if sys.version_info > (3, ): self.tableModel.beginResetModel() self.tableModel.endResetModel() else: self.tableModel.reset() self.mobileTableView.resizeColumnsToContents() self.mobileTableView.resizeRowsToContents() # redraw image with rectangle if bounds_str is not None: xy = bounds_str.split('][')[0].split('[')[1] wh = bounds_str.split('][')[1].split(']')[0] x, y = xy.split(',') w, h = wh.split(',') # get label size pixmap = self.mobileImageLabel.pixmap() xlabel = pixmap.width() ylabel = pixmap.height() # resize the rectangle y_scaled = (pixmap.height() * int(y)) / self.origHeight x_scaled = (pixmap.width() * int(x)) / self.origWidth h_scaled = (pixmap.height() * (int(h) - int(y))) / self.origHeight w_scaled = (pixmap.width() * (int(w) - int(x))) / self.origWidth # finally reload self.reloadScreen(x=int(x_scaled), y=int(y_scaled), w=int(w_scaled), h=int(h_scaled)) def onDeviceReady(self): """ On device ready """ self.refreshAction.setEnabled(True) self.refreshCheckbox.setEnabled(True) self.clickCheckbox.setEnabled(True) def refreshScreen(self): """ Refresh the screen """ self.RefreshScreen.emit() def onRefreshChanged(self, state): """ On refresh changed """ if state == Qt.Checked: self.RefreshAutomatic.emit(True) else: self.RefreshAutomatic.emit(False) def pixelSelect(self, event): """ Select pixel to click """ position = QPoint(event.pos().x(), event.pos().y()) x = event.pos().x() y = event.pos().y() pixmap = self.mobileImageLabel.pixmap() x_scaled = int((self.origWidth * x) / pixmap.width()) y_scaled = int((self.origHeight * y) / pixmap.height()) self.screenTapLabel.setText("Tap on (%s,%s)" % (x_scaled, y_scaled)) if self.clickCheckbox.isChecked(): self.TapOn.emit(x_scaled, y_scaled) def drawRectangle(self, x=0, y=0, w=0, h=0): """ Draw a rectangle """ self.mobileImageLabel.update() pixmap = self.mobileImageLabel.pixmap() if pixmap is not None: p = QPainter(pixmap) pen = QPen(Qt.red, 2, Qt.SolidLine) p.setPen(pen) p.drawRect(x, y, w, h) p.end() def reloadScreen(self, x, y, w, h): """ Reload the screen """ if self.imagePath is not None: self.updateScreen(filename=self.imagePath, xmlPath='', x=x, y=y, w=w, h=h, reloadMode=True) def updateScreen(self, filename, xmlPath, x=0, y=0, w=0, h=0, reloadMode=False): """ Update the screen """ self.imagePath = filename if not reloadMode: self.tableModel.mylist = [] self.tableModel.beginResetModel() self.tableModel.endResetModel() pixmap = QPixmap(filename) if pixmap is not None: self.origWidth = pixmap.width() self.origHeight = pixmap.height() self.screenResolutionLabel.setText( "Resolution=%sx%s" % (self.origWidth, self.origHeight)) #portrait if self.origWidth < self.origHeight: pixmap = pixmap.scaledToHeight(Settings.getInt( 'MobileAndroid', 'resolution-screen-height'), mode=Qt.SmoothTransformation) self.mobileImageLabel.setPixmap(pixmap) else: pixmap = pixmap.scaledToWidth(Settings.getInt( 'MobileAndroid', 'resolution-screen-width'), mode=Qt.SmoothTransformation) self.mobileImageLabel.setPixmap(pixmap) self.drawRectangle(x=x, y=y, w=w, h=h) self.resize(pixmap.width(), pixmap.height()) # convert xml to dict if len(xmlPath): f = QFile(xmlPath) if f.open(QIODevice.ReadOnly): document = QDomDocument() if document.setContent(f): newModel = DomModel(document, self) self.mobileTreeView.setModel(newModel) self.mobileTreeView.expandAll() self.mobileTreeView.resizeColumnToContents(0) f.close()
class AcercaDe(QDialog): def __init__(self, parent): QDialog.__init__(self, parent, Qt.WindowMinMaxButtonsHint) self.clicks = 0 self.setWindowTitle(self.tr("Acerca de Edis")) self.setMinimumWidth(485) box = QVBoxLayout(self) self.label_logo = QLabel() self.label_logo.setPixmap(QPixmap(":image/edis")) title_label = QLabel(self.tr("<h1>Edis</h1>\n<i>a simple " "cross-platform IDE for C</i>")) title_label.setAlignment(Qt.AlignRight) box_logo = QHBoxLayout() box_logo.addWidget(self.label_logo) box_logo.addWidget(title_label) box.addLayout(box_logo) lbl_version = QLabel(self.tr("<b>Versión:</b> {0}").format(ui.__version__)) box.addWidget(lbl_version) http = "http://" lbl_link = QLabel( "<b>Web:</b> <a href='%s'><span style='color: " "#626655;'>%s</span></a>" % (ui.__web__, ui.__web__.replace(http, "")) ) lbl_sc = QLabel( self.tr("<b>Código fuente:</b> <a href='{0}'><span" " style='color: #626655;'>{1}</span></a>").format( ui.__source_code__, ui.__source_code__.replace(http, "") ) ) box.addWidget(lbl_link) box.addWidget(lbl_sc) # License box.addWidget( QLabel( self.tr( "<b>Licencia:</b> <i>Edis</i> se " "distribuye bajo los términos de la " "licencia <b>GPLv3+</b>" ) ) ) box.addWidget(QLabel(self.tr("<b>Autor:</b> {0}").format(ui.__author__))) box.addWidget(QLabel(self.tr("<b>e-mail:</b> {0}").format(ui.__email_author__))) # Thanks to lbl_contributors = QLabel( self.tr( "Agradezco a los que <a href=" "{0}><span style='color: #626655;'>" "contribuyeron</span></a> con Edis" ).format(ui.__contributors__) ) box.addWidget(lbl_contributors) box_boton = QHBoxLayout() box_boton.addSpacerItem(QSpacerItem(0, 10, QSizePolicy.Expanding)) btn_ok = QPushButton(self.tr("Aceptar")) box_boton.addWidget(btn_ok) box.addLayout(box_boton) # Conexiones btn_ok.clicked.connect(self.close) lbl_link.linkActivated["QString"].connect(self._open_link) lbl_sc.linkActivated["QString"].connect(self._open_link) lbl_contributors.linkActivated["QString"].connect(self._open_link) self.label_logo.installEventFilter(self) def _open_link(self, link): webbrowser.open_new(link) def eventFilter(self, obj, event): if obj == self.label_logo and event.type() == QEvent.MouseButtonPress: self.clicks += 1 if self.clicks == 6: self.close() editor_container = Edis.get_component("principal") editor_container.show_snake() return False
class MuWizard(QWizard): def __init__(self, R=None, parent=None): QWizard.__init__(self, parent) self.R = R self.data = None self.addPage(self.introPage()) self.addPage(self.loadPage()) self.addPage(self.modelsPage()) self.addPage(self.resultsPage()) self.setWindowTitle('Wizard of muScale') self.setPixmap(QWizard.LogoPixmap, QPixmap(RES + ICONS + LOGO)) self.setStyleSheet('QWizard {' + GRADIENT +'}\ QPushButton {\ color: #333;\ border: 1px solid #555;\ border-radius: 11px;\ padding: 2px;\ background: qradialgradient(cx: 0.3, cy: -0.4,\ fx: 0.3, fy: -0.4,\ radius: 1.35, stop: 0 #fff, stop: 1 #888);\ min-width: 80px;}\ QPushButton:hover {\ color: #fff;\ background: qradialgradient(cx: 0.3, cy: -0.4,\ fx: 0.3, fy: -0.4,\ radius: 1.35, stop: 0 #fff, stop: 1 #bbb);}\ QPushButton:pressed {\ color: #800;\ background: qradialgradient(cx: 0.4, cy: -0.1,\ fx: 0.4, fy: -0.1,\ radius: 1.35, stop: 0 #fff, stop: 1 #ddd);}\ QPushButton:checked {\ background: qradialgradient(cx: 0.4, cy: -0.1,\ fx: 0.4, fy: -0.1,\ radius: 1.35, stop: 0 #fff, stop: 1 #ddd);}\ QComboBox {\ color: #333;\ border: 1px solid #555;\ border-radius: 11px;\ padding: 1px 18px 1px 3px;\ background: qradialgradient(cx: 0.3, cy: -0.4,\ fx: 0.3, fy: -0.4,\ radius: 1.35, stop: 0 #fff, stop: 1 #888);\ min-width: 20px;}\ QComboBox:hover {\ color: #fff;\ background: qradialgradient(cx: 0.3, cy: -0.4,\ fx: 0.3, fy: -0.4,\ radius: 1.35, stop: 0 #fff, stop: 1 #bbb);}\ QComboBox::down-arrow {\ image: url(' + RES + ICONS + ARROW_DOWN + ');}\ QComboBox::down-arrow:on {\ top: 1px;\ left: 1px;}\ QComboBox::drop-down {\ subcontrol-origin: padding;\ subcontrol-position: top right;\ width: 15px;\ border-left-width: 1px;\ border-left-color: darkgray;\ border-left-style: solid;\ border-top-right-radius: 3px;\ border-bottom-right-radius: 3px;}\ QToolButton {\ color: #333;\ border: 1px solid #555;\ border-radius: 11px;\ padding: 2px;\ background: qradialgradient(cx: 0.3, cy: -0.4,\ fx: 0.3, fy: -0.4,\ radius: 1.35, stop: 0 #fff, stop: 1 #888);\ min-width: 20px;}\ QToolButton:hover {\ color: #fff;\ background: qradialgradient(cx: 0.3, cy: -0.4,\ fx: 0.3, fy: -0.4,\ radius: 1.35, stop: 0 #fff, stop: 1 #bbb);}\ QToolButton:pressed {\ background: qradialgradient(cx: 0.4, cy: -0.1,\ fx: 0.4, fy: -0.1,\ radius: 1.35, stop: 0 #fff, stop: 1 #ddd);}\ QToolButton:checked {\ background: qradialgradient(cx: 0.4, cy: -0.1,\ fx: 0.4, fy: -0.1,\ radius: 1.35, stop: 0 #fff, stop: 1 #ddd);}') def introPage(self): intro = QWizardPage() intro.setTitle('Hello and welcome') label = QLabel('''This is a wizard. Now you're ready to forecast some time series! ''') label.setWordWrap(True) layout = QVBoxLayout() layout.addWidget(label) intro.setLayout(layout) return intro def loadPage(self): load = WizardPageEx('loadCheck') load.setTitle('Initial data') pathLbl = QLabel("<font style='color: gray'>Specify the file with time series to forecast:</font>") loadLbl = QLabel("<font style='color: gray'>Click</font>") loadLbl.setAlignment(Qt.AlignCenter) self.path = QLineEdit() self.path.setPlaceholderText('path to file') getPath = QToolButton() getPath.setText('...') self.resultLbl = QLabel() self.resultLbl.setAlignment(Qt.AlignCenter) self.resultLbl.hide() self.preview = QLabel() self.preview.setAlignment(Qt.AlignCenter) self.preview.setWordWrap(True) self.preview.hide() self.preview.setAttribute(Qt.WA_Hover) self.filter = Filter() self.preview.installEventFilter(self.filter) getPath.clicked.connect(self.loadData) layout = QGridLayout() layout.addWidget(pathLbl, 0, 0) layout.addWidget(loadLbl, 0, 1) layout.addWidget(self.path, 1, 0) layout.addWidget(getPath, 1, 1) layout.addWidget(self.resultLbl, 2, 0, 1, 2) layout.addWidget(self.preview, 3, 0, 1, 2) load.setLayout(layout) load.previewSeries = SeriesPreview() self.previewSeries = load.previewSeries # to be able to reference from class namespace self.loadCheck = load.check return load def modelsPage(self): models = WizardPageEx('modelCheck') models.setTitle('Forecast') lbl = QLabel("<font style='color: gray'>Forecast horizon:</font>") self.steps = QSpinBox() self.steps.setRange(MIN_FORECAST, MAX_FORECAST) self.steps.setValue(10) self.start = QPushButton('Forecast') self.start.clicked.connect(self.modelling) self.custom = QPushButton('Advanced') self.processing = QLabel() self.gifLoading = QMovie(RES + ICONS + PROGRESS, QByteArray(), self) self.gifLoading.setCacheMode(QMovie.CacheAll) self.gifLoading.setSpeed(100) self.processing.setMovie(self.gifLoading) self.processing.setAlignment(Qt.AlignCenter) self.processing.hide() self.status = QLabel() self.status.setAlignment(Qt.AlignCenter) self.status.hide() layout = QGridLayout() layout.addWidget(lbl, 0, 0) layout.addWidget(self.steps, 0, 1) layout.addWidget(self.start, 0, 2) layout.addWidget(self.custom, 0, 3) layout.addWidget(self.status, 1, 0, 1, 4) layout.addWidget(self.processing, 2, 0, 1, 4) models.setLayout(layout) self.customOpt = CustomOption() self.custom.clicked.connect(self.customOpt.show) self.modelCheck = models.check return models def resultsPage(self): results = QWizardPage() results.setFinalPage(True) results.setTitle('Results') self.graph = QLabel("<font style='font-size: 16px;'>Plot</font>") self.export = QLabel("<font style='font-size: 16px;'>Export</font>") self.showData = QLabel("<font style='font-size: 16px;'>Data</font>") self.plotResult = MplWidget(None) self.plotResult.canvas.fig.set_facecolor('white') self.resData = QLabel('') self.resData.setAlignment(Qt.AlignCenter) self.resData.setWordWrap(True) self.resData.hide() self.resFilter = ResFilter() self.resLayout = QVBoxLayout() self.resLayout.addWidget(self.export) self.resLayout.addWidget(self.graph) self.resLayout.addWidget(self.showData) self.resLayout.addWidget(self.plotResult) self.resLayout.addWidget(self.resData) self.plotResult.hide() for index in range(0, self.resLayout.count()): try: self.resLayout.itemAt(index).widget().setAlignment(Qt.AlignCenter) self.resLayout.itemAt(index).widget().setStyleSheet('QLabel { color: gray; }') self.resLayout.itemAt(index).widget().setAttribute(Qt.WA_Hover) self.resLayout.itemAt(index).widget().installEventFilter(self.resFilter) except Exception: pass self.resLayout.setAlignment(Qt.AlignCenter) self.resLayout.setSpacing(60) results.setLayout(self.resLayout) return results #---- actions ----# def loadData(self): fileName = unicode(QFileDialog.getOpenFileName(self, 'Open text file', RES)) if fileName: self.resultLbl.hide() self.preview.hide() if DataParser.istextfile(fileName): self.data = DataParser.getTimeSeriesFromTextData(data=open(fileName, 'r').read()) if len(self.data[0]) > DATA_LOW_LIMIT: self.resultLbl.setText("<font style='color: gray'>Success! Loaded<b> " + str(len(self.data[0])) + '</b> values, errors: <b>' + str( self.data[1]) + '</b></font>') self.resultLbl.show() self.path.setText(fileName) previewLength = 40 self.preview.setText("<font style='color: gray'><b>Preview:</b> "+ ' '.join( [str(e) for e in self.data[0][:previewLength]]) + "...</font>") self.previewSeries.updateData(self.data) self.preview.show() self.loadCheck.setChecked(True) else: self.resultLbl.setText("<font style='color: gray'>Not enough values to form data series.</font>") self.resultLbl.show() else: self.resultLbl.setText("<font style='color: gray'>Specified file is binary file!</font>") self.resultLbl.show() def modelling(self): self.processing.show() self.gifLoading.start() self.status.setText('') statusText = u"<font style='color: gray'>" # decomposition # if self.customOpt.options['enable']: self.signalEx = self.customOpt.options['signal'] self.wavelet = pywt.Wavelet(self.customOpt.options['wavelet']) wLevel = self.customOpt.options['lvls'] - 1 maxLevel = pywt.dwt_max_level(len(self.data[0]), self.wavelet) if wLevel > maxLevel: wLevel = maxLevel self.wInitialCoefficients = pywt.wavedec(self.data[0], self.wavelet, level=wLevel, mode=self.signalEx) self.wCoefficients = self.wInitialCoefficients else: self.signalEx = pywt.MODES.sp1 selected = select_wavelet(self.data[0], self.R) index = max(selected) self.wavelet = pywt.Wavelet(selected[index][1]) wLevel = calculate_suitable_lvl(self.data[0], self.wavelet, self.R, swt=False) self.wInitialCoefficients = pywt.wavedec(self.data[0], self.wavelet, level=wLevel, mode=self.signalEx) self.wCoefficients = self.wInitialCoefficients statusText += 'Wavelet: <b>' + self.wavelet.family_name + \ '</b> (' + self.wavelet.name + ', ' + self.wavelet.symmetry + ', orthogonal: ' + \ str(self.wavelet.orthogonal) + ')<br/>' statusText += 'Discrete Wavelet Transfom: <b>' + str(wLevel + 1) + ' levels</b><br/>' # models # options = {} options['multi'] = True options['fractal'] = False options['ljung'] = False self.models = auto_model(self.wCoefficients, self.R, options, self.data[0]) statusText += '<br/>Selected models:<br/>' for lvl, model in self.models.iteritems(): statusText += str(lvl) + '. <b>' + model.enumname.replace('_', ' ') + '</b><br/>' # forecasting # try: frequency = self.customOpt.options['frequency'] except Exception: frequency = 8 aic = False options['hw_gamma'] = True options['hw_model'] = 'additive' options['hw_period'] = frequency options['ar_aic'] = aic options['ar_method'] = 'burg' options['ar_order'] = 50 options['arima_auto'] = False options['arima_nons'] = True options['arima_nons_order'] = [6, 0, 9] options['arima_seas'] = True options['arima_seas_order'] = [9, 0, 1] options['lsf_aic'] = aic options['lsf_order'] = 30 options['ets_auto'] = aic options['ets_period'] = frequency options['sts_type'] = 'trend' options['append_fit'] = True self.multi_model_thread = MultiModelThread(self.models, self.wCoefficients, self.R, self.steps.value(), options,) self.multi_model_thread.done.connect(self.multiForecastFinished) self.multi_model_thread.start() statusText += '<br/>Forecasting...' self.status.setText(statusText) self.status.show() def multiForecastFinished(self, results): self.forecast = results self.gifLoading.stop() self.processing.hide() self.status.setText('<br/>'.join(str(self.status.text()).split('<br/>')[:-1]) + '<br/>Forecast complete.') self.modelCheck.setChecked(True) #---- results -----# def togglePlot(self): if self.plotResult.isVisible(): self.plotResult.hide() self.export.show() self.showData.show() self.resLayout.setSpacing(60) else: self.updateGraph() self.plotResult.show() self.export.hide() self.showData.hide() self.resLayout.setSpacing(5) def toggleData(self): if self.resData.isVisible(): self.export.show() self.graph.show() self.showData.show() self.resData.hide() self.resLayout.setSpacing(60) self.adjustSize() else: self.plotResult.hide() self.graph.hide() self.export.hide() self.showData.show() self.resData.show() self.resLayout.setSpacing(5) res = self.inverseWT() max = len(self.data[0]) - 1 resText = '<table border="0" align="center" style="border-style: groove;">' resText += '<tr><td align="center"><i>Initial</i></td><td align="center"><i>Forecast</i></td></tr>' resText += '<tr><td align="center">...</td><td></td></tr>' table = zip(self.data[0][max-10:max], res[max-10:max]) for i, j in table: resText += '<tr>' resText += '<td align="center">' + str(i) + '</td>' resText += '<td align="center">' + str(j) + '</td>' resText += '</tr>' for e in res[max+1:max+10]: resText += '<tr>' resText += '<td align="center"></td>' resText += '<td align="center">' + str(e) + '</td>' resText += '</tr>' resText += '<tr><td align="center"></td><td align="center">...</td></tr>' resText += '</table>' self.resData.setText(resText) self.adjustSize() def inverseWT(self): return pywt.waverec(update_dwt([e [1] for e in self.forecast], self.wavelet, self.signalEx), self.wavelet, mode=self.signalEx) def updateGraph(self): self.plotResult.updatePlot(self.inverseWT(), label='Simulation', color='r') self.plotResult.updatePlot(self.data[0], label='Time series', color='b') def exportToXls(self): # opening file dialog fileName = QFileDialog.getSaveFileName(self, 'Save as', RES, 'Microsoft Excel Spreadsheet (*.xls)') if fileName.count() > 0: try: COLUMN_WIDTH = 3000 alignment = Alignment() alignment.horizontal = Alignment.HORZ_CENTER alignment.vertical = Alignment.VERT_CENTER borders = Borders() borders.left = Borders.THIN borders.right = Borders.THIN borders.top = Borders.THIN borders.bottom = Borders.THIN style = XFStyle() style.alignment = alignment style.borders = borders font = Font() font.bold = True headerStyle = XFStyle() headerStyle.font = font separate = Borders() separate.left = Borders.THIN separate.right = Borders.DOUBLE separate.top = Borders.THIN separate.bottom = Borders.THIN separateStyle = XFStyle() separateStyle.borders = separate book = Workbook(encoding='utf-8') # modelling data dec_sheet = book.add_sheet('Data decomposition') # decomposition data # initial data column = 0 row = 0 dec_sheet.write(row, column, 'Time series', headerStyle) dec_sheet.col(column).width = COLUMN_WIDTH row += 1 for item in self.data[0]: dec_sheet.write(row, column, item, separateStyle) row += 1 # decomposition for lvl in self.wCoefficients: row = 0 column += 1 dec_sheet.write(row, column, 'Level' + str(column - 1), headerStyle) dec_sheet.col(column).width = COLUMN_WIDTH row += 1 for item in lvl: dec_sheet.write(row, column, item, style) row += 1 # decomposition graphs pass levels_sheet = book.add_sheet('Multiscale forecast') # levels data column = 0 for lvl in self.forecast: row = 0 levels_sheet.write(row, column, 'Level' + str(column), headerStyle) levels_sheet.col(column).width = COLUMN_WIDTH row += 1 for item in lvl[1]: levels_sheet.write(row, column, float(item), style) row += 1 column += 1 result_sheet = book.add_sheet('Results') # initial column = 0 row = 0 result_sheet.write(row, column, 'Initial data', headerStyle) result_sheet.col(column).width = COLUMN_WIDTH row += 1 for item in self.data[0]: result_sheet.write(row, column, item, separateStyle) row += 1 # forecast row = 0 column += 1 result_sheet.write(row, column, 'Forecast', headerStyle) result_sheet.col(column).width = COLUMN_WIDTH row += 1 for item in self.inverseWT(): result_sheet.write(row, column, item, style) row += 1 row = 0 column = 2 self.updateGraph() self.plotResult.saveFigure('forecast', format='bmp') result_sheet.insert_bitmap(RES + TEMP + 'forecast.bmp', row, column) # saving xls try: book.save(unicode(fileName)) except Exception: pass except Exception, e: pass
class AcercaDe(QDialog): def __init__(self, parent): QDialog.__init__(self, parent, Qt.WindowMinMaxButtonsHint) self.clicks = 0 self.setWindowTitle(self.tr("Acerca de Edis")) self.setMinimumWidth(485) box = QVBoxLayout(self) self.label_logo = QLabel() self.label_logo.setPixmap(QPixmap(":image/edis")) title_label = QLabel( self.tr("<h1>Edis</h1>\n<i>a simple " "cross-platform IDE for C</i>")) title_label.setAlignment(Qt.AlignRight) box_logo = QHBoxLayout() box_logo.addWidget(self.label_logo) box_logo.addWidget(title_label) box.addLayout(box_logo) lbl_version = QLabel( self.tr("<b>Versión:</b> {0}").format(ui.__version__)) box.addWidget(lbl_version) http = "http://" lbl_link = QLabel("<b>Web:</b> <a href='%s'><span style='color: " "#626655;'>%s</span></a>" % (ui.__web__, ui.__web__.replace(http, ""))) lbl_sc = QLabel( self.tr("<b>Código fuente:</b> <a href='{0}'><span" " style='color: #626655;'>{1}</span></a>").format( ui.__source_code__, ui.__source_code__.replace(http, ""))) box.addWidget(lbl_link) box.addWidget(lbl_sc) # License box.addWidget( QLabel( self.tr("<b>Licencia:</b> <i>Edis</i> se " "distribuye bajo los términos de la " "licencia <b>GPLv3+</b>"))) box.addWidget( QLabel(self.tr("<b>Autor:</b> {0}").format(ui.__author__))) box.addWidget( QLabel(self.tr("<b>e-mail:</b> {0}").format(ui.__email_author__))) # Thanks to lbl_contributors = QLabel( self.tr("Agradezco a los que <a href=" "{0}><span style='color: #626655;'>" "contribuyeron</span></a> con Edis").format( ui.__contributors__)) box.addWidget(lbl_contributors) box_boton = QHBoxLayout() box_boton.addSpacerItem(QSpacerItem(0, 10, QSizePolicy.Expanding)) btn_ok = QPushButton(self.tr("Aceptar")) box_boton.addWidget(btn_ok) box.addLayout(box_boton) # Conexiones btn_ok.clicked.connect(self.close) lbl_link.linkActivated['QString'].connect(self._open_link) lbl_sc.linkActivated['QString'].connect(self._open_link) lbl_contributors.linkActivated['QString'].connect(self._open_link) self.label_logo.installEventFilter(self) def _open_link(self, link): webbrowser.open_new(link) def eventFilter(self, obj, event): if obj == self.label_logo and event.type() == QEvent.MouseButtonPress: self.clicks += 1 if self.clicks == 6: self.close() editor_container = Edis.get_component("principal") editor_container.show_snake() return False
class AboutNinja(QDialog): def __init__(self, parent=None): QDialog.__init__(self, parent, Qt.Dialog) self.setWindowTitle(self.tr("About NINJA-IDE")) self.setMaximumSize(QSize(0, 0)) vbox = QVBoxLayout(self) #Create an icon for the Dialog pixmap = QPixmap(resources.IMAGES['icon']) self.lblIcon = QLabel() self.lblIcon.setPixmap(pixmap) hbox = QHBoxLayout() hbox.addWidget(self.lblIcon) lblTitle = QLabel( '<h1>NINJA-IDE</h1>\n<i>Ninja-IDE Is Not Just Another IDE<i>') lblTitle.setTextFormat(Qt.RichText) lblTitle.setAlignment(Qt.AlignLeft) hbox.addWidget(lblTitle) vbox.addLayout(hbox) #Add description vbox.addWidget( QLabel( self.tr( """NINJA-IDE (from: "Ninja Is Not Just Another IDE"), is a cross-platform integrated development environment specially design to build Python Applications. NINJA-IDE provides tools to simplify the Python-software development and handles all kinds of situations thanks to its rich extensibility."""))) vbox.addWidget(QLabel(self.tr("Version: %s") % ninja_ide.__version__)) link_ninja = QLabel( self.tr('Website: <a href="%s"><span style=" ' 'text-decoration: underline; color:#ff9e21;">' '%s</span></a>') % (ninja_ide.__url__, ninja_ide.__url__)) vbox.addWidget(link_ninja) link_source = QLabel( self.tr( 'Source Code: <a href="%s"><span style=" ' 'text-decoration: underline; color:#ff9e21;">%s</span></a>') % (ninja_ide.__source__, ninja_ide.__source__)) vbox.addWidget(link_source) self.connect(link_ninja, SIGNAL("linkActivated(QString)"), self.link_activated) self.connect(link_source, SIGNAL("linkActivated(QString)"), self.link_activated) self.lblIcon.installEventFilter(self) def link_activated(self, link): webbrowser.open(str(link)) def eventFilter(self, obj, event): if obj == self.lblIcon and event.type() == QEvent.MouseButtonPress: self.show_retsae() return False def show_retsae(self): height = main_container.MainContainer().size().height() width = main_container.MainContainer().size().width() tetris = TetrisMainWindow(width, height) main_container.MainContainer().add_tab(tetris, 'Tetris') self.close()
class GUI(QWidget): def __init__(self, parent=None): super(GUI, self).__init__(parent) self.create_ui_components() self.compose_ui() # Initializing: window composition, it's contents and event handlers self.init_composition() self.init_contents() self.init_actions() self.on_start() def create_ui_components(self): """ Create layouts and qt controls. """ self.layout = QGridLayout() self.kanjiGroup = QGroupBox() self.kanjiLayout = QGridLayout() # Kanji ui group self.day, self.week, self.month, self.year = \ QLabel(KANJI), QLabel(KANJI), QLabel(KANJI), QLabel(KANJI) self.dayLabel, self.weekLabel, self.monthLabel, self.yearLabel = \ QLabel('<b>Day</b>'), QLabel('<b>Week</b>'), \ QLabel('<b>Month</b>'), QLabel('<b>Year</b>') # Main layout self.showAbout = QPushButton('A&bout') # DB controls (top) self.showDB, self.availableDB, self.changeDB = \ QPushButton('&Change DB (active:)'), QComboBox(), QPushButton('&Remap') # General controls (bottom) self.getAll, self.showStats, self.quitApp, self.authGen, self.methodCombo = \ QPushButton('&Get all'), QPushButton('&Stats'), QPushButton('&Quit'), \ QPushButton('&Auth'), QComboBox() # Notifications self.progressBar = QProgressBar() self.statusMessage = QLabel() # About self.aboutBox = QMessageBox() def compose_ui(self): """ Fill layouts and groups, initialize filters. """ self.kanjiLayout.addWidget(self.day, 0, 0) self.kanjiLayout.addWidget(self.week, 0, 1) self.kanjiLayout.addWidget(self.dayLabel, 1, 0) self.kanjiLayout.addWidget(self.weekLabel, 1, 1) self.kanjiLayout.addWidget(self.month, 2, 0) self.kanjiLayout.addWidget(self.year, 2, 1) self.kanjiLayout.addWidget(self.monthLabel, 3, 0) self.kanjiLayout.addWidget(self.yearLabel, 3, 1) self.kanjiGroup.setLayout(self.kanjiLayout) self.layout.addWidget(self.showDB, 0, 0, 1, 2) self.layout.addWidget(self.availableDB, 1, 0) self.layout.addWidget(self.changeDB, 1, 1) self.layout.addWidget(self.kanjiGroup, 2, 0, 1, 2) self.layout.addWidget(self.getAll, 3, 0) self.layout.addWidget(self.showStats, 3, 1) self.layout.addWidget(self.methodCombo, 4, 0) self.layout.addWidget(self.authGen, 4, 1) #self.layout.addWidget(self.quitApp, 5, 0, 1, 2) self.layout.addWidget(self.quitApp, 5, 0) self.layout.addWidget(self.showAbout, 5, 1) self.layout.addWidget(self.progressBar, 6, 0, 1, 2) self.layout.addWidget(self.statusMessage, 7, 0, 1, 2) self.setLayout(self.layout) self.eFilter = LabelEventFilter() def on_start(self): """ Additional procedures run on application start. """ # Let's initialize even some stuff! self.al = None self.auth_thread = None self.init_backend() choose_db(str(self.availableDB.currentText())) self.showDB.setText("&Change DB (active: %s)" % self.availableDB.currentText()) self.stats = StatsUI(self.al, self) def init_composition(self): """ Window composition and general params. """ self.setWindowTitle(NAME + ' ' + __version__) desktop = QApplication.desktop() self.setGeometry((desktop.width() - WIDTH)/2, (desktop.height() - HEIGHT)/2, WIDTH, HEIGHT) def init_contents(self): """ Setting up qt controls. """ self.changeDB.hide() self.availableDB.hide() self.availableDB.addItems(dbs.keys()) self.kanjiGroup.setAlignment(Qt.AlignCenter) self.kanjiGroup.setStyleSheet("QGroupBox { border: 1px solid gray; border-radius: 3px; }") self.day.setAlignment(Qt.AlignCenter) self.week.setAlignment(Qt.AlignCenter) self.month.setAlignment(Qt.AlignCenter) self.year.setAlignment(Qt.AlignCenter) self.dayLabel.setAlignment(Qt.AlignCenter) self.weekLabel.setAlignment(Qt.AlignCenter) self.monthLabel.setAlignment(Qt.AlignCenter) self.yearLabel.setAlignment(Qt.AlignCenter) self.day.setFont(QFont(PRETTY_FONT, KANJI_SIZE)) self.week.setFont(QFont(PRETTY_FONT, KANJI_SIZE)) self.month.setFont(QFont(PRETTY_FONT, KANJI_SIZE)) self.year.setFont(QFont(PRETTY_FONT, KANJI_SIZE)) self.methodCombo.addItems(RandomMess.algs.keys()) self.methodCombo.setCurrentIndex(1) self.statusMessage.setAlignment(Qt.AlignCenter) self.statusMessage.hide() self.statusMessage.setMaximumHeight(MESSAGE_HEIGHT) self.statusMessage.setStyleSheet(WARNING_STYLE) self.progressBar.setMaximum(0) self.progressBar.setMaximumHeight(PROGRESS_HEIGHT) self.progressBar.hide() QToolTip.setFont(QFont(PRETTY_FONT, TOOLTIP_FONT_SIZE)) self.getAll.setToolTip('Randomly select all 4 kanji') self.methodCombo.setToolTip('Choose algorithm for randomness') self.authGen.setToolTip('Authorize on remote RNG services') self.showStats.setToolTip('Show/hide dialog with comprehensive statistics') self.quitApp.setToolTip('Close application') self.showDB.setToolTip('Show/hide available databases') self.availableDB.setToolTip('Available kanji frequency charts db') self.changeDB.setToolTip('Pick new kanji from currently selected db') # About dialog self.aboutBox.layout().itemAt(1).widget().setAlignment(Qt.AlignLeft) self.aboutBox.setTextFormat(Qt.RichText) self.aboutBox.setText('Version:\t<b>' + __version__ + '</b><br/>Python:\t<b>' + platform.python_version() + '</b>' + '<br/>Platform:\t<b>' + platform.system() + ' ' + platform.release() + '</b>' + '<br/>Author:\t<b>' + __author__ + '</b>' + app_about) self.aboutBox.setWindowTitle('About ' + app_name) self.aboutBox.setIconPixmap(QPixmap(paths['icon'])) def init_actions(self): """ Binding events/handlers. """ self.showDB.clicked.connect(self.show_available_db) self.changeDB.clicked.connect(self.change_db) self.quitApp.clicked.connect(self.close) self.getAll.clicked.connect(self.get_all) self.authGen.clicked.connect(self.auth_task) self.showStats.clicked.connect(self.show_stats) self.methodCombo.currentIndexChanged.connect(self.update_alg) self.showAbout.clicked.connect(self.app_help) # Mouse events for labels self.day.setAttribute(Qt.WA_Hover, True) self.week.setAttribute(Qt.WA_Hover, True) self.month.setAttribute(Qt.WA_Hover, True) self.year.setAttribute(Qt.WA_Hover, True) self.day.installEventFilter(self.eFilter) self.week.installEventFilter(self.eFilter) self.month.installEventFilter(self.eFilter) self.year.installEventFilter(self.eFilter) ##### actions ##### def show_stats(self): if self.stats.isVisible(): self.stats.hide() else: self.stats.show() def show_available_db(self): if self.availableDB.isVisible(): self.availableDB.hide() self.changeDB.hide() else: self.availableDB.show() self.changeDB.show() def change_db(self): try: choose_db(str(self.availableDB.currentText())) self.availableDB.hide() self.changeDB.hide() self.show_message_then_hide("DB successfully remaped!", False) self.showDB.setText("&Change DB (active: %s)" % self.availableDB.currentText()) self.stats.update_stat_info() self.stats.refresh_plot() except NoDbException as e: self.show_message_then_hide(e.message) def get_all(self): self.random_kanji_task = RandomKanjiTask(self.al) self.random_kanji_task.done.connect(self.update_kanji) self.show_progress('Selecting kanji...') self.random_kanji_task.start() def update_kanji(self, results): if results['success']: kanji_set = results['kanji_set'] for_a_day = kanji_set.pop() for_a_week = kanji_set.pop() for_a_month = kanji_set.pop() for_a_year = kanji_set.pop() self.day.setText(for_a_day.character) self.dayLabel.setText('<b>Day:</b> ' + str(for_a_day.frequency) + ' | ' + str(for_a_day.dominance) + '%') self.week.setText(for_a_week.character) self.weekLabel.setText('<b>Week:</b> ' + str(for_a_week.frequency) + ' | ' + str(for_a_week.dominance) + '%') self.month.setText(for_a_month.character) self.monthLabel.setText('<b>Month:</b> ' + str(for_a_month.frequency) + ' | ' + str(for_a_month.dominance) + '%') self.year.setText(for_a_year.character) self.yearLabel.setText('<b>Year:</b> ' + str(for_a_year.frequency) + ' | ' + str(for_a_year.dominance) + '%') self.kanji_tooltip(self.day) self.kanji_tooltip(self.week) self.kanji_tooltip(self.month) self.kanji_tooltip(self.year) if self.stats.isVisible(): self.stats.update_stat_info() self.stats.refresh_plot() self.hide_message() else: self.show_message_then_hide(results['message']) self.hide_progress() def pretty_font(self): pass def update_alg(self): self.al.set_active(str(self.methodCombo.currentText())) def init_backend(self): self.al = RandomMess() self.update_alg() def auth_task(self): self.auth_thread = AuthorizationTask(self.al) self.auth_thread.done.connect(self.auth_complete) #self.auth_thread.run() # IT DOESN't work on windows as it should! self.auth_thread.start() self.show_progress('Authorizing on RNG services...') def auth_complete(self, success): self.hide_message() self.hide_progress() if success: self.show_message_then_hide("Successfully authenticated!", False) else: self.show_message_then_hide("Sorry, could not authenticate.") def show_message_then_hide(self, message, error=True): if error: self.statusMessage.setStyleSheet(WARNING_STYLE) else: self.statusMessage.setStyleSheet(NOTE_STYLE) self.statusMessage.setText(message) self.statusMessage.show() QTimer.singleShot(MESSAGE_TIMEOUT, self.hide_message) def show_progress(self, message): self.statusMessage.setStyleSheet(NOTE_STYLE) self.statusMessage.setText(message) self.statusMessage.show() self.progressBar.show() def hide_message(self): self.statusMessage.setText('') self.statusMessage.hide() def hide_progress(self): self.progressBar.hide() def toggle_kanji_info(self, label, info): label.setToolTip(info.info()) def kanji_tooltip(self, label): found = JDIC.search(label.text()) if found: label.setToolTip(found.info()) else: label.setToolTip('No such kanji in kanjidic2!') def kanji_info(self, kanji): pass def app_help(self): self.aboutBox.show() #### Utility events #### def resizeEvent(self, QResizeEvent): self.updateStatsPosition() self.updateStatsSize() def moveEvent(self, QMoveEvent): self.updateStatsPosition() self.updateStatsSize() def updateStatsPosition(self): self.stats.move(self.x() + self.width() + 20, self.y()) def updateStatsSize(self): self.stats.resize(QSize(self.stats.width(), self.height()))
class XPushButton(QPushButton): def __init__(self, *args, **kwds): super(XPushButton, self).__init__(*args, **kwds) # sets whether or not this button will display rich text self._showRichText = False self._richTextLabel = None self._text = '' def eventFilter(self, object, event): """ Ignore all events for the text label. :param object | <QObject> event | <QEvent> """ if object == self._richTextLabel: if event.type() in (event.MouseButtonPress, event.MouseMove, event.MouseButtonRelease, event.MouseButtonDblClick): event.ignore() return True return False def resizeEvent(self, event): """ Overloads the resize event to auto-resize the rich text label to the size of this QPushButton. :param event | <QResizeEvent> """ super(XPushButton, self).resizeEvent(event) if self._richTextLabel: self._richTextLabel.resize(event.size()) def richTextLabel(self): """ Returns the label that is used for drawing the rich text to this button. :return <QLabel> """ if not self._richTextLabel: self._richTextLabel = QLabel(self) self._richTextLabel.installEventFilter(self) self._richTextLabel.setMargin(10) return self._richTextLabel def setShowRichText(self, state): """ Sets whether or not to display rich text for this button. :param state | <bool> """ self._showRichText = state text = self.text() if state: label = self.richTextLabel() label.setText(text) label.show() super(XPushButton, self).setText('') else: if self._richTextLabel: self._richTextLabel.hide() super(XPushButton, self).setText(text) def setText(self, text): """ Sets the text for this button. If it is set to show rich text, then it will update the label text, leaving the root button text blank, otherwise it will update the button. :param text | <str> """ self._text = str(text) if self.showRichText(): self.richTextLabel().setText(text) else: super(XPushButton, self).setText(text) def showRichText(self): """ Returns whether or not rich text is visible for this button. :return <bool> """ return self._showRichText def text(self): """ Returns the source text for this button. :return <str> """ return self._text x_showRichText = qt.Property(bool, showRichText, setShowRichText)
class GUI(QWidget): def __init__(self, parent=None): super(GUI, self).__init__(parent) self.create_ui_components() self.compose_ui() # Initializing: window composition, it's contents and event handlers self.init_composition() self.init_contents() self.init_actions() self.on_start() def create_ui_components(self): """ Create layouts and qt controls. """ self.layout = QGridLayout() self.kanjiGroup = QGroupBox() self.kanjiLayout = QGridLayout() # Kanji ui group self.day, self.week, self.month, self.year = \ QLabel(KANJI), QLabel(KANJI), QLabel(KANJI), QLabel(KANJI) self.dayLabel, self.weekLabel, self.monthLabel, self.yearLabel = \ QLabel('<b>Day</b>'), QLabel('<b>Week</b>'), \ QLabel('<b>Month</b>'), QLabel('<b>Year</b>') # Main layout self.showAbout = QPushButton('A&bout') # DB controls (top) self.showDB, self.availableDB, self.changeDB = \ QPushButton('&Change DB (active:)'), QComboBox(), QPushButton('&Remap') # General controls (bottom) self.getAll, self.showStats, self.quitApp, self.authGen, self.methodCombo = \ QPushButton('&Get all'), QPushButton('&Stats'), QPushButton('&Quit'), \ QPushButton('&Auth'), QComboBox() # Notifications self.progressBar = QProgressBar() self.statusMessage = QLabel() # About self.aboutBox = QMessageBox() def compose_ui(self): """ Fill layouts and groups, initialize filters. """ self.kanjiLayout.addWidget(self.day, 0, 0) self.kanjiLayout.addWidget(self.week, 0, 1) self.kanjiLayout.addWidget(self.dayLabel, 1, 0) self.kanjiLayout.addWidget(self.weekLabel, 1, 1) self.kanjiLayout.addWidget(self.month, 2, 0) self.kanjiLayout.addWidget(self.year, 2, 1) self.kanjiLayout.addWidget(self.monthLabel, 3, 0) self.kanjiLayout.addWidget(self.yearLabel, 3, 1) self.kanjiGroup.setLayout(self.kanjiLayout) self.layout.addWidget(self.showDB, 0, 0, 1, 2) self.layout.addWidget(self.availableDB, 1, 0) self.layout.addWidget(self.changeDB, 1, 1) self.layout.addWidget(self.kanjiGroup, 2, 0, 1, 2) self.layout.addWidget(self.getAll, 3, 0) self.layout.addWidget(self.showStats, 3, 1) self.layout.addWidget(self.methodCombo, 4, 0) self.layout.addWidget(self.authGen, 4, 1) #self.layout.addWidget(self.quitApp, 5, 0, 1, 2) self.layout.addWidget(self.quitApp, 5, 0) self.layout.addWidget(self.showAbout, 5, 1) self.layout.addWidget(self.progressBar, 6, 0, 1, 2) self.layout.addWidget(self.statusMessage, 7, 0, 1, 2) self.setLayout(self.layout) self.eFilter = LabelEventFilter() def on_start(self): """ Additional procedures run on application start. """ # Let's initialize even some stuff! self.al = None self.auth_thread = None self.init_backend() choose_db(str(self.availableDB.currentText())) self.showDB.setText("&Change DB (active: %s)" % self.availableDB.currentText()) self.stats = StatsUI(self.al, self) def init_composition(self): """ Window composition and general params. """ self.setWindowTitle(NAME + ' ' + __version__) desktop = QApplication.desktop() self.setGeometry((desktop.width() - WIDTH) / 2, (desktop.height() - HEIGHT) / 2, WIDTH, HEIGHT) def init_contents(self): """ Setting up qt controls. """ self.changeDB.hide() self.availableDB.hide() self.availableDB.addItems(dbs.keys()) self.kanjiGroup.setAlignment(Qt.AlignCenter) self.kanjiGroup.setStyleSheet( "QGroupBox { border: 1px solid gray; border-radius: 3px; }") self.day.setAlignment(Qt.AlignCenter) self.week.setAlignment(Qt.AlignCenter) self.month.setAlignment(Qt.AlignCenter) self.year.setAlignment(Qt.AlignCenter) self.dayLabel.setAlignment(Qt.AlignCenter) self.weekLabel.setAlignment(Qt.AlignCenter) self.monthLabel.setAlignment(Qt.AlignCenter) self.yearLabel.setAlignment(Qt.AlignCenter) self.day.setFont(QFont(PRETTY_FONT, KANJI_SIZE)) self.week.setFont(QFont(PRETTY_FONT, KANJI_SIZE)) self.month.setFont(QFont(PRETTY_FONT, KANJI_SIZE)) self.year.setFont(QFont(PRETTY_FONT, KANJI_SIZE)) self.methodCombo.addItems(RandomMess.algs.keys()) self.methodCombo.setCurrentIndex(1) self.statusMessage.setAlignment(Qt.AlignCenter) self.statusMessage.hide() self.statusMessage.setMaximumHeight(MESSAGE_HEIGHT) self.statusMessage.setStyleSheet(WARNING_STYLE) self.progressBar.setMaximum(0) self.progressBar.setMaximumHeight(PROGRESS_HEIGHT) self.progressBar.hide() QToolTip.setFont(QFont(PRETTY_FONT, TOOLTIP_FONT_SIZE)) self.getAll.setToolTip('Randomly select all 4 kanji') self.methodCombo.setToolTip('Choose algorithm for randomness') self.authGen.setToolTip('Authorize on remote RNG services') self.showStats.setToolTip( 'Show/hide dialog with comprehensive statistics') self.quitApp.setToolTip('Close application') self.showDB.setToolTip('Show/hide available databases') self.availableDB.setToolTip('Available kanji frequency charts db') self.changeDB.setToolTip('Pick new kanji from currently selected db') # About dialog self.aboutBox.layout().itemAt(1).widget().setAlignment(Qt.AlignLeft) self.aboutBox.setTextFormat(Qt.RichText) self.aboutBox.setText('Version:\t<b>' + __version__ + '</b><br/>Python:\t<b>' + platform.python_version() + '</b>' + '<br/>Platform:\t<b>' + platform.system() + ' ' + platform.release() + '</b>' + '<br/>Author:\t<b>' + __author__ + '</b>' + app_about) self.aboutBox.setWindowTitle('About ' + app_name) self.aboutBox.setIconPixmap(QPixmap(paths['icon'])) def init_actions(self): """ Binding events/handlers. """ self.showDB.clicked.connect(self.show_available_db) self.changeDB.clicked.connect(self.change_db) self.quitApp.clicked.connect(self.close) self.getAll.clicked.connect(self.get_all) self.authGen.clicked.connect(self.auth_task) self.showStats.clicked.connect(self.show_stats) self.methodCombo.currentIndexChanged.connect(self.update_alg) self.showAbout.clicked.connect(self.app_help) # Mouse events for labels self.day.setAttribute(Qt.WA_Hover, True) self.week.setAttribute(Qt.WA_Hover, True) self.month.setAttribute(Qt.WA_Hover, True) self.year.setAttribute(Qt.WA_Hover, True) self.day.installEventFilter(self.eFilter) self.week.installEventFilter(self.eFilter) self.month.installEventFilter(self.eFilter) self.year.installEventFilter(self.eFilter) ##### actions ##### def show_stats(self): if self.stats.isVisible(): self.stats.hide() else: self.stats.show() def show_available_db(self): if self.availableDB.isVisible(): self.availableDB.hide() self.changeDB.hide() else: self.availableDB.show() self.changeDB.show() def change_db(self): try: choose_db(str(self.availableDB.currentText())) self.availableDB.hide() self.changeDB.hide() self.show_message_then_hide("DB successfully remaped!", False) self.showDB.setText("&Change DB (active: %s)" % self.availableDB.currentText()) self.stats.update_stat_info() self.stats.refresh_plot() except NoDbException as e: self.show_message_then_hide(e.message) def get_all(self): self.random_kanji_task = RandomKanjiTask(self.al) self.random_kanji_task.done.connect(self.update_kanji) self.show_progress('Selecting kanji...') self.random_kanji_task.start() def update_kanji(self, results): if results['success']: kanji_set = results['kanji_set'] for_a_day = kanji_set.pop() for_a_week = kanji_set.pop() for_a_month = kanji_set.pop() for_a_year = kanji_set.pop() self.day.setText(for_a_day.character) self.dayLabel.setText('<b>Day:</b> ' + str(for_a_day.frequency) + ' | ' + str(for_a_day.dominance) + '%') self.week.setText(for_a_week.character) self.weekLabel.setText('<b>Week:</b> ' + str(for_a_week.frequency) + ' | ' + str(for_a_week.dominance) + '%') self.month.setText(for_a_month.character) self.monthLabel.setText('<b>Month:</b> ' + str(for_a_month.frequency) + ' | ' + str(for_a_month.dominance) + '%') self.year.setText(for_a_year.character) self.yearLabel.setText('<b>Year:</b> ' + str(for_a_year.frequency) + ' | ' + str(for_a_year.dominance) + '%') self.kanji_tooltip(self.day) self.kanji_tooltip(self.week) self.kanji_tooltip(self.month) self.kanji_tooltip(self.year) if self.stats.isVisible(): self.stats.update_stat_info() self.stats.refresh_plot() self.hide_message() else: self.show_message_then_hide(results['message']) self.hide_progress() def pretty_font(self): pass def update_alg(self): self.al.set_active(str(self.methodCombo.currentText())) def init_backend(self): self.al = RandomMess() self.update_alg() def auth_task(self): self.auth_thread = AuthorizationTask(self.al) self.auth_thread.done.connect(self.auth_complete) #self.auth_thread.run() # IT DOESN't work on windows as it should! self.auth_thread.start() self.show_progress('Authorizing on RNG services...') def auth_complete(self, success): self.hide_message() self.hide_progress() if success: self.show_message_then_hide("Successfully authenticated!", False) else: self.show_message_then_hide("Sorry, could not authenticate.") def show_message_then_hide(self, message, error=True): if error: self.statusMessage.setStyleSheet(WARNING_STYLE) else: self.statusMessage.setStyleSheet(NOTE_STYLE) self.statusMessage.setText(message) self.statusMessage.show() QTimer.singleShot(MESSAGE_TIMEOUT, self.hide_message) def show_progress(self, message): self.statusMessage.setStyleSheet(NOTE_STYLE) self.statusMessage.setText(message) self.statusMessage.show() self.progressBar.show() def hide_message(self): self.statusMessage.setText('') self.statusMessage.hide() def hide_progress(self): self.progressBar.hide() def toggle_kanji_info(self, label, info): label.setToolTip(info.info()) def kanji_tooltip(self, label): found = JDIC.search(label.text()) if found: label.setToolTip(found.info()) else: label.setToolTip('No such kanji in kanjidic2!') def kanji_info(self, kanji): pass def app_help(self): self.aboutBox.show() #### Utility events #### def resizeEvent(self, QResizeEvent): self.updateStatsPosition() self.updateStatsSize() def moveEvent(self, QMoveEvent): self.updateStatsPosition() self.updateStatsSize() def updateStatsPosition(self): self.stats.move(self.x() + self.width() + 20, self.y()) def updateStatsSize(self): self.stats.resize(QSize(self.stats.width(), self.height()))