class Window(QWidget): def __init__(self): super().__init__() # Make widgets ################# self.edit1 = QDateEdit() self.edit2 = QDateEdit() self.edit3 = QDateEdit() self.edit1.setMinimumDate(datetime.date(year=2017, month=9, day=1)) self.edit2.setMinimumDate(datetime.date(year=2017, month=9, day=1)) self.edit3.setMinimumDate(datetime.date(year=2017, month=9, day=1)) self.edit1.setMaximumDate(datetime.date(year=2020, month=9, day=1)) self.edit2.setMaximumDate(datetime.date(year=2020, month=9, day=1)) self.edit3.setMaximumDate(datetime.date(year=2020, month=9, day=1)) self.edit1.setDate(datetime.datetime.now().date()) self.edit2.setDate(datetime.datetime.now().date()) self.edit3.setDate(datetime.datetime.now().date()) self.edit1.setCalendarPopup(True) self.edit2.setCalendarPopup(True) self.edit3.setCalendarPopup(True) # Format: see http://doc.qt.io/qt-5/qdatetime.html#toString-2 self.edit1.setDisplayFormat("yyyy-MM-dd") self.edit2.setDisplayFormat("dd/MM/yyyy") self.edit3.setDisplayFormat("dddd d MMMM yyyy") self.btn = QPushButton("Print") # Set button slot ############## self.btn.clicked.connect(self.printText) # Set the layout ############### vbox = QVBoxLayout() vbox.addWidget(self.edit1) vbox.addWidget(self.edit2) vbox.addWidget(self.edit3) vbox.addWidget(self.btn) self.setLayout(vbox) def printText(self): print(self.edit1.text()) print(self.edit2.text()) print(self.edit3.text())
class HydroprintGUI(myqt.DialogWindow): ConsoleSignal = QSignal(str) def __init__(self, datamanager, parent=None): super(HydroprintGUI, self).__init__(parent, maximize=True) self.__updateUI = True # Child widgets: self.dmngr = datamanager self.dmngr.wldsetChanged.connect(self.wldset_changed) self.dmngr.wxdsetChanged.connect(self.wxdset_changed) self.page_setup_win = PageSetupWin(self) self.page_setup_win.newPageSetupSent.connect(self.layout_changed) self.color_palette_win = ColorsSetupWin(self) self.color_palette_win.newColorSetupSent.connect(self.update_colors) # Memory path variable: self.save_fig_dir = self.workdir # Generate UI: self.__initUI__() def __initUI__(self): # ---- Toolbar self.btn_save = btn_save = QToolButtonNormal(icons.get_icon('save')) btn_save.setToolTip('Save the well hydrograph') # btn_draw is usefull for debugging purposes btn_draw = QToolButtonNormal(icons.get_icon('refresh')) btn_draw.setToolTip('Force a refresh of the well hydrograph') btn_draw.hide() self.btn_load_layout = QToolButtonNormal( icons.get_icon('load_graph_config')) self.btn_load_layout.setToolTip( "<p>Load graph layout for the current water level " " datafile if it exists</p>") self.btn_load_layout.clicked.connect(self.load_layout_isClicked) self.btn_save_layout = QToolButtonNormal( icons.get_icon('save_graph_config')) self.btn_save_layout.setToolTip('Save current graph layout') self.btn_save_layout.clicked.connect(self.save_layout_isClicked) btn_bestfit_waterlvl = QToolButtonNormal(icons.get_icon('fit_y')) btn_bestfit_waterlvl.setToolTip('Best fit the water level scale') btn_bestfit_time = QToolButtonNormal(icons.get_icon('fit_x')) btn_bestfit_time.setToolTip('Best fit the time scale') self.btn_page_setup = QToolButtonNormal(icons.get_icon('page_setup')) self.btn_page_setup.setToolTip('Show the page setup window') self.btn_page_setup.clicked.connect(self.page_setup_win.show) btn_color_pick = QToolButtonNormal(icons.get_icon('color_picker')) btn_color_pick.setToolTip('<p>Show a window to setup the color palette' ' used to draw the hydrograph</p.') btn_color_pick.clicked.connect(self.color_palette_win.show) self.btn_language = LangToolButton() self.btn_language.setToolTip( "Set the language of the text shown in the graph.") self.btn_language.sig_lang_changed.connect(self.layout_changed) self.btn_language.setIconSize(icons.get_iconsize('normal')) # ---- Zoom Panel btn_zoom_out = QToolButtonSmall(icons.get_icon('zoom_out')) btn_zoom_out.setToolTip('Zoom out (ctrl + mouse-wheel-down)') btn_zoom_out.clicked.connect(self.zoom_out) btn_zoom_in = QToolButtonSmall(icons.get_icon('zoom_in')) btn_zoom_in.setToolTip('Zoom in (ctrl + mouse-wheel-up)') btn_zoom_in.clicked.connect(self.zoom_in) self.zoom_disp = QSpinBox() self.zoom_disp.setAlignment(Qt.AlignCenter) self.zoom_disp.setButtonSymbols(QAbstractSpinBox.NoButtons) self.zoom_disp.setReadOnly(True) self.zoom_disp.setSuffix(' %') self.zoom_disp.setRange(0, 9999) self.zoom_disp.setValue(100) zoom_pan = myqt.QFrameLayout() zoom_pan.setSpacing(3) zoom_pan.addWidget(btn_zoom_out, 0, 0) zoom_pan.addWidget(btn_zoom_in, 0, 1) zoom_pan.addWidget(self.zoom_disp, 0, 2) # LAYOUT : btn_list = [btn_save, btn_draw, self.btn_load_layout, self.btn_save_layout, VSep(), btn_bestfit_waterlvl, btn_bestfit_time, VSep(), self.btn_page_setup, btn_color_pick, self.btn_language, VSep(), zoom_pan] subgrid_toolbar = QGridLayout() toolbar_widget = QWidget() row = 0 for col, btn in enumerate(btn_list): subgrid_toolbar.addWidget(btn, row, col) subgrid_toolbar.setSpacing(5) subgrid_toolbar.setContentsMargins(0, 0, 0, 0) subgrid_toolbar.setColumnStretch(col + 1, 100) toolbar_widget.setLayout(subgrid_toolbar) # ---- LEFT PANEL # SubGrid Hydrograph Frame : self.hydrograph = hydrograph.Hydrograph() self.hydrograph_scrollarea = mplFigViewer.ImageViewer() self.hydrograph_scrollarea.zoomChanged.connect(self.zoom_disp.setValue) grid_hydrograph = QGridLayout() grid_hydrograph.addWidget(self.hydrograph_scrollarea, 0, 0) grid_hydrograph.setRowStretch(0, 500) grid_hydrograph.setColumnStretch(0, 500) grid_hydrograph.setContentsMargins(0, 0, 0, 0) # (L, T, R, B) # ASSEMBLING SubGrids : grid_layout = QGridLayout() self.grid_layout_widget = QFrame() row = 0 grid_layout.addWidget(toolbar_widget, row, 0) row += 1 grid_layout.addLayout(grid_hydrograph, row, 0) grid_layout.setContentsMargins(0, 0, 0, 0) # (L, T, R, B) grid_layout.setSpacing(5) grid_layout.setColumnStretch(0, 500) grid_layout.setRowStretch(1, 500) self.grid_layout_widget.setLayout(grid_layout) # ---- Right Panel self.tabscales = self.__init_scalesTabWidget__() self.right_panel = myqt.QFrameLayout() self.right_panel.addWidget(self.dmngr, 0, 0) self.right_panel.addWidget(self.tabscales, 1, 0) self.right_panel.setRowStretch(2, 100) self.right_panel.setSpacing(15) # ---- MAIN GRID mainGrid = QGridLayout() mainGrid.addWidget(self.grid_layout_widget, 0, 0) mainGrid.addWidget(VSep(), 0, 1) mainGrid.addWidget(self.right_panel, 0, 2) mainGrid.setContentsMargins(10, 10, 10, 10) # (L, T, R, B) mainGrid.setSpacing(15) mainGrid.setColumnStretch(0, 500) mainGrid.setColumnMinimumWidth(2, 250) self.setLayout(mainGrid) # ---- EVENTS # Toolbox Layout : btn_bestfit_waterlvl.clicked.connect(self.best_fit_waterlvl) btn_bestfit_time.clicked.connect(self.best_fit_time) btn_draw.clicked.connect(self.draw_hydrograph) btn_save.clicked.connect(self.select_save_path) # Hydrograph Layout : self.Ptot_scale.valueChanged.connect(self.layout_changed) self.qweather_bin.currentIndexChanged.connect(self.layout_changed) # ---- Init Image self.hydrograph_scrollarea.load_mpl_figure(self.hydrograph) def __init_scalesTabWidget__(self): class QRowLayout(QGridLayout): def __init__(self, items, parent=None): super(QRowLayout, self).__init__(parent) for col, item in enumerate(items): self.addWidget(item, 0, col) self.setContentsMargins(0, 0, 0, 0) self.setColumnStretch(0, 100) # ---- Time axis properties # Generate the widgets : self.date_start_widget = QDateEdit() self.date_start_widget.setDisplayFormat('01 / MM / yyyy') self.date_start_widget.setAlignment(Qt.AlignCenter) self.date_start_widget.dateChanged.connect(self.layout_changed) self.date_end_widget = QDateEdit() self.date_end_widget.setDisplayFormat('01 / MM / yyyy') self.date_end_widget.setAlignment(Qt.AlignCenter) self.date_end_widget.dateChanged.connect(self.layout_changed) self.time_scale_label = QComboBox() self.time_scale_label.setEditable(False) self.time_scale_label.setInsertPolicy(QComboBox.NoInsert) self.time_scale_label.addItems(['Month', 'Year']) self.time_scale_label.setCurrentIndex(0) self.time_scale_label.currentIndexChanged.connect(self.layout_changed) self.dateDispFreq_spinBox = QSpinBox() self.dateDispFreq_spinBox.setSingleStep(1) self.dateDispFreq_spinBox.setMinimum(1) self.dateDispFreq_spinBox.setMaximum(100) self.dateDispFreq_spinBox.setValue( self.hydrograph.date_labels_pattern) self.dateDispFreq_spinBox.setAlignment(Qt.AlignCenter) self.dateDispFreq_spinBox.setKeyboardTracking(False) self.dateDispFreq_spinBox.valueChanged.connect(self.layout_changed) # Setting up the layout : widget_time_scale = QFrame() widget_time_scale.setFrameStyle(0) grid_time_scale = QGridLayout() GRID = [[QLabel('From :'), self.date_start_widget], [QLabel('To :'), self.date_end_widget], [QLabel('Scale :'), self.time_scale_label], [QLabel('Date Disp. Pattern:'), self.dateDispFreq_spinBox]] for i, ROW in enumerate(GRID): grid_time_scale.addLayout(QRowLayout(ROW), i, 1) grid_time_scale.setVerticalSpacing(5) grid_time_scale.setContentsMargins(10, 10, 10, 10) widget_time_scale.setLayout(grid_time_scale) # ----- Water level axis properties # Widget : self.waterlvl_scale = QDoubleSpinBox() self.waterlvl_scale.setSingleStep(0.05) self.waterlvl_scale.setMinimum(0.05) self.waterlvl_scale.setSuffix(' m') self.waterlvl_scale.setAlignment(Qt.AlignCenter) self.waterlvl_scale.setKeyboardTracking(False) self.waterlvl_scale.valueChanged.connect(self.layout_changed) self.waterlvl_scale.setFixedWidth(100) self.waterlvl_max = QDoubleSpinBox() self.waterlvl_max.setSingleStep(0.1) self.waterlvl_max.setSuffix(' m') self.waterlvl_max.setAlignment(Qt.AlignCenter) self.waterlvl_max.setMinimum(-1000) self.waterlvl_max.setMaximum(1000) self.waterlvl_max.setKeyboardTracking(False) self.waterlvl_max.valueChanged.connect(self.layout_changed) self.waterlvl_max.setFixedWidth(100) self.NZGridWL_spinBox = QSpinBox() self.NZGridWL_spinBox.setSingleStep(1) self.NZGridWL_spinBox.setMinimum(1) self.NZGridWL_spinBox.setMaximum(50) self.NZGridWL_spinBox.setValue(self.hydrograph.NZGrid) self.NZGridWL_spinBox.setAlignment(Qt.AlignCenter) self.NZGridWL_spinBox.setKeyboardTracking(False) self.NZGridWL_spinBox.valueChanged.connect(self.layout_changed) self.NZGridWL_spinBox.setFixedWidth(100) self.datum_widget = QComboBox() self.datum_widget.addItems(['Ground Surface', 'Sea Level']) self.datum_widget.currentIndexChanged.connect(self.layout_changed) # Layout : subgrid_WLScale = QGridLayout() GRID = [[QLabel('Minimum :'), self.waterlvl_max], [QLabel('Scale :'), self.waterlvl_scale], [QLabel('Grid Divisions :'), self.NZGridWL_spinBox], [QLabel('Datum :'), self.datum_widget]] for i, ROW in enumerate(GRID): subgrid_WLScale.addLayout(QRowLayout(ROW), i, 1) subgrid_WLScale.setVerticalSpacing(5) subgrid_WLScale.setContentsMargins(10, 10, 10, 10) # (L, T, R, B) WLScale_widget = QFrame() WLScale_widget.setFrameStyle(0) WLScale_widget.setLayout(subgrid_WLScale) # ---- Weather Axis # Widgets : self.Ptot_scale = QSpinBox() self.Ptot_scale.setSingleStep(5) self.Ptot_scale.setMinimum(5) self.Ptot_scale.setMaximum(500) self.Ptot_scale.setValue(20) self.Ptot_scale.setSuffix(' mm') self.Ptot_scale.setAlignment(Qt.AlignCenter) self.qweather_bin = QComboBox() self.qweather_bin.setEditable(False) self.qweather_bin.setInsertPolicy(QComboBox.NoInsert) self.qweather_bin.addItems(['day', 'week', 'month']) self.qweather_bin.setCurrentIndex(1) # Layout : layout = QGridLayout() GRID = [[QLabel('Precip. Scale :'), self.Ptot_scale], [QLabel('Resampling :'), self.qweather_bin]] for i, row in enumerate(GRID): layout.addLayout(QRowLayout(row), i, 1) layout.setVerticalSpacing(5) layout.setContentsMargins(10, 10, 10, 10) # (L,T,R,B) layout.setRowStretch(i+1, 100) widget_weather_scale = QFrame() widget_weather_scale.setFrameStyle(0) widget_weather_scale.setLayout(layout) # ---- ASSEMBLING TABS tabscales = QTabWidget() tabscales.addTab(widget_time_scale, 'Time') tabscales.addTab(WLScale_widget, 'Water Level') tabscales.addTab(widget_weather_scale, 'Weather') return tabscales @property def workdir(self): return self.dmngr.workdir # ---- Utilities def zoom_in(self): self.hydrograph_scrollarea.zoomIn() def zoom_out(self): self.hydrograph_scrollarea.zoomOut() def update_colors(self): self.hydrograph.update_colors() self.hydrograph_scrollarea.load_mpl_figure(self.hydrograph) # ---- Datasets Handlers @property def wldset(self): return self.dmngr.get_current_wldset() @property def wxdset(self): return self.dmngr.get_current_wxdset() def wldset_changed(self): """Handle when the water level dataset of the datamanager changes.""" if self.wldset is None: self.clear_hydrograph() return else: self.hydrograph.set_wldset(self.wldset) self.hydrograph.gluedf = self.wldset.get_glue_at(-1) # Load the manual measurements. fname = os.path.join( self.workdir, "Water Levels", 'waterlvl_manual_measurements') tmeas, wlmeas = load_waterlvl_measures(fname, self.wldset['Well']) self.wldset.set_wlmeas(tmeas, wlmeas) # Setup the layout of the hydrograph. layout = self.wldset.get_layout() if layout is not None: msg = ("Loading existing graph layout for well %s." % self.wldset['Well']) print(msg) self.ConsoleSignal.emit('<font color=black>%s</font>' % msg) self.load_graph_layout(layout) else: print('No graph layout exists for well %s.' % self.wldset['Well']) # Fit Water Level in Layout : self.__updateUI = False self.best_fit_waterlvl() self.best_fit_time() if self.dmngr.set_closest_wxdset() is None: self.draw_hydrograph() self.__updateUI = True def wxdset_changed(self): """Handle when the weather dataset of the datamanager changes.""" if self.wldset is None: self.clear_hydrograph() else: self.hydrograph.set_wxdset(self.wxdset) QCoreApplication.processEvents() self.draw_hydrograph() # ---- Draw Hydrograph Handlers def best_fit_waterlvl(self): wldset = self.dmngr.get_current_wldset() if wldset is not None: WLscale, WLmin = self.hydrograph.best_fit_waterlvl() self.waterlvl_scale.setValue(WLscale) self.waterlvl_max.setValue(WLmin) def best_fit_time(self): wldset = self.dmngr.get_current_wldset() if wldset is not None: date0, date1 = self.hydrograph.best_fit_time(wldset.xldates) self.date_start_widget.setDate(QDate(date0[0], date0[1], date0[2])) self.date_end_widget.setDate(QDate(date1[0], date1[1], date1[2])) @QSlot() def mrc_wl_changed(self): """ Force a redraw of the MRC water levels after the results have changed for the dataset. """ self.hydrograph.draw_mrc_wl() self.hydrograph.setup_legend() self.hydrograph_scrollarea.load_mpl_figure(self.hydrograph) @QSlot(GLUEDataFrameBase) def glue_wl_changed(self, gluedf): """ Force a redraw of the GLUE water levels after the results have changed for the dataset. """ self.hydrograph.set_gluedf(gluedf) self.hydrograph_scrollarea.load_mpl_figure(self.hydrograph) def layout_changed(self): """ When an element of the graph layout is changed in the UI. """ if self.__updateUI is False: return self.update_graph_layout_parameter() if self.hydrograph.isHydrographExists is False: return sender = self.sender() if sender == self.btn_language: self.hydrograph.draw_ylabels() self.hydrograph.setup_xticklabels() self.hydrograph.setup_legend() elif sender in [self.waterlvl_max, self.waterlvl_scale]: self.hydrograph.setup_waterlvl_scale() self.hydrograph.draw_ylabels() elif sender == self.NZGridWL_spinBox: self.hydrograph.setup_waterlvl_scale() self.hydrograph.update_precip_scale() self.hydrograph.draw_ylabels() elif sender == self.Ptot_scale: self.hydrograph.update_precip_scale() self.hydrograph.draw_ylabels() elif sender == self.datum_widget: yoffset = int(self.wldset['Elevation']/self.hydrograph.WLscale) yoffset *= self.hydrograph.WLscale self.hydrograph.WLmin = (yoffset - self.hydrograph.WLmin) self.waterlvl_max.blockSignals(True) self.waterlvl_max.setValue(self.hydrograph.WLmin) self.waterlvl_max.blockSignals(False) # This is calculated so that trailing zeros in the altitude of the # well is not carried to the y axis labels, so that they remain a # int multiple of *WLscale*. self.hydrograph.setup_waterlvl_scale() self.hydrograph.draw_waterlvl() self.hydrograph.draw_ylabels() elif sender in [self.date_start_widget, self.date_end_widget]: self.hydrograph.set_time_scale() self.hydrograph.draw_weather() self.hydrograph.draw_figure_title() elif sender == self.dateDispFreq_spinBox: self.hydrograph.set_time_scale() self.hydrograph.setup_xticklabels() elif sender == self.page_setup_win: self.hydrograph.update_fig_size() # Implicitly call : set_margins() # draw_ylabels() # set_time_scale() # draw_figure_title self.hydrograph.draw_waterlvl() self.hydrograph.setup_legend() elif sender == self.qweather_bin: self.hydrograph.resample_bin() self.hydrograph.draw_weather() self.hydrograph.draw_ylabels() elif sender == self.time_scale_label: self.hydrograph.set_time_scale() self.hydrograph.draw_weather() else: print('No action for this widget yet.') # !!!! temporary fix until I can find a better solution !!!! # sender.blockSignals(True) if type(sender) in [QDoubleSpinBox, QSpinBox]: sender.setReadOnly(True) for i in range(10): QCoreApplication.processEvents() self.hydrograph_scrollarea.load_mpl_figure(self.hydrograph) for i in range(10): QCoreApplication.processEvents() if type(sender) in [QDoubleSpinBox, QSpinBox]: sender.setReadOnly(False) # sender.blockSignals(False) def update_graph_layout_parameter(self): # language : self.hydrograph.language = self.btn_language.language # Scales : self.hydrograph.WLmin = self.waterlvl_max.value() self.hydrograph.WLscale = self.waterlvl_scale.value() self.hydrograph.RAINscale = self.Ptot_scale.value() self.hydrograph.NZGrid = self.NZGridWL_spinBox.value() # WL Datum : self.hydrograph.WLdatum = self.datum_widget.currentIndex() # Dates : self.hydrograph.datemode = self.time_scale_label.currentText() year = self.date_start_widget.date().year() month = self.date_start_widget.date().month() self.hydrograph.TIMEmin = xldate_from_date_tuple((year, month, 1), 0) year = self.date_end_widget.date().year() month = self.date_end_widget.date().month() self.hydrograph.TIMEmax = xldate_from_date_tuple((year, month, 1), 0) self.hydrograph.date_labels_pattern = self.dateDispFreq_spinBox.value() # Page Setup : self.hydrograph.fwidth = self.page_setup_win.pageSize[0] self.hydrograph.fheight = self.page_setup_win.pageSize[1] self.hydrograph.va_ratio = self.page_setup_win.va_ratio self.hydrograph.trend_line = self.page_setup_win.isTrendLine self.hydrograph.isLegend = self.page_setup_win.isLegend self.hydrograph.isGraphTitle = self.page_setup_win.isGraphTitle self.hydrograph.set_meteo_on(self.page_setup_win.is_meteo_on) self.hydrograph.set_glue_wl_on(self.page_setup_win.is_glue_wl_on) self.hydrograph.set_mrc_wl_on(self.page_setup_win.is_mrc_wl_on) self.hydrograph.set_figframe_lw(self.page_setup_win.figframe_lw) # Weather bins : self.hydrograph.bwidth_indx = self.qweather_bin.currentIndex() def clear_hydrograph(self): """Clear the hydrograph figure to show only a blank canvas.""" self.hydrograph.clf() self.hydrograph_scrollarea.load_mpl_figure(self.hydrograph) def draw_hydrograph(self): if self.dmngr.wldataset_count() == 0: msg = 'Please import a valid water level data file first.' self.ConsoleSignal.emit('<font color=red>%s</font>' % msg) self.emit_warning(msg) return self.update_graph_layout_parameter() # Generate and Display Graph : for i in range(5): QCoreApplication.processEvents() QApplication.setOverrideCursor(Qt.WaitCursor) self.hydrograph.set_wldset(self.dmngr.get_current_wldset()) self.hydrograph.set_wxdset(self.dmngr.get_current_wxdset()) self.hydrograph.generate_hydrograph() self.hydrograph_scrollarea.load_mpl_figure(self.hydrograph) QApplication.restoreOverrideCursor() def select_save_path(self): """ Open a dialog where the user can select a file name to save the hydrograph. """ if self.wldset is None: return ffmat = "*.pdf;;*.svg;;*.png" fname = find_unique_filename(osp.join( self.save_fig_dir, 'hydrograph_%s.pdf' % self.wldset['Well'])) fname, ftype = QFileDialog.getSaveFileName( self, "Save Figure", fname, ffmat) if fname: ftype = ftype.replace('*', '') fname = fname if fname.endswith(ftype) else fname + ftype self.save_fig_dir = os.path.dirname(fname) try: self.save_figure(fname) except PermissionError: msg = "The file is in use by another application or user." QMessageBox.warning(self, 'Warning', msg, QMessageBox.Ok) self.select_save_path() def save_figure(self, fname): """Save the hydrograph figure in a file.""" self.hydrograph.generate_hydrograph() self.hydrograph.savefig(fname) # ---- Graph Layout Handlers def load_layout_isClicked(self): """Handle when the button to load the graph layout is clicked.""" if self.wldset is None: self.emit_warning( "Please import a valid water level data file first.") return layout = self.wldset.get_layout() if layout is None: self.emit_warning( "No graph layout exists for well %s." % self.wldset['Well']) else: self.load_graph_layout(layout) def load_graph_layout(self, layout): """Load the graph layout into the GUI.""" self.__updateUI = False # Scales : date = layout['TIMEmin'] date = xldate_as_tuple(date, 0) self.date_start_widget.setDate(QDate(date[0], date[1], date[2])) date = layout['TIMEmax'] date = xldate_as_tuple(date, 0) self.date_end_widget.setDate(QDate(date[0], date[1], date[2])) self.dateDispFreq_spinBox.setValue(layout['date_labels_pattern']) self.waterlvl_scale.setValue(layout['WLscale']) self.waterlvl_max.setValue(layout['WLmin']) self.NZGridWL_spinBox.setValue(layout['NZGrid']) self.Ptot_scale.setValue(layout['RAINscale']) x = ['mbgs', 'masl'].index(layout['WLdatum']) self.datum_widget.setCurrentIndex(x) self.qweather_bin.setCurrentIndex(layout['bwidth_indx']) self.time_scale_label.setCurrentIndex( self.time_scale_label.findText(layout['datemode'])) # ---- Language and colors self.btn_language.set_language(layout['language']) self.color_palette_win.load_colors() # ---- Page Setup self.page_setup_win.pageSize = (layout['fwidth'], layout['fheight']) self.page_setup_win.va_ratio = layout['va_ratio'] self.page_setup_win.isLegend = layout['legend_on'] self.page_setup_win.isGraphTitle = layout['title_on'] self.page_setup_win.isTrendLine = layout['trend_line'] self.page_setup_win.is_meteo_on = layout['meteo_on'] self.page_setup_win.is_glue_wl_on = layout['glue_wl_on'] self.page_setup_win.is_mrc_wl_on = layout['mrc_wl_on'] self.page_setup_win.figframe_lw = layout['figframe_lw'] self.page_setup_win.legend_on.set_value(layout['legend_on']) self.page_setup_win.title_on.set_value(layout['title_on']) self.page_setup_win.wltrend_on.set_value(layout['trend_line']) self.page_setup_win.meteo_on.set_value(layout['meteo_on']) self.page_setup_win.glue_wl_on.set_value(layout['glue_wl_on']) self.page_setup_win.mrc_wl_on.set_value(layout['mrc_wl_on']) self.page_setup_win.fframe_lw_widg.setValue(layout['figframe_lw']) self.page_setup_win.fwidth.setValue(layout['fwidth']) self.page_setup_win.fheight.setValue(layout['fheight']) self.page_setup_win.va_ratio_spinBox.setValue(layout['va_ratio']) # Check if Weather Dataset : if layout['wxdset'] in self.dmngr.wxdsets: self.dmngr.set_current_wxdset(layout['wxdset']) else: if self.dmngr.set_closest_wxdset() is None: self.draw_hydrograph() self.__updateUI = True def save_layout_isClicked(self): wldset = self.wldset if wldset is None: self.emit_warning( "Please import a valid water level data file first.") return layout = wldset.get_layout() if layout is not None: msg = ('A graph layout already exists for well %s.Do you want to' ' you want to replace it?') % wldset['Well'] reply = QMessageBox.question(self, 'Save Graph Layout', msg, QMessageBox.Yes | QMessageBox.No) if reply == QMessageBox.Yes: self.save_graph_layout() elif reply == QMessageBox.No: msg = "Graph layout not saved for well %s." % wldset['Well'] self.ConsoleSignal.emit('<font color=black>%s' % msg) else: self.save_graph_layout() def save_graph_layout(self): """Save the graph layout in the project hdf5 file.""" print("Saving the graph layout for well %s..." % self.wldset['Well'], end=" ") layout = {'WLmin': self.waterlvl_max.value(), 'WLscale': self.waterlvl_scale.value(), 'RAINscale': self.Ptot_scale.value(), 'fwidth': self.page_setup_win.pageSize[0], 'fheight': self.page_setup_win.pageSize[1], 'va_ratio': self.page_setup_win.va_ratio, 'NZGrid': self.NZGridWL_spinBox.value(), 'bwidth_indx': self.qweather_bin.currentIndex(), 'date_labels_pattern': self.dateDispFreq_spinBox.value(), 'datemode': self.time_scale_label.currentText()} layout['wxdset'] = None if self.wxdset is None else self.wxdset.name year = self.date_start_widget.date().year() month = self.date_start_widget.date().month() layout['TIMEmin'] = xldate_from_date_tuple((year, month, 1), 0) year = self.date_end_widget.date().year() month = self.date_end_widget.date().month() layout['TIMEmax'] = xldate_from_date_tuple((year, month, 1), 0) if self.datum_widget.currentIndex() == 0: layout['WLdatum'] = 'mbgs' else: layout['WLdatum'] = 'masl' # ---- Page Setup layout['title_on'] = bool(self.page_setup_win.isGraphTitle) layout['legend_on'] = bool(self.page_setup_win.isLegend) layout['language'] = self.btn_language.language layout['trend_line'] = bool(self.page_setup_win.isTrendLine) layout['meteo_on'] = bool(self.page_setup_win.is_meteo_on) layout['glue_wl_on'] = bool(self.page_setup_win.is_glue_wl_on) layout['mrc_wl_on'] = bool(self.page_setup_win.is_mrc_wl_on) layout['figframe_lw'] = self.page_setup_win.figframe_lw # Save the colors : cdb = ColorsReader() cdb.load_colors_db() layout['colors'] = cdb.RGB # Save the layout : self.wldset.save_layout(layout) msg = 'Layout saved successfully for well %s.' % self.wldset['Well'] self.ConsoleSignal.emit('<font color=black>%s</font>' % msg) print("done")
class DateCtrl(BaseParamWidget): def __init__(self, layout_dir: str, title, initial_date): super().__init__(layout_dir) self.prefix = lab_title = QLabel(text=title) path_layout = QHBoxLayout() path_layout.addWidget(lab_title) self.ctrl = QDateEdit() path_layout.addWidget(self.ctrl) calendar_widget = QCalendar() self.ctrl.setCalendar(calendar_widget) self.central_layout.addLayout(path_layout) self.set_value(initial_date) def set_value(self, value: Union[Tuple[int, int, int], float, int]): if isinstance(value, tuple): assert len(value) == 3 date = QDate(*value) elif isinstance(value, (float, int)): loc_time = time.localtime(value) print(loc_time) date = QDate(loc_time.tm_year, loc_time.tm_mon, loc_time.tm_mday) else: raise ValueError("value is not allowed", value) self.ctrl.setDate(date) def get_value(self) -> float: """ 计算值 :return: """ return time.mktime(self.ctrl.date().toPyDate().timetuple())
class AddNewsForm(QWidget): def __init__(self, url=0): super().__init__() self.initUI() self.setupPars(url) self.connectSlots() def initUI(self): vLay = QVBoxLayout() h1 = QHBoxLayout() self.lab1 = QLabel('Заголовок : ') self.leHeader = QLineEdit() h1.addWidget(self.lab1) h1.addWidget(self.leHeader) vLay.addLayout(h1) h2 = QHBoxLayout() self.lab2 = QLabel('URL : ') self.leURL = QLineEdit() h2.addWidget(self.lab2) h2.addWidget(self.leURL) vLay.addLayout(h2) h3 = QHBoxLayout() self.lab3 = QLabel('Дата : ') self.dateEdit = QDateEdit() h3.addWidget(self.lab3) h3.addWidget(self.dateEdit) self.dateEdit.setDate(QDate.currentDate()) vLay.addLayout(h3) self.pbSave = QPushButton('Сохранить') vLay.addWidget(self.pbSave) self.setWindowTitle('Добавление новости') self.setLayout(vLay) def getPyDate(self): cur_date = self.dateEdit.date() return cur_date.toPyDate() def setupPars(self, url): if url: title = url[0] if '|' in title: title = title.split('|')[0] self.leURL.setText(title) self.leHeader.setText(url[1]) self.webData = WebPageData() def connectSlots(self): self.pbSave.clicked.connect(self.saveRecord) def saveRecord(self): self.webData.insertRecord(title=self.leHeader.text(), url=self.leURL.text(), date=self.getPyDate()) self.close()
def add_date_field(self, f_title, top, left, f_date, widthchange=0, need_calendar=True, default_value=QDate(1980, 1, 1), readonly=False, label_margin=2, label_font_size=LABEL_FONT_SIZE, field_size=4): label = QLabel(self.parent) label.setText(f_title) font = QFont() font.setPointSize(label_font_size) label.setFont(font) geo_label = QRect(left * self.width_step, top, label_margin * self.width_step, 30) label.setGeometry(geo_label) field = QDateEdit(self.parent) field.setCalendarPopup(need_calendar) geo_field = QRect((left + label_margin) * self.width_step, top, field_size * self.width_step, 30) field.setGeometry(geo_field) if f_date: Defdate = QDate(int(f_date.split('.')[2]), int(f_date.split('.')[1]), int(f_date.split('.')[0])) else: Defdate = default_value field.setDate(Defdate) field.setReadOnly(readonly) return field
class StudentTable(QTableWidget): def __init__(self, *args): self.rows = [] super(StudentTable, self).__init__(*args) self.gender = ['MALE', 'FEMALE'] self.medium = ['TAMIL', 'ENGLISH', 'MALAYALAM', 'TELUGU', 'HINDI'] self.gender_combo = None self.medium_combo = None self.dob_edit = None def add(self, student): self.add_row() print(self.rowCount()) self.setItem(self.rowCount() - 1, 0, QTableWidgetItem(student.name)) self.cellWidget(self.rowCount() - 1, 1).setCurrentText(student.gender) self.cellWidget(self.rowCount() - 1, 2).setDate(student.date_of_birth) self.cellWidget(self.rowCount() - 1, 3).setCurrentText(student.medium) def add_row(self): self.gender_combo = QComboBox() self.medium_combo = QComboBox() self.gender_combo.addItems(self.gender) self.medium_combo.addItems(self.medium) self.dob_edit = QDateEdit() self.dob_edit.setDisplayFormat('dd/MM/yyyy') self.dob_edit.setCalendarPopup(True) self.dob_edit.setDate(QDate.currentDate()) self.insertRow(self.rowCount()) self.setCellWidget(self.rowCount() - 1, 1, self.gender_combo) self.setCellWidget(self.rowCount() - 1, 2, self.dob_edit) self.setCellWidget(self.rowCount() - 1, 3, self.medium_combo)
class ReceiptParserUI(QWidget): """ 仓单数据解析界面 """ def __init__(self, *args, **kwargs): super(ReceiptParserUI, self).__init__(*args, **kwargs) main_layout = QVBoxLayout() opt_layout = QHBoxLayout() self.current_date = QDateEdit(self) self.current_date.setDate(QDate.currentDate()) self.current_date.setCalendarPopup(True) self.current_date.setDisplayFormat("yyyy-MM-dd") opt_layout.addWidget(self.current_date) self.parser_button = QPushButton("提取数据", self) opt_layout.addWidget(self.parser_button) self.message_label = QLabel("请在【后台管理】-【行业数据】-【交易所数据】获取仓单源文件后再提取", self) opt_layout.addWidget(self.message_label) opt_layout.addStretch() main_layout.addLayout(opt_layout) self.preview_table = QTableWidget(self) self.preview_table.setColumnCount(7) self.preview_table.setHorizontalHeaderLabels( ["仓库编号", "简称", "品种", "交易代码", "日期", "仓单", "增减"]) main_layout.addWidget(self.preview_table) self.commit_button = QPushButton("提交保存", self) main_layout.addWidget(self.commit_button, alignment=Qt.AlignRight) self.setLayout(main_layout)
def addDateToBill(self, complaintno: int): if (len(self.ui.quotationsTbl.selectionModel().selectedRows())) == 0: return complaintno = int( self.ui.quotationsTbl.selectionModel().selectedRows()[0].data()) addDateDialogBox = QDialog() addDateDialogBox.setGeometry(500, 500, 300, 120) # monthComBox.move(60, 50) selectDateBox = QDateEdit(addDateDialogBox) selectDateBox.setDate(datetime.datetime.now()) selectDateBox.setDisplayFormat("d/M/yyyy") # selectDateBox. enterBtn = QPushButton("Enter", addDateDialogBox) enterBtn.clicked.connect(lambda: self.addDateToExcelAndDatabase( complaintno, selectDateBox.date().toString("d/MMM/yyyy"))) enterBtn.move(150, 50) okButton = QPushButton("OK", addDateDialogBox) okButton.clicked.connect(lambda: addDateDialogBox.close()) okButton.move(150, 90) selectDateBox.move(60, 50) addDateDialogBox.setWindowTitle("Enter Date to Complaint No.: " + str(complaintno)) addDateDialogBox.setWindowModality(Qt.ApplicationModal) addDateDialogBox.exec_()
def createHorizontalLayout(self): self.horizontalQWidget = QWidget() layout1 = QHBoxLayout() # Label Date label_date = QLabel('Date', self) layout1.addWidget(label_date) # QDateEdit: Edit Date DateEdit = QDateEdit(self) DateEdit.setDisplayFormat("dd-MMMM-yyyy") DateEdit.setLocale(QLocale(QLocale.English, QLocale.UnitedStates)) DateEdit.setCalendarPopup(True) layout1.addWidget(DateEdit) today = QDateTime.currentDateTime().date() DateEdit.setDate(QDate(today)) DateEdit.dateChanged[QDate].connect(self.on_ShowDate) self.date = DateEdit.date() self.date = self.date.toPyDate() self.year, self.month, self.day = self.date.year, '{:02d}'.format( self.date.month), '{:02d}'.format(self.date.day) # Edit path to Narrowband Data label_PathNarrow = QLabel('Path to Narrowband Data', self) layout1.addWidget(label_PathNarrow) self.PathText = QLineEdit("C:/NarrowbandData/", self) self.PathText.textChanged[str].connect(self.update_PathFileNames) layout1.addWidget(self.PathText) # Select directory button BtnSelectDir = QPushButton('...', self) BtnSelectDir.clicked.connect(self.on_SelectDir) layout1.addWidget(BtnSelectDir) self.horizontalQWidget.setLayout(layout1)
def createEditor(self, parent: QWidget, option: QStyleOptionViewItem, index: QModelIndex) -> QWidget: wdgt = QDateEdit(parent) wdgt.setDisplayFormat("yyyy-MM-dd") wdgt.setDate(datetime.date.today()) wdgt.setCalendarPopup(True) return wdgt
class DateEdit(WidgetWithTZinfo): def __init__(self, parent=None): super(DateEdit, self).__init__(parent) self.initQDateEdit() self.initTZinfoEdit() def initQDateEdit(self): self.dateEdit = QDateEdit(self) self.dateEdit.setKeyboardTracking(False) self.dateEdit.setDisplayFormat("dd.MM.yyyy") self.layout().addWidget(self.dateEdit) def date(self) -> Date: date = self.dateEdit.date().toPyDate() tzinfo = self.tzinfoEdit.getObj2add() dateDate = Date(year=date.year, month=date.month, day=date.day, tzinfo=tzinfo) #TODO change if aas changes return dateDate def setDate(self, val: datetime.date): if isinstance(val, datetime.date): self.dateEdit.setDate(val) self.tzinfoEdit.setVal(val.tzinfo) else: raise TypeError("arg1 must be instance of type datetime.date:", type(val))
class 시간날짜편집기(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): label = QLabel('QTimeEdit') label.setAlignment(Qt.AlignCenter) time = QTimeEdit(self) time.setTime(QTime.currentTime()) time.setTimeRange(QTime(00, 00, 00), QTime.currentTime()) time.setDisplayFormat('a:hh:mm:ss.zzz') label2 = QLabel('QDateEdit') label2.setAlignment(Qt.AlignCenter) self.date_edit = QDateEdit(self) self.date_edit.setDate(QDate.currentDate()) self.date_edit.setDateRange(QDate(2000, 1, 1), QDate.currentDate()) # self.date_edit.setDisplayFormat('yyyy년 MMMM d일') self.date_edit.dateChanged.connect(self.dateChange) self.label3 = QLabel('이곳에 QDateEdit에서 선택된 값이 나타납니다.') self.label3.setAlignment(Qt.AlignCenter) label4 = QLabel('QDateTimeEdit') label4.setAlignment(Qt.AlignCenter) label5 = QLabel(self) label5.setAlignment(Qt.AlignCenter) label5.setText( f'QDateTime \n 현재 시간은 {QDateTime.currentDateTime().toString("yyyy년 MMMM d일 ap hh시 mm분 ss초.zzz")} 입니다.' ) dt_edit = QDateTimeEdit(self) dt_edit.setDateTimeRange(QDateTime(2020, 1, 1, 00, 00, 00),\ QDateTime(2021, 1, 1, 00, 00, 00)) dt_edit.setDisplayFormat('yyyy.MM.dd hh:mm:ss') vbox = QVBoxLayout() vbox.addWidget(label) vbox.addWidget(time) vbox.addWidget(label2) vbox.addWidget(self.date_edit) vbox.addWidget(self.label3) vbox.addWidget(label4) vbox.addWidget(label5) vbox.addWidget(dt_edit) self.setLayout(vbox) self.setWindowTitle('QTime, QDateEdit, QDateTimeEdit') self.setGeometry(300, 300, 400, 300) self.show() def dateChange(self): self.label3.setText(self.date_edit.date().toString('yyyy년 MMMM d일'))
def initWidget(self): layout = QGridLayout(self) layout.setSpacing(0) # lbl = QLabel() # lbl.setText(self.inputName) # lbl.setContentsMargins(-10,10,10,10) dateDiff = math.floor( (self.maxValue.year() - self.minValue.year()) / 2 ) # difference between the first date and last date, used to handle min and max values for the sliders minScroller = QSlider(Qt.Horizontal, self) minScroller.setMinimum(self.minValue.year()) minScroller.setMaximum(self.maxValue.year()) minScroller.setTickInterval(1) minScroller.setSingleStep(1) minScroller.setSliderPosition(self.minValue.year()) maxScroller = QSlider(Qt.Horizontal, self) maxScroller.setMinimum(self.minValue.year()) maxScroller.setMaximum(self.maxValue.year()) maxScroller.setTickInterval(1) maxScroller.setSingleStep(1) maxScroller.setSliderPosition(self.maxValue.year()) minEdit = QDateEdit() minEdit.setDate(self.minValue) minEdit.setDisplayFormat("yyyy") minEdit.setMinimumDate(self.minValue) minEdit.setMaximumDate(self.maxValue) maxEdit = QDateEdit() maxEdit.setDate(self.maxValue) maxEdit.setDisplayFormat("yyyy") maxEdit.setMaximumDate(self.maxValue) maxEdit.setMinimumDate(self.minValue) minScroller.valueChanged.connect(self._updateMinEdit) minEdit.dateChanged.connect(self._updateMinSlider) maxScroller.valueChanged.connect(self._updateMaxEdit) maxEdit.dateChanged.connect(self._updateMaxSlider) # layout.addWidget(lbl,0,0,0,1,QtCore.Qt.AlignCenter) layout.addWidget(minScroller, 1, 2) layout.addWidget(minEdit, 1, 3) layout.addWidget(maxScroller, 2, 2) layout.addWidget(maxEdit, 2, 3) self.setLayout(layout) self.minScroller = minScroller self.minEdit = minEdit self.maxEdit = maxEdit self.maxScroller = maxScroller
def _handleDate(self, name, parameterType, tooltip, defaultVal, minVal=None, maxVal=None): if (minVal is not None): minDate = QDate.fromString(minVal, 'yyyy-MM-dd') if (maxVal is not None): maxDate = QDate.fromString(maxVal, 'yyyy-MM-dd') defaultDate = QDate.fromString(defaultVal.strftime('%Y-%m-%d'), 'yyyy-MM-dd') widget = QDateEdit(self.parameterTable) widget.setDate(defaultDate) widget.setToolTip(tooltip) widget.setCalendarPopup(True) self.parameters[name] = [parameterType, widget] if (minVal is not None and maxVal is not None): self.parameters[name][1].setDateRange(minDate, maxDate)
class AddDecrementWidget(QWidget): def __init__(self, parent=None): QWidget.__init__(self, parent) # Creating and setting the components and their characteristics size = QSize(400, 250) self.setFixedSize(size) self.main_layout = QVBoxLayout() title: str = centralize_text("Добавить расход продукта") self.title = QLabel(title, parent=self) self.data_layout = QHBoxLayout() self.quantity_layout = QVBoxLayout() self.quantity_title = QLabel("Кол-во:", parent=self) self.quantity_value = QDoubleSpinBox(parent=self) self.quantity_value.setSingleStep(1.0) self.quantity_value.setRange(0.0, 1000000.0) self.quantity_value.setDecimals(3) self.quantity_checker = QCheckBox("На 1 ребёнка", parent=self) self.date_layout = QVBoxLayout() self.date_title = QLabel("Выберите дату:", parent=self) self.today_radio = QRadioButton("Сегодня", parent=self) self.today_radio.setChecked(True) self.today_radio.clicked.connect(self.disable_date_edit) self.otherday_radio = QRadioButton("Другой день", parent=self) self.otherday_radio.clicked.connect(self.enable_date_edit) self.otherday_edit = QDateEdit(date=date.today(), parent=self) self.otherday_edit.setDisabled(True) self.button = QPushButton("Добавить &расход", parent=self) # Locating the components in the widget self.setLayout(self.main_layout) self.main_layout.addWidget(self.title) self.main_layout.addLayout(self.data_layout) self.data_layout.addLayout(self.quantity_layout) self.quantity_layout.addWidget(self.quantity_title) self.quantity_layout.addWidget(self.quantity_value) self.quantity_layout.addWidget(self.quantity_checker) self.data_layout.addLayout(self.date_layout) self.date_layout.addWidget(self.date_title) self.date_layout.addWidget(self.today_radio) self.date_layout.addWidget(self.otherday_radio) self.date_layout.addWidget(self.otherday_edit) self.main_layout.addWidget(self.button) def enable_date_edit(self): # The user would choose another date self.otherday_edit.setEnabled(True) def disable_date_edit(self): # The user chose today self.otherday_edit.setDate(date.today()) self.otherday_edit.setDisabled(True)
def initUI(self): lbl = QLabel('QDateEdit') dateedit = QDateEdit(self) dateedit.setDate(QDate.currentDate()) dateedit.setMinimumDate(QDate(1900, 1, 1)) dateedit.setMaximumDate(QDate(2100, 12, 31)) # dateedit.setDateRange(QDate(1900, 1, 1), QDate(2100, 12, 31)) vbox = QVBoxLayout() vbox.addWidget(lbl) vbox.addWidget(dateedit) vbox.addStretch() self.setLayout(vbox) self.show_basic()
def initUI(self): label = QLabel('QDateEdit') date_edit = QDateEdit(self) date_edit.setDate(QDate.currentDate()) date_edit.setMinimumDate(QDate(1900, 1, 1)) date_edit.setMaximumDate(QDate(2100, 12, 31)) # date_edit.setDateRange(QDate(1900, 1, 1), QDate(2100, 12, 31)) vbox = QVBoxLayout() vbox.addWidget(label) vbox.addWidget(date_edit) vbox.addStretch() self.setLayout(vbox) self.setWindowTitle('QDateEdit') self.setGeometry(300, 300, 300, 200) self.show()
class MyApp(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): lbl = QLabel('QDateEdit') self.dateEditWidget = QDateEdit() # theDate = QDate() # self.dateEditWidget.setDate(theDate.currentDate()) # 현재 날짜 # theDate.setDate() # self.dateEditWidget.setDate(QDate.currentDate()) # 현재 날짜 self.dateEditWidget.setMinimumDate(QDate(2000, 1, 1)) self.dateEditWidget.setMaximumDate(QDate(2100, 12, 31)) self.dateEditWidget.setDisplayFormat('yyyy.MM.dd') self.dateEditWidget.setCalendarPopup(True) self.dateEditWidget.setDate(QDate(2020, 5, 1)) # 지정한 날짜 # self.dateEditWidget.setDate(QDate.currentDate()) self.dateEditWidget.dateChanged.connect(self.__dateChanged) vbox = QVBoxLayout() vbox.addWidget(lbl) vbox.addWidget(self.dateEditWidget) vbox.addStretch() self.setLayout(vbox) self.setWindowTitle('QDateEdit') self.setGeometry(300, 300, 300, 200) def __dateChanged(self): varQDate = self.dateEditWidget.date() # QDate print(varQDate) print(varQDate.toString('yyyy-MM-dd')) print(f'Year:{varQDate.year()} Month:{varQDate.month()} Day:{varQDate.day()}') print('5 Years later:\t', varQDate.addYears(5).toString('yyyy-MM-dd')) print('5 Months later:\t', varQDate.addMonths(5).toString('yyyy-MM-dd')) print('5 Days later:\t', varQDate.addDays(5).toString('yyyy-MM-dd'))
def setUI(self): self.cleanChoixVilleBool = False labelVille = QLabel("Ville / Code postal : ") labelJour = QLabel("Jour : ") textEditVille = QLineEdit() calendarJour = QDateEdit() calendarJour.setCalendarPopup(True) calendarJour.setDate(QDate.currentDate()) buttonValiderParam = QPushButton("Valider") splitterRes = QSplitter() splitterRes.setOrientation(Qt.Horizontal) hboxParam = QHBoxLayout() hboxChoixVille = QVBoxLayout() hboxResultats = QHBoxLayout() vboxGlobal = QVBoxLayout() hboxParam.addWidget(labelVille) hboxParam.addWidget(textEditVille) hboxParam.addWidget(labelJour) hboxParam.addWidget(calendarJour) hboxParam.addWidget(buttonValiderParam) hboxResultats.addWidget(splitterRes) vboxGlobal.addLayout(hboxParam) vboxGlobal.addLayout(hboxChoixVille) vboxGlobal.addLayout(hboxResultats) self.setLayout(vboxGlobal) buttonValiderParam.clicked.connect( lambda: self.choixVille(textEditVille.text(), calendarJour.date())) textEditVille.returnPressed.connect( lambda: self.choixVille(textEditVille.text(), calendarJour.date())) self.setWindowTitle('Super Cinemon 2000 ExtraPlus') self.show()
class NotesForm: note_id = None def __init__(self, note=None): self.form_layout = QFormLayout() self.date = QDateEdit() self.notes = QTextEdit() self.notes.setMinimumHeight(420) if note is not None and note['id'] is not None: self.note_id = note['id'] self.date.setCalendarPopup(True) self.date.setDisplayFormat('dd MMMM yyyy') if note is not None and note['date'] is not None: self.date.setDate(QDate.fromString(note['date'], "d.M.yyyy")) if note is not None and note['notes'] is not None: self.notes.setText(note['notes']) date_label = QLabel('Дата:') notes_label = QLabel('Примечание:') self.form_layout.addRow(date_label, self.date) self.form_layout.addRow(notes_label, self.notes) def get_layout(self): return self.form_layout def get_date(self): tmp_date = self.date.date() tmp_date = tmp_date.toPyDate() return '{0:%d.%m.%Y}'.format(tmp_date) def get_notes(self): return self.notes.toPlainText() def get_note_id(self): return self.note_id def validate_form(self): errors = list() # errors.append(self.first_name.validator())
class TableWidget(QWidget): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.resize(700, 72) self.setMinimumWidth(700) # Widgets self.lesson = QLineEdit(self) self.lesson.setReadOnly(True) self.lesson.setToolTip('Описание предмета') self.deadline = QDateEdit(self) self.deadline.setToolTip('Дата окончания') self.deadline.setReadOnly(True) self.deadline.setDate(date.today()) self.deadline.setMinimumDate(date(2017, 9, 1)) self.save_button = QPushButton('Сохранить', self) self.delete_button = QPushButton('Удалить', self) self.result = QDoubleSpinBox(self) self.result.setSingleStep(0.01) self.result.setToolTip('Результат') self.done = QCheckBox(self) self.done.setToolTip('Задача выполнена') # Layouts grid_layout = QGridLayout(self) grid_layout.addWidget(self.lesson, 0, 1) grid_layout.addWidget(self.deadline, 0, 3) buttons_layout = QVBoxLayout() buttons_layout.addWidget(self.save_button) buttons_layout.addWidget(self.delete_button) grid_layout.addLayout(buttons_layout, 0, 5) grid_layout.addWidget(self.result, 0, 4) grid_layout.addWidget(self.done, 0, 0) # Tab order self.setTabOrder(self.done, self.lesson) self.setTabOrder(self.lesson, self.deadline) self.setTabOrder(self.deadline, self.result) self.setTabOrder(self.result, self.save_button) self.setTabOrder(self.save_button, self.delete_button)
class ShortMessageAdminUI(QWidget): def __init__(self, *args, **kwargs): super(ShortMessageAdminUI, self).__init__(*args, **kwargs) main_layout = QVBoxLayout() opt_layout = QHBoxLayout() self.date_edit = QDateEdit(self) self.date_edit.setDate(QDate.currentDate()) self.date_edit.setDisplayFormat("yyyy-MM-dd") opt_layout.addWidget(self.date_edit) self.query_button = QPushButton("查询", self) opt_layout.addWidget(self.query_button) opt_layout.addStretch() main_layout.addLayout(opt_layout) self.scroll_area = QScrollArea(self) self.scroll_area.setWidgetResizable(True) self.scroll_area.setBackgroundRole(QPalette.Light) self.scroll_area.setFrameShape(QFrame.NoFrame) main_layout.addWidget(self.scroll_area) self.setLayout(main_layout)
def initUI(self): """ cal = QCalendarWidget(self) cal.setGridVisible(True) cal.move(20, 20) cal.clicked[QDate].connect(self.showDate) """ cal = QCalendarWidget(self) dtEdit = QDateEdit(QDate.currentDate(), self) dtEdit.setCalendarPopup(True) dtEdit.setCalendarWidget(cal) dtEdit.setDate(cal.selectedDate()) dtEdit.dateChanged.connect(self.showDate) self.lbl = QLabel(self) date = cal.selectedDate() self.lbl.setText(date.toString()) self.lbl.move(130, 260) self.setGeometry(300, 300, 350, 300) self.setWindowTitle('Calendar') self.show()
def initUI(self): lbl = QLabel('QDateEdit') dateedit = QDateEdit(self) dateedit.setDate(QDate.currentDate()) dateedit.setMinimumDate(QDate(1900, 1, 1)) dateedit.setMaximumDate(QDate(2100, 12, 31)) # QDateEdit 클래스를 이용해서 날짜 편집 위젯을 하나 만들어줍니다. # # setDate 메서드에 QDate.currentDate()를 입력해서 프로그램이 실행될 때 # 현재 날짜로 표시되도록 합니다. # # setMinimumDate와 setMaximumDate를 이용하면 사용자가 # 선택할 수 있는 날짜의 범위를 제한할 수 있습니다. # # 최소 날짜는 디폴트로 1752년 9월 14일로 설정되어 있고, # 최대 날짜는 9999년 12월 31일로 설정되어 있습니다. # # 최소 날짜는 최소 100년 1월 1일 이상이어야합니다. # dateedit.setDateRange(QDate(1900, 1, 1), QDate(2100, 12, 31)) # setDateRange 메서드는 setMinimumDate와 setMaximumDate를 # 동시에 사용하는 것과 같습니다. vbox = QVBoxLayout() vbox.addWidget(lbl) vbox.addWidget(dateedit) vbox.addStretch() # 수직 박스 레이아웃을 이용해서 라벨과 날짜 편집 위젯을 수직으로 배치하고, # 전체 위젯의 레이아웃으로 설정합니다. self.setLayout(vbox) self.setWindowTitle('QDateEdit') self.setGeometry(300, 300, 300, 200) self.show()
class Window(QWidget): def __init__(self): super().__init__() self.db = run() self.setWindowTitle("To-Do") self.setWindowIcon(QIcon('web.png')) self.setGeometry(100, 50, 1920, 1080) self.layout = QVBoxLayout(self) self.prelayout = QHBoxLayout(self) self.row = 0 #=================== #widget part #------------------- self.label = QLabel('To-Do!', self) self.plus = QPushButton("+", self) self.plus.resize(700, 100) self.plus.clicked.connect(self.createTask) self.today = QPushButton("Tasks on today") self.today.resize(500, 30) self.today.clicked.connect(self.day_notifications) ## self.grid.addWidget(self.plus, 0, 2, 3, 2) self.layout.addWidget(self.label) self.layout.addWidget(self.plus) self.layout.addWidget(self.today) self.all = QPushButton("All") self.active = QPushButton("Active") self.done = QPushButton("Done") self.all.clicked.connect(self.all_tasks) self.active.clicked.connect(self.active_tasks) self.done.clicked.connect(self.done_tasks) self.prelayout.addWidget(self.all) self.prelayout.addWidget(self.active) self.prelayout.addWidget(self.done) self.layout.addLayout(self.prelayout) self.scrollArea = QScrollArea(self) self.scrollArea.setWidgetResizable(True) self.scrollAreaWidgetContents = QWidget() self.tasks = QGridLayout(self.scrollAreaWidgetContents) self.scrollArea.setWidget(self.scrollAreaWidgetContents) self.layout.addWidget(self.scrollArea) self.tasks.setSpacing(10) self.layout.addLayout(self.tasks) self.createTaskWithStuff #=================== #CSS part #-------------------- self.label.setStyleSheet("""font-size: 14.5pt; font-family: MS Gothic 2; """) self.all.setStyleSheet("""QPushButton{ margin-top: 40px; margin-right: 0px; margin-left: 0px; border: 1px solid gray; } QPushButton:hover{ background-color: lightgray; } """) self.active.setStyleSheet("""QPushButton{ margin-top: 40px; margin-right: 0px; margin-left: 0px; border: 1px solid gray; } QPushButton:hover{ background-color: lightgray; } """) self.done.setStyleSheet("""QPushButton{ margin-top: 40px; margin-right: 0px; margin-left: 0px; border: 1px solid gray; } QPushButton:hover{ background-color: lightgray; } """) #==================== self.layouts = {} self.layouts1 = {} self.layouts2 = {} self.layouts3 = {} self.layouts4 = {} self.done_layouts = {} self.str_louts = {} self.x_pos = 0 self.y_pos = 0 for task in self.db.read_all(): if task[1] != 'notnamed': self.createTaskWithStuff(id=task[0], name=task[1], date_exec=task[2], text=task[3], date_until=task[4], status=task[5]) else: self.db.delete_the_task(task[0]) self.show() def save(self): self.widget = self.sender() self.key_list = list(self.layouts2.keys()) self.val_list = list(self.layouts2.values()) self.position = self.val_list.index(self.widget) self.item = self.key_list[self.position] self.cur_id = int(self.layouts[self.item][0].text()) self.date = self.layouts[self.item][2].date().toString('yyyy-MM-dd') self.text = str(self.layouts[self.item][4].toPlainText()) self.date1 = self.layouts[self.item][3].date().toString('yyyy-MM-dd') self.name = str(self.layouts[self.item][1].text()) print(self.date) print(self.text) print(self.date1) print(self.name) self.db.update(self.date, self.text, self.date1, self.cur_id, self.name if self.name else None) self.layouts[self.item][1].setReadOnly(True) self.layouts[self.item][2].setReadOnly(True) self.layouts[self.item][3].setReadOnly(True) self.layouts[self.item][4].setReadOnly(True) self.layouts[self.item][5].setEnabled(True) self.layouts[self.item][6].setEnabled(False) self.layouts[self.item][7].setEnabled(True) def edit(self): self.widget = self.sender() self.key_list = list(self.layouts3.keys()) self.val_list = list(self.layouts3.values()) self.position = self.val_list.index(self.widget) self.item = self.key_list[self.position] self.layouts[self.item][1].setReadOnly(False) self.layouts[self.item][2].setReadOnly(False) self.layouts[self.item][3].setReadOnly(False) self.layouts[self.item][4].setReadOnly(False) self.layouts[self.item][6].setEnabled(True) self.layouts[self.item][7].setEnabled(False) def delete(self): self.widget = self.sender() self.key_list = list(self.layouts1.keys()) self.val_list = list(self.layouts1.values()) self.position = self.val_list.index(self.widget) self.item = self.key_list[self.position] self.db.delete_the_task(int(self.layouts[self.item][0].text())) for i in self.layouts[self.item]: i.deleteLater() if self.layouts[self.item] == None: break del self.layouts[self.item] self.y_pos -= 1 def createTask(self): self.y_pos = self.y_pos + 1 self.elem = [] self.task = QGridLayout() self.label = QLabel(f"{self.y_pos}") self.line = QLineEdit() self.date = QDateTimeEdit() self.date.setDisplayFormat("yyyy-MM-dd") self.date.setDate(date.today()) self.date1 = QDateTimeEdit() self.date1.setDisplayFormat("yyyy-MM-dd") self.date1.setDate(date.today()) self.text = QTextEdit() self.button = QPushButton(f"Delete") self.button1 = QPushButton(f"Save") self.button2 = QPushButton(f"Edit") self.button3 = QPushButton(f"Done") self.elem.append(self.label) self.elem.append(self.line) self.elem.append(self.date) self.elem.append(self.date1) self.elem.append(self.text) self.elem.append(self.button) self.elem.append(self.button1) self.elem.append(self.button2) self.elem.append(self.button3) self.task.addWidget(self.label, self.y_pos, 0) self.task.addWidget(self.line, self.y_pos, 1) self.task.addWidget(self.date, self.y_pos, 2) self.task.addWidget(self.date1, self.y_pos, 3) self.task.addWidget(self.text, self.y_pos, 4) self.task.addWidget(self.button2, self.y_pos, 5) self.task.addWidget(self.button1, self.y_pos, 6) self.task.addWidget(self.button, self.y_pos, 7) self.task.addWidget(self.button3, self.y_pos, 8) self.button.clicked.connect(self.delete) self.button2.clicked.connect(self.edit) self.button1.clicked.connect(self.save) self.button3.clicked.connect(self.doneTask) self.layouts[self.task] = self.elem self.layouts1[self.task] = self.button self.layouts2[self.task] = self.button1 self.layouts3[self.task] = self.button2 self.layouts4[self.task] = self.button3 self.str_louts[str(self.task)] = self.task self.button2.setEnabled(False) self.tasks.addLayout(self.task, self.y_pos, 0) self.db.create_a_task(None, None, None, "Active", self.task, None, self.y_pos) def doneTask(self): self.widget = self.sender() self.widget.setEnabled(False) self.key_list = list(self.layouts4.keys()) self.val_list = list(self.layouts4.values()) self.position = self.val_list.index(self.widget) self.item = self.key_list[self.position] self.db.done(int(self.layouts[self.item][0].text())) def createTaskWithStuff(self, id, name, date_exec, date_until, text, status): self.y_pos += 1 self.elem = [] self.task = QGridLayout() self.label = QLabel(f"{id}") self.line = QLineEdit() self.line.setText(name) self.line.setReadOnly(True) self.date = QDateEdit() self.date.setDate(QDate.fromString(date_exec, "yyyy-MM-dd")) self.date.setDisplayFormat("yyyy-MM-dd") self.date.setReadOnly(True) self.date1 = QDateEdit() self.date1.setDate(QDate.fromString(date_until, "yyyy-MM-dd")) self.date1.setDisplayFormat("yyyy-MM-dd") self.date1.setReadOnly(True) self.text = QTextEdit() self.text.setText(text) self.text.setReadOnly(True) self.button = QPushButton(f"Delete") self.button1 = QPushButton(f"Save") self.button2 = QPushButton(f"Edit") self.button3 = QPushButton(f"Done") self.button1.setEnabled(False) if status == "Done": self.button3.setEnabled(False) self.elem.append(self.label) self.elem.append(self.line) self.elem.append(self.date) self.elem.append(self.date1) self.elem.append(self.text) self.elem.append(self.button) self.elem.append(self.button1) self.elem.append(self.button2) self.elem.append(self.button3) self.task.addWidget(self.label, id, 0) self.task.addWidget(self.line, id, 1) self.task.addWidget(self.date, id, 2) self.task.addWidget(self.date1, id, 3) self.task.addWidget(self.text, id, 4) self.task.addWidget(self.button2, id, 5) self.task.addWidget(self.button1, id, 6) self.task.addWidget(self.button, id, 7) self.task.addWidget(self.button3, id, 8) self.button.clicked.connect(self.delete) self.button2.clicked.connect(self.edit) self.button1.clicked.connect(self.save) self.button3.clicked.connect(self.doneTask) self.layouts[self.task] = self.elem self.layouts1[self.task] = self.button self.layouts2[self.task] = self.button1 self.layouts3[self.task] = self.button2 self.layouts4[self.task] = self.button3 self.str_louts[str(self.task)] = self.task self.db.grid(int(self.layouts[self.task][0].text()), str(self.task)) self.tasks.addLayout(self.task, id, 0) def all_tasks(self): self.y_pos = 0 for task in self.db.read_all(): self.createTaskWithStuff(id=task[0], name=task[1], date_exec=task[2], text=task[3], date_until=task[4], status=task[5]) def active_tasks(self): for task in self.db.read_all(): if task[5] == "Active": self.createTaskWithStuff(id=task[0], name=task[1], date_exec=task[2], text=task[3], date_until=task[4], status=task[5]) else: for i in self.layouts: for p in self.layouts[i]: p.deleteLater() del self.layouts[i][0] self.y_pos -= 1 def done_tasks(self): for task in self.db.read_all(): if task[5] == "Done": self.createTaskWithStuff(id=task[0], name=task[1], date_exec=task[2], text=task[3], date_until=task[4], status=task[5]) else: for i in self.layouts[self.str_louts[task[6]]]: i.deleteLater() del self.layouts[self.str_louts[task[6]]] self.y_pos -= 1 def day_notifications(self): self.str_of_tasks = "Today, you need to do these tasks - " self.tasks_num = 0 for task in self.db.read_all(): if task[4] == str(date.today()) or task[2] == str(date.today()): self.str_of_tasks = self.str_of_tasks + str(task[1]) + ", " self.tasks_num += 1 if self.tasks_num == 0: self.str_of_tasks = "You're relaxing today! You don't need to do anything today." elif self.tasks_num > 0: self.str_of_tasks = self.str_of_tasks[:-2] self.str_of_tasks = self.str_of_tasks + "." QMessageBox.about(self, 'Tasks', self.str_of_tasks)
class Example(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): con = sqlite3.connect("Launch_Data.db") self.cur = con.cursor() self.setGeometry(0, 0, 1500, 800) self.setWindowTitle('Моделирование движения ракеты') layout = QVBoxLayout( ) # установка стиля расположения UI элементов вертикально # создание интерфэйса # Поле для ввода широты self.Latitudelabel = QLabel(self) self.Latitudelabel.setText("Latitude") self.Latitudelabel.move(20, 30) self.Latitudelabel.resize(120, 20) layout.addWidget(self.Latitudelabel) self.LatitudeInput = QLineEdit(self) self.LatitudeInput.setText('70') self.LatitudeInput.move(80, 30) self.LatitudeInput.resize(125, 20) layout.addWidget(self.LatitudeInput) # при изменений значения поля ввода вызывается функция adjustLatitude self.LatitudeInput.textChanged.connect(self.adjustLatitude) # поля для ввода долготы self.LongitudeLabel = QLabel(self) self.LongitudeLabel.setText("Longitude") self.LongitudeLabel.move(20, 60) layout.addWidget(self.LongitudeLabel) self.LongitudeInput = QLineEdit(self) self.LongitudeInput.setText('-90') self.LongitudeInput.move(80, 60) self.LongitudeInput.resize(125, 20) layout.addWidget(self.LongitudeInput) self.LongitudeInput.textChanged.connect(self.adjustLongitude) # поля для ввода высоты над уровнем моря self.ElevationLabel = QLabel(self) self.ElevationLabel.setText("Elevation") self.ElevationLabel.move(20, 90) layout.addWidget(self.ElevationLabel) self.ElevationInput = QLineEdit(self) self.ElevationInput.setText('560') self.ElevationInput.move(80, 90) self.ElevationInput.resize(125, 20) layout.addWidget(self.ElevationInput) # поля для ввода угла наклона ракеты self.InclinationLabel = QLabel(self) self.InclinationLabel.setText("Inclination") layout.addWidget(self.InclinationLabel) self.InclinationInput = QLineEdit(self) self.InclinationInput.setText('85') layout.addWidget(self.InclinationInput) self.InclinationInput.textChanged.connect(self.adjustInclination) # поля для ввода даты запуска self.DateLabel = QLabel(self) self.DateLabel.move(20, 120) self.DateLabel.setText("Date") layout.addWidget(self.DateLabel) # текущяя дата now = datetime.datetime.now() self.DateInput = QDateEdit(self) self.DateInput.setDate(now) self.DateInput.move(80, 120) self.DateInput.resize(125, 20) layout.addWidget(self.DateInput) self.DateInput.dateTimeChanged.connect(self.adjustDate) # кнопка для получения графиков об атмосферных условиях в ту дату self.EnvironmentInfo = QPushButton("Environment") self.EnvironmentInfo.move(20, 150) layout.addWidget(self.EnvironmentInfo) self.EnvironmentInfo.clicked.connect(self.EnvironmentD) # группирование все радио кнопок для выбора ввида мотора self.motorgroup = QButtonGroup() self.m7450 = QRadioButton("Cesaroni 7450M2505") self.m7450.move(20, 180) self.motorgroup.addButton(self.m7450) layout.addWidget(self.m7450) # заранее активирование одной радио кнопки self.m7450.setEnabled(True) # каждый раз при выборе этой радикнопки вызывается функция для установки текущего выбора self.m7450.toggled.connect(lambda: self.setMotor(self.m7450.text())) self.j360 = QRadioButton("Cesaroni J360") self.j360.move(20, 210) self.motorgroup.addButton(self.j360) layout.addWidget(self.j360) self.j360.toggled.connect(lambda: self.setMotor(self.j360.text())) self.m1300 = QRadioButton("Cesaroni M1300") self.motorgroup.addButton(self.m1300) layout.addWidget(self.m1300) self.m1300.toggled.connect(lambda: self.setMotor(self.m1300.text())) self.m1400 = QRadioButton("Cesaroni M1400") self.motorgroup.addButton(self.m1400) layout.addWidget(self.m1400) self.m1400.toggled.connect(lambda: self.setMotor(self.m1400.text())) self.m1540 = QRadioButton("Cesaroni M1540") self.motorgroup.addButton(self.m1540) layout.addWidget(self.m1540) self.m1540.toggled.connect(lambda: self.setMotor(self.m1540.text())) self.m1670 = QRadioButton("Cesaroni M1670") self.motorgroup.addButton(self.m1670) layout.addWidget(self.m1670) self.m1670.toggled.connect(lambda: self.setMotor(self.m1670.text())) self.m3100 = QRadioButton("Cesaroni M3100") self.motorgroup.addButton(self.m3100) layout.addWidget(self.m3100) self.m3100.toggled.connect(lambda: self.setMotor(self.m3100.text())) self.j115 = QRadioButton("Hypertek J115") self.motorgroup.addButton(self.j115) layout.addWidget(self.j115) self.j115.toggled.connect(lambda: self.setMotor(self.j115.text())) # кнопка для вывода графика сопротивления со временем мотора self.motorinfo = QPushButton("Motor") layout.addWidget(self.motorinfo) # при нажатий вызывается функция для вывода графика self.motorinfo.clicked.connect(self.motorInfo) # группирование всех радио кнопок для выбора ракеты self.rocketgroup = QButtonGroup() self.caldene = QRadioButton("Caldene") self.rocketgroup.addButton(self.caldene) layout.addWidget(self.caldene) self.caldene.toggled.connect( lambda: self.setRocket(self.caldene.text())) # заранее выбор одной из радио кнопок self.caldene.setEnabled(True) # создание радио кнопок для выбора вида ракеты self.calisto = QRadioButton("Calisto") self.rocketgroup.addButton(self.calisto) layout.addWidget(self.calisto) # при выборе вызов функций меняющий текущий вид ракеты self.calisto.toggled.connect( lambda: self.setRocket(self.calisto.text())) self.europia = QRadioButton("Euporia") self.rocketgroup.addButton(self.europia) layout.addWidget(self.europia) self.europia.toggled.connect( lambda: self.setRocket(self.europia.text())) self.jiboia = QRadioButton("Jiboia") self.rocketgroup.addButton(self.jiboia) layout.addWidget(self.jiboia) self.jiboia.toggled.connect(lambda: self.setRocket(self.jiboia.text())) self.keron = QRadioButton("Keron") self.rocketgroup.addButton(self.keron) layout.addWidget(self.keron) self.keron.toggled.connect(lambda: self.setRocket(self.keron.text())) self.mandioca = QRadioButton("Mandioca") self.rocketgroup.addButton(self.mandioca) layout.addWidget(self.mandioca) self.mandioca.toggled.connect( lambda: self.setRocket(self.mandioca.text())) # кнопка при нажатий выдаёт график траекторий полёта ракеты self.trajectory = QPushButton("Trajectory") layout.addWidget(self.trajectory) self.trajectory.clicked.connect(self.GetTrajectory) # кнопка при нажатий выдаёт график кинематических данных полёта self.kinematics = QPushButton("Kinematics data") layout.addWidget(self.kinematics) self.kinematics.clicked.connect(self.GetKinematics) # кнопка при нажатий выдаёт график скоростный данных self.altitude = QPushButton("Altitude data") layout.addWidget(self.altitude) self.altitude.clicked.connect(self.GetAltitude) # кнопка при нажатий выдаёт график данных об энергий во время полёта self.energy = QPushButton("Energy Data") layout.addWidget(self.energy) self.energy.clicked.connect(self.GetEnergy) # "растягиваем" расположение чтобы элементы UI оказались на верхней стороне окна layout.addStretch(1) # добавляем новый стиль горизонтального расположения horlayout = QHBoxLayout() # "растягиваем" горизонтальное расположение чтобы UI оказался на правой стороне horlayout.addStretch(1) # соедениям оба стиля расположения в одно horlayout.addLayout(layout) # устанавливаем расположение self.setLayout(horlayout) # функция проверяет поле широты на попадание в диапозон -90,90 иначе меняет значение на полях def adjustLatitude(self): latitude = self.LatitudeInput.text() if latitude != '' and latitude != '-': latitude = int(latitude) if latitude < -90: self.LatitudeInput.setText("-90") elif latitude > 90: self.LatitudeInput.setText("90") # функция проверяет поле долготы на попадание в диапозон -180,180 иначе меняет значение на полях def adjustLongitude(self): longitude = self.LongitudeInput.text() if longitude != '' and longitude != '-': longitude = int(longitude) if longitude < -180: self.LongitudeInput.setText("-180") elif longitude > 180: self.LongitudeInput.setText("180") # функция проверяет поле угла наклона ракеты на попадание в диапозон 0,90 иначе меняет значение на полях def adjustInclination(self): inclination = self.InclinationInput.text() if inclination != '' and inclination != '-': inclination = int(inclination) if inclination < 0: self.InclinationInput.setText("0") elif inclination > 90: self.InclinationInput.setText("90") # функция проверяет введенный год на попадание в диапозон 2017,2020 иначе меняет значение года def adjustDate(self): date = self.DateInput.date() if date.year() < 2017: date.setDate(2017, date.month(), date.day()) elif date.year() > 2020: date.setDate(2020, date.month(), date.day()) self.DateInput.setDate(date) # функция выводящее график об атмосферных данных в введенную дату и в введенных координатах def EnvironmentD(self): self.setEnvironment() self.Env.info() # функция инициализируещее атмосферные данные в модуле Environment def setEnvironment(self): self.longitude = int(self.LongitudeInput.text()) self.elevation = int(self.ElevationInput.text()) self.date = self.DateInput.date() self.latitude = int(self.LatitudeInput.text()) # подстраивание значений под диапозоны имеющихся данных if self.latitude > -90 and self.latitude < -30: self.Env = Environment( railLength=5.2, date=(self.date.year() - 2, self.date.month(), self.date.day(), 6), latitude=-7.5 + 3 * (-90 - self.latitude) / -60, longitude=324 + (2.25 * (-180 - self.longitude) / -360), elevation=self.elevation) # получение значения файла о погоде из базы данных weatherfile = self.cur.execute( '''SELECT File_Path FROM WeatherFiles WHERE File_Path LIKE "%CLBI%" AND Year=?''', (self.date.year(), )).fetchone() self.Env.setAtmosphericModel(type='Reanalysis', file=weatherfile[0], dictionary='ECMWF') elif self.latitude >= -30 and self.latitude < 30: self.Env = Environment( railLength=5.2, date=(self.date.year() - 2, self.date.month(), self.date.day(), 6), latitude=-3.75 + 5.25 * (-30 - self.latitude) / -60, longitude=314.25 + 3 * (-180 - self.longitude) / -360, elevation=self.elevation) weatherfile = self.cur.execute( '''SELECT File_Path FROM WeatherFiles WHERE File_Path LIKE "%Alcantara%" AND Year=?''', (self.date.year(), )).fetchone() self.Env.setAtmosphericModel(type='Reanalysis', file=weatherfile[0], dictionary='ECMWF') elif self.latitude >= 30 and self.latitude <= 90: self.Env = Environment( railLength=5.2, date=(self.date.year() - 2, self.date.month(), self.date.day(), 6), latitude=31.5 + 3 * (90 - self.latitude) / 60, longitude=252 + 2.25 * (-180 - self.longitude) / -360, elevation=self.elevation) weatherfile = self.cur.execute( '''SELECT File_Path FROM WeatherFiles WHERE File_Path LIKE "%Spaceport%" AND Year=?''', (self.date.year(), )).fetchone() self.Env.setAtmosphericModel(type='Reanalysis', file=weatherfile[0], dictionary='ECMWF') # функция назначает имя текущего выбранного мотора из группы радиокнопок def setMotor(self, name): name = name.split() name = '_'.join(name) self.motorName = name # функция инициализирует модель ракеты внутри модуля SolidMotor def setMotorModel(self): motorfile = self.cur.execute( 'SELECT File_Path FROM Motors WHERE Motor_Name=?', (self.motorName, )).fetchone() motorfile = str(motorfile[0]) self.motor_model = SolidMotor(thrustSource=motorfile, burnOut=3.9, grainNumber=5, grainSeparation=5 / 1000, grainDensity=1815, grainOuterRadius=33 / 1000, grainInitialInnerRadius=15 / 1000, grainInitialHeight=120 / 1000, nozzleRadius=33 / 1000, throatRadius=11 / 1000, interpolationMethod='linear') # функция выводит график сопротивления мотора def motorInfo(self): self.setMotorModel() self.motor_model.info() # функция назначает текущее имя выбранного типа ракеты def setRocket(self, name): self.rocketName = name # функция инициализирует модель ракеты с помощью модуля Rocket def setRocketModel(self): self.inclination = int(self.InclinationInput.text()) # получение файла толчка из базы данных thrustcurve = self.cur.execute( 'SELECT File_Path FROM Rockets WHERE Rocket_Name=?', (self.rocketName, )).fetchone() thrustcurve = str(thrustcurve[0]) self.RocketModel = Rocket( motor=self.motor_model, radius=127 / 2000, mass=19.197 - 2.956, inertiaI=6.60, inertiaZ=0.0351, distanceRocketNozzle=-1.255, distanceRocketPropellant=-0.85704, powerOffDrag="data/calisto/powerOffDragCurve.csv", powerOnDrag=thrustcurve) self.RocketModel.setRailButtons([0.2, -0.5]) # добавление деталей в модель ракеты по модулю Rocket NoseCone = self.RocketModel.addNose(length=0.55829, kind="vonKarman", distanceToCM=0.71971) FinSet = self.RocketModel.addFins(4, span=0.100, rootChord=0.120, tipChord=0.040, distanceToCM=-1.04956) Tail = self.RocketModel.addTail(topRadius=0.0635, bottomRadius=0.0435, length=0.060, distanceToCM=-1.194656) # добавление парашютов Main = self.RocketModel.addParachute('Main', CdS=10.0, trigger=self.mainTrigger, samplingRate=105, lag=1.5, noise=(0, 8.3, 0.5)) Drogue = self.RocketModel.addParachute('Drogue', CdS=1.0, trigger=self.drogueTrigger, samplingRate=105, lag=1.5, noise=(0, 8.3, 0.5)) self.TestFlight = Flight(rocket=self.RocketModel, environment=self.Env, inclination=self.inclination, heading=0) # функции активаций парашютов def drogueTrigger(self, p, y): return True if y[5] < 0 else False def mainTrigger(self, p, y): return True if y[5] < 0 and y[2] < 800 else False # функция выдаёт траекторию ракеты def GetTrajectory(self): self.setMotorModel() self.setEnvironment() self.setRocketModel() self.TestFlight.plot3dTrajectory() # функция выдаёт график кинематических данных def GetKinematics(self): self.setMotorModel() self.setEnvironment() self.setRocketModel() self.TestFlight.plotLinearKinematicsData() # функция выдаёт график скоростных данных def GetAltitude(self): self.setMotorModel() self.setEnvironment() self.setRocketModel() self.TestFlight.plotAttitudeData() # функция выдаёт график энергий во время полёта def GetEnergy(self): self.setMotorModel() self.setEnvironment() self.setRocketModel() self.TestFlight.plotEnergyData()
class AddTransactionsForm(QVBoxLayout): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # Title self.title = QLabel(self.tr("Add Transaction")) self.title.setFont(TitleFont()) self.title.setAlignment(Qt.AlignCenter) # First line: Date self.label1 = QLabel(self.tr("Date")) # self.label1.setMinimumWidth(120) self.label1.setMaximumWidth(120) self.date_edit = QDateEdit(datetime.now()) self.date_edit.setDisplayFormat("dd/MM/yyyy") self.date_edit.setCalendarPopup(True) self.label1_checkbox = QPushButton(self.tr("Today")) self.label1_checkbox.setMaximumWidth(50) self.label1_checkbox.clicked.connect(self.setToday) self.line1 = QHBoxLayout() self.line1.addWidget(self.label1) self.line1.addWidget(self.date_edit) self.line1.addWidget(self.label1_checkbox) # Second Line: Account self.label2 = QLabel(self.tr("Sender Account")) self.label2.setMinimumWidth(120) self.label2.setMaximumWidth(120) self.senderaccount_select = QComboBox() self.senderaccount_select.setEditable(True) self.senderaccount_select.setDuplicatesEnabled(False) currentaccounts = [a[0] for a in balances.get_all_accounts()] self.senderaccount_select.addItems(currentaccounts) self.line2 = QHBoxLayout() self.line2.addWidget(self.label2) self.line2.addWidget(self.senderaccount_select, Qt.AlignLeft) # Third Line: Receiver Account self.label3 = QLabel(self.tr("Receiver Account")) self.label3.setMinimumWidth(120) self.label3.setMaximumWidth(120) self.receiveraccount_select = QComboBox() self.receiveraccount_select.setEditable(True) self.receiveraccount_select.setDuplicatesEnabled(False) currentaccounts = [a[0] for a in balances.get_all_accounts()] self.receiveraccount_select.addItems(currentaccounts) self.receiveraccount_select.setCurrentIndex(1) self.line3 = QHBoxLayout() self.line3.addWidget(self.label3) self.line3.addWidget(self.receiveraccount_select, Qt.AlignLeft) # Fourth Line: Amount self.label4 = QLabel(self.tr("Amount")) self.label4.setMinimumWidth(120) self.label4.setMaximumWidth(120) self.amount_select = QSpinBox() self.amount_select.setSuffix(" €") self.amount_select.setMinimum(0) self.amount_select.setMaximum(999999999) self.amount_select.setAccelerated(True) self.line4 = QHBoxLayout() self.line4.addWidget(self.label4) self.line4.addWidget(self.amount_select, Qt.AlignLeft) # Fifth Line: Deposit or Withdrawal self.group = QButtonGroup(self) self.deposit_checkbox = QCheckBox('Deposit') self.deposit_checkbox.stateChanged.connect(self.handlechecks) self.withdrawal_checkbox = QCheckBox('Withdrawal') self.withdrawal_checkbox.stateChanged.connect(self.handlechecks) self.transfer_checkbox = QCheckBox('Transfer') self.transfer_checkbox.stateChanged.connect(self.handlechecks) self.line5 = QHBoxLayout() self.line5.addWidget(self.deposit_checkbox) self.line5.addWidget(self.withdrawal_checkbox) self.line5.addWidget(self.transfer_checkbox) # Sixth Line: Description self.label6 = QLabel(self.tr("Description")) self.label6.setFixedWidth(120) self.description_edit = QLineEdit() self.line6 = QHBoxLayout() self.line6.addWidget(self.label6) self.line6.addWidget(self.description_edit) # Buttons self.button_layout = QHBoxLayout() self.insert_button = QPushButton(self.tr("Insert")) self.insert_button.setMaximumWidth(50) self.button_layout.setAlignment(Qt.AlignHCenter | Qt.AlignTop) # Centering it self.button_layout.setContentsMargins(QMargins( 10, 10, 10, 10)) # A little bit of margin self.insert_button.clicked.connect(self.insertTransaction) self.button_layout.addWidget(self.insert_button, Qt.AlignVCenter) self.addWidget(self.title) self.addLayout(self.line1) self.addLayout(self.line2) self.addLayout(self.line3) self.addLayout(self.line4) self.addLayout(self.line5) self.addLayout(self.line6) self.addLayout(self.button_layout) # Signal handle self.receiveraccount_select.currentTextChanged.connect( self.handleselections) self.senderaccount_select.currentTextChanged.connect( self.handleselections) def setToday(self): self.date_edit.setDate(datetime.now()) def insertTransaction(self): # Current data self.current_date = datetime(self.date_edit.date().year(), self.date_edit.date().month(), self.date_edit.date().day()).timestamp() self.current_senderaccount = self.senderaccount_select.currentText() self.current_receiveraccount = self.receiveraccount_select.currentText( ) self.current_amount = int(float(self.amount_select.text()[:-2])) # Deposit/Withdrawal/Transfer if self.deposit_checkbox.isChecked(): self.currenttype = 1 elif self.withdrawal_checkbox.isChecked(): self.currenttype = -1 else: # No checked defaults to transfer self.currenttype = 0 # If there is a new account involved, it should be created first all_accounts = [i[0] for i in balances.get_all_accounts()] if self.current_senderaccount not in all_accounts: balances.add_account(self.current_senderaccount, 0) if self.current_receiveraccount not in all_accounts: balances.add_account(self.current_receiveraccount, 0) # Adding the transaction on db transactions.add_transaction(self.current_date, self.current_senderaccount, self.current_amount, self.current_receiveraccount, self.currenttype, description=self.description_edit.text()) def handlechecks(self, state): """ Proper checkbox behavour """ # Checking if state is checked if state == Qt.Checked: if self.sender() == self.deposit_checkbox: # making others unchecked self.withdrawal_checkbox.setChecked(False) self.transfer_checkbox.setChecked(False) elif self.sender() == self.withdrawal_checkbox: # making others unchecked self.deposit_checkbox.setChecked(False) self.transfer_checkbox.setChecked(False) elif self.sender() == self.transfer_checkbox: # making others unchecked self.deposit_checkbox.setChecked(False) self.withdrawal_checkbox.setChecked(False) # Now that only one checkbox is checked, we change the form according to the transfer type if self.deposit_checkbox.isChecked(): self.senderaccount_select.setCurrentText("Cash") if self.withdrawal_checkbox.isChecked(): self.receiveraccount_select.setCurrentText("Cash") else: pass def handleselections(self): """ Establishing certain retrictions """ if self.receiveraccount_select.currentText( ) == self.senderaccount_select.currentText(): # We move the currentIndex, so that both accounts can't be the same self.senderaccount_select.setStyleSheet("color: red") self.receiveraccount_select.setStyleSheet("color:red") self.insert_button.hide() else: self.senderaccount_select.setStyleSheet("") self.receiveraccount_select.setStyleSheet("") self.insert_button.show() # 'Cash' special cases if self.senderaccount_select.currentText() != 'Cash' and \ self.receiveraccount_select.currentText() != 'Cash': self.transfer_checkbox.setChecked(True)
class HydroprintGUI(myqt.DialogWindow): ConsoleSignal = QSignal(str) def __init__(self, datamanager, parent=None): super(HydroprintGUI, self).__init__(parent, maximize=True) self.__updateUI = True # Child widgets: self.dmngr = datamanager self.dmngr.wldsetChanged.connect(self.wldset_changed) self.dmngr.wxdsetChanged.connect(self.wxdset_changed) self.page_setup_win = PageSetupWin(self) self.page_setup_win.newPageSetupSent.connect(self.layout_changed) self.color_palette_win = ColorsSetupWin(self) self.color_palette_win.newColorSetupSent.connect(self.update_colors) # Memory path variable: self.save_fig_dir = self.workdir # Generate UI: self.__initUI__() def __initUI__(self): # ---- Toolbar self.btn_save = btn_save = QToolButtonNormal(icons.get_icon('save')) btn_save.setToolTip('Save the well hydrograph') # btn_draw is usefull for debugging purposes btn_draw = QToolButtonNormal(icons.get_icon('refresh')) btn_draw.setToolTip('Force a refresh of the well hydrograph') btn_draw.hide() self.btn_load_layout = QToolButtonNormal( icons.get_icon('load_graph_config')) self.btn_load_layout.setToolTip( "<p>Load graph layout for the current water level " " datafile if it exists</p>") self.btn_load_layout.clicked.connect(self.load_layout_isClicked) self.btn_save_layout = QToolButtonNormal( icons.get_icon('save_graph_config')) self.btn_save_layout.setToolTip('Save current graph layout') self.btn_save_layout.clicked.connect(self.save_layout_isClicked) btn_bestfit_waterlvl = QToolButtonNormal(icons.get_icon('fit_y')) btn_bestfit_waterlvl.setToolTip('Best fit the water level scale') btn_bestfit_time = QToolButtonNormal(icons.get_icon('fit_x')) btn_bestfit_time.setToolTip('Best fit the time scale') self.btn_page_setup = QToolButtonNormal(icons.get_icon('page_setup')) self.btn_page_setup.setToolTip('Show the page setup window') self.btn_page_setup.clicked.connect(self.page_setup_win.show) btn_color_pick = QToolButtonNormal(icons.get_icon('color_picker')) btn_color_pick.setToolTip('<p>Show a window to setup the color palette' ' used to draw the hydrograph</p.') btn_color_pick.clicked.connect(self.color_palette_win.show) self.btn_language = LangToolButton() self.btn_language.setToolTip( "Set the language of the text shown in the graph.") self.btn_language.sig_lang_changed.connect(self.layout_changed) self.btn_language.setIconSize(icons.get_iconsize('normal')) # ---- Zoom Panel btn_zoom_out = QToolButtonSmall(icons.get_icon('zoom_out')) btn_zoom_out.setToolTip('Zoom out (ctrl + mouse-wheel-down)') btn_zoom_out.clicked.connect(self.zoom_out) btn_zoom_in = QToolButtonSmall(icons.get_icon('zoom_in')) btn_zoom_in.setToolTip('Zoom in (ctrl + mouse-wheel-up)') btn_zoom_in.clicked.connect(self.zoom_in) self.zoom_disp = QSpinBox() self.zoom_disp.setAlignment(Qt.AlignCenter) self.zoom_disp.setButtonSymbols(QAbstractSpinBox.NoButtons) self.zoom_disp.setReadOnly(True) self.zoom_disp.setSuffix(' %') self.zoom_disp.setRange(0, 9999) self.zoom_disp.setValue(100) zoom_pan = myqt.QFrameLayout() zoom_pan.setSpacing(3) zoom_pan.addWidget(btn_zoom_out, 0, 0) zoom_pan.addWidget(btn_zoom_in, 0, 1) zoom_pan.addWidget(self.zoom_disp, 0, 2) # LAYOUT : btn_list = [ btn_save, btn_draw, self.btn_load_layout, self.btn_save_layout, VSep(), btn_bestfit_waterlvl, btn_bestfit_time, VSep(), self.btn_page_setup, btn_color_pick, self.btn_language, VSep(), zoom_pan ] subgrid_toolbar = QGridLayout() toolbar_widget = QWidget() row = 0 for col, btn in enumerate(btn_list): subgrid_toolbar.addWidget(btn, row, col) subgrid_toolbar.setSpacing(5) subgrid_toolbar.setContentsMargins(0, 0, 0, 0) subgrid_toolbar.setColumnStretch(col + 1, 100) toolbar_widget.setLayout(subgrid_toolbar) # ---- LEFT PANEL # SubGrid Hydrograph Frame : self.hydrograph = hydrograph.Hydrograph() self.hydrograph_scrollarea = mplFigViewer.ImageViewer() self.hydrograph_scrollarea.zoomChanged.connect(self.zoom_disp.setValue) grid_hydrograph = QGridLayout() grid_hydrograph.addWidget(self.hydrograph_scrollarea, 0, 0) grid_hydrograph.setRowStretch(0, 500) grid_hydrograph.setColumnStretch(0, 500) grid_hydrograph.setContentsMargins(0, 0, 0, 0) # (L, T, R, B) # ASSEMBLING SubGrids : grid_layout = QGridLayout() self.grid_layout_widget = QFrame() row = 0 grid_layout.addWidget(toolbar_widget, row, 0) row += 1 grid_layout.addLayout(grid_hydrograph, row, 0) grid_layout.setContentsMargins(0, 0, 0, 0) # (L, T, R, B) grid_layout.setSpacing(5) grid_layout.setColumnStretch(0, 500) grid_layout.setRowStretch(1, 500) self.grid_layout_widget.setLayout(grid_layout) # ---- Right Panel self.tabscales = self.__init_scalesTabWidget__() self.right_panel = myqt.QFrameLayout() self.right_panel.addWidget(self.dmngr, 0, 0) self.right_panel.addWidget(self.tabscales, 1, 0) self.right_panel.setRowStretch(2, 100) self.right_panel.setSpacing(15) # ---- MAIN GRID mainGrid = QGridLayout() mainGrid.addWidget(self.grid_layout_widget, 0, 0) mainGrid.addWidget(VSep(), 0, 1) mainGrid.addWidget(self.right_panel, 0, 2) mainGrid.setContentsMargins(10, 10, 10, 10) # (L, T, R, B) mainGrid.setSpacing(15) mainGrid.setColumnStretch(0, 500) mainGrid.setColumnMinimumWidth(2, 250) self.setLayout(mainGrid) # ---- EVENTS # Toolbox Layout : btn_bestfit_waterlvl.clicked.connect(self.best_fit_waterlvl) btn_bestfit_time.clicked.connect(self.best_fit_time) btn_draw.clicked.connect(self.draw_hydrograph) btn_save.clicked.connect(self.select_save_path) # Hydrograph Layout : self.Ptot_scale.valueChanged.connect(self.layout_changed) self.qweather_bin.currentIndexChanged.connect(self.layout_changed) # ---- Init Image self.hydrograph_scrollarea.load_mpl_figure(self.hydrograph) def __init_scalesTabWidget__(self): class QRowLayout(QGridLayout): def __init__(self, items, parent=None): super(QRowLayout, self).__init__(parent) for col, item in enumerate(items): self.addWidget(item, 0, col) self.setContentsMargins(0, 0, 0, 0) self.setColumnStretch(0, 100) # ---- Time axis properties # Generate the widgets : self.date_start_widget = QDateEdit() self.date_start_widget.setDisplayFormat('01 / MM / yyyy') self.date_start_widget.setAlignment(Qt.AlignCenter) self.date_start_widget.dateChanged.connect(self.layout_changed) self.date_end_widget = QDateEdit() self.date_end_widget.setDisplayFormat('01 / MM / yyyy') self.date_end_widget.setAlignment(Qt.AlignCenter) self.date_end_widget.dateChanged.connect(self.layout_changed) self.time_scale_label = QComboBox() self.time_scale_label.setEditable(False) self.time_scale_label.setInsertPolicy(QComboBox.NoInsert) self.time_scale_label.addItems(['Month', 'Year']) self.time_scale_label.setCurrentIndex(0) self.time_scale_label.currentIndexChanged.connect(self.layout_changed) self.dateDispFreq_spinBox = QSpinBox() self.dateDispFreq_spinBox.setSingleStep(1) self.dateDispFreq_spinBox.setMinimum(1) self.dateDispFreq_spinBox.setMaximum(100) self.dateDispFreq_spinBox.setValue(self.hydrograph.date_labels_pattern) self.dateDispFreq_spinBox.setAlignment(Qt.AlignCenter) self.dateDispFreq_spinBox.setKeyboardTracking(False) self.dateDispFreq_spinBox.valueChanged.connect(self.layout_changed) # Setting up the layout : widget_time_scale = QFrame() widget_time_scale.setFrameStyle(0) grid_time_scale = QGridLayout() GRID = [[QLabel('From :'), self.date_start_widget], [QLabel('To :'), self.date_end_widget], [QLabel('Scale :'), self.time_scale_label], [QLabel('Date Disp. Pattern:'), self.dateDispFreq_spinBox]] for i, ROW in enumerate(GRID): grid_time_scale.addLayout(QRowLayout(ROW), i, 1) grid_time_scale.setVerticalSpacing(5) grid_time_scale.setContentsMargins(10, 10, 10, 10) widget_time_scale.setLayout(grid_time_scale) # ----- Water level axis properties # Widget : self.waterlvl_scale = QDoubleSpinBox() self.waterlvl_scale.setSingleStep(0.05) self.waterlvl_scale.setMinimum(0.05) self.waterlvl_scale.setSuffix(' m') self.waterlvl_scale.setAlignment(Qt.AlignCenter) self.waterlvl_scale.setKeyboardTracking(False) self.waterlvl_scale.valueChanged.connect(self.layout_changed) self.waterlvl_scale.setFixedWidth(100) self.waterlvl_max = QDoubleSpinBox() self.waterlvl_max.setSingleStep(0.1) self.waterlvl_max.setSuffix(' m') self.waterlvl_max.setAlignment(Qt.AlignCenter) self.waterlvl_max.setMinimum(-1000) self.waterlvl_max.setMaximum(1000) self.waterlvl_max.setKeyboardTracking(False) self.waterlvl_max.valueChanged.connect(self.layout_changed) self.waterlvl_max.setFixedWidth(100) self.NZGridWL_spinBox = QSpinBox() self.NZGridWL_spinBox.setSingleStep(1) self.NZGridWL_spinBox.setMinimum(1) self.NZGridWL_spinBox.setMaximum(50) self.NZGridWL_spinBox.setValue(self.hydrograph.NZGrid) self.NZGridWL_spinBox.setAlignment(Qt.AlignCenter) self.NZGridWL_spinBox.setKeyboardTracking(False) self.NZGridWL_spinBox.valueChanged.connect(self.layout_changed) self.NZGridWL_spinBox.setFixedWidth(100) self.datum_widget = QComboBox() self.datum_widget.addItems(['Ground Surface', 'Sea Level']) self.datum_widget.currentIndexChanged.connect(self.layout_changed) # Layout : subgrid_WLScale = QGridLayout() GRID = [[QLabel('Minimum :'), self.waterlvl_max], [QLabel('Scale :'), self.waterlvl_scale], [QLabel('Grid Divisions :'), self.NZGridWL_spinBox], [QLabel('Datum :'), self.datum_widget]] for i, ROW in enumerate(GRID): subgrid_WLScale.addLayout(QRowLayout(ROW), i, 1) subgrid_WLScale.setVerticalSpacing(5) subgrid_WLScale.setContentsMargins(10, 10, 10, 10) # (L, T, R, B) WLScale_widget = QFrame() WLScale_widget.setFrameStyle(0) WLScale_widget.setLayout(subgrid_WLScale) # ---- Weather Axis # Widgets : self.Ptot_scale = QSpinBox() self.Ptot_scale.setSingleStep(5) self.Ptot_scale.setMinimum(5) self.Ptot_scale.setMaximum(500) self.Ptot_scale.setValue(20) self.Ptot_scale.setSuffix(' mm') self.Ptot_scale.setAlignment(Qt.AlignCenter) self.qweather_bin = QComboBox() self.qweather_bin.setEditable(False) self.qweather_bin.setInsertPolicy(QComboBox.NoInsert) self.qweather_bin.addItems(['day', 'week', 'month']) self.qweather_bin.setCurrentIndex(1) # Layout : layout = QGridLayout() GRID = [[QLabel('Precip. Scale :'), self.Ptot_scale], [QLabel('Resampling :'), self.qweather_bin]] for i, row in enumerate(GRID): layout.addLayout(QRowLayout(row), i, 1) layout.setVerticalSpacing(5) layout.setContentsMargins(10, 10, 10, 10) # (L,T,R,B) layout.setRowStretch(i + 1, 100) widget_weather_scale = QFrame() widget_weather_scale.setFrameStyle(0) widget_weather_scale.setLayout(layout) # ---- ASSEMBLING TABS tabscales = QTabWidget() tabscales.addTab(widget_time_scale, 'Time') tabscales.addTab(WLScale_widget, 'Water Level') tabscales.addTab(widget_weather_scale, 'Weather') return tabscales @property def workdir(self): return self.dmngr.workdir # ---- Utilities def zoom_in(self): self.hydrograph_scrollarea.zoomIn() def zoom_out(self): self.hydrograph_scrollarea.zoomOut() def update_colors(self): self.hydrograph.update_colors() self.hydrograph_scrollarea.load_mpl_figure(self.hydrograph) # ---- Datasets Handlers @property def wldset(self): return self.dmngr.get_current_wldset() @property def wxdset(self): return self.dmngr.get_current_wxdset() def wldset_changed(self): """Handle when the water level dataset of the datamanager changes.""" if self.wldset is None: self.clear_hydrograph() return else: wldset = self.wldset self.hydrograph.set_wldset(wldset) self.hydrograph.gluedf = self.wldset.get_glue_at(-1) # Load the manual measurements. fname = os.path.join(self.workdir, "Water Levels", 'waterlvl_manual_measurements') tmeas, wlmeas = load_waterlvl_measures(fname, wldset['Well']) wldset.set_wlmeas(tmeas, wlmeas) # Setup the layout of the hydrograph. layout = wldset.get_layout() if layout is not None: msg = 'Loading existing graph layout for well %s.' % wldset['Well'] print(msg) self.ConsoleSignal.emit('<font color=black>%s</font>' % msg) self.load_graph_layout(layout) else: print('No graph layout exists for well %s.' % wldset['Well']) # Fit Water Level in Layout : self.__updateUI = False self.best_fit_waterlvl() self.best_fit_time() self.dmngr.set_closest_wxdset() self.__updateUI = True def wxdset_changed(self): """Handle when the weather dataset of the datamanager changes.""" if self.wldset is None: self.clear_hydrograph() else: self.hydrograph.set_wxdset(self.wxdset) QCoreApplication.processEvents() self.draw_hydrograph() # ---- Draw Hydrograph Handlers def best_fit_waterlvl(self): wldset = self.dmngr.get_current_wldset() if wldset is not None: WLscale, WLmin = self.hydrograph.best_fit_waterlvl() self.waterlvl_scale.setValue(WLscale) self.waterlvl_max.setValue(WLmin) def best_fit_time(self): wldset = self.dmngr.get_current_wldset() if wldset is not None: date0, date1 = self.hydrograph.best_fit_time(wldset['Time']) self.date_start_widget.setDate(QDate(date0[0], date0[1], date0[2])) self.date_end_widget.setDate(QDate(date1[0], date1[1], date1[2])) @QSlot() def mrc_wl_changed(self): """ Force a redraw of the MRC water levels after the results have changed for the dataset. """ self.hydrograph.draw_mrc_wl() self.hydrograph.setup_legend() self.hydrograph_scrollarea.load_mpl_figure(self.hydrograph) @QSlot(GLUEDataFrameBase) def glue_wl_changed(self, gluedf): """ Force a redraw of the GLUE water levels after the results have changed for the dataset. """ self.hydrograph.set_gluedf(gluedf) self.hydrograph_scrollarea.load_mpl_figure(self.hydrograph) def layout_changed(self): """ When an element of the graph layout is changed in the UI. """ if self.__updateUI is False: return self.update_graph_layout_parameter() if self.hydrograph.isHydrographExists is False: return sender = self.sender() if sender == self.btn_language: self.hydrograph.draw_ylabels() self.hydrograph.setup_xticklabels() self.hydrograph.setup_legend() elif sender in [self.waterlvl_max, self.waterlvl_scale]: self.hydrograph.setup_waterlvl_scale() self.hydrograph.draw_ylabels() elif sender == self.NZGridWL_spinBox: self.hydrograph.setup_waterlvl_scale() self.hydrograph.update_precip_scale() self.hydrograph.draw_ylabels() elif sender == self.Ptot_scale: self.hydrograph.update_precip_scale() self.hydrograph.draw_ylabels() elif sender == self.datum_widget: yoffset = int(self.wldset['Elevation'] / self.hydrograph.WLscale) yoffset *= self.hydrograph.WLscale self.hydrograph.WLmin = (yoffset - self.hydrograph.WLmin) self.waterlvl_max.blockSignals(True) self.waterlvl_max.setValue(self.hydrograph.WLmin) self.waterlvl_max.blockSignals(False) # This is calculated so that trailing zeros in the altitude of the # well is not carried to the y axis labels, so that they remain a # int multiple of *WLscale*. self.hydrograph.setup_waterlvl_scale() self.hydrograph.draw_waterlvl() self.hydrograph.draw_ylabels() elif sender in [self.date_start_widget, self.date_end_widget]: self.hydrograph.set_time_scale() self.hydrograph.draw_weather() self.hydrograph.draw_figure_title() elif sender == self.dateDispFreq_spinBox: self.hydrograph.set_time_scale() self.hydrograph.setup_xticklabels() elif sender == self.page_setup_win: self.hydrograph.update_fig_size() # Implicitly call : set_margins() # draw_ylabels() # set_time_scale() # draw_figure_title self.hydrograph.draw_waterlvl() self.hydrograph.setup_legend() elif sender == self.qweather_bin: self.hydrograph.resample_bin() self.hydrograph.draw_weather() self.hydrograph.draw_ylabels() elif sender == self.time_scale_label: self.hydrograph.set_time_scale() self.hydrograph.draw_weather() else: print('No action for this widget yet.') # !!!! temporary fix until I can find a better solution !!!! # sender.blockSignals(True) if type(sender) in [QDoubleSpinBox, QSpinBox]: sender.setReadOnly(True) for i in range(10): QCoreApplication.processEvents() self.hydrograph_scrollarea.load_mpl_figure(self.hydrograph) for i in range(10): QCoreApplication.processEvents() if type(sender) in [QDoubleSpinBox, QSpinBox]: sender.setReadOnly(False) # sender.blockSignals(False) def update_graph_layout_parameter(self): # language : self.hydrograph.language = self.btn_language.language # Scales : self.hydrograph.WLmin = self.waterlvl_max.value() self.hydrograph.WLscale = self.waterlvl_scale.value() self.hydrograph.RAINscale = self.Ptot_scale.value() self.hydrograph.NZGrid = self.NZGridWL_spinBox.value() # WL Datum : self.hydrograph.WLdatum = self.datum_widget.currentIndex() # Dates : self.hydrograph.datemode = self.time_scale_label.currentText() year = self.date_start_widget.date().year() month = self.date_start_widget.date().month() self.hydrograph.TIMEmin = xldate_from_date_tuple((year, month, 1), 0) year = self.date_end_widget.date().year() month = self.date_end_widget.date().month() self.hydrograph.TIMEmax = xldate_from_date_tuple((year, month, 1), 0) self.hydrograph.date_labels_pattern = self.dateDispFreq_spinBox.value() # Page Setup : self.hydrograph.fwidth = self.page_setup_win.pageSize[0] self.hydrograph.fheight = self.page_setup_win.pageSize[1] self.hydrograph.va_ratio = self.page_setup_win.va_ratio self.hydrograph.trend_line = self.page_setup_win.isTrendLine self.hydrograph.isLegend = self.page_setup_win.isLegend self.hydrograph.isGraphTitle = self.page_setup_win.isGraphTitle self.hydrograph.set_meteo_on(self.page_setup_win.is_meteo_on) self.hydrograph.set_glue_wl_on(self.page_setup_win.is_glue_wl_on) self.hydrograph.set_mrc_wl_on(self.page_setup_win.is_mrc_wl_on) self.hydrograph.set_figframe_lw(self.page_setup_win.figframe_lw) # Weather bins : self.hydrograph.bwidth_indx = self.qweather_bin.currentIndex() def clear_hydrograph(self): """Clear the hydrograph figure to show only a blank canvas.""" self.hydrograph.clf() self.hydrograph_scrollarea.load_mpl_figure(self.hydrograph) def draw_hydrograph(self): if self.dmngr.wldataset_count() == 0: msg = 'Please import a valid water level data file first.' self.ConsoleSignal.emit('<font color=red>%s</font>' % msg) self.emit_warning(msg) return self.update_graph_layout_parameter() # Generate and Display Graph : for i in range(5): QCoreApplication.processEvents() QApplication.setOverrideCursor(Qt.WaitCursor) self.hydrograph.set_wldset(self.dmngr.get_current_wldset()) self.hydrograph.set_wxdset(self.dmngr.get_current_wxdset()) self.hydrograph.generate_hydrograph() self.hydrograph_scrollarea.load_mpl_figure(self.hydrograph) QApplication.restoreOverrideCursor() def select_save_path(self): """ Open a dialog where the user can select a file name to save the hydrograph. """ if self.wldset is None: return ffmat = "*.pdf;;*.svg;;*.png" fname = find_unique_filename( osp.join(self.save_fig_dir, 'hydrograph_%s.pdf' % self.wldset['Well'])) fname, ftype = QFileDialog.getSaveFileName(self, "Save Figure", fname, ffmat) if fname: ftype = ftype.replace('*', '') fname = fname if fname.endswith(ftype) else fname + ftype self.save_fig_dir = os.path.dirname(fname) try: self.save_figure(fname) except PermissionError: msg = "The file is in use by another application or user." QMessageBox.warning(self, 'Warning', msg, QMessageBox.Ok) self.select_save_path() def save_figure(self, fname): """Save the hydrograph figure in a file.""" self.hydrograph.generate_hydrograph() self.hydrograph.savefig(fname) # ---- Graph Layout Handlers def load_layout_isClicked(self): """Handle when the button to load the graph layout is clicked.""" if self.wldset is None: self.emit_warning( "Please import a valid water level data file first.") return layout = self.wldset.get_layout() if layout is None: self.emit_warning("No graph layout exists for well %s." % self.wldset['Well']) else: self.load_graph_layout(layout) def load_graph_layout(self, layout): """Load the graph layout into the GUI.""" self.__updateUI = False # Scales : date = layout['TIMEmin'] date = xldate_as_tuple(date, 0) self.date_start_widget.setDate(QDate(date[0], date[1], date[2])) date = layout['TIMEmax'] date = xldate_as_tuple(date, 0) self.date_end_widget.setDate(QDate(date[0], date[1], date[2])) self.dateDispFreq_spinBox.setValue(layout['date_labels_pattern']) self.waterlvl_scale.setValue(layout['WLscale']) self.waterlvl_max.setValue(layout['WLmin']) self.NZGridWL_spinBox.setValue(layout['NZGrid']) self.Ptot_scale.setValue(layout['RAINscale']) x = ['mbgs', 'masl'].index(layout['WLdatum']) self.datum_widget.setCurrentIndex(x) self.qweather_bin.setCurrentIndex(layout['bwidth_indx']) self.time_scale_label.setCurrentIndex( self.time_scale_label.findText(layout['datemode'])) # ---- Language and colors self.btn_language.set_language(layout['language']) self.color_palette_win.load_colors() # ---- Page Setup self.page_setup_win.pageSize = (layout['fwidth'], layout['fheight']) self.page_setup_win.va_ratio = layout['va_ratio'] self.page_setup_win.isLegend = layout['legend_on'] self.page_setup_win.isGraphTitle = layout['title_on'] self.page_setup_win.isTrendLine = layout['trend_line'] self.page_setup_win.is_meteo_on = layout['meteo_on'] self.page_setup_win.is_glue_wl_on = layout['glue_wl_on'] self.page_setup_win.is_mrc_wl_on = layout['mrc_wl_on'] self.page_setup_win.figframe_lw = layout['figframe_lw'] self.page_setup_win.legend_on.set_value(layout['legend_on']) self.page_setup_win.title_on.set_value(layout['title_on']) self.page_setup_win.wltrend_on.set_value(layout['trend_line']) self.page_setup_win.meteo_on.set_value(layout['meteo_on']) self.page_setup_win.glue_wl_on.set_value(layout['glue_wl_on']) self.page_setup_win.mrc_wl_on.set_value(layout['mrc_wl_on']) self.page_setup_win.fframe_lw_widg.setValue(layout['figframe_lw']) self.page_setup_win.fwidth.setValue(layout['fwidth']) self.page_setup_win.fheight.setValue(layout['fheight']) self.page_setup_win.va_ratio_spinBox.setValue(layout['va_ratio']) # Check if Weather Dataset : if layout['wxdset'] in self.dmngr.wxdsets: self.dmngr.set_current_wxdset(layout['wxdset']) else: self.dmngr.set_closest_wxdset() self.__updateUI = True def save_layout_isClicked(self): wldset = self.wldset if wldset is None: self.emit_warning( "Please import a valid water level data file first.") return layout = wldset.get_layout() if layout is not None: msg = ('A graph layout already exists for well %s.Do you want to' ' you want to replace it?') % wldset['Well'] reply = QMessageBox.question(self, 'Save Graph Layout', msg, QMessageBox.Yes | QMessageBox.No) if reply == QMessageBox.Yes: self.save_graph_layout() elif reply == QMessageBox.No: msg = "Graph layout not saved for well %s." % wldset['Well'] self.ConsoleSignal.emit('<font color=black>%s' % msg) else: self.save_graph_layout() def save_graph_layout(self): """Save the graph layout in the project hdf5 file.""" print("Saving the graph layout for well %s..." % self.wldset['Well'], end=" ") layout = { 'WLmin': self.waterlvl_max.value(), 'WLscale': self.waterlvl_scale.value(), 'RAINscale': self.Ptot_scale.value(), 'fwidth': self.page_setup_win.pageSize[0], 'fheight': self.page_setup_win.pageSize[1], 'va_ratio': self.page_setup_win.va_ratio, 'NZGrid': self.NZGridWL_spinBox.value(), 'bwidth_indx': self.qweather_bin.currentIndex(), 'date_labels_pattern': self.dateDispFreq_spinBox.value(), 'datemode': self.time_scale_label.currentText() } layout['wxdset'] = None if self.wxdset is None else self.wxdset.name year = self.date_start_widget.date().year() month = self.date_start_widget.date().month() layout['TIMEmin'] = xldate_from_date_tuple((year, month, 1), 0) year = self.date_end_widget.date().year() month = self.date_end_widget.date().month() layout['TIMEmax'] = xldate_from_date_tuple((year, month, 1), 0) if self.datum_widget.currentIndex() == 0: layout['WLdatum'] = 'mbgs' else: layout['WLdatum'] = 'masl' # ---- Page Setup layout['title_on'] = bool(self.page_setup_win.isGraphTitle) layout['legend_on'] = bool(self.page_setup_win.isLegend) layout['language'] = self.btn_language.language layout['trend_line'] = bool(self.page_setup_win.isTrendLine) layout['meteo_on'] = bool(self.page_setup_win.is_meteo_on) layout['glue_wl_on'] = bool(self.page_setup_win.is_glue_wl_on) layout['mrc_wl_on'] = bool(self.page_setup_win.is_mrc_wl_on) layout['figframe_lw'] = self.page_setup_win.figframe_lw # Save the colors : cdb = ColorsReader() cdb.load_colors_db() layout['colors'] = cdb.RGB # Save the layout : self.wldset.save_layout(layout) msg = 'Layout saved successfully for well %s.' % self.wldset['Well'] self.ConsoleSignal.emit('<font color=black>%s</font>' % msg) print("done")
class Window(QWidget): def __init__(self): super(Window, self).__init__() self.proxyModel = MySortFilterProxyModel(self) self.proxyModel.setDynamicSortFilter(True) self.sourceView = QTreeView() self.sourceView.setRootIsDecorated(False) self.sourceView.setAlternatingRowColors(True) sourceLayout = QHBoxLayout() sourceLayout.addWidget(self.sourceView) sourceGroupBox = QGroupBox("Original Model") sourceGroupBox.setLayout(sourceLayout) self.filterCaseSensitivityCheckBox = QCheckBox("Case sensitive filter") self.filterCaseSensitivityCheckBox.setChecked(True) self.filterPatternLineEdit = QLineEdit() self.filterPatternLineEdit.setText("Grace|Sports") filterPatternLabel = QLabel("&Filter pattern:") filterPatternLabel.setBuddy(self.filterPatternLineEdit) self.filterSyntaxComboBox = QComboBox() self.filterSyntaxComboBox.addItem("Regular expression", QRegExp.RegExp) self.filterSyntaxComboBox.addItem("Wildcard", QRegExp.Wildcard) self.filterSyntaxComboBox.addItem("Fixed string", QRegExp.FixedString) self.fromDateEdit = QDateEdit() self.fromDateEdit.setDate(QDate(2006, 12, 22)) self.fromDateEdit.setCalendarPopup(True) fromLabel = QLabel("F&rom:") fromLabel.setBuddy(self.fromDateEdit) self.toDateEdit = QDateEdit() self.toDateEdit.setDate(QDate(2007, 1, 5)) self.toDateEdit.setCalendarPopup(True) toLabel = QLabel("&To:") toLabel.setBuddy(self.toDateEdit) self.filterPatternLineEdit.textChanged.connect(self.textFilterChanged) self.filterSyntaxComboBox.currentIndexChanged.connect(self.textFilterChanged) self.filterCaseSensitivityCheckBox.toggled.connect(self.textFilterChanged) self.fromDateEdit.dateChanged.connect(self.dateFilterChanged) self.toDateEdit.dateChanged.connect(self.dateFilterChanged) self.proxyView = QTreeView() self.proxyView.setRootIsDecorated(False) self.proxyView.setAlternatingRowColors(True) self.proxyView.setModel(self.proxyModel) self.proxyView.setSortingEnabled(True) self.proxyView.sortByColumn(1, Qt.AscendingOrder) self.textFilterChanged() self.dateFilterChanged() proxyLayout = QGridLayout() proxyLayout.addWidget(self.proxyView, 0, 0, 1, 3) proxyLayout.addWidget(filterPatternLabel, 1, 0) proxyLayout.addWidget(self.filterPatternLineEdit, 1, 1) proxyLayout.addWidget(self.filterSyntaxComboBox, 1, 2) proxyLayout.addWidget(self.filterCaseSensitivityCheckBox, 2, 0, 1, 3) proxyLayout.addWidget(fromLabel, 3, 0) proxyLayout.addWidget(self.fromDateEdit, 3, 1, 1, 2) proxyLayout.addWidget(toLabel, 4, 0) proxyLayout.addWidget(self.toDateEdit, 4, 1, 1, 2) proxyGroupBox = QGroupBox("Sorted/Filtered Model") proxyGroupBox.setLayout(proxyLayout) mainLayout = QVBoxLayout() mainLayout.addWidget(sourceGroupBox) mainLayout.addWidget(proxyGroupBox) self.setLayout(mainLayout) self.setWindowTitle("Custom Sort/Filter Model") self.resize(500, 450) def setSourceModel(self, model): self.proxyModel.setSourceModel(model) self.sourceView.setModel(model) def textFilterChanged(self): syntax = QRegExp.PatternSyntax( self.filterSyntaxComboBox.itemData( self.filterSyntaxComboBox.currentIndex())) caseSensitivity = ( self.filterCaseSensitivityCheckBox.isChecked() and Qt.CaseSensitive or Qt.CaseInsensitive) regExp = QRegExp(self.filterPatternLineEdit.text(), caseSensitivity, syntax) self.proxyModel.setFilterRegExp(regExp) def dateFilterChanged(self): self.proxyModel.setFilterMinimumDate(self.fromDateEdit.date()) self.proxyModel.setFilterMaximumDate(self.toDateEdit.date())
class Window(QWidget): def __init__(self): super(Window, self).__init__() self.createPreviewGroupBox() self.createGeneralOptionsGroupBox() self.createDatesGroupBox() self.createTextFormatsGroupBox() layout = QGridLayout() layout.addWidget(self.previewGroupBox, 0, 0) layout.addWidget(self.generalOptionsGroupBox, 0, 1) layout.addWidget(self.datesGroupBox, 1, 0) layout.addWidget(self.textFormatsGroupBox, 1, 1) layout.setSizeConstraint(QLayout.SetFixedSize) self.setLayout(layout) self.previewLayout.setRowMinimumHeight( 0, self.calendar.sizeHint().height()) self.previewLayout.setColumnMinimumWidth( 0, self.calendar.sizeHint().width()) self.setWindowTitle("Calendar Widget") def localeChanged(self, index): self.calendar.setLocale(self.localeCombo.itemData(index)) def firstDayChanged(self, index): self.calendar.setFirstDayOfWeek( Qt.DayOfWeek(self.firstDayCombo.itemData(index))) def selectionModeChanged(self, index): self.calendar.setSelectionMode( QCalendarWidget.SelectionMode( self.selectionModeCombo.itemData(index))) def horizontalHeaderChanged(self, index): self.calendar.setHorizontalHeaderFormat( QCalendarWidget.HorizontalHeaderFormat( self.horizontalHeaderCombo.itemData(index))) def verticalHeaderChanged(self, index): self.calendar.setVerticalHeaderFormat( QCalendarWidget.VerticalHeaderFormat( self.verticalHeaderCombo.itemData(index))) def selectedDateChanged(self): self.currentDateEdit.setDate(self.calendar.selectedDate()) def minimumDateChanged(self, date): self.calendar.setMinimumDate(date) self.maximumDateEdit.setDate(self.calendar.maximumDate()) def maximumDateChanged(self, date): self.calendar.setMaximumDate(date) self.minimumDateEdit.setDate(self.calendar.minimumDate()) def weekdayFormatChanged(self): format = QTextCharFormat() format.setForeground( Qt.GlobalColor( self.weekdayColorCombo.itemData( self.weekdayColorCombo.currentIndex()))) self.calendar.setWeekdayTextFormat(Qt.Monday, format) self.calendar.setWeekdayTextFormat(Qt.Tuesday, format) self.calendar.setWeekdayTextFormat(Qt.Wednesday, format) self.calendar.setWeekdayTextFormat(Qt.Thursday, format) self.calendar.setWeekdayTextFormat(Qt.Friday, format) def weekendFormatChanged(self): format = QTextCharFormat() format.setForeground( Qt.GlobalColor( self.weekendColorCombo.itemData( self.weekendColorCombo.currentIndex()))) self.calendar.setWeekdayTextFormat(Qt.Saturday, format) self.calendar.setWeekdayTextFormat(Qt.Sunday, format) def reformatHeaders(self): text = self.headerTextFormatCombo.currentText() format = QTextCharFormat() if text == "Bold": format.setFontWeight(QFont.Bold) elif text == "Italic": format.setFontItalic(True) elif text == "Green": format.setForeground(Qt.green) self.calendar.setHeaderTextFormat(format) def reformatCalendarPage(self): if self.firstFridayCheckBox.isChecked(): firstFriday = QDate(self.calendar.yearShown(), self.calendar.monthShown(), 1) while firstFriday.dayOfWeek() != Qt.Friday: firstFriday = firstFriday.addDays(1) firstFridayFormat = QTextCharFormat() firstFridayFormat.setForeground(Qt.blue) self.calendar.setDateTextFormat(firstFriday, firstFridayFormat) # May 1st in Red takes precedence. if self.mayFirstCheckBox.isChecked(): mayFirst = QDate(self.calendar.yearShown(), 5, 1) mayFirstFormat = QTextCharFormat() mayFirstFormat.setForeground(Qt.red) self.calendar.setDateTextFormat(mayFirst, mayFirstFormat) def createPreviewGroupBox(self): self.previewGroupBox = QGroupBox("Preview") self.calendar = QCalendarWidget() self.calendar.setMinimumDate(QDate(1900, 1, 1)) self.calendar.setMaximumDate(QDate(3000, 1, 1)) self.calendar.setGridVisible(True) self.calendar.currentPageChanged.connect(self.reformatCalendarPage) self.previewLayout = QGridLayout() self.previewLayout.addWidget(self.calendar, 0, 0, Qt.AlignCenter) self.previewGroupBox.setLayout(self.previewLayout) def createGeneralOptionsGroupBox(self): self.generalOptionsGroupBox = QGroupBox("General Options") self.localeCombo = QComboBox() curLocaleIndex = -1 index = 0 this_language = self.locale().nativeLanguageName() this_country = self.locale().nativeCountryName() for locale in QLocale.matchingLocales(QLocale.AnyLanguage, QLocale.AnyScript, QLocale.AnyCountry): language = locale.nativeLanguageName() country = locale.nativeCountryName() if language == this_language and country == this_country: curLocaleIndex = index self.localeCombo.addItem('%s/%s' % (language, country), locale) index += 1 if curLocaleIndex != -1: self.localeCombo.setCurrentIndex(curLocaleIndex) self.localeLabel = QLabel("&Locale") self.localeLabel.setBuddy(self.localeCombo) self.firstDayCombo = QComboBox() self.firstDayCombo.addItem("Sunday", Qt.Sunday) self.firstDayCombo.addItem("Monday", Qt.Monday) self.firstDayCombo.addItem("Tuesday", Qt.Tuesday) self.firstDayCombo.addItem("Wednesday", Qt.Wednesday) self.firstDayCombo.addItem("Thursday", Qt.Thursday) self.firstDayCombo.addItem("Friday", Qt.Friday) self.firstDayCombo.addItem("Saturday", Qt.Saturday) self.firstDayLabel = QLabel("Wee&k starts on:") self.firstDayLabel.setBuddy(self.firstDayCombo) self.selectionModeCombo = QComboBox() self.selectionModeCombo.addItem("Single selection", QCalendarWidget.SingleSelection) self.selectionModeCombo.addItem("None", QCalendarWidget.NoSelection) self.selectionModeLabel = QLabel("&Selection mode:") self.selectionModeLabel.setBuddy(self.selectionModeCombo) self.gridCheckBox = QCheckBox("&Grid") self.gridCheckBox.setChecked(self.calendar.isGridVisible()) self.navigationCheckBox = QCheckBox("&Navigation bar") self.navigationCheckBox.setChecked(True) self.horizontalHeaderCombo = QComboBox() self.horizontalHeaderCombo.addItem( "Single letter day names", QCalendarWidget.SingleLetterDayNames) self.horizontalHeaderCombo.addItem("Short day names", QCalendarWidget.ShortDayNames) self.horizontalHeaderCombo.addItem("Long day names", QCalendarWidget.LongDayNames) self.horizontalHeaderCombo.addItem("None", QCalendarWidget.NoHorizontalHeader) self.horizontalHeaderCombo.setCurrentIndex(1) self.horizontalHeaderLabel = QLabel("&Horizontal header:") self.horizontalHeaderLabel.setBuddy(self.horizontalHeaderCombo) self.verticalHeaderCombo = QComboBox() self.verticalHeaderCombo.addItem("ISO week numbers", QCalendarWidget.ISOWeekNumbers) self.verticalHeaderCombo.addItem("None", QCalendarWidget.NoVerticalHeader) self.verticalHeaderLabel = QLabel("&Vertical header:") self.verticalHeaderLabel.setBuddy(self.verticalHeaderCombo) self.localeCombo.currentIndexChanged.connect(self.localeChanged) self.firstDayCombo.currentIndexChanged.connect(self.firstDayChanged) self.selectionModeCombo.currentIndexChanged.connect( self.selectionModeChanged) self.gridCheckBox.toggled.connect(self.calendar.setGridVisible) self.navigationCheckBox.toggled.connect( self.calendar.setNavigationBarVisible) self.horizontalHeaderCombo.currentIndexChanged.connect( self.horizontalHeaderChanged) self.verticalHeaderCombo.currentIndexChanged.connect( self.verticalHeaderChanged) checkBoxLayout = QHBoxLayout() checkBoxLayout.addWidget(self.gridCheckBox) checkBoxLayout.addStretch() checkBoxLayout.addWidget(self.navigationCheckBox) outerLayout = QGridLayout() outerLayout.addWidget(self.localeLabel, 0, 0) outerLayout.addWidget(self.localeCombo, 0, 1) outerLayout.addWidget(self.firstDayLabel, 1, 0) outerLayout.addWidget(self.firstDayCombo, 1, 1) outerLayout.addWidget(self.selectionModeLabel, 2, 0) outerLayout.addWidget(self.selectionModeCombo, 2, 1) outerLayout.addLayout(checkBoxLayout, 3, 0, 1, 2) outerLayout.addWidget(self.horizontalHeaderLabel, 4, 0) outerLayout.addWidget(self.horizontalHeaderCombo, 4, 1) outerLayout.addWidget(self.verticalHeaderLabel, 5, 0) outerLayout.addWidget(self.verticalHeaderCombo, 5, 1) self.generalOptionsGroupBox.setLayout(outerLayout) self.firstDayChanged(self.firstDayCombo.currentIndex()) self.selectionModeChanged(self.selectionModeCombo.currentIndex()) self.horizontalHeaderChanged(self.horizontalHeaderCombo.currentIndex()) self.verticalHeaderChanged(self.verticalHeaderCombo.currentIndex()) def createDatesGroupBox(self): self.datesGroupBox = QGroupBox(self.tr("Dates")) self.minimumDateEdit = QDateEdit() self.minimumDateEdit.setDisplayFormat('MMM d yyyy') self.minimumDateEdit.setDateRange(self.calendar.minimumDate(), self.calendar.maximumDate()) self.minimumDateEdit.setDate(self.calendar.minimumDate()) self.minimumDateLabel = QLabel("&Minimum Date:") self.minimumDateLabel.setBuddy(self.minimumDateEdit) self.currentDateEdit = QDateEdit() self.currentDateEdit.setDisplayFormat('MMM d yyyy') self.currentDateEdit.setDate(self.calendar.selectedDate()) self.currentDateEdit.setDateRange(self.calendar.minimumDate(), self.calendar.maximumDate()) self.currentDateLabel = QLabel("&Current Date:") self.currentDateLabel.setBuddy(self.currentDateEdit) self.maximumDateEdit = QDateEdit() self.maximumDateEdit.setDisplayFormat('MMM d yyyy') self.maximumDateEdit.setDateRange(self.calendar.minimumDate(), self.calendar.maximumDate()) self.maximumDateEdit.setDate(self.calendar.maximumDate()) self.maximumDateLabel = QLabel("Ma&ximum Date:") self.maximumDateLabel.setBuddy(self.maximumDateEdit) self.currentDateEdit.dateChanged.connect(self.calendar.setSelectedDate) self.calendar.selectionChanged.connect(self.selectedDateChanged) self.minimumDateEdit.dateChanged.connect(self.minimumDateChanged) self.maximumDateEdit.dateChanged.connect(self.maximumDateChanged) dateBoxLayout = QGridLayout() dateBoxLayout.addWidget(self.currentDateLabel, 1, 0) dateBoxLayout.addWidget(self.currentDateEdit, 1, 1) dateBoxLayout.addWidget(self.minimumDateLabel, 0, 0) dateBoxLayout.addWidget(self.minimumDateEdit, 0, 1) dateBoxLayout.addWidget(self.maximumDateLabel, 2, 0) dateBoxLayout.addWidget(self.maximumDateEdit, 2, 1) dateBoxLayout.setRowStretch(3, 1) self.datesGroupBox.setLayout(dateBoxLayout) def createTextFormatsGroupBox(self): self.textFormatsGroupBox = QGroupBox("Text Formats") self.weekdayColorCombo = self.createColorComboBox() self.weekdayColorCombo.setCurrentIndex( self.weekdayColorCombo.findText("Black")) self.weekdayColorLabel = QLabel("&Weekday color:") self.weekdayColorLabel.setBuddy(self.weekdayColorCombo) self.weekendColorCombo = self.createColorComboBox() self.weekendColorCombo.setCurrentIndex( self.weekendColorCombo.findText("Red")) self.weekendColorLabel = QLabel("Week&end color:") self.weekendColorLabel.setBuddy(self.weekendColorCombo) self.headerTextFormatCombo = QComboBox() self.headerTextFormatCombo.addItem("Bold") self.headerTextFormatCombo.addItem("Italic") self.headerTextFormatCombo.addItem("Plain") self.headerTextFormatLabel = QLabel("&Header text:") self.headerTextFormatLabel.setBuddy(self.headerTextFormatCombo) self.firstFridayCheckBox = QCheckBox("&First Friday in blue") self.mayFirstCheckBox = QCheckBox("May &1 in red") self.weekdayColorCombo.currentIndexChanged.connect( self.weekdayFormatChanged) self.weekendColorCombo.currentIndexChanged.connect( self.weekendFormatChanged) self.headerTextFormatCombo.currentIndexChanged.connect( self.reformatHeaders) self.firstFridayCheckBox.toggled.connect(self.reformatCalendarPage) self.mayFirstCheckBox.toggled.connect(self.reformatCalendarPage) checkBoxLayout = QHBoxLayout() checkBoxLayout.addWidget(self.firstFridayCheckBox) checkBoxLayout.addStretch() checkBoxLayout.addWidget(self.mayFirstCheckBox) outerLayout = QGridLayout() outerLayout.addWidget(self.weekdayColorLabel, 0, 0) outerLayout.addWidget(self.weekdayColorCombo, 0, 1) outerLayout.addWidget(self.weekendColorLabel, 1, 0) outerLayout.addWidget(self.weekendColorCombo, 1, 1) outerLayout.addWidget(self.headerTextFormatLabel, 2, 0) outerLayout.addWidget(self.headerTextFormatCombo, 2, 1) outerLayout.addLayout(checkBoxLayout, 3, 0, 1, 2) self.textFormatsGroupBox.setLayout(outerLayout) self.weekdayFormatChanged() self.weekendFormatChanged() self.reformatHeaders() self.reformatCalendarPage() def createColorComboBox(self): comboBox = QComboBox() comboBox.addItem("Red", Qt.red) comboBox.addItem("Blue", Qt.blue) comboBox.addItem("Black", Qt.black) comboBox.addItem("Magenta", Qt.magenta) return comboBox
class MainWindow(QWidget): articleInfoUpdate = pyqtSignal() entityUpdate = pyqtSignal() crawlerUpdate = pyqtSignal() def __init__(self): super(MainWindow, self).__init__() self.initUI() self.articleInfoUpdate.connect(self.updateArticleInfo) self.entityUpdate.connect(self.updateEntityList) def initUI(self): self.setGeometry(0, 0, 500, 700) self.center() self.setWindowTitle('PView') mainLayout = QVBoxLayout() self.createArticleInfoBox() self.createViewArticleBox() self.createEntityBox() self.createReportBox() self.createDatabaseBox() mainLayout.addWidget(self.infoBox) mainLayout.addWidget(self.viewArticleBox) mainLayout.addWidget(self.entityBox) mainLayout.addWidget(self.raportBox) mainLayout.addWidget(self.databaseBox) self.setLayout(mainLayout) self.show() def createArticleInfoBox(self): self.articleCount = self.selectCountArticles() entityCount = self.selectCountEntities() associationsCount = self.selectCountAssociations() classifiedCount = self.selectCountClassifiedAssociations() label = "Number of articles: " + str(self.articleCount) self.articleCountLabel = QLabel(label) label = "Number of entities: " + str(entityCount) self.entitiesCountLabel = QLabel(label) label = "Number of associations: " + str(associationsCount) self.associationsCountLabel = QLabel(label) label = "Number of classified associations: " + str(classifiedCount) self.classifiedCountLabel = QLabel(label) layout = QVBoxLayout() layout.addWidget(self.articleCountLabel) layout.addWidget(self.entitiesCountLabel) layout.addWidget(self.associationsCountLabel) layout.addWidget(self.classifiedCountLabel) self.infoBox = QGroupBox("Statistics") self.infoBox.setLayout(layout) def createCrawlerBox(self): self.crawlButton = QPushButton("Crawl") self.crawlButton.setFocusPolicy(Qt.NoFocus) self.websiteList = QComboBox() self.websiteList.addItem("HotNews") layout = QGridLayout() layout.addWidget(self.websiteList, 0, 0, 1, 1) layout.addWidget(self.crawlButton, 0, 1, 1, 1) layout.setColumnStretch(0, 1) layout.setColumnStretch(1, 1) self.crawlerBox = QGroupBox("Crawler") self.crawlerBox.setLayout(layout) def createViewArticleBox(self): self.articleNumberLineEdit = QLineEdit("") self.articleNumberLineEdit.setAlignment(Qt.AlignHCenter) self.viewArticleButton = QPushButton("Open") self.viewArticleButton.clicked.connect(self.viewArticle) layout = QGridLayout() layout.addWidget(self.articleNumberLineEdit, 0, 0, 1, 1) layout.addWidget(self.viewArticleButton, 0, 1, 1, 1) layout.setColumnStretch(0, 1) layout.setColumnStretch(1, 1) self.viewArticleBox = QGroupBox("View Article") self.viewArticleBox.setLayout(layout) def createReportBox(self): minDate, maxDate = self.selectMinAndMaxDate() minDate = QDate(minDate.year, minDate.month, minDate.day) maxDate = QDate(maxDate.year, maxDate.month, maxDate.day) self.fromDateEdit = QDateEdit() self.fromDateEdit.setDate(minDate) self.fromDateEdit.setDisplayFormat('d MMM yyyy') self.fromDateEdit.setAlignment(Qt.AlignHCenter) self.toDateEdit = QDateEdit() self.toDateEdit.setDate(maxDate) self.toDateEdit.setDisplayFormat('d MMM yyyy') self.toDateEdit.setAlignment(Qt.AlignHCenter) self.reportTypeComboBox = QComboBox() for item in reportTypes: self.reportTypeComboBox.addItem(item) monthlyButton = QPushButton("View") monthlyButton.clicked.connect(self.createReport) layout = QGridLayout() layout.addWidget(self.fromDateEdit, 0, 0, 1, 1) layout.addWidget(self.toDateEdit, 0, 1, 1, 1) layout.addWidget(self.reportTypeComboBox, 1, 0, 1, 1) layout.addWidget(monthlyButton, 1, 1, 1, 1) layout.setColumnStretch(0, 1) layout.setColumnStretch(1, 1) self.raportBox = QGroupBox("Charts") self.raportBox.setLayout(layout) def createEntityBox(self): rows = self.selectCountEntities() self.entityList = QListWidget() entities = self.selectAllEntities() for entity in entities: self.doAssociationsForEntity(entity[1]) self.entityList.addItem(entity[1]) addButton = QPushButton("Add") addButton.clicked.connect(self.addEntity) removeButton = QPushButton("Delete") removeButton.clicked.connect(self.removeEntity) self.addEntityLineEdit = QLineEdit("") viewArticlesButton = QPushButton("View articles") viewArticlesButton.clicked.connect(self.viewArticleByEntity) self.algorithmComboBox = QComboBox() for key in classifiers.keys(): self.algorithmComboBox.addItem(key) classifyButton = QPushButton("Classify") classifyButton.clicked.connect(self.classifyAllAssociations) layout = QGridLayout() layout.addWidget(self.entityList, 0, 0, 1, 4) layout.addWidget(self.addEntityLineEdit, 1, 0, 1, 2) layout.addWidget(addButton, 1, 2, 1, 1) layout.addWidget(removeButton, 1, 3, 1, 1) layout.addWidget(viewArticlesButton, 2, 0, 1, 4) layout.addWidget(self.algorithmComboBox, 3, 0, 1, 2) layout.addWidget(classifyButton, 3, 2, 1, 2) layout.setColumnStretch(0, 1) layout.setColumnStretch(1, 1) layout.setColumnStretch(2, 1) layout.setColumnStretch(3, 1) self.entityBox = QGroupBox("Entities") self.entityBox.setLayout(layout) def createDatabaseBox(self): deleteClassificationsButton = QPushButton("Remove all classifications") deleteClassificationsButton.clicked.connect(self.clearAllCalculatedPolarities) deleteEntitiesButton = QPushButton("Remove all entities") deleteEntitiesButton.clicked.connect(self.deleteAllEntities) deleteAssociationsButton = QPushButton("Remove all associations") deleteAssociationsButton.clicked.connect(self.deleteAllAssociations) layout = QVBoxLayout() layout.addWidget(deleteClassificationsButton) layout.addWidget(deleteAssociationsButton) layout.addWidget(deleteEntitiesButton) self.databaseBox = QGroupBox("Database") self.databaseBox.setLayout(layout) def center(self): qr = self.frameGeometry() cp = QDesktopWidget().availableGeometry().center() qr.moveCenter(cp) self.move(qr.topLeft()) def monthsBetweenDates(self, fromDate, toDate): curDate = QDate(fromDate) months =[] while curDate < toDate: months.append(curDate) curDate = curDate.addMonths(1) return months def makeMonthlyPolarityChart(self, entities, fromDate, toDate): cursor = mysql_conn.cursor() chartData = [] for (entityId, entity) in entities: monthlyPol = self.selectAllPolaritiesForEntity(entityId, fromDate, toDate) trace0=Bar( x = [self.monthYearLabel(month) for (month, _, _) in monthlyPol], y = [(0.0 + rows.count(1L)) / (l+1) * 100 for (_, l, rows) in monthlyPol], name = entity, marker = Marker( color = 'rgb(204,204,204)', opacity = 0.5, ), ) chartData.append(trace0) chartData = Data(chartData) layout = Layout( xaxis=XAxis( #set x-axis' labels direction at 45 degree angle tickangle=-45, ), barmode='group', ) fig = Figure(data = chartData, layout = layout) py.image.save_as({'data': chartData}, "polarities.png") img = Image.open("polarities.png") img.show() def makeMonthlyAppearanceChart(self, entities, fromDate, toDate): cursor = mysql_conn.cursor() chartData = [] for (entityId, entity) in entities: monthlyApp = self.selectCountAssociationsForEntityBetweenDates(entityId, fromDate, toDate) trace0=Bar( x = [self.monthYearLabel(month) for (month, _) in monthlyApp], y = [count for (_, count) in monthlyApp], name = entity, marker = Marker( color = 'rgb(204,204,204)', opacity = 0.5, ), ) chartData.append(trace0) chartData = Data(chartData) layout = Layout( xaxis=XAxis( #set x-axis' labels direction at 45 degree angle tickangle=-45, ), barmode='group', ) fig = Figure(data = chartData, layout = layout) py.image.save_as({'data': chartData}, "appearances.png") img = Image.open("appearances.png") img.show() def getStringDate(self, date): sDate = str(date.year()) sDate += '-'+str(date.month()) sDate += '-'+'01' time = '00:00:00' return sDate + ' ' + time def monthYearLabel(self, date): label = monthIntToString[date.month()] + ' ' label += str(date.year()) return label def createReport(self): reportType = self.reportTypeComboBox.currentText() fromDate = self.fromDateEdit.date() toDate = self.toDateEdit.date() entities = [] if "All entities" in reportType: entities = self.selectAllEntities() else: selected = self.entityList.selectedItems() if len(selected) == 1: entity = selected[0].text() entities = [(self.selectEntityId(entity), entity)] if len(entities) > 0: if "Opinions" in reportType: self.makeMonthlyPolarityChart(entities, fromDate, toDate) else: print entities self.makeMonthlyAppearanceChart(entities, fromDate, toDate) def viewArticle(self): try: articleId = int(self.articleNumberLineEdit.text()) if articleId > 0 and articleId < self.articleCount: self.viewArticleButton.setEnabled(False) self.articleNumberLineEdit.setDisabled(True) articleList = [i+1 for i in xrange(self.articleCount)] articleView = Article(articleId-1, articleList, parentW=self) articleView.exec_() self.viewArticleButton.setEnabled(True) self.articleNumberLineEdit.setDisabled(False) except ValueError: print "Invalid article id" def viewArticleByEntity(self): selected = self.entityList.selectedItems() if len(selected) == 1: articles = self.selectAllArticlesByEntity(selected[0].text()) articleList = [a[0] for a in articles] articleView = Article(0, articleList, shuffle_=True, parentW=self) articleView.exec_() def addEntity(self): newEntity = self.addEntityLineEdit.text().strip() newEntity = re.sub(r' +', ' ', newEntity) cursor = mysql_conn.cursor() if len(newEntity) != 0: selectStmt = """SELECT * FROM entities WHERE entity=%s""" data = (newEntity,) cursor.execute(selectStmt, data) rows = cursor.fetchall() if len(rows) == 0: insertStmt = """INSERT INTO entities (entity) VALUES (%s)""" data = (newEntity,) cursor.execute(insertStmt, data) cursor.execute("""COMMIT""") self.entityUpdate.emit() self.doAssociationsForEntity(newEntity) self.addEntityLineEdit.setText("") def removeEntity(self): selected = self.entityList.selectedItems() cursor = mysql_conn.cursor() for item in selected: self.deleteAssciationsForEntity(item.text()) selectStmt = """SELECT entity_id FROM entities WHERE entity=%s""" data = (item.text(),) cursor.execute(selectStmt, data) entityId = cursor.fetchone() deleteStmt = """DELETE FROM entities WHERE entity_id=%s""" data = (entityId[0],) cursor.execute(deleteStmt, data) cursor.execute("""COMMIT""") self.entityUpdate.emit() def updateEntityList(self): self.entityList.clear() entities = self.selectAllEntities() for entity in entities: self.entityList.addItem(entity[1]) label = "Number of entities: " + str(len(entities)) self.entitiesCountLabel.setText(label) def updateArticleInfo(self): self.articleCount = self.selectCountArticles() entityCount = self.selectCountEntities() associationsCount = self.selectCountAssociations() classifiedCount = self.selectCountClassifiedAssociations() label = "Number of articles: " + str(self.articleCount) self.articleCountLabel.setText(label) label = "Number of entities: " + str(entityCount) self.entitiesCountLabel.setText(label) label = "Number of classified associations: " + str(classifiedCount) self.classifiedCountLabel.setText(label) label = "Number of associations: " + str(associationsCount) self.associationsCountLabel.setText(label) def classifyAllAssociations(self): cursor = mysql_conn.cursor() entities = self.selectAllEntities() for (entityId, entity) in entities: manualPol = self.selectManualPolaritiesForEntity(entityId) trainingData = [self.selectArticle(id_)[4] for (id_, _) in manualPol] trainingTarget = [polarity for (_, polarity) in manualPol] algorithm = self.algorithmComboBox.currentText() textClf = Pipeline([('vect', CountVectorizer()), ('tfidf', TfidfTransformer()), ('clf', classifiers[algorithm]), ]) textClf.fit(trainingData, trainingTarget) # select all articles associated with entity that need to be classified selectStmt = """SELECT article_id FROM assocEntityArticle WHERE polarity_manual IS NULL AND polarity_calculated IS NULL AND entity_id=%s""" data = (entityId,) cursor.execute(selectStmt, data) ids = cursor.fetchall() if len(ids) > 0: ids = [a[0] for a in ids] testData = [self.selectArticle(id_)[4] for id_ in ids] predicted = textClf.predict(testData) print [x for x in predicted].count(1) updateData = zip(predicted, ids) updateData = [(polarity, entityId, id_) for (polarity, id_) in updateData] updateStmt = """UPDATE assocEntityArticle SET polarity_calculated=%s WHERE entity_id=%s AND article_id=%s""" cursor.executemany(updateStmt, updateData) cursor.execute("""COMMIT""") self.articleInfoUpdate.emit() def selectArticle(self, articleId): cursor = mysql_conn.cursor() selectStmt = """SELECT * FROM articles WHERE article_id=%s""" data = (articleId,) cursor.execute(selectStmt, data) row = cursor.fetchone() return row def selectEntityId(self, entity): cursor = mysql_conn.cursor() selectStmt = """SELECT entity_id FROM entities WHERE entity=%s""" data = (entity,) cursor.execute(selectStmt, data) entityId = cursor.fetchone()[0] return entityId def selectAllArticlesByEntity(self, entity): cursor = mysql_conn.cursor() selectStmt = """SELECT * FROM articles WHERE content LIKE %s""" data = ("%" + entity + "%",) cursor.execute(selectStmt, data) rows = cursor.fetchall() return rows def selectAllEntities(self): cursor = mysql_conn.cursor() selectStmt = """SELECT * FROM entities""" cursor.execute(selectStmt) rows = cursor.fetchall() return rows def selectMinAndMaxDate(self): cursor = mysql_conn.cursor() selectStmt = """SELECT MIN(date), MAX(date) FROM articles""" cursor.execute(selectStmt) row = cursor.fetchone() return row def selectCountArticles(self): cursor = mysql_conn.cursor() selectStmt = """SELECT count(*) FROM articles""" cursor.execute(selectStmt) row = cursor.fetchone() return row[0] def selectCountAuthors(self): cursor = mysql_conn.cursor() selectStmt = """SELECT count(*) FROM authors""" cursor.execute(selectStmt) row = cursor.fetchone() return row[0] def selectCountEntities(self): cursor = mysql_conn.cursor() selectStmt = """SELECT count(*) FROM entities""" cursor.execute(selectStmt) row = cursor.fetchone() return row[0] def selectCountAssociations(self): cursor = mysql_conn.cursor() selectStmt = """SELECT count(*) FROM assocEntityArticle""" cursor.execute(selectStmt) row = cursor.fetchone() return row[0] def selectCountAssociationsForEntityBetweenDates(self, entityId, fromDate, toDate): cursor = mysql_conn.cursor() months = self.monthsBetweenDates(fromDate, toDate) selectStmt = """SELECT count(*) FROM assocEntityArticle a, articles b WHERE a.article_id = b.article_id AND b.date BETWEEN %s AND %s AND a.entity_id=%s""" associations = [] if len(months) != 0: for month in months: fromDateString = self.getStringDate(month) toDateString = self.getStringDate(month.addMonths(1)) data = (fromDateString, toDateString, entityId) cursor.execute(selectStmt, data) count = cursor.fetchone()[0] associations.append((month, count)) return associations def selectCountClassifiedAssociations(self): cursor = mysql_conn.cursor() selectStmt = """SELECT count(*) FROM assocEntityArticle WHERE polarity_calculated IS NOT NULL OR polarity_manual IS NOT NULL""" cursor.execute(selectStmt) row = cursor.fetchone() return row[0] def selectManualPolaritiesForEntity(self, entityId): cursor = mysql_conn.cursor() selectStmt = """SELECT article_id, polarity_manual FROM assocEntityArticle WHERE polarity_manual IS NOT NULL AND entity_id=%s""" data = (entityId,) cursor.execute(selectStmt, data) rows = cursor.fetchall() return rows def selectAllPolaritiesForEntity(self, entityId, fromDate, toDate): cursor = mysql_conn.cursor() months = self.monthsBetweenDates(fromDate, toDate) selectStmt = """SELECT a.polarity_manual, a.polarity_calculated FROM assocEntityArticle a, articles b WHERE (a.polarity_manual IS NOT NULL OR a.polarity_calculated IS NOT NULL) AND a.article_id = b.article_id AND b.date BETWEEN %s AND %s AND a.entity_id=%s""" polarities = [] if len(months) != 0: for month in months: fromDateString = self.getStringDate(month) toDateString = self.getStringDate(month.addMonths(1)) data = (fromDateString, toDateString, entityId) cursor.execute(selectStmt, data) rows = cursor.fetchall() rows = [a or b for a, b in rows] polarities.append((month, len(rows), rows)) return polarities def doAssociationsForEntity(self, entity): cursor = mysql_conn.cursor() # select entity_id for entity given as parameter entityId = self.selectEntityId(entity) # select list of article_id for which associations exist # in database for entity given as param selectStmt = """SELECT article_id FROM assocEntityArticle WHERE entity_id=%s""" data = (entityId,) cursor.execute(selectStmt, data) articleIdsInDB = cursor.fetchall() articleIdsInDB = [pair[0] for pair in articleIdsInDB] # select all articles that contain entity in content selectStmt = """SELECT article_id FROM articles WHERE content LIKE %s""" data = ("%" + entity + "%",) cursor.execute(selectStmt, data) rows = cursor.fetchall() rows = [pair[0] for pair in rows] # find articles for which associations don't exist in the database diff = list(set(rows) - set(articleIdsInDB)) if len(diff) != 0: insertStmt = """INSERT INTO assocEntityArticle (article_id, entity_id) VALUES (%s, %s)""" data = [(articleId, entityId) for articleId in diff] cursor.executemany(insertStmt, data) cursor.execute("""COMMIT""") self.articleInfoUpdate.emit() def deleteAssciationsForEntity(self, entity): cursor = mysql_conn.cursor() selectStmt = """SELECT entity_id FROM entities WHERE entity=%s""" data = (entity,) cursor.execute(selectStmt, data) entityId = cursor.fetchone()[0] deleteStmt = """DELETE FROM assocEntityArticle WHERE entity_id=%s""" data = (entityId,) cursor.execute(deleteStmt, data) cursor.execute("""COMMIT""") self.articleInfoUpdate.emit() def doAllAssociations(self): cursor = mysql_conn.cursor() entities = self.selectAllEntities() for entity in entities: self.doAssociationsForEntity(entity) self.articleInfoUpdate.emit() def deleteAllAssociations(self): cursor = mysql_conn.cursor() deleteStmt = """DELETE FROM assocEntityArticle WHERE article_id > 0""" cursor.execute(deleteStmt) cursor.execute("""COMMIT""") self.articleInfoUpdate.emit() def clearAllCalculatedPolarities(self): cursor = mysql_conn.cursor() updateStmt = """UPDATE assocEntityArticle SET polarity_calculated=%s WHERE polarity_calculated IS NOT NULL""" data = (None,) cursor.execute(updateStmt, data) cursor.execute("""COMMIT""") self.articleInfoUpdate.emit() def deleteAllArticles(self): try: cursor = mysql_conn.cursor() deleteStmt = """DELETE FROM articles WHERE article_id > 0""" cursor.execute(deleteStmt) alterTableStmt = """ALTER TABLE articles AUTO_INCREMENT = 1""" cursor.execute(alterTableStmt) cursor.execute("""COMMIT""") self.articleInfoUpdate.emit() except IntegrityError: pass def deleteAllAuthors(self): cursor = mysql_conn.cursor() deleteStmt = """DELETE FROM authors WHERE author_id > 0""" cursor.execute(deleteStmt) alterTableStmt = """ALTER TABLE authors AUTO_INCREMENT = 1""" cursor.execute(alterTableStmt) cursor.execute("""COMMIT""") def deleteAllArticlesAndAuthors(self): self.deleteAllArticles() self.deleteAllAuthors() def deleteAllEntities(self): cursor = mysql_conn.cursor() deleteStmt = """DELETE FROM entities WHERE entity_id > 0""" cursor.execute(deleteStmt) alterTableStmt = """ALTER TABLE entities AUTO_INCREMENT = 1""" cursor.execute(alterTableStmt) cursor.execute("""COMMIT""") self.articleInfoUpdate.emit() self.entityUpdate.emit()
class Window(QWidget): def __init__(self): super(Window, self).__init__() self.createPreviewGroupBox() self.createGeneralOptionsGroupBox() self.createDatesGroupBox() self.createTextFormatsGroupBox() layout = QGridLayout() layout.addWidget(self.previewGroupBox, 0, 0) layout.addWidget(self.generalOptionsGroupBox, 0, 1) layout.addWidget(self.datesGroupBox, 1, 0) layout.addWidget(self.textFormatsGroupBox, 1, 1) layout.setSizeConstraint(QLayout.SetFixedSize) self.setLayout(layout) self.previewLayout.setRowMinimumHeight(0, self.calendar.sizeHint().height()) self.previewLayout.setColumnMinimumWidth(0, self.calendar.sizeHint().width()) self.setWindowTitle("Calendar Widget") def localeChanged(self, index): self.calendar.setLocale(self.localeCombo.itemData(index)) def firstDayChanged(self, index): self.calendar.setFirstDayOfWeek( Qt.DayOfWeek(self.firstDayCombo.itemData(index))) def selectionModeChanged(self, index): self.calendar.setSelectionMode( QCalendarWidget.SelectionMode( self.selectionModeCombo.itemData(index))) def horizontalHeaderChanged(self, index): self.calendar.setHorizontalHeaderFormat( QCalendarWidget.HorizontalHeaderFormat( self.horizontalHeaderCombo.itemData(index))) def verticalHeaderChanged(self, index): self.calendar.setVerticalHeaderFormat( QCalendarWidget.VerticalHeaderFormat( self.verticalHeaderCombo.itemData(index))) def selectedDateChanged(self): self.currentDateEdit.setDate(self.calendar.selectedDate()) def minimumDateChanged(self, date): self.calendar.setMinimumDate(date) self.maximumDateEdit.setDate(self.calendar.maximumDate()) def maximumDateChanged(self, date): self.calendar.setMaximumDate(date) self.minimumDateEdit.setDate(self.calendar.minimumDate()) def weekdayFormatChanged(self): format = QTextCharFormat() format.setForeground( Qt.GlobalColor( self.weekdayColorCombo.itemData( self.weekdayColorCombo.currentIndex()))) self.calendar.setWeekdayTextFormat(Qt.Monday, format) self.calendar.setWeekdayTextFormat(Qt.Tuesday, format) self.calendar.setWeekdayTextFormat(Qt.Wednesday, format) self.calendar.setWeekdayTextFormat(Qt.Thursday, format) self.calendar.setWeekdayTextFormat(Qt.Friday, format) def weekendFormatChanged(self): format = QTextCharFormat() format.setForeground( Qt.GlobalColor( self.weekendColorCombo.itemData( self.weekendColorCombo.currentIndex()))) self.calendar.setWeekdayTextFormat(Qt.Saturday, format) self.calendar.setWeekdayTextFormat(Qt.Sunday, format) def reformatHeaders(self): text = self.headerTextFormatCombo.currentText() format = QTextCharFormat() if text == "Bold": format.setFontWeight(QFont.Bold) elif text == "Italic": format.setFontItalic(True) elif text == "Green": format.setForeground(Qt.green) self.calendar.setHeaderTextFormat(format) def reformatCalendarPage(self): if self.firstFridayCheckBox.isChecked(): firstFriday = QDate(self.calendar.yearShown(), self.calendar.monthShown(), 1) while firstFriday.dayOfWeek() != Qt.Friday: firstFriday = firstFriday.addDays(1) firstFridayFormat = QTextCharFormat() firstFridayFormat.setForeground(Qt.blue) self.calendar.setDateTextFormat(firstFriday, firstFridayFormat) # May 1st in Red takes precedence. if self.mayFirstCheckBox.isChecked(): mayFirst = QDate(self.calendar.yearShown(), 5, 1) mayFirstFormat = QTextCharFormat() mayFirstFormat.setForeground(Qt.red) self.calendar.setDateTextFormat(mayFirst, mayFirstFormat) def createPreviewGroupBox(self): self.previewGroupBox = QGroupBox("Preview") self.calendar = QCalendarWidget() self.calendar.setMinimumDate(QDate(1900, 1, 1)) self.calendar.setMaximumDate(QDate(3000, 1, 1)) self.calendar.setGridVisible(True) self.calendar.currentPageChanged.connect(self.reformatCalendarPage) self.previewLayout = QGridLayout() self.previewLayout.addWidget(self.calendar, 0, 0, Qt.AlignCenter) self.previewGroupBox.setLayout(self.previewLayout) def createGeneralOptionsGroupBox(self): self.generalOptionsGroupBox = QGroupBox("General Options") self.localeCombo = QComboBox() curLocaleIndex = -1 index = 0 this_language = self.locale().nativeLanguageName() this_country = self.locale().nativeCountryName() for locale in QLocale.matchingLocales(QLocale.AnyLanguage, QLocale.AnyScript, QLocale.AnyCountry): language = locale.nativeLanguageName() country = locale.nativeCountryName() if language == this_language and country == this_country: curLocaleIndex = index self.localeCombo.addItem('%s/%s' % (language, country), locale) index += 1 if curLocaleIndex != -1: self.localeCombo.setCurrentIndex(curLocaleIndex) self.localeLabel = QLabel("&Locale") self.localeLabel.setBuddy(self.localeCombo) self.firstDayCombo = QComboBox() self.firstDayCombo.addItem("Sunday", Qt.Sunday) self.firstDayCombo.addItem("Monday", Qt.Monday) self.firstDayCombo.addItem("Tuesday", Qt.Tuesday) self.firstDayCombo.addItem("Wednesday", Qt.Wednesday) self.firstDayCombo.addItem("Thursday", Qt.Thursday) self.firstDayCombo.addItem("Friday", Qt.Friday) self.firstDayCombo.addItem("Saturday", Qt.Saturday) self.firstDayLabel = QLabel("Wee&k starts on:") self.firstDayLabel.setBuddy(self.firstDayCombo) self.selectionModeCombo = QComboBox() self.selectionModeCombo.addItem("Single selection", QCalendarWidget.SingleSelection) self.selectionModeCombo.addItem("None", QCalendarWidget.NoSelection) self.selectionModeLabel = QLabel("&Selection mode:") self.selectionModeLabel.setBuddy(self.selectionModeCombo) self.gridCheckBox = QCheckBox("&Grid") self.gridCheckBox.setChecked(self.calendar.isGridVisible()) self.navigationCheckBox = QCheckBox("&Navigation bar") self.navigationCheckBox.setChecked(True) self.horizontalHeaderCombo = QComboBox() self.horizontalHeaderCombo.addItem("Single letter day names", QCalendarWidget.SingleLetterDayNames) self.horizontalHeaderCombo.addItem("Short day names", QCalendarWidget.ShortDayNames) self.horizontalHeaderCombo.addItem("Long day names", QCalendarWidget.LongDayNames) self.horizontalHeaderCombo.addItem("None", QCalendarWidget.NoHorizontalHeader) self.horizontalHeaderCombo.setCurrentIndex(1) self.horizontalHeaderLabel = QLabel("&Horizontal header:") self.horizontalHeaderLabel.setBuddy(self.horizontalHeaderCombo) self.verticalHeaderCombo = QComboBox() self.verticalHeaderCombo.addItem("ISO week numbers", QCalendarWidget.ISOWeekNumbers) self.verticalHeaderCombo.addItem("None", QCalendarWidget.NoVerticalHeader) self.verticalHeaderLabel = QLabel("&Vertical header:") self.verticalHeaderLabel.setBuddy(self.verticalHeaderCombo) self.localeCombo.currentIndexChanged.connect(self.localeChanged) self.firstDayCombo.currentIndexChanged.connect(self.firstDayChanged) self.selectionModeCombo.currentIndexChanged.connect( self.selectionModeChanged) self.gridCheckBox.toggled.connect(self.calendar.setGridVisible) self.navigationCheckBox.toggled.connect( self.calendar.setNavigationBarVisible) self.horizontalHeaderCombo.currentIndexChanged.connect( self.horizontalHeaderChanged) self.verticalHeaderCombo.currentIndexChanged.connect( self.verticalHeaderChanged) checkBoxLayout = QHBoxLayout() checkBoxLayout.addWidget(self.gridCheckBox) checkBoxLayout.addStretch() checkBoxLayout.addWidget(self.navigationCheckBox) outerLayout = QGridLayout() outerLayout.addWidget(self.localeLabel, 0, 0) outerLayout.addWidget(self.localeCombo, 0, 1) outerLayout.addWidget(self.firstDayLabel, 1, 0) outerLayout.addWidget(self.firstDayCombo, 1, 1) outerLayout.addWidget(self.selectionModeLabel, 2, 0) outerLayout.addWidget(self.selectionModeCombo, 2, 1) outerLayout.addLayout(checkBoxLayout, 3, 0, 1, 2) outerLayout.addWidget(self.horizontalHeaderLabel, 4, 0) outerLayout.addWidget(self.horizontalHeaderCombo, 4, 1) outerLayout.addWidget(self.verticalHeaderLabel, 5, 0) outerLayout.addWidget(self.verticalHeaderCombo, 5, 1) self.generalOptionsGroupBox.setLayout(outerLayout) self.firstDayChanged(self.firstDayCombo.currentIndex()) self.selectionModeChanged(self.selectionModeCombo.currentIndex()) self.horizontalHeaderChanged(self.horizontalHeaderCombo.currentIndex()) self.verticalHeaderChanged(self.verticalHeaderCombo.currentIndex()) def createDatesGroupBox(self): self.datesGroupBox = QGroupBox(self.tr("Dates")) self.minimumDateEdit = QDateEdit() self.minimumDateEdit.setDisplayFormat('MMM d yyyy') self.minimumDateEdit.setDateRange(self.calendar.minimumDate(), self.calendar.maximumDate()) self.minimumDateEdit.setDate(self.calendar.minimumDate()) self.minimumDateLabel = QLabel("&Minimum Date:") self.minimumDateLabel.setBuddy(self.minimumDateEdit) self.currentDateEdit = QDateEdit() self.currentDateEdit.setDisplayFormat('MMM d yyyy') self.currentDateEdit.setDate(self.calendar.selectedDate()) self.currentDateEdit.setDateRange(self.calendar.minimumDate(), self.calendar.maximumDate()) self.currentDateLabel = QLabel("&Current Date:") self.currentDateLabel.setBuddy(self.currentDateEdit) self.maximumDateEdit = QDateEdit() self.maximumDateEdit.setDisplayFormat('MMM d yyyy') self.maximumDateEdit.setDateRange(self.calendar.minimumDate(), self.calendar.maximumDate()) self.maximumDateEdit.setDate(self.calendar.maximumDate()) self.maximumDateLabel = QLabel("Ma&ximum Date:") self.maximumDateLabel.setBuddy(self.maximumDateEdit) self.currentDateEdit.dateChanged.connect(self.calendar.setSelectedDate) self.calendar.selectionChanged.connect(self.selectedDateChanged) self.minimumDateEdit.dateChanged.connect(self.minimumDateChanged) self.maximumDateEdit.dateChanged.connect(self.maximumDateChanged) dateBoxLayout = QGridLayout() dateBoxLayout.addWidget(self.currentDateLabel, 1, 0) dateBoxLayout.addWidget(self.currentDateEdit, 1, 1) dateBoxLayout.addWidget(self.minimumDateLabel, 0, 0) dateBoxLayout.addWidget(self.minimumDateEdit, 0, 1) dateBoxLayout.addWidget(self.maximumDateLabel, 2, 0) dateBoxLayout.addWidget(self.maximumDateEdit, 2, 1) dateBoxLayout.setRowStretch(3, 1) self.datesGroupBox.setLayout(dateBoxLayout) def createTextFormatsGroupBox(self): self.textFormatsGroupBox = QGroupBox("Text Formats") self.weekdayColorCombo = self.createColorComboBox() self.weekdayColorCombo.setCurrentIndex( self.weekdayColorCombo.findText("Black")) self.weekdayColorLabel = QLabel("&Weekday color:") self.weekdayColorLabel.setBuddy(self.weekdayColorCombo) self.weekendColorCombo = self.createColorComboBox() self.weekendColorCombo.setCurrentIndex( self.weekendColorCombo.findText("Red")) self.weekendColorLabel = QLabel("Week&end color:") self.weekendColorLabel.setBuddy(self.weekendColorCombo) self.headerTextFormatCombo = QComboBox() self.headerTextFormatCombo.addItem("Bold") self.headerTextFormatCombo.addItem("Italic") self.headerTextFormatCombo.addItem("Plain") self.headerTextFormatLabel = QLabel("&Header text:") self.headerTextFormatLabel.setBuddy(self.headerTextFormatCombo) self.firstFridayCheckBox = QCheckBox("&First Friday in blue") self.mayFirstCheckBox = QCheckBox("May &1 in red") self.weekdayColorCombo.currentIndexChanged.connect( self.weekdayFormatChanged) self.weekendColorCombo.currentIndexChanged.connect( self.weekendFormatChanged) self.headerTextFormatCombo.currentIndexChanged.connect( self.reformatHeaders) self.firstFridayCheckBox.toggled.connect(self.reformatCalendarPage) self.mayFirstCheckBox.toggled.connect(self.reformatCalendarPage) checkBoxLayout = QHBoxLayout() checkBoxLayout.addWidget(self.firstFridayCheckBox) checkBoxLayout.addStretch() checkBoxLayout.addWidget(self.mayFirstCheckBox) outerLayout = QGridLayout() outerLayout.addWidget(self.weekdayColorLabel, 0, 0) outerLayout.addWidget(self.weekdayColorCombo, 0, 1) outerLayout.addWidget(self.weekendColorLabel, 1, 0) outerLayout.addWidget(self.weekendColorCombo, 1, 1) outerLayout.addWidget(self.headerTextFormatLabel, 2, 0) outerLayout.addWidget(self.headerTextFormatCombo, 2, 1) outerLayout.addLayout(checkBoxLayout, 3, 0, 1, 2) self.textFormatsGroupBox.setLayout(outerLayout) self.weekdayFormatChanged() self.weekendFormatChanged() self.reformatHeaders() self.reformatCalendarPage() def createColorComboBox(self): comboBox = QComboBox() comboBox.addItem("Red", Qt.red) comboBox.addItem("Blue", Qt.blue) comboBox.addItem("Black", Qt.black) comboBox.addItem("Magenta", Qt.magenta) return comboBox
class SeriesDialog(QDialog): "A window for adding/modifying series" series_queue = queue.Queue() SERIES = pyqtSignal(list) SERIES_EDIT = pyqtSignal(list, int) #series_list = [] # might want to extend this to allow mass series adding def _init__(self, parent=None): super().__init__() #TODO: Implement a way to mass add series' #IDEA: Extend dialog in a ScrollArea with more forms... def initUI(self): main_layout = QVBoxLayout() f_web = QGroupBox("From the Web") f_web.setCheckable(False) main_layout.addWidget(f_web) web_layout = QHBoxLayout() f_web.setLayout(web_layout) f_local = QGroupBox("From local folder") f_local.setCheckable(False) main_layout.addWidget(f_local) local_layout = QHBoxLayout() f_local.setLayout(local_layout) f_series = QGroupBox("Series Info") f_series.setCheckable(False) main_layout.addWidget(f_series) series_layout = QFormLayout() f_series.setLayout(series_layout) def basic_web(name): return QLabel(name), QLineEdit(), QPushButton("Fetch") exh_lbl, exh_edit, exh_btn = basic_web("ExHentai:") web_layout.addWidget(exh_lbl, 0, Qt.AlignLeft) web_layout.addWidget(exh_edit, 0) web_layout.addWidget(exh_btn, 0, Qt.AlignRight) choose_folder = QPushButton("Choose Folder") choose_folder.clicked.connect(self.choose_dir) local_layout.addWidget(choose_folder, Qt.AlignLeft) self.title_edit = QLineEdit() self.title_edit.setFocus() self.author_edit = QLineEdit() self.descr_edit = QTextEdit() self.descr_edit.setFixedHeight(70) self.descr_edit.setPlaceholderText("HTML 4 tags are supported") self.lang_box = QComboBox() self.lang_box.addItems(["English", "Japanese", "Other"]) self.lang_box.setCurrentIndex(0) self.tags_edit = QLineEdit() self.tags_edit.setPlaceholderText("namespace1:tag1, tag2, namespace3:tag3, etc..") self.type_box = QComboBox() self.type_box.addItems(["Manga", "Doujinshi", "Other"]) self.type_box.setCurrentIndex(0) #self.type_box.currentIndexChanged[int].connect(self.doujin_show) #self.doujin_parent = QLineEdit() #self.doujin_parent.setVisible(False) self.status_box = QComboBox() self.status_box.addItems(["Unknown", "Ongoing", "Completed"]) self.status_box.setCurrentIndex(0) self.pub_edit = QDateEdit() self.pub_edit.setCalendarPopup(True) self.pub_edit.setDate(QDate.currentDate()) self.path_lbl = QLabel("unspecified...") self.path_lbl.setWordWrap(True) series_layout.addRow("Title:", self.title_edit) series_layout.addRow("Author:", self.author_edit) series_layout.addRow("Description:", self.descr_edit) series_layout.addRow("Language:", self.lang_box) series_layout.addRow("Tags:", self.tags_edit) series_layout.addRow("Type:", self.type_box) series_layout.addRow("Publication Date:", self.pub_edit) series_layout.addRow("Path:", self.path_lbl) final_buttons = QHBoxLayout() final_buttons.setAlignment(Qt.AlignRight) main_layout.addLayout(final_buttons) done = QPushButton("Done") done.setDefault(True) done.clicked.connect(self.accept) cancel = QPushButton("Cancel") cancel.clicked.connect(self.reject) final_buttons.addWidget(cancel) final_buttons.addWidget(done) self.setLayout(main_layout) # TODO: complete this... maybe another time.. #def doujin_show(self, index): # if index is 1: # self.doujin_parent.setVisible(True) # else: # self.doujin_parent.setVisible(False) def choose_dir(self): dir_name = QFileDialog.getExistingDirectory(self, 'Choose a folder') head, tail = os.path.split(dir_name) self.title_edit.setText(tail) self.path_lbl.setText(dir_name) def check(self): if len(self.title_edit.text()) is 0: self.title_edit.setFocus() self.title_edit.setStyleSheet("border-style:outset;border-width:2px;border-color:red;") return False elif len(self.author_edit.text()) is 0: self.author_edit.setText("Anon") if len(self.descr_edit.toPlainText()) is 0: self.descr_edit.setText("<i>No description..</i>") #if self.path_lbl.text() == "unspecified...": # return False return True def accept(self): from ..database import seriesdb def do_chapters(series): thread = threading.Thread(target=self.set_chapters, args=(series,)) thread.start() thread.join() return self.series_queue.get() if self.check(): new_series = seriesdb.Series() new_series.title = self.title_edit.text() new_series.artist = self.author_edit.text() new_series.path = self.path_lbl.text() new_series.info = self.descr_edit.toPlainText() new_series.type = self.type_box.currentText() new_series.language = self.lang_box.currentText() new_series.status = self.status_box.currentText() qpub_d = self.pub_edit.date().toString("ddMMyyyy") dpub_d = datetime.strptime(qpub_d, "%d%m%Y").date() new_series.pub_date = dpub_d updated_series = do_chapters(new_series) #for ser in self.series: self.SERIES.emit([updated_series]) super().accept() def set_chapters(self, series_object): path = series_object.path con = os.listdir(path) # list all folders in series dir chapters = sorted([os.path.join(path,sub) for sub in con if os.path.isdir(os.path.join(path, sub))]) #subfolders # if series has chapters divided into sub folders if len(chapters) != 0: for numb, ch in enumerate(chapters): chap_path = os.path.join(path, ch) series_object.chapters[numb] = chap_path else: #else assume that all images are in series folder series_object.chapters[0] = path #find last edited file times = set() for root, dirs, files in os.walk(path, topdown=False): for img in files: fp = os.path.join(root, img) times.add( os.path.getmtime(fp) ) series_object.last_update = time.asctime(time.gmtime(max(times))) self.series_queue.put(series_object) return True def reject(self): if self.check(): msgbox = QMessageBox() msgbox.setText("<font color='red'><b>Noo oniichan! You were about to add a new series.</b></font>") msgbox.setInformativeText("Do you really want to discard?") msgbox.setStandardButtons(QMessageBox.Yes | QMessageBox.No) msgbox.setDefaultButton(QMessageBox.No) if msgbox.exec() == QMessageBox.Yes: super().reject() else: super().reject() def trigger(self, list_of_index=None): if not list_of_index: self.initUI() else: assert isinstance(list_of_index, list) self.position = list_of_index[0].row() for index in list_of_index: series = index.data(Qt.UserRole+1) self.setSeries(series) from ..constants import WINDOW as parent self.resize(500,200) frect = self.frameGeometry() frect.moveCenter(QDesktopWidget().availableGeometry().center()) self.move(frect.topLeft()-QPoint(0,120)) self.setAttribute(Qt.WA_DeleteOnClose) self.setWindowFlags(Qt.FramelessWindowHint) self.exec() def setSeries(self, series): "To be used for when editing a series" self.series = series main_layout = QVBoxLayout() f_web = QGroupBox("Fetch metadata from Web") f_web.setCheckable(False) main_layout.addWidget(f_web) web_layout = QHBoxLayout() f_web.setLayout(web_layout) f_series = QGroupBox("Series Info") f_series.setCheckable(False) main_layout.addWidget(f_series) series_layout = QFormLayout() f_series.setLayout(series_layout) def basic_web(name): return QLabel(name), QLineEdit(), QPushButton("Fetch") exh_lbl, exh_edit, exh_btn = basic_web("ExHentai:") web_layout.addWidget(exh_lbl, 0, Qt.AlignLeft) web_layout.addWidget(exh_edit, 0) web_layout.addWidget(exh_btn, 0, Qt.AlignRight) self.title_edit = QLineEdit() self.title_edit.setText(series.title) self.author_edit = QLineEdit() self.author_edit.setText(series.artist) self.descr_edit = QTextEdit() self.descr_edit.setText(series.info) self.descr_edit.setAcceptRichText(True) self.descr_edit.setFixedHeight(70) self.lang_box = QComboBox() self.lang_box.addItems(["English", "Japanese", "Other"]) if series.language is "English": self.lang_box.setCurrentIndex(0) elif series.language is "Japanese": self.lang_box.setCurrentIndex(1) else: self.lang_box.setCurrentIndex(2) self.tags_edit = QLineEdit() #TODO Finish this.. self.tags_edit.setPlaceholderText("namespace1:tag1, tag2, namespace3:tag3, etc..") self.type_box = QComboBox() self.type_box.addItems(["Manga", "Doujinshi", "Other"]) if series.type is "Manga": self.type_box.setCurrentIndex(0) elif series.type is "Doujinshi": self.type_box.setCurrentIndex(1) else: self.type_box.setCurrentIndex(2) #self.type_box.currentIndexChanged[int].connect(self.doujin_show) #self.doujin_parent = QLineEdit() #self.doujin_parent.setVisible(False) self.status_box = QComboBox() self.status_box.addItems(["Unknown", "Ongoing", "Completed"]) if series.status is "Ongoing": self.status_box.setCurrentIndex(1) elif series.status is "Completed": self.status_box.setCurrentIndex(2) else: self.status_box.setCurrentIndex(0) self.pub_edit = QDateEdit() # TODO: Finish this.. self.pub_edit.setCalendarPopup(True) series_pub_date = "{}".format(series.pub_date) qdate_pub_date = QDate.fromString(series_pub_date, "yyyy-MM-dd") self.pub_edit.setDate(qdate_pub_date) self.path_lbl = QLabel("unspecified...") self.path_lbl.setWordWrap(True) self.path_lbl.setText(series.path) series_layout.addRow("Title:", self.title_edit) series_layout.addRow("Author:", self.author_edit) series_layout.addRow("Description:", self.descr_edit) series_layout.addRow("Language:", self.lang_box) series_layout.addRow("Tags:", self.tags_edit) series_layout.addRow("Type:", self.type_box) series_layout.addRow("Publication Date:", self.pub_edit) series_layout.addRow("Path:", self.path_lbl) final_buttons = QHBoxLayout() final_buttons.setAlignment(Qt.AlignRight) main_layout.addLayout(final_buttons) done = QPushButton("Done") done.setDefault(True) done.clicked.connect(self.accept_edit) cancel = QPushButton("Cancel") cancel.clicked.connect(self.reject_edit) final_buttons.addWidget(cancel) final_buttons.addWidget(done) self.setLayout(main_layout) def accept_edit(self): if self.check(): new_series = self.series new_series.title = self.title_edit.text() new_series.artist = self.author_edit.text() new_series.path = self.path_lbl.text() new_series.info = self.descr_edit.toPlainText() new_series.type = self.type_box.currentText() new_series.language = self.lang_box.currentText() new_series.status = self.status_box.currentText() qpub_d = self.pub_edit.date().toString("ddMMyyyy") dpub_d = datetime.strptime(qpub_d, "%d%m%Y").date() new_series.pub_date = dpub_d #for ser in self.series: self.SERIES_EDIT.emit([new_series], self.position) super().accept() def reject_edit(self): super().reject()
class MainWindow(PageWindow): def __init__(self, dir): super().__init__() self.storage = firebase.screening() try: self.ser = serial.Serial(port='COM3', baudrate=115200, bytesize=8, parity='N', stopbits=1) except Exception as ex: message = template.format(type(ex).__name__, ex.args) print(message) self.dirname = dir self.seperator_vertical = QVSeperationLine() self.seperator_horizontal = QHSeperationLine() self.initUI() self.setWindowTitle("MainWindow") self.overlay = Overlay(self.centralWidget()) self.available_cameras = QCameraInfo.availableCameras() if not self.available_cameras: pass #quit self.select_camera(0) def initUI(self): self.homeUI() def homeUI(self): self.preview_widget = QWidget() self.footer_widget = QWidget() self.grid_widget = QWidget() self.graph_widget = QWidget() self.home = True self.viewfinder = QCameraViewfinder() self.viewfinder.show() self.setCentralWidget(self.viewfinder) self.cap = None # -capture <-> +cap self.horizontalLayout = QHBoxLayout() self.horizontalLayout2 = QHBoxLayout() self.horizontalLayout.setObjectName("horizontalLayout") self.verticalLayout = QVBoxLayout() self.chartLayout = QVBoxLayout() self.verticalLayout.setObjectName("verticalLayout") self.image_label = QLabel() self.image_label.setText("") self.image_label.setObjectName("image_label") self.image_label.setStyleSheet("QLabel { margin-right:4px; }") self.temp = QLabel() self.temp.setText("TEMPERATURE : ") self.temp.setObjectName("temp") self.temp.setFont(QFont("Gadugi", 15, weight=QFont.Bold)) #self.temp.setAlignment(QtCore.Qt.AlignCenter) self.temp_reading = QLabel() self.temp_reading.setText("READING...") self.temp_reading.setObjectName("temp_reading") self.temp_reading.setFont(QFont("Gadugi", 15, weight=QFont.Bold)) #self.temp_reading.setAlignment(QtCore.Qt.AlignCenter) self.temp2 = QLabel() self.temp2.setText("ROOM READING : ") self.temp2.setFont(QFont("Gadugi", 15, weight=QFont.Bold)) self.temp2.setObjectName("temp2") #self.temp2.setAlignment(QtCore.Qt.AlignCenter) self.temp2_reading = QLabel() self.temp2_reading.setText("READING...") self.temp2_reading.setFont(QFont("Gadugi", 15, weight=QFont.Bold)) #self.temp2_reading.setAlignment(QtCore.Qt.AlignCenter) self.temp2_reading.setObjectName("temp2_reading") self.image_label.setScaledContents(True) self.matplotlibWidget = MatplotlibWidget(self) self.threadSample = ThreadSample(self) self.threadSample.newSample.connect(self.on_threadSample_newSample) self.threadSample.finished.connect(self.on_threadSample_finished) self.gridLayout = QGridLayout(self) self.gridLayout.addWidget(self.temp, 0, 0, 1, 1) self.gridLayout.addWidget(self.temp_reading, 0, 1, 1, 3) self.gridLayout.addWidget(self.temp2, 2, 0, 1, 1) self.gridLayout.addWidget(self.temp2_reading, 2, 1, 1, 3) self.clock(self.gridLayout, 3, 0, 3, 3) self.grid_widget.setLayout(self.gridLayout) self.grid_widget.setMinimumHeight(250) self.grid_widget.setMaximumHeight(250) self.grid_widget.setMinimumWidth(600) self.grid_widget.setMaximumWidth(600) self.horizontalLayout.addWidget(self.image_label) #self.horizontalLayout.addWidget(self.seperator_vertical) self.horizontalLayout.addWidget(self.graph_widget) self.preview_widget.setLayout(self.horizontalLayout) self.preview_widget.setMinimumHeight(200) self.preview_widget.setMaximumHeight(200) self.preview_widget.setMinimumWidth(600) self.preview_widget.setMaximumWidth(600) # self.chartLayout.addWidget(self.matplotlibWidget) # self.graph_widget.setLayout(self.chartLayout) self.graph_widget.setMinimumHeight(250) self.graph_widget.setMaximumHeight(250) self.graph_widget.setMinimumWidth(250) self.graph_widget.setMaximumWidth(250) self.horizontalLayout2.addWidget(self.grid_widget) # self.horizontalLayout2.addWidget(self.seperator_vertical) #self.horizontalLayout2.addWidget(self.clock) #self.clock(self.horizontalLayout2) self.footer_widget.setLayout(self.horizontalLayout2) self.footer_widget.setMinimumHeight(250) self.footer_widget.setMaximumHeight(250) self.footer_widget.setMinimumWidth(600) self.footer_widget.setMaximumWidth(600) self.verticalLayout.addWidget(self.preview_widget) self.verticalLayout.addWidget(self.seperator_horizontal) self.verticalLayout.addWidget(self.footer_widget) #self.verticalLayout.addWidget(self.image_label2) self.timer = QTimer(self, interval=5) self.timer.timeout.connect(self.update_frame) self._image_counter = 0 centralWidget = QWidget(self) self.setCentralWidget(centralWidget) self.centralWidget().setLayout(self.verticalLayout) self.start_webcam() self.update_frame() # self.setCentralWidget(self.scroll) self.setGeometry(300, 300, 400, 700) thread = Thread(target=self.read_temp) thread.daemon = True thread.start() def select_camera(self, i): self.camera = QCamera(self.available_cameras[i]) self.camera.setViewfinder(self.viewfinder) self.camera.setCaptureMode(QCamera.CaptureStillImage) self.camera.error.connect( lambda: self.alert(self.camera.errorString())) self.camera.start() self.capture = QCameraImageCapture(self.camera) self.capture.error.connect(lambda i, e, s: self.alert(s)) self.capture.imageCaptured.connect(lambda d, i: self.statusmessage( "Image %04d captured" % self.save_seq)) self.current_camera_name = self.available_cameras[i].description() self.save_seq = 0 def read_temp(self): temp = [] while True: self.ser.write(b'0x55,0xAA,5,1,4') response = self.ser.readline() print(str(response)) if 'body' in str(response): temp.append(str(response)) #print("temp-"+str(response)) #print(temp) elif 'Vbat' in str(response): if len(temp) != 0: temp[1] = temp[1].replace('b\'T body =', '') temp[1] = temp[1].replace("\\r\\n'", '') temp[0] = temp[0].replace('b\'T body =', '') temp[0] = temp[0].replace("compensate\\r\\n'", '') self.findFaces('-'.join(temp)) self.update_label(temp[0], temp[1], '12') temp = [] time.sleep(1) # start = time.clock() # while True: # if True: # if True: # temp.append(str(random.randint(0,100))) # temp.append(str(random.randint(0,100))) # self.overlay.show() # self.findFaces('-'.join(temp)) # self.update_label(temp[0],temp[1],'12') # self.overlay.hide() # print("Done-"+ ' '.join(temp)) # temp = [] # time.sleep(1) def statusmessage(self, msg): self.statusBar().showMessage(msg) def update_label(self, temp1, temp2, time): print(temp1) temp2 = self.getTemp(str(temp2)) temp1 = self.getTemp(str(temp1)) if temp2 >= 36.1 and temp2 <= 37.2: pal = self.temp_reading.palette() pal.setColor(QPalette.WindowText, QColor("green")) self.temp_reading.setPalette(pal) else: pal = self.temp_reading.palette() pal.setColor(QPalette.WindowText, QColor("red")) self.temp_reading.setPalette(pal) # if temp2>=36.1 and temp2<=37.2: # pal = self.temp_reading.palette() # pal.setColor(QPalette.WindowText, QColor("black")) # self.temp2_reading.setPalette(pal) # else: # pal = self.temp_reading.palette() # pal.setColor(QPalette.WindowText, QColor("black")) # self.temp2_reading.setPalette(pal) self.temp_reading.setText(str(temp2) + " °C") self.temp2_reading.setText(str(temp1) + " °C") #self.temp2_reading.setColor(QPalette.WindowText, QtGui.QColor("red")) def getTemp(self, inp): temp = re.findall(r"[-+]?\d*\.\d+|\d+", inp) temp = ''.join(temp) if temp == '': return 0 else: return float(temp) def filter(self, text): text = text.replace('bTbody', 'body') text = text.replace('\'', '') text = text.replace('\\r\n\'b\'Tbody', '-') text = text.replace('\\r', '') text = text.replace('\r', '') text = text.replace('\\xa8', '') text = text.replace('\\xa1\\xe6', '') text = text.replace('\\n', '-') text = text.replace(' ', '') text = text.replace(', ', ',') text = text.replace('=', '_') text = text.replace(',', '-') return text def alert(self, s): """ Handle errors coming from QCamera dn QCameraImageCapture by displaying alerts. """ err = QErrorMessage(self) err.showMessage(s) @QtCore.pyqtSlot() def start_webcam(self): if self.cap is None: self.cap = cv2.VideoCapture(0) self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) self.timer.start() def start_cam(self): self.cap.open(0) def stop_webcam(self): self.cap.release() def closeEvent(self, event): print("closing PyQtTest") self.cap.close() @QtCore.pyqtSlot() def update_frame(self): if self.cap.isOpened(): ret, image = self.cap.read() #self.face_detect(image,file_name) simage = cv2.flip(image, 1) self.displayImage(image, True) def findFaces(self, file_name): face_detect = True while face_detect: if self.cap.isOpened(): ret, frame = self.cap.read() face_locations = fl(frame) print("I found {} face(s) in this photograph.".format( len(face_locations))) #self.statusmessage("I found {} face(s) in this photograph.".format(len(face_locations))) for face_location in face_locations: face_detect = False # Print the location of each face in this image top, right, bottom, left = face_location print( "A face is located at pixel location Top: {}, Left: {}, Bottom: {}, Right: {}" .format(top, left, bottom, right)) # ts = time.time() # You can access the actual face itself like this: face_image = frame[top - 100:bottom + 100, left - 100:right + 100] ts = datetime.now().strftime('%Y_%m_%d-%H_%M_%S') cv2.imwrite( os.path.abspath( os.path.join(self.dirname, (ts + '-' + file_name + '.jpg'))), face_image) self.storage.upload(self.dirname, (ts + '-' + file_name + '.jpg')) def face_detect(self, file_name): face_locations = [] face_encodings = [] face_names = [] process_this_frame = True i = 0 face_detect = True # Resize frame of video to 1/4 size for faster face recognition processing while face_detect: ret, frame = self.cap.read() #self.face_detect(image,file_name) #simage = cv2.flip(image, 1) small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25) # Convert the image from BGR color (which OpenCV uses) to RGB color (which face_recognition uses) rgb_small_frame = small_frame[:, :, ::-1] # Only process every other frame of video to save time if process_this_frame: # Find all the faces and face encodings in the current frame of video face_locations = face_recognition.face_locations( rgb_small_frame) face_encodings = face_recognition.face_encodings( rgb_small_frame, face_locations) face_names = [] for face_encoding in face_encodings: # See if the face is a match for the known face(s) face_detect = False name = "Unknown" cv2.imwrite( os.path.abspath( os.path.join( self.dirname, (datetime.today().strftime('%Y-%m-%d') + '-' + file_name + '-' + str(++i) + '.png'))), frame) #self.storage.upload(self.dirname,(datetime.today().strftime('%Y-%m-%d')+'-'+file_name+'-'+str(i)+'.png')) i = i + 1 print("I see someone named {}!".format(name)) # # If a match was found in known_face_encodings, just use the first one. # if True in matches: # first_match_index = matches.index(True) # name = known_face_names[first_match_index] # Or instead, use the known face with the smallest distance to the new face process_this_frame = not process_this_frame @QtCore.pyqtSlot() def capture_image(self): if self.cap.isOpened(): flag, frame = self.cap.read() timestamp = time.strftime("%d-%b-%Y-%H_%M_%S") self.save_seq += 1 path = self.dirname # if flag: QtWidgets.QApplication.beep() name = "my_image.jpg" cv2.imwrite( os.path.join( self.dirname, "%s-%04d-%s.jpg" % (self.current_camera_name, self.save_seq, timestamp)), frame) self.alert('Image Store Successfully.') self._image_counter += 1 def displayImage(self, img, window=True): qformat = QImage.Format_Indexed8 if len(img.shape) == 3: if img.shape[2] == 4: qformat = QImage.Format_RGBA8888 else: qformat = QImage.Format_RGB888 outImage = QImage(img, img.shape[1], img.shape[0], img.strides[0], qformat) outImage = outImage.rgbSwapped() if window: self.image_label.setStyleSheet(""" QLabel { height:300px !important; } """) self.image_label.setPixmap(QPixmap.fromImage(outImage)) def clock(self, layout, row, col, row_span, col_span): self.verticalLayoutClock = QVBoxLayout(self) self.dateEdit = QDateEdit(self) self.dateEdit.setDisplayFormat("MMM dd yyyy") self.dateEdit.setDisabled(True) self.verticalLayoutClock.addWidget(self.dateEdit) self.timeEdit = QTimeEdit(self) self.timeEdit.setDisplayFormat("hh:mm:ss AP") self.timeEdit.setDisabled(True) self.verticalLayoutClock.addWidget(self.timeEdit) self.updateTime() self.timer = QTimer(self) self.timer.timeout.connect(self.updateTime) self.timer.start(1000) layout.addLayout(self.verticalLayoutClock, row, col, row_span, col_span) @QtCore.pyqtSlot(list) def on_threadSample_newSample(self, sample): self.matplotlibWidget.axis.plot(sample) self.matplotlibWidget.canvas.draw() @QtCore.pyqtSlot() def on_threadSample_finished(self): self.samples += 1 if self.samples <= 2: self.threadSample.start() @QtCore.pyqtSlot() def on_pushButtonPlot_clicked(self): self.samples = 0 self.matplotlibWidget.axis.clear() self.threadSample.start() def updateTime(self): current = QtCore.QDateTime.currentDateTime() self.dateEdit.setDate(current.date()) self.timeEdit.setTime(current.time())
class TaskView(QWidget): close = pyqtSignal() def __init__(self, model): super().__init__() self.header = QLabel('') self.desc = QLineEdit() self.date = QDateEdit() self.time = QTimeEdit() self.init_ui() self.mapper = QDataWidgetMapper() self.mapper.setModel(model) self.mapper.setSubmitPolicy(QDataWidgetMapper.ManualSubmit) self.mapper.addMapping(self.desc, TaskModel.col_desc) self.mapper.addMapping(self.date, TaskModel.col_date) self.mapper.addMapping(self.time, TaskModel.col_time) def set_task(self, index): self.mapper.setCurrentIndex(index) self.header.setText('РЕДАКТИРОВАНИЕ ЗАДАЧИ') # text = 'НОВАЯ ЗАДАЧА' # self.date.setDate(QDate().currentDate()) def create_date(self): self.date.setDisplayFormat('dd.MM.yyyy') self.date.setCalendarPopup(True) self.date.setFixedWidth(120) return self.date def create_time(self): self.time.setDisplayFormat('hh.mm') self.time.setFixedWidth(120) return self.time def create_date_buttons(self): date_lt = QHBoxLayout() btn_now = QPushButton('сегодня') btn_now.clicked.connect(lambda: self.date.setDate(QDate().currentDate())) date_lt.addWidget(btn_now, 0, Qt.AlignCenter) btn_tomorrow = QPushButton('завтра') btn_tomorrow.clicked.connect(lambda: self.date.setDate(QDate().currentDate().addDays(1))) date_lt.addWidget(btn_tomorrow, 0, Qt.AlignCenter) btn_week_later = QPushButton('через неделю') btn_week_later.clicked.connect(lambda: self.date.setDate(QDate().currentDate().addDays(7))) date_lt.addWidget(btn_week_later, 0, Qt.AlignCenter) return date_lt # def create_time_choice(self): # self.time.setMaxVisibleItems(15) # self.time.setStyleSheet('QComboBox { combobox-popup: 0; }') # for it in range(24): # self.time.insertItem(it * 2 + 0, '%.2d:00' % it) # self.time.insertItem(it * 2 + 1, '%.2d:30' % it) # # return self.time def save(self): print('save', self.mapper.submit()) self.close.emit() def cancel(self): self.close.emit() def remove(self): self.mapper.model().removeRow(self.mapper.currentIndex()) self.close.emit() def create_control_buttons(self): control_lt = QHBoxLayout() btn_save = QPushButton('Сохранить') btn_save.clicked.connect(self.save) control_lt.addWidget(btn_save, 0, Qt.AlignCenter) btn_cancel = QPushButton('Отменить') btn_cancel.clicked.connect(self.cancel) control_lt.addWidget(btn_cancel, 0, Qt.AlignCenter) btn_remove = QPushButton('Удалить') btn_remove.clicked.connect(self.remove) control_lt.addWidget(btn_remove, 1, Qt.AlignRight) return control_lt def create_main_form(self): fm = QFormLayout() fm.addRow(self.header) fm.addRow(QLabel('')) fm.addRow(self.desc) fm.addRow(QLabel('')) fm.addRow(QLabel('Когда это нужно сделать?')) fm.addRow(self.create_date()) fm.addRow(self.create_date_buttons()) fm.addRow(QLabel('')) fm.addRow(QLabel('Во сколько?')) fm.addRow(self.create_time()) return fm def init_ui(self): layout = QVBoxLayout() layout.addLayout(self.create_main_form()) layout.addStretch() layout.addLayout(self.create_control_buttons()) self.setLayout(layout)
class BookLog(QWidget): NavigationMode, AddingMode, EditingMode = range(3) def __init__(self, parent=None): super(BookLog, self).__init__(parent) self.contacts = SortedDict() self.oldTitle = '' self.oldMemo = '' self.oldShoziflag = False self.oldIsbn = '' self.oldDokuryodate = QDate() self.currentMode = self.NavigationMode #ラベル titleLabel = QLabel("書名:") self.titleLine = QLineEdit() self.titleLine.setReadOnly(True) dokuryoLabel = QLabel("読了日:") self.dokuryodate = QDateEdit() self.dokuryodate.setReadOnly(True) memoLabel = QLabel("メモ:") self.memoText = QTextEdit() self.memoText.setReadOnly(True) isbnLabel = QLabel("ISBN:") self.isbnLine = QLineEdit() self.isbnLine.setReadOnly(True) shoziflag = QLabel("所持:") self.shoziflag = QCheckBox() self.addButton = QPushButton("&追加") self.addButton.show() self.editButton = QPushButton("&編集") self.editButton.setEnabled(False) self.removeButton = QPushButton("&削除") self.removeButton.setEnabled(False) self.findButton = QPushButton("&検索") self.findButton.setEnabled(False) self.submitButton = QPushButton("&挿入") self.submitButton.hide() self.cancelButton = QPushButton("&キャンセル") self.cancelButton.hide() self.nextButton = QPushButton("&次") self.nextButton.setEnabled(False) self.previousButton = QPushButton("&前") self.previousButton.setEnabled(False) self.loadButton = QPushButton("&Load...") self.loadButton.setToolTip("Load contacts from a file") self.saveButton = QPushButton("Sa&ve...") self.saveButton.setToolTip("Save contacts to a file") self.saveButton.setEnabled(False) self.exportButton = QPushButton("Ex&port") self.exportButton.setToolTip("Export as vCard") self.exportButton.setEnabled(False) self.dialog = FindDialog() self.addButton.clicked.connect(self.addContact) self.submitButton.clicked.connect(self.submitContact) self.editButton.clicked.connect(self.editContact) self.removeButton.clicked.connect(self.removeContact) #self.findButton.clicked.connect(self.findContact) self.cancelButton.clicked.connect(self.cancel) self.nextButton.clicked.connect(self.next) self.previousButton.clicked.connect(self.previous) self.loadButton.clicked.connect(self.loadFromFile) self.saveButton.clicked.connect(self.saveToFile) self.exportButton.clicked.connect(self.exportAsVCard) #self.createMenus() #topFiller = QWidget() #topFiller.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) buttonLayout1 = QVBoxLayout() buttonLayout1.addWidget(self.addButton) buttonLayout1.addWidget(self.editButton) buttonLayout1.addWidget(self.removeButton) buttonLayout1.addWidget(self.findButton) buttonLayout1.addWidget(self.submitButton) buttonLayout1.addWidget(self.cancelButton) buttonLayout1.addWidget(self.loadButton) buttonLayout1.addWidget(self.saveButton) buttonLayout1.addWidget(self.exportButton) buttonLayout1.addStretch() buttonLayout2 = QHBoxLayout() buttonLayout2.addWidget(self.previousButton) buttonLayout2.addWidget(self.nextButton) mainLayout = QGridLayout() mainLayout.addWidget(titleLabel, 0, 0) mainLayout.addWidget(self.titleLine, 0, 1) mainLayout.addWidget(memoLabel, 3, 0, Qt.AlignTop) mainLayout.addWidget(self.memoText, 3, 1) mainLayout.addWidget(dokuryoLabel, 2, 0) mainLayout.addWidget(self.dokuryodate, 2, 1) mainLayout.addWidget(isbnLabel, 1, 0) mainLayout.addWidget(self.isbnLine, 1, 1) mainLayout.addWidget(shoziflag, 4, 0) mainLayout.addWidget(self.shoziflag, 4, 1) mainLayout.addLayout(buttonLayout1, 6, 2) mainLayout.addLayout(buttonLayout2, 5, 1) #テーブル self.table = QTableWidget(100, 5,) self.table.setHorizontalHeaderLabels(["書名", "ISBN", "読了日", "メモ", "所持"]) self.table.verticalHeader().setVisible(False) #for i, (title, memo) in enumerate(tableData): i = 0 for title, obj in self.contacts.items(): titleItem = QTableWidgetItem(title) memoItem = QTableWidgetItem() memoItem.setData(Qt.DisplayRole, memo) if obj['shoziflag'] == True: maru = '○' else: maru = '' self.table.setItem(i, 0, titleItem) self.table.setItem(i, 1, QTableWidgetItem(obj['isbn'])) self.table.setItem(i, 2, QTableWidgetItem(obj['dokuryodate'])) self.table.setItem(i, 3, QTableWidgetItem(obj['memo'])) self.table.setItem(i, 4, QTableWidgetItem(maru)) i += 1 #table.resize(150, 50) #self.table.resizeColumnToContents(0) self.table.horizontalHeader().setStretchLastSection(True) self.table.doubleClicked.connect(self.tableclick) mainLayout.addWidget(self.table, 6, 1) #mainLayout.addWidget(topFiller) self.setLayout(mainLayout) self.setWindowTitle("Simple Book Log") #self.csvImport() self.loadFromFile('./a.bl') def createUI(self): self.setWindowTitle('Equipment Manager 0.3') #Menu Bar fileMenuBar = QMenuBar(self) menuFile = QMenu(fileMenuBar) actionChangePath = QAction(tr("Change Path"), self) fileMenuBar.addMenu(menuFile) menuFile.addAction(actionChangePath) def addContact(self): self.oldTitle = self.titleLine.text() self.oldMemo = self.memoText.toPlainText() self.oldIsbn = self.isbnLine.text() self.titleLine.clear() self.memoText.clear() self.isbnLine.clear() self.updateInterface(self.AddingMode) def editContact(self): self.oldTitle = self.titleLine.text() self.oldMemo = self.memoText.toPlainText() self.oldDokuryodate = self.dokuryodate.text() self.oldIsbn = self.isbnLine.text() self.oldShoziflag = self.shoziflag.isChecked() self.updateInterface(self.EditingMode) def submitContact(self): title = self.titleLine.text() memo = self.memoText.toPlainText() isbn = self.isbnLine.text() dokuryodate = self.dokuryodate.text() shoziflag = self.shoziflag.isChecked() if title == "" or memo == "": QMessageBox.information(self, "Empty Field", "Please enter a title and memo.") return if self.currentMode == self.AddingMode: if title not in self.contacts: self.contacts[title] = {'memo':memo, 'dokuryodate':dokuryodate, 'isbn':isbn, 'shoziflag':shoziflag} QMessageBox.information(self, "追加しました", "\"%s\" は追加されました。" % title) else: QMessageBox.information(self, "追加できませんでした", "\"%s\" はすでに存在しています。" % title) return elif self.currentMode == self.EditingMode: if self.oldTitle != title: if title not in self.contacts: QMessageBox.information(self, "編集しました", "\"%s\" は編集されました。" % self.oldTitle) del self.contacts[self.oldTitle] self.contacts[title] = memo else: QMessageBox.information(self, "編集できませんでした。", "\"%s\"はすでに存在しています。" % title) return elif self.oldMemo != memo: QMessageBox.information(self, "編集しました", "\"%s\"は編集されました。" % title) self.contacts[title] = {memo:memo, dokuryodate:dokuryodate, shoziflag:shoziflag, isbn:isbn } self.updateInterface(self.NavigationMode) # ボタンの処理 def cancel(self): self.titleLine.setText(self.oldTitle) self.memoText.setText(self.oldMemo) self.dokuryodate.setDate(self.oldDokuryodate) self.shoziflag.setChecked(self.oldShoziflag) self.isbnLine.setText(self.oldIsbn) self.updateInterface(self.NavigationMode) def removeContact(self): title = self.titleLine.text() memo = self.memoText.toPlainText() if title in self.contacts: button = QMessageBox.question(self, "Confirm Remove", "Are you sure you want to remove \"%s\"?" % title, QMessageBox.Yes | QMessageBox.No) if button == QMessageBox.Yes: self.previous() del self.contacts[title] QMessageBox.information(self, "Remove Successful", "\"%s\" has been removed from your memo book." % title) self.updateInterface(self.NavigationMode) def next(self): title = self.titleLine.text() it = iter(self.contacts) try: while True: this_title, _ = it.next() if this_title == title: next_title, next_memo, next_date = it.next() break except StopIteration: next_title, next_memo = iter(self.contacts).next() self.titleLine.setText(next_title) self.memoText.setText(next_memo) def previous(self): title = self.titleLine.text() prev_title = prev_memo = None for this_title, this_memo in self.contacts: if this_title == title: break prev_title = this_title prev_memo = this_memo else: self.titleLine.clear() self.memoText.clear() return if prev_title is None: for prev_title, prev_memo in self.contacts: pass self.titleLine.setText(prev_title) self.memoText.setText(prev_memo) def Contact(self): self.dialog.show() if self.dialog.exec_() == QDialog.Accepted: contactTitle = self.dialog.getFindText() found = False for this_title, this_memo in self.contacts: # if contactTitle in this_title: if re.search(contactTitle, this_title): found = True break if found: self.titleLine.setText(this_title) self.memoText.setText(self.contacts[this_title]) self.isbnLine.setText(self.contacts[this_title]) self.dokuryodate.setDate(self.contacts[this_title]) self.shoziflag.setChecked(self.contacts[this_title]) else: QMessageBox.information(self, "Contact Not Found", "Sorry, \"%s\" is not in your address book." % contactTitle) return self.updateInterface(self.NavigationMode) # ボタンを押せるか押せないかの処理 def updateInterface(self, mode): self.currentMode = mode if self.currentMode in (self.AddingMode, self.EditingMode): self.titleLine.setReadOnly(False) self.titleLine.setFocus(Qt.OtherFocusReason) self.isbnLine.setReadOnly(False) self.dokuryodate.setReadOnly(False) self.memoText.setReadOnly(False) self.addButton.setEnabled(False) self.editButton.setEnabled(False) self.removeButton.setEnabled(False) self.nextButton.setEnabled(False) self.previousButton.setEnabled(False) self.submitButton.show() self.cancelButton.show() self.loadButton.setEnabled(False) self.saveButton.setEnabled(False) self.exportButton.setEnabled(False) elif self.currentMode == self.NavigationMode: if not self.contacts: self.titleLine.clear() self.memoText.clear() self.dokuryodate.clear() self.isbnLine.clear() self.titleLine.setReadOnly(True) self.memoText.setReadOnly(True) self.dokuryodate.setReadOnly(True) self.shoziflag self.isbnLine.setReadOnly(True) self.addButton.setEnabled(True) number = len(self.contacts) self.editButton.setEnabled(number >= 1) self.removeButton.setEnabled(number >= 1) self.findButton.setEnabled(number > 2) self.nextButton.setEnabled(number > 1) self.previousButton.setEnabled(number >1 ) self.submitButton.hide() self.cancelButton.hide() self.exportButton.setEnabled(number >= 1) self.loadButton.setEnabled(True) self.saveButton.setEnabled(number >= 1) #テーブルの更新 i = 0 for title, obj in self.contacts.items(): titleItem = QTableWidgetItem(title) memoItem = QTableWidgetItem() memoItem.setData(Qt.DisplayRole, obj['memo']) if obj['shoziflag'] == True: maru = '○' else: maru = '' self.table.setItem(i, 0, titleItem) self.table.setItem(i, 1, QTableWidgetItem(obj['isbn'])) self.table.setItem(i, 2, QTableWidgetItem(obj['dokuryodate'])) self.table.setItem(i, 3, QTableWidgetItem(obj['memo'])) self.table.setItem(i, 4, QTableWidgetItem(maru)) i += 1 def saveToFile(self): fileTitle, _ = QFileDialog.getSaveFileName(self, "Save book log", '', "Book Log (*.bl);;All Files (*)") if not fileTitle: return try: out_file = open(str(fileTitle), 'wb') except IOError: QMessageBox.information(self, "Unable to open file", "There was an error opening \"%s\"" % fileTitle) return pickle.dump(self.contacts, out_file) out_file.close() def loadFromFile(self, fileName= None): if not fileName: fileName, _ = QFileDialog.getOpenFileName(self, "Open Address Book", '', "Address Book (*.bl);;All Files (*)") try: in_file = open(str(fileName), 'rb') except IOError: QMessageBox.information(self, "Unable to open file", "There was an error opening \"%s\"" % fileName) return self.contacts = pickle.load(in_file) in_file.close() if len(self.contacts) == 0: QMessageBox.information(self, "No contacts in file", "The file you are attempting to open contains no " "contacts.") else: for title, obj in self.contacts: date = QDate.fromString(obj['dokuryodate']) self.titleLine.setText(title) self.memoText.setText(obj['memo']) self.shoziflag.setChecked(obj['shoziflag']) self.isbnLine.setText(obj['isbn']) self.dokuryodate.setDate(date) self.updateInterface(self.NavigationMode) def exportAsVCard(self): title = str(self.titleLine.text()) memo = self.memoText.toPlainText() titleList = title.split() if len(titleList) > 1: firstName = nameList[0] lastName = nameList[-1] else: firstName = name lastName = '' fileName, _ = QFileDialog.getSaveFileName(self, "Export Contact", '', "vCard Files (*.vcf);;All Files (*)") if not fileName: return out_file = QFile(fileName) if not out_file.open(QIODevice.WriteOnly): QMessageBox.information(self, "Unable to open file", out_file.errorString()) return out_s = QTextStream(out_file) out_s << 'BEGIN:VCARD' << '\n' out_s << 'VERSION:2.1' << '\n' out_s << 'N:' << lastName << ';' << firstName << '\n' out_s << 'FN:' << ' '.join(nameList) << '\n' address.replace(';', '\\;') address.replace('\n', ';') address.replace(',', ' ') out_s << 'ADR;HOME:;' << address << '\n' out_s << 'END:VCARD' << '\n' QMessageBox.information(self, "Export Successful", "\"%s\" has been exported as a vCard." % name) def csvImport(self): with open('MediaMarkerExport.csv', newline='', encoding='utf-8') as f: reader = csv.reader(f) for r in reader: if r[2] == 1: flag = True else: flag = False self.contacts[r[0]] = {'isbn':r[1], 'dokuryodate':r[3].replace('-', '/'), 'shoziflag':flag, 'memo':''} aa = 0 def createMenus(self): self.fileMenu = self.menuBar().addMenu("&File") #self.fileMenu.addAction(self.newAct) #self.fileMenu.addAction(self.openAct) #self.fileMenu.addAction(self.saveAct) #self.fileMenu.addAction(self.printAct) #self.fileMenu.addSeparator() #self.fileMenu.addAction(self.exitAct) self.editMenu = self.menuBar().addMenu("&Edit") self.editMenu.addAction(self.undoAct) self.editMenu.addAction(self.redoAct) self.editMenu.addSeparator() self.editMenu.addAction(self.cutAct) self.editMenu.addAction(self.copyAct) self.editMenu.addAction(self.pasteAct) self.editMenu.addSeparator() self.helpMenu = self.menuBar().addMenu("&Help") self.helpMenu.addAction(self.aboutAct) self.helpMenu.addAction(self.aboutQtAct) self.formatMenu = self.editMenu.addMenu("&Format") self.formatMenu.addAction(self.boldAct) self.formatMenu.addAction(self.italicAct) self.formatMenu.addSeparator().setText("Alignment") self.formatMenu.addAction(self.leftAlignAct) self.formatMenu.addAction(self.rightAlignAct) self.formatMenu.addAction(self.justifyAct) self.formatMenu.addAction(self.centerAct) self.formatMenu.addSeparator() self.formatMenu.addAction(self.setLineSpacingAct) self.formatMenu.addAction(self.setParagraphSpacingAct) def tableclick(self, mi): row = mi.row() column = mi.column() #QMessageBox.information(self, "Export Successful", # "%d x %d" % (row, column)) title = self.titleLine.text() it = iter(self.contacts) try: n = 0 while True: next_title, next_obj = it.next() if row == n: break n += 1 except StopIteration: next_title, next_obj = iter(self.contacts).next() self.titleLine.setText(next_title) self.memoText.setText(next_obj['memo']) self.isbnLine.setText(next_obj['isbn']) self.dokuryodate.setDate(next_obj['dokuryodate']) self.shoziflag.setChecked(next_obj['shoziflag'])
class ThirdTab(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): grid = QGridLayout() grid.addWidget(self.create_choice_groupbox(), 0, 0) grid.addWidget(self.create_view_groupbox(), 0, 1) self.setLayout(grid) # Groupbox : 기간 선택 def create_choice_groupbox(self): gbox = QGroupBox() hbox = QHBoxLayout() vbox = QVBoxLayout() hbox2 = QHBoxLayout() # widget lbl_period = QLabel('조회기간') self.dateed_start = QDateEdit() lbl_mark = QLabel('~') self.dateed_end = QDateEdit() self.dateed_start.setDate(QDate.currentDate()) self.dateed_end.setDate(QDate.currentDate()) self.dateed_start.setCalendarPopup(True) self.dateed_end.setCalendarPopup(True) btn_week = QPushButton('1주') btn_view = QPushButton('조회') # Signal btn_week.clicked.connect(self.change_week_period) btn_view.clicked.connect(self.lookup_period_sales) hbox.addWidget(lbl_period) hbox.addWidget(self.dateed_start) hbox.addWidget(lbl_mark) hbox.addWidget(self.dateed_end) hbox2.addWidget(btn_week) hbox2.addWidget(btn_view) vbox.addLayout(hbox) vbox.addLayout(hbox2) gbox.setLayout(vbox) return gbox # Groupbox : 조회 def create_view_groupbox(self): gbox = QGroupBox() vbox = QVBoxLayout() # widget '''cbox = QComboBox() cbox.addItem('매출건수') cbox.addItem('매출수량') cbox.addItem('매출총액') cbox.activated[str].connect()''' self.canvas = PlotCanvas(self, width=5, height=4) vbox.addWidget(self.canvas) gbox.setLayout(vbox) return gbox @pyqtSlot() def change_week_period(self): self.dateed_start.setDate(self.dateed_end.date().addDays(-6)) @pyqtSlot() def lookup_period_sales(self): if self.dateed_end.date() < self.dateed_start.date(): self.warn_period() else: stats.stats_period_sales(self.dateed_start.date().toPyDate(), self.dateed_end.date().toPyDate()) self.canvas.plot() @pyqtSlot() def warn_period(self): msg = QMessageBox.information(self, '조회기간 경고', '시작일은 종료일보다 나중일 수 없습니다.', QMessageBox.Ok, QMessageBox.Ok)
class GalleryDialog(QWidget): """ A window for adding/modifying gallery. Pass a list of QModelIndexes to edit their data or pass a path to preset path """ gallery_queue = queue.Queue() SERIES = pyqtSignal(list) SERIES_EDIT = pyqtSignal(list, int) #gallery_list = [] # might want to extend this to allow mass gallery adding def __init__(self, parent=None, arg=None): super().__init__(parent, Qt.Dialog) self.setAttribute(Qt.WA_DeleteOnClose) self.parent_widget = parent log_d('Triggered Gallery Edit/Add Dialog') m_l = QVBoxLayout() self.main_layout = QVBoxLayout() dummy = QWidget(self) scroll_area = QScrollArea(self) scroll_area.setWidgetResizable(True) scroll_area.setFrameStyle(scroll_area.StyledPanel) dummy.setLayout(self.main_layout) scroll_area.setWidget(dummy) m_l.addWidget(scroll_area, 3) final_buttons = QHBoxLayout() final_buttons.setAlignment(Qt.AlignRight) m_l.addLayout(final_buttons) self.done = QPushButton("Done") self.done.setDefault(True) cancel = QPushButton("Cancel") final_buttons.addWidget(cancel) final_buttons.addWidget(self.done) def new_gallery(): self.setWindowTitle('Add a new gallery') self.newUI() self.commonUI() self.done.clicked.connect(self.accept) cancel.clicked.connect(self.reject) if arg: if isinstance(arg, list): self.setWindowTitle('Edit gallery') self.position = arg[0].row() for index in arg: gallery = index.data(Qt.UserRole+1) self.commonUI() self.setGallery(gallery) self.done.clicked.connect(self.accept_edit) cancel.clicked.connect(self.reject_edit) elif isinstance(arg, str): new_gallery() self.choose_dir(arg) else: new_gallery() log_d('GalleryDialog: Create UI: successful') #TODO: Implement a way to mass add galleries #IDEA: Extend dialog in a ScrollArea with more forms... self.setLayout(m_l) self.resize(500,560) frect = self.frameGeometry() frect.moveCenter(QDesktopWidget().availableGeometry().center()) self.move(frect.topLeft()) #self.setAttribute(Qt.WA_DeleteOnClose) def commonUI(self): f_web = QGroupBox("Metadata from the Web") f_web.setCheckable(False) self.main_layout.addWidget(f_web) web_main_layout = QVBoxLayout() web_layout = QHBoxLayout() web_main_layout.addLayout(web_layout) f_web.setLayout(web_main_layout) f_gallery = QGroupBox("Gallery Info") f_gallery.setCheckable(False) self.main_layout.addWidget(f_gallery) gallery_layout = QFormLayout() f_gallery.setLayout(gallery_layout) def basic_web(name): return QLabel(name), QLineEdit(), QPushButton("Get metadata"), QProgressBar() url_lbl, self.url_edit, url_btn, url_prog = basic_web("URL:") url_btn.clicked.connect(lambda: self.web_metadata(self.url_edit.text(), url_btn, url_prog)) url_prog.setTextVisible(False) url_prog.setMinimum(0) url_prog.setMaximum(0) web_layout.addWidget(url_lbl, 0, Qt.AlignLeft) web_layout.addWidget(self.url_edit, 0) web_layout.addWidget(url_btn, 0, Qt.AlignRight) web_layout.addWidget(url_prog, 0, Qt.AlignRight) self.url_edit.setPlaceholderText("Paste g.e-hentai/exhentai gallery url or just press the button.") url_prog.hide() self.title_edit = QLineEdit() self.author_edit = QLineEdit() author_completer = misc.GCompleter(self, False, True, False) author_completer.setCaseSensitivity(Qt.CaseInsensitive) self.author_edit.setCompleter(author_completer) self.descr_edit = QTextEdit() self.descr_edit.setFixedHeight(45) self.descr_edit.setAcceptRichText(True) self.lang_box = QComboBox() self.lang_box.addItems(["English", "Japanese", "Other"]) self.lang_box.setCurrentIndex(0) tags_l = QVBoxLayout() tag_info = misc.ClickedLabel("How do i write namespace & tags? (hover)", parent=self) tag_info.setToolTip("Ways to write tags:\n\nNormal tags:\ntag1, tag2, tag3\n\n"+ "Namespaced tags:\nns1:tag1, ns1:tag2\n\nNamespaced tags with one or more"+ " tags under same namespace:\nns1:[tag1, tag2, tag3], ns2:[tag1, tag2]\n\n"+ "Those three ways of writing namespace & tags can be combined freely.\n"+ "Tags are seperated by a comma, NOT whitespace.\nNamespaces will be capitalized while tags"+ " will be lowercased.") tag_info.setToolTipDuration(99999999) tags_l.addWidget(tag_info) self.tags_edit = misc.CompleterTextEdit() self.tags_edit.setCompleter(misc.GCompleter(self, False, False)) tags_l.addWidget(self.tags_edit, 3) self.tags_edit.setFixedHeight(70) self.tags_edit.setPlaceholderText("Press Tab to autocomplete (Ctrl + E to show popup)") self.type_box = QComboBox() self.type_box.addItems(["Manga", "Doujinshi", "Artist CG Sets", "Game CG Sets", "Western", "Image Sets", "Non-H", "Cosplay", "Other"]) self.type_box.setCurrentIndex(0) #self.type_box.currentIndexChanged[int].connect(self.doujin_show) #self.doujin_parent = QLineEdit() #self.doujin_parent.setVisible(False) self.status_box = QComboBox() self.status_box.addItems(["Unknown", "Ongoing", "Completed"]) self.status_box.setCurrentIndex(0) self.pub_edit = QDateEdit() self.pub_edit.setCalendarPopup(True) self.pub_edit.setDate(QDate.currentDate()) self.path_lbl = QLabel("") self.path_lbl.setWordWrap(True) link_layout = QHBoxLayout() self.link_lbl = QLabel("") self.link_lbl.setWordWrap(True) self.link_edit = QLineEdit() link_layout.addWidget(self.link_edit) link_layout.addWidget(self.link_lbl) self.link_edit.hide() self.link_btn = QPushButton("Modify") self.link_btn.setFixedWidth(50) self.link_btn2 = QPushButton("Set") self.link_btn2.setFixedWidth(40) self.link_btn.clicked.connect(self.link_modify) self.link_btn2.clicked.connect(self.link_set) link_layout.addWidget(self.link_btn) link_layout.addWidget(self.link_btn2) self.link_btn2.hide() gallery_layout.addRow("Title:", self.title_edit) gallery_layout.addRow("Author:", self.author_edit) gallery_layout.addRow("Description:", self.descr_edit) gallery_layout.addRow("Language:", self.lang_box) gallery_layout.addRow("Tags:", tags_l) gallery_layout.addRow("Type:", self.type_box) gallery_layout.addRow("Status:", self.status_box) gallery_layout.addRow("Publication Date:", self.pub_edit) gallery_layout.addRow("Path:", self.path_lbl) gallery_layout.addRow("Link:", link_layout) self.title_edit.setFocus() def _find_combobox_match(self, combobox, key, default): f_index = combobox.findText(key, Qt.MatchFixedString) try: combobox.setCurrentIndex(f_index) except: combobox.setCurrentIndex(default) def setGallery(self, gallery): "To be used for when editing a gallery" self.gallery = gallery self.url_edit.setText(gallery.link) self.title_edit.setText(gallery.title) self.author_edit.setText(gallery.artist) self.descr_edit.setText(gallery.info) self.tags_edit.setText(utils.tag_to_string(gallery.tags)) self._find_combobox_match(self.lang_box, gallery.language, 2) self._find_combobox_match(self.type_box, gallery.type, 0) self._find_combobox_match(self.status_box, gallery.status, 0) gallery_pub_date = "{}".format(gallery.pub_date).split(' ') try: self.gallery_time = datetime.strptime(gallery_pub_date[1], '%H:%M:%S').time() except IndexError: pass qdate_pub_date = QDate.fromString(gallery_pub_date[0], "yyyy-MM-dd") self.pub_edit.setDate(qdate_pub_date) self.link_lbl.setText(gallery.link) self.path_lbl.setText(gallery.path) def newUI(self): f_local = QGroupBox("Directory/Archive") f_local.setCheckable(False) self.main_layout.addWidget(f_local) local_layout = QHBoxLayout() f_local.setLayout(local_layout) choose_folder = QPushButton("From Directory") choose_folder.clicked.connect(lambda: self.choose_dir('f')) local_layout.addWidget(choose_folder) choose_archive = QPushButton("From Archive") choose_archive.clicked.connect(lambda: self.choose_dir('a')) local_layout.addWidget(choose_archive) self.file_exists_lbl = QLabel() local_layout.addWidget(self.file_exists_lbl) self.file_exists_lbl.hide() def choose_dir(self, mode): """ Pass which mode to open the folder explorer in: 'f': directory 'a': files Or pass a predefined path """ self.done.show() self.file_exists_lbl.hide() if mode == 'a': name = QFileDialog.getOpenFileName(self, 'Choose archive', filter=utils.FILE_FILTER) name = name[0] elif mode == 'f': name = QFileDialog.getExistingDirectory(self, 'Choose folder') elif mode: if os.path.exists(mode): name = mode else: return None if not name: return head, tail = os.path.split(name) name = os.path.join(head, tail) parsed = utils.title_parser(tail) self.title_edit.setText(parsed['title']) self.author_edit.setText(parsed['artist']) self.path_lbl.setText(name) l_i = self.lang_box.findText(parsed['language']) if l_i != -1: self.lang_box.setCurrentIndex(l_i) if gallerydb.GalleryDB.check_exists(name): self.file_exists_lbl.setText('<font color="red">Gallery already exists.</font>') self.file_exists_lbl.show() # check galleries gs = 1 if name.endswith(utils.ARCHIVE_FILES): gs = len(utils.check_archive(name)) elif os.path.isdir(name): g_dirs, g_archs = utils.recursive_gallery_check(name) gs = len(g_dirs) + len(g_archs) if gs == 0: self.file_exists_lbl.setText('<font color="red">Invalid gallery source.</font>') self.file_exists_lbl.show() self.done.hide() if app_constants.SUBFOLDER_AS_GALLERY: if gs > 1: self.file_exists_lbl.setText('<font color="red">More than one galleries detected in source! Use other methods to add.</font>') self.file_exists_lbl.show() self.done.hide() def check(self): if len(self.title_edit.text()) is 0: self.title_edit.setFocus() self.title_edit.setStyleSheet("border-style:outset;border-width:2px;border-color:red;") return False elif len(self.author_edit.text()) is 0: self.author_edit.setText("Unknown") if len(self.path_lbl.text()) == 0 or self.path_lbl.text() == 'No path specified': self.path_lbl.setStyleSheet("color:red") self.path_lbl.setText('No path specified') return False return True def set_chapters(self, gallery_object, add_to_model=True): path = gallery_object.path chap_container = gallerydb.ChaptersContainer(gallery_object) metafile = utils.GMetafile() try: log_d('Listing dir...') con = scandir.scandir(path) # list all folders in gallery dir log_i('Gallery source is a directory') log_d('Sorting') chapters = sorted([sub.path for sub in con if sub.is_dir() or sub.name.endswith(utils.ARCHIVE_FILES)]) #subfolders # if gallery has chapters divided into sub folders if len(chapters) != 0: log_d('Chapters divided in folders..') for ch in chapters: chap = chap_container.create_chapter() chap.title = utils.title_parser(ch)['title'] chap.path = os.path.join(path, ch) metafile.update(utils.GMetafile(chap.path)) chap.pages = len(list(scandir.scandir(chap.path))) else: #else assume that all images are in gallery folder chap = chap_container.create_chapter() chap.title = utils.title_parser(os.path.split(path)[1])['title'] chap.path = path metafile.update(utils.GMetafile(path)) chap.pages = len(list(scandir.scandir(path))) except NotADirectoryError: if path.endswith(utils.ARCHIVE_FILES): gallery_object.is_archive = 1 log_i("Gallery source is an archive") archive_g = sorted(utils.check_archive(path)) for g in archive_g: chap = chap_container.create_chapter() chap.path = g chap.in_archive = 1 metafile.update(utils.GMetafile(g, path)) arch = utils.ArchiveFile(path) chap.pages = len(arch.dir_contents(g)) arch.close() metafile.apply_gallery(gallery_object) if add_to_model: self.SERIES.emit([gallery_object]) log_d('Sent gallery to model') def reject(self): if self.check(): msgbox = QMessageBox() msgbox.setText("<font color='red'><b>Noo oniichan! You were about to add a new gallery.</b></font>") msgbox.setInformativeText("Do you really want to discard?") msgbox.setStandardButtons(QMessageBox.Yes | QMessageBox.No) msgbox.setDefaultButton(QMessageBox.No) if msgbox.exec() == QMessageBox.Yes: self.close() else: self.close() def web_metadata(self, url, btn_widget, pgr_widget): self.link_lbl.setText(url) f = fetch.Fetch() thread = QThread(self) thread.setObjectName('Gallerydialog web metadata') btn_widget.hide() pgr_widget.show() def status(stat): def do_hide(): try: pgr_widget.hide() btn_widget.show() except RuntimeError: pass if stat: do_hide() else: danger = """QProgressBar::chunk { background: QLinearGradient( x1: 0, y1: 0, x2: 1, y2: 0,stop: 0 #FF0350,stop: 0.4999 #FF0020,stop: 0.5 #FF0019,stop: 1 #FF0000 ); border-bottom-right-radius: 5px; border-bottom-left-radius: 5px; border: .px solid black;}""" pgr_widget.setStyleSheet(danger) QTimer.singleShot(3000, do_hide) f.deleteLater() def gallery_picker(gallery, title_url_list, q): self.parent_widget._web_metadata_picker(gallery, title_url_list, q, self) try: dummy_gallery = self.make_gallery(self.gallery) except AttributeError: dummy_gallery = self.make_gallery(gallerydb.Gallery(), False) if not dummy_gallery: status(False) return None dummy_gallery.link = url f.galleries = [dummy_gallery] f.moveToThread(thread) f.GALLERY_PICKER.connect(gallery_picker) f.GALLERY_EMITTER.connect(self.set_web_metadata) thread.started.connect(f.auto_web_metadata) thread.finished.connect(thread.deleteLater) f.FINISHED.connect(status) thread.start() def set_web_metadata(self, metadata): assert isinstance(metadata, gallerydb.Gallery) self.link_lbl.setText(metadata.link) self.title_edit.setText(metadata.title) self.author_edit.setText(metadata.artist) tags = "" lang = ['English', 'Japanese'] self._find_combobox_match(self.lang_box, metadata.language, 2) self.tags_edit.setText(utils.tag_to_string(metadata.tags)) pub_string = "{}".format(metadata.pub_date) pub_date = QDate.fromString(pub_string.split()[0], "yyyy-MM-dd") self.pub_edit.setDate(pub_date) self._find_combobox_match(self.type_box, metadata.type, 0) def make_gallery(self, new_gallery, add_to_model=True, new=False): if self.check(): new_gallery.title = self.title_edit.text() log_d('Adding gallery title') new_gallery.artist = self.author_edit.text() log_d('Adding gallery artist') log_d('Adding gallery path') if new and app_constants.MOVE_IMPORTED_GALLERIES: app_constants.OVERRIDE_MONITOR = True new_gallery.path = utils.move_files(self.path_lbl.text()) else: new_gallery.path = self.path_lbl.text() new_gallery.info = self.descr_edit.toPlainText() log_d('Adding gallery descr') new_gallery.type = self.type_box.currentText() log_d('Adding gallery type') new_gallery.language = self.lang_box.currentText() log_d('Adding gallery lang') new_gallery.status = self.status_box.currentText() log_d('Adding gallery status') new_gallery.tags = utils.tag_to_dict(self.tags_edit.toPlainText()) log_d('Adding gallery: tagging to dict') qpub_d = self.pub_edit.date().toString("ddMMyyyy") dpub_d = datetime.strptime(qpub_d, "%d%m%Y").date() try: d_t = self.gallery_time except AttributeError: d_t = datetime.now().time().replace(microsecond=0) dpub_d = datetime.combine(dpub_d, d_t) new_gallery.pub_date = dpub_d log_d('Adding gallery pub date') new_gallery.link = self.link_lbl.text() log_d('Adding gallery link') if not new_gallery.chapters: log_d('Starting chapters') thread = threading.Thread(target=self.set_chapters, args=(new_gallery,add_to_model), daemon=True) thread.start() thread.join() log_d('Finished chapters') return new_gallery def link_set(self): t = self.link_edit.text() self.link_edit.hide() self.link_lbl.show() self.link_lbl.setText(t) self.link_btn2.hide() self.link_btn.show() def link_modify(self): t = self.link_lbl.text() self.link_lbl.hide() self.link_edit.show() self.link_edit.setText(t) self.link_btn.hide() self.link_btn2.show() def accept(self): new_gallery = self.make_gallery(gallerydb.Gallery(), new=True) if new_gallery: self.close() def accept_edit(self): new_gallery = self.make_gallery(self.gallery) #for ser in self.gallery: if new_gallery: self.SERIES_EDIT.emit([new_gallery], self.position) self.close() def reject_edit(self): self.close()