Example #1
1
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")
Example #2
0
 def createEditor(self, parent, option, index):
     editor = QDateEdit(parent)
     editor.setDisplayFormat('dd.MM.yyyy')
     editor.date().toString('dd.MM.yyyy')
     editor.setCalendarPopup(True)
     return editor
Example #3
0
class NetHoldingWindow(AncestorWindow):
    def __init__(self, *args, **kwargs):
        super(NetHoldingWindow, self).__init__(*args, **kwargs)
        # """连接数据库"""
        # self.__connect_database()
        """绑定公用属性"""
        self.products = None
        self.db_worker = None
        # 线程是否结束标志位
        self.exchange_lib_thread_over = True
        self.selected_variety_thread_over = True
        self.selected_contract_thread_over = True
        """总布局"""
        vertical_layout = QVBoxLayout()  # 总纵向布局
        top_select = QHBoxLayout()  # 顶部横向条件选择栏
        """交易所选择下拉框"""
        exchange_label = QLabel('选择交易所:')
        self.exchange_lib = QComboBox()
        self.exchange_lib.activated[str].connect(
            self.exchange_lib_selected)  # 选择交易所调用的方法
        """品种选择下拉框"""
        variety_label = QLabel('选择品种:')
        self.variety_lib = QComboBox()
        self.variety_lib.setMinimumSize(80, 20)
        self.variety_lib.activated[str].connect(
            self.variety_lib_selected)  # 选择品种所调用的方法
        """合约代码下拉框"""
        contract_label = QLabel('合约代码:')
        self.contract_lib = QComboBox()
        self.contract_lib.activated[str].connect(self.contract_lib_selected)
        """时间选择"""
        begin_time_label = QLabel("起始日期:")
        self.begin_time = QDateEdit(
            QDate.currentDate().addDays(-2))  # 参数为设置的日期
        self.begin_time.setDisplayFormat('yyyy-MM-dd')  # 时间显示格式
        self.begin_time.setCalendarPopup(True)  # 使用日历选择时间
        end_time_label = QLabel("终止日期:")
        self.end_time = QDateEdit(QDate.currentDate().addDays(-1))  # 参数为设置的日期
        self.end_time.setDisplayFormat('yyyy-MM-dd')  # 时间显示格式
        self.end_time.setCalendarPopup(True)  # 使用日历选择时间
        """确定按钮"""
        self.confirm_button = QPushButton("确定")
        self.confirm_button.clicked.connect(self.confirm)
        """各控件加入水平布局"""
        top_select.addWidget(exchange_label,
                             alignment=Qt.AlignTop | Qt.AlignLeft)
        top_select.addWidget(self.exchange_lib,
                             alignment=Qt.AlignTop | Qt.AlignLeft)
        top_select.addWidget(variety_label,
                             alignment=Qt.AlignTop | Qt.AlignLeft)
        top_select.addWidget(self.variety_lib,
                             alignment=Qt.AlignTop | Qt.AlignLeft)
        top_select.addWidget(contract_label,
                             alignment=Qt.AlignTop | Qt.AlignLeft)
        top_select.addWidget(self.contract_lib,
                             alignment=Qt.AlignTop | Qt.AlignLeft)
        top_select.addWidget(begin_time_label,
                             alignment=Qt.AlignTop | Qt.AlignLeft)
        top_select.addWidget(self.begin_time,
                             alignment=Qt.AlignTop | Qt.AlignLeft)
        top_select.addWidget(end_time_label,
                             alignment=Qt.AlignTop | Qt.AlignLeft)
        top_select.addWidget(self.end_time,
                             alignment=Qt.AlignTop | Qt.AlignLeft)
        top_select.addWidget(self.confirm_button,
                             alignment=Qt.AlignTop | Qt.AlignLeft)
        """自定义部件"""
        # 画布
        self.map_widget = MapWidget()
        # 表格,参数为列数
        self.table_widget = TableWidget(7)
        # 设置列名称
        self.table_widget.set_style(
            header_labels=['日期', '价格', '总持仓', '净多', '净空', '净持仓', '净持率'])
        """创建QSplitter"""
        show_splitter = QSplitter()
        show_splitter.setOrientation(Qt.Vertical)  # 垂直拉伸
        # 加入自定义控件
        show_splitter.addWidget(self.map_widget)
        show_splitter.addWidget(self.table_widget)
        """垂直布局添加布局和部件"""
        # vertical_layout.addLayout(self.title_hlayout)  # 窗口标题水平布局
        vertical_layout.addLayout(top_select)
        vertical_layout.addWidget(show_splitter)
        """设置总布局"""
        self.setLayout(vertical_layout)  # 总布局,只能设置一次

    def fill_init_data(self):
        """填充交易所"""
        self.exchange_lib.clear()
        for lib in RESEARCH_LIB:
            self.exchange_lib.addItem(lib)
        # 获取当前交易所的品种并填充
        self.exchange_lib_selected()

    def fill_contract(self, data):
        """根据品种选择线程执行返回的信号信息填充相应的品种"""
        data.reverse()
        # print("信号槽函数返回的信息", data)
        self.contract_lib.clear()
        for contract in data:
            self.contract_lib.addItem(contract)
        # 当合约填充完毕就解开交易所的选择锁
        self.exchange_lib_thread_over = True
        self.selected_variety_thread_over = True
        # 确定合约,显示时间
        self.contract_lib_selected()

    def change_time_interval(self, data):
        """根据合约选择线程返回的信号改变当前显示的时间"""
        current_date = datetime.datetime.today()
        min_time, max_time = data[0], data[1]
        if not min_time or not max_time:
            return
        # 转为时间类
        min_date = datetime.datetime.strptime(min_time, '%Y%m%d')
        max_date = datetime.datetime.strptime(max_time, '%Y%m%d')
        # 计算天数间隔
        big_time_interval = -(current_date - min_date).days  # 要往前取数,调整为负值
        small_time_interval = -(current_date - max_date).days
        # 设置时间
        self.begin_time.setDate(QDate.currentDate().addDays(big_time_interval))
        self.end_time.setDate(QDate.currentDate().addDays(small_time_interval))
        # 设置完时间就所有锁打开
        self.exchange_lib_thread_over = True
        self.selected_variety_thread_over = True
        self.selected_contract_thread_over = True
        # 设置完时间就设置确认按钮可用
        self.confirm_button.setEnabled(True)

    def exchange_lib_selected(self):
        """
        选择交易所调用的方法,线程执行:
        查询品种并填充
        """
        # 设置确认按钮不可用
        self.confirm_button.setEnabled(False)

        if not self.exchange_lib_thread_over:
            QMessageBox.warning(self, "错误", "您手速太快啦...", QMessageBox.Ok)
            return
        lib = self.exchange_lib.currentText()
        self.variety_lib.clear()
        if lib == "中国金融期货交易所":
            key = 'cffex'
            self.db_worker = self.cffex_getter
            self.products = CFFEX_PRODUCT_NAMES
        elif lib == "上海期货交易所":
            key = 'shfe'
            self.db_worker = self.shfe_getter
            self.products = SHFE_PRODUCT_NAMES
        elif lib == "大连商品交易所":
            key = 'dce'
            self.db_worker = self.dce_getter
            self.products = DCE_PRODUCT_NAMES
        elif lib == "郑州商品交易所":
            key = 'czce'
            self.db_worker = self.czce_getter
            self.products = CZCE_PRODUCT_NAMES
        else:
            self.db_worker = None
            self.products = None
            QMessageBox.information(self, '错误', "没有此项交易所..", QMessageBox.Ok)
            return
        for variety in GOODS_LIB.get(key):
            self.variety_lib.addItem(variety)

        self.exchange_lib_thread_over = False  # 选择完交易所就锁上不能再选择
        # 交易所确定,确定品种
        self.variety_lib_selected()

    def get_variety_en(self, variety):
        """获取相应的品种英文代号"""
        # 获取品种英文名称
        if not self.products:
            # print("没有品种库:", self.products)
            QMessageBox.warning(self, "错误", "内部发生未知错误")
            return ''
        return self.products.get(variety)

    def variety_lib_selected(self):
        """
        选择品种所调用的方法,线程执行:
        查询合约并填充合约
        """
        # 设置确认按钮不可用
        self.confirm_button.setEnabled(False)
        if not self.selected_variety_thread_over:
            QMessageBox.warning(self, "错误", "您手速太快啦...", QMessageBox.Ok)
            return
        variety = self.variety_lib.currentText()
        en_variety = self.get_variety_en(variety)
        # !!!(务必将线程绑在self对象上,否则无法实现多线程)
        self.selected_variety_thread_over = False
        if self.db_worker:
            self.variety_selected_thread = VarietySelectedThread(
                db_worker=self.db_worker, variety=en_variety)
            self.variety_selected_thread.result_signal.connect(
                self.fill_contract)
            self.variety_selected_thread.start()

    def contract_lib_selected(self):
        """
        选择了合约代码,查询本合约代码的时间周期,线程执行:
        信号返回结果,设置时间
        """
        # 设置确认按钮不可用
        self.confirm_button.setEnabled(False)

        if not self.selected_contract_thread_over:
            QMessageBox.warning(self, "错误", "您手速太快啦...", QMessageBox.Ok)
            return
        variety = self.variety_lib.currentText()
        variety_en = self.get_variety_en(variety)
        contract = self.contract_lib.currentText()
        # print("选择了合约代码:\n当前交易所:{}\n当前品种:{}\n当前合约:{}".format(lib, variety_en, contract))
        if self.db_worker:
            self.contract_selected_thread = ContractSelectedThread(
                db_worker=self.db_worker,
                variety=variety_en,
                contract=contract)
            self.contract_selected_thread.result_signal.connect(
                self.change_time_interval)
            self.contract_selected_thread.start()

    def confirm(self):
        """
        条件选择好了确认查询相应的数据进行图表生成,线程执行:
        信号返回结果设置状态
        """
        # 定时器计时
        self.timer.start(1000)
        # 设置确认按钮不可用,提示消息改为提交成功
        self.confirm_button.setText("提交成功")
        self.confirm_button.setEnabled(False)
        # 清除原图表并设置样式
        self.map_widget.delete()
        self.table_widget.clear()
        self.table_widget.set_style(
            header_labels=['日期', '价格', '总持仓', '净多', '净空', '净持仓', '净持率'])
        # 获取各数据
        lib = self.exchange_lib.currentText()
        variety = self.variety_lib.currentText()
        variety_en = self.get_variety_en(variety)
        contract = self.contract_lib.currentText()
        begin_time = re.sub('-', '', str(self.begin_time.date().toPyDate()))
        end_time = re.sub('-', '', str(self.end_time.date().toPyDate()))
        # print("确认提交:\n当前交易所:{}\n当前品种:{}:{}\n当前合约:{}\n起始时间:{}\n终止时间:{}".format(lib, variety, variety_en, contract, begin_time, end_time))
        # 转成可计算的datetime.datetime时间对象
        begin_time_datetime_cls = datetime.datetime.strptime(
            begin_time, "%Y%m%d")
        end_time_datetime_cls = datetime.datetime.strptime(end_time, "%Y%m%d")
        # 起止时间应早于终止时间
        if begin_time_datetime_cls >= end_time_datetime_cls:
            QMessageBox.warning(self, "错误", "起止时间应早于终止时间", QMessageBox.Ok)
            self.message_signal.emit("时间选择有误!")
            self.timer.stop()
            self.cost_time = 0
            # 设置确认按钮可用
            self.confirm_button.setText("确定")
            self.confirm_button.setEnabled(True)
            return
        # 生成时间可迭代对象
        iterator = GenerateTime(begin=begin_time_datetime_cls,
                                end=end_time_datetime_cls)
        # 线程执行查询目标数据
        self.confirm_thread = ConfirmQueryThread(db_worker=self.db_worker,
                                                 variety=variety_en,
                                                 contract=contract,
                                                 iterator=iterator,
                                                 lib=lib)
        self.confirm_thread.result_signal.connect(self.draw_map_table)
        self.confirm_thread.process_signal.connect(self.show_process)
        self.confirm_thread.start()

    def show_process(self, data):
        self.process_signal.emit(data)

    def draw_map_table(self, data):
        prices = data.get("prices")
        rates = data.get("rates")
        times = data.get("times")
        items = data.get("items")
        message = data.get("message")
        # 设置样式
        self.map_widget.set_style()
        # 重新设置标题
        self.map_widget.axes1.set_title(message + "合约价格-净持率趋势图")
        # 进行画图
        self.map_widget.net_holding_map(y_left=prices, y_right=rates, x=times)
        # 填充表格
        self.table_widget.net_holding_table(items)
        # 结果执行完程序
        self.message_signal.emit("处理完毕,生成图表成功!")
        self.timer.stop()
        self.cost_time = 0
        # 设置确认按钮可用
        self.confirm_button.setText("确定")
        self.confirm_button.setEnabled(True)
Example #4
0
class InputDialog(QDialog):
    def __init__(self, parent=None):
        QDialog.__init__(self, parent)
        self.setWindowTitle('Ввод данных')

        self.typePageLabel = QLabel("Тип листка:")
        self.typePageLineEdit = UpperSimplifiedLineEdit()
        self.surnameLabel = QLabel("Фамилия:")
        self.surnameLineEdit = UpperSimplifiedLineEdit()
        self.nameLabel = QLabel("Имя:")
        self.nameLineEdit = UpperSimplifiedLineEdit()
        self.patronymicLabel = QLabel("Отчество:")
        self.patronymicLineEdit = UpperSimplifiedLineEdit()

        self.personLayout = QGridLayout()
        self.personLayout.addWidget(self.typePageLabel, 0, 0)
        self.personLayout.addWidget(self.typePageLineEdit, 0, 1)
        self.personLayout.addWidget(self.surnameLabel, 0, 2)
        self.personLayout.addWidget(self.surnameLineEdit, 0, 3)
        self.personLayout.addWidget(self.nameLabel, 0, 4)
        self.personLayout.addWidget(self.nameLineEdit, 0, 5)
        self.personLayout.addWidget(self.patronymicLabel, 0, 6)
        self.personLayout.addWidget(self.patronymicLineEdit, 0, 7)
        self.personGroupBox = QGroupBox("ФИО")
        self.personGroupBox.setLayout(self.personLayout)

        self.birthdayLabel = QLabel("Дата:")
        self.birthdayLineEdit = UpperSimplifiedLineEdit()
        self.countryLabel = QLabel("Государство:")
        self.countryLineEdit = UpperSimplifiedLineEdit()
        self.regionLabel = QLabel("Область:")
        self.regionLineEdit = UpperSimplifiedLineEdit()
        self.cityLabel = QLabel("Город:")
        self.cityLineEdit = UpperSimplifiedLineEdit()
        self.districtLabel = QLabel("Район:")
        self.districtLineEdit = UpperSimplifiedLineEdit()
        self.localityLabel = QLabel("Населенный пункт:")
        self.localityLineEdit = UpperSimplifiedLineEdit()

        self.birthLayout = QGridLayout()
        self.birthLayout.addWidget(self.birthdayLabel, 0, 0)
        self.birthLayout.addWidget(self.birthdayLineEdit, 0, 1)
        self.birthLayout.addWidget(self.countryLabel, 1, 0)
        self.birthLayout.addWidget(self.countryLineEdit, 1, 1)
        self.birthLayout.addWidget(self.regionLabel, 1, 2)
        self.birthLayout.addWidget(self.regionLineEdit, 1, 3)
        self.birthLayout.addWidget(self.cityLabel, 1, 4)
        self.birthLayout.addWidget(self.cityLineEdit, 1, 5)
        self.birthLayout.addWidget(self.districtLabel, 4, 0)
        self.birthLayout.addWidget(self.districtLineEdit, 4, 1)
        self.birthLayout.addWidget(self.localityLabel, 4, 2)
        self.birthLayout.addWidget(self.localityLineEdit, 4, 3)
        self.birthGroupBox = QGroupBox("Рождение")
        self.birthGroupBox.setLayout(self.birthLayout)

        self.countryResidenceLabel = QLabel("Государство:")
        self.countryResidenceLineEdit = UpperSimplifiedLineEdit()
        self.regionResidenceLabel = QLabel("Область:")
        self.regionResidenceLineEdit = UpperSimplifiedLineEdit()
        self.cityResidenceLabel = QLabel("Город:")
        self.cityResidenceLineEdit = UpperSimplifiedLineEdit()
        self.districtResidenceLabel = QLabel("Район:")
        self.districtResidenceLineEdit = UpperSimplifiedLineEdit()
        self.localityResidenceLabel = QLabel("Населенный пункт:")
        self.localityResidenceLineEdit = UpperSimplifiedLineEdit()
        self.streetResidenceLabel = QLabel("Улица:")
        self.streetResidenceLineEdit = UpperSimplifiedLineEdit()
        self.houseResidenceLabel = QLabel("Дом:")
        self.houseResidenceLineEdit = UpperSimplifiedLineEdit()
        self.caseResidenceLabel = QLabel("Корпус:")
        self.caseResidenceLineEdit = UpperSimplifiedLineEdit()
        self.apartmentResidenceLabel = QLabel("Квартира:")
        self.apartmentResidenceLineEdit = UpperSimplifiedLineEdit()

        self.residenceLayout = QGridLayout()
        self.residenceLayout.addWidget(self.countryResidenceLabel, 0, 0)
        self.residenceLayout.addWidget(self.countryResidenceLineEdit, 0, 1)
        self.residenceLayout.addWidget(self.regionResidenceLabel, 0, 2)
        self.residenceLayout.addWidget(self.regionResidenceLineEdit, 0, 3)
        self.residenceLayout.addWidget(self.cityResidenceLabel, 0, 4)
        self.residenceLayout.addWidget(self.cityResidenceLineEdit, 0, 5)
        self.residenceLayout.addWidget(self.districtResidenceLabel, 1, 0)
        self.residenceLayout.addWidget(self.districtResidenceLineEdit, 1, 1)
        self.residenceLayout.addWidget(self.localityResidenceLabel, 1, 2)
        self.residenceLayout.addWidget(self.localityResidenceLineEdit, 1, 3)
        self.residenceLayout.addWidget(self.streetResidenceLabel, 2, 0)
        self.residenceLayout.addWidget(self.streetResidenceLineEdit, 2, 1)
        self.residenceLayout.addWidget(self.houseResidenceLabel, 2, 2)
        self.residenceLayout.addWidget(self.houseResidenceLineEdit, 2, 3)
        self.residenceLayout.addWidget(self.caseResidenceLabel, 2, 4)
        self.residenceLayout.addWidget(self.caseResidenceLineEdit, 2, 5)
        self.residenceLayout.addWidget(self.apartmentResidenceLabel, 2, 6)
        self.residenceLayout.addWidget(self.apartmentResidenceLineEdit, 2, 7)
        self.residenceGroupBox = QGroupBox("Адрес места жительства")
        self.residenceGroupBox.setLayout(self.residenceLayout)

        self.documentLabel = QLabel("Вид документа:")
        self.documentLineEdit = UpperSimplifiedLineEdit()
        self.seriesLabel = QLabel("Серия:")
        self.seriesLineEdit = UpperSimplifiedLineEdit()
        self.numberLabel = QLabel("Номер:")
        self.numberLineEdit = UpperSimplifiedLineEdit()
        self.dateIssueLabel = QLabel("Дата выдачи:")
        self.dateIssueLineEdit = UpperSimplifiedLineEdit()
        self.issuedLabel = QLabel("Кем выдан:")
        self.issuedLineEdit = UpperSimplifiedLineEdit()

        self.documentLayout = QGridLayout()
        self.documentLayout.addWidget(self.documentLabel, 0, 0)
        self.documentLayout.addWidget(self.documentLineEdit, 0, 1)
        self.documentLayout.addWidget(self.seriesLabel, 1, 0)
        self.documentLayout.addWidget(self.seriesLineEdit, 1, 1)
        self.documentLayout.addWidget(self.numberLabel, 1, 2)
        self.documentLayout.addWidget(self.numberLineEdit, 1, 3)
        self.documentLayout.addWidget(self.dateIssueLabel, 1, 4)
        self.documentLayout.addWidget(self.dateIssueLineEdit, 1, 5)
        self.documentLayout.addWidget(self.issuedLabel, 2, 0)
        self.documentLayout.addWidget(self.issuedLineEdit, 2, 1, 1, 5)
        self.documentGroupBox = QGroupBox("Документ")
        self.documentGroupBox.setLayout(self.documentLayout)

        self.dateArrivalLabel = QLabel("Дата прибытия:")
        self.dateArrivalDateEdit = QDateEdit()
        self.dateRetirementLabel = QLabel("Дата выбытия:")
        self.dateRetirementDateEdit = QDateEdit()
        self.nameHotelLabel = QLabel("Название гостиницы:")
        self.nameHotelLineEdit = UpperSimplifiedLineEdit()
        self.structureLabel = QLabel("Строение/Корпус/Сектор:")
        self.structureLineEdit = UpperSimplifiedLineEdit()
        self.roomLabel = QLabel("Комната:")
        self.roomLineEdit = UpperSimplifiedLineEdit()

        self.checkLayout = QGridLayout()
        self.checkLayout.addWidget(self.dateArrivalLabel, 0, 0)
        self.checkLayout.addWidget(self.dateArrivalDateEdit, 0, 1)
        self.checkLayout.addWidget(self.dateRetirementLabel, 0, 2)
        self.checkLayout.addWidget(self.dateRetirementDateEdit, 0, 3)
        self.checkLayout.addWidget(self.nameHotelLabel, 2, 0)
        self.checkLayout.addWidget(self.nameHotelLineEdit, 2, 1)
        self.checkLayout.addWidget(self.structureLabel, 2, 2)
        self.checkLayout.addWidget(self.structureLineEdit, 2, 3)
        self.checkLayout.addWidget(self.roomLabel, 2, 4)
        self.checkLayout.addWidget(self.roomLineEdit, 2, 5)
        self.checkGroupBox = QGroupBox("Регистрация")
        self.checkGroupBox.setLayout(self.checkLayout)

        self.saveButton = QPushButton("Сохранить")
        self.cancelButton = QPushButton("Отмена")

        self.bottomLayout = QHBoxLayout()
        self.bottomLayout.addStretch()
        self.bottomLayout.addWidget(self.saveButton)
        self.bottomLayout.addWidget(self.cancelButton)

        self.layout = QVBoxLayout()
        self.layout.addWidget(self.personGroupBox)
        self.layout.addWidget(self.birthGroupBox)
        self.layout.addWidget(self.residenceGroupBox)
        self.layout.addWidget(self.documentGroupBox)
        self.layout.addWidget(self.checkGroupBox)
        self.layout.addLayout(self.bottomLayout)

        self.setLayout(self.layout)

        self.saveButton.clicked.connect(self.save_data)
        self.cancelButton.clicked.connect(self.cancel)

        self.connect = self.connect_database()

    def connect_database(self):
        return sqlite3.connect('fms.db')

    def save_data(self):
        cursor = self.connect.cursor()
        cursor.execute(
            "INSERT INTO profile(type_page, surname, name, patronymic, birthday, country, region, city, district, "
            "locality, country_residence, region_residence, city_residence, district_residence, locality_residence, "
            "street_residence, house_residence, case_residence, apartment_residence, document, series, number, date_issue, "
            "issued, date_arrival_str, date_retirement_str, name_hotel, structure, room, date_arrival, date_retirement) "
            "VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
            (self.typePageLineEdit.text(), self.surnameLineEdit.text(),
             self.nameLineEdit.text(), self.patronymicLineEdit.text(),
             self.birthdayLineEdit.text(), self.countryLineEdit.text(),
             self.regionLineEdit.text(), self.cityLineEdit.text(),
             self.districtLineEdit.text(), self.localityLineEdit.text(),
             self.countryResidenceLineEdit.text(),
             self.regionResidenceLineEdit.text(),
             self.cityResidenceLineEdit.text(),
             self.districtResidenceLineEdit.text(),
             self.localityResidenceLineEdit.text(),
             self.streetResidenceLineEdit.text(),
             self.houseResidenceLineEdit.text(),
             self.caseResidenceLineEdit.text(),
             self.apartmentResidenceLineEdit.text(),
             self.documentLineEdit.text(), self.seriesLineEdit.text(),
             self.numberLineEdit.text(), self.dateIssueLineEdit.text(),
             self.issuedLineEdit.text(),
             self.dateArrivalDateEdit.date().toString("dd.MM.yyyy"),
             self.dateRetirementDateEdit.date().toString("dd.MM.yyyy"),
             self.nameHotelLineEdit.text(), self.structureLineEdit.text(),
             self.roomLineEdit.text(),
             self.dateArrivalDateEdit.date().toString("yyyy-MM-dd"),
             self.dateRetirementDateEdit.date().toString("yyyy-MM-dd")))
        self.connect.commit()
        cursor.close()
        self.connect.close()
        self.accept()

    def cancel(self):
        self.connect.close()
        self.reject()
Example #5
0
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())
Example #6
0
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()
Example #7
0
class QTransactionsAdd(QWidget):
    Session: sessionmaker = sessionmaker(bind=engine)
    entities: Session = Session()

    label_date: QLabel
    label_currency: QLabel
    label_currency: QLabel
    label_type: QLabel
    label_amount: QLabel
    label_describe: QLabel
    date: QDateEdit
    describe: QTextEdit

    closed: pyqtSignal = pyqtSignal()

    def __init__(self):
        super().__init__()

        self.setWindowTitle("Add a transaction")
        self.resize(950, 450)

        # QLabels
        self.label_date = QLabel("Date of transaction :")
        self.label_currency = QLabel("Currency :")
        self.label_type = QLabel("Type of transaction :")
        self.label_amount = QLabel("Amount :")
        self.label_describe = QLabel("Describe :")

        # Date
        self.date = QDateEdit(QDate.currentDate())
        self.date.setDisplayFormat("dd/MM/yyyy")

        # Currencies combobox
        self.currency = QComboBox()
        self.currency.addItem("BTC")
        self.currency.addItem("ETH")
        self.currency.addItem("LTC")
        self.currency.addItem("WXT")
        self.currency.addItem("XRP")
        self.currency.addItem("XLM")
        self.currency.addItem("WAVES")
        self.currency.addItem("WLO")
        self.currency.addItem("DAI")
        self.currency.addItem("NANO")
        self.currency.addItem("EUR")
        self.currency.addItem("USD")

        self.type_transaction = QComboBox()
        self.type_transaction.addItem("Credits")
        self.type_transaction.addItem("Debits")

        self.amount = QDoubleSpinBox()
        self.amount.setValue(0)
        self.amount.setDecimals(8)
        self.amount.setSingleStep(0.00000001)
        self.amount.setSuffix(" " + self.currency.currentText())

        spacer_describe = QSpacerItem(1, 15)
        self.describe = QTextEdit()

        validate_button = QPushButton("Validate")
        cancel_button = QPushButton("Cancel")

        # Vertical layout for date
        vlayout_date = QVBoxLayout()
        vlayout_date.addWidget(self.label_date)
        vlayout_date.addWidget(self.date)

        # Vertical layout for currencies
        vlayout_currency = QVBoxLayout()
        vlayout_currency.addWidget(self.label_currency)
        vlayout_currency.addWidget(self.currency)

        # Vertical layout for type of transaction
        vlayout_type = QVBoxLayout()
        vlayout_type.addWidget(self.label_type)
        vlayout_type.addWidget(self.type_transaction)

        # Vertical layout for amount
        vlayout_amount = QVBoxLayout()
        vlayout_amount.addWidget(self.label_amount)
        vlayout_amount.addWidget(self.amount)

        # Horizontal layout for transaction form
        hlayout_transaction = QHBoxLayout()
        hlayout_transaction.addLayout(vlayout_date)
        hlayout_transaction.addLayout(vlayout_currency)
        hlayout_transaction.addLayout(vlayout_type)
        hlayout_transaction.addLayout(vlayout_amount)

        # Vertical layout for describe
        vlayout_describe = QVBoxLayout()
        vlayout_describe.addSpacerItem(spacer_describe)
        vlayout_describe.addWidget(self.label_describe)
        vlayout_describe.addWidget(self.describe)

        spacer_desc_buttons = QSpacerItem(1, 180)

        # Vertical layout for buttons
        vlayout_buttons = QVBoxLayout()
        vlayout_buttons.addWidget(validate_button)
        vlayout_buttons.addWidget(cancel_button)
        vlayout_buttons.addSpacerItem(spacer_desc_buttons)

        spacer_desc_buttons = QSpacerItem(30, 1)

        # Horizontal layout for describe & buttons
        hlayout_desc_buttons = QHBoxLayout()
        hlayout_desc_buttons.addLayout(vlayout_describe)
        hlayout_desc_buttons.addSpacerItem(spacer_desc_buttons)
        hlayout_desc_buttons.addLayout(vlayout_buttons)
        hlayout_desc_buttons.addSpacerItem(spacer_desc_buttons)

        # Vertical layout for transaction layout & describe & buttons
        vertical_layout = QVBoxLayout(self)
        vertical_layout.addLayout(hlayout_transaction)
        vertical_layout.addLayout(hlayout_desc_buttons)

        # Add signal event in clicked cancel button
        cancel_button.clicked.connect(self.on_clicked_cancel_button)

        # Add signal event in clicked validate button
        validate_button.clicked.connect(self.on_clicked_validate_button)

        # Add signal event in change currency ComboBox
        self.currency.currentTextChanged.connect(
            self.on_currenttextchanged_currency_combobox)

    def on_clicked_cancel_button(self):
        self.close()

    def on_currenttextchanged_currency_combobox(self):
        self.amount.setSuffix(" " + self.currency.currentText())

    def on_clicked_validate_button(self):
        transaction = TransactionsEntity()
        transaction.date = self.date.date().toPyDate()
        transaction.currency = self.currency.currentText()
        transaction.type = self.type_transaction.currentIndex()
        transaction.amount = self.amount.value()
        transaction.describe = self.describe.toPlainText()

        if not self.currency.currentText() == 'BTC':
            transaction.btc = self.calc_price(self.currency.currentText(),
                                              'BTC')
        else:
            transaction.btc = 0

        transaction.eur = self.calc_price(self.currency.currentText(), 'EUR')
        transaction.usd = self.calc_price(self.currency.currentText(), 'USD')

        self.entities.add(transaction)
        self.entities.commit()
        self.close()

    def calc_price(self, crypto, currency_dest='EUR') -> float:
        price: float = 0
        value: float = 0
        url = 'https://api.coinbase.com/v2/prices/'

        if crypto == "ETH" or crypto == "LTC" or crypto == "XRP" or crypto == "XLM" or crypto == "DAI":
            if self.type_transaction.currentIndex() == 0:
                if currency_dest == 'BTC':
                    price = float(
                        json.loads(
                            requests.get(url + crypto + '-' +
                                         'USD/sell').content)['data']
                        ['amount'])
                    value = self.amount.value() * price

                    price = float(
                        json.loads(requests.get(url + 'BTC-USD/sell').content)
                        ['data']['amount'])
                    value = value / price
                else:
                    price = float(
                        json.loads(
                            requests.get(url + crypto + '-' + currency_dest +
                                         '/sell').content)['data']['amount'])
                    value = self.amount.value() * price
            else:
                if currency_dest == 'BTC':
                    price = float(
                        json.loads(
                            requests.get(url + crypto + '-' +
                                         'USD/buy').content)['data']['amount'])
                    value = self.amount.value() * price

                    price = float(
                        json.loads(requests.get(url + 'BTC-USD/buy').content)
                        ['data']['amount'])
                    value = value / price
                else:
                    price = float(
                        json.loads(
                            requests.get(url + crypto + '-' + currency_dest +
                                         '/buy').content)['data']['amount'])
                    value = self.amount.value() * price
        elif crypto == 'BTC':
            if self.type_transaction.currentIndex() == 0:
                price = float(
                    json.loads(
                        requests.get(url + crypto + '-' + currency_dest +
                                     '/sell').content)['data']['amount'])
                value = self.amount.value() * price
            else:
                price = float(
                    json.loads(
                        requests.get(url + crypto + '-' + currency_dest +
                                     '/buy').content)['data']['amount'])
                value = self.amount.value() * price

        return value

    def closeEvent(self, a0: QCloseEvent) -> None:
        self.closed.emit()
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())
Example #9
0
class MySpinBox(QGroupBox):
    def __init__(self):
        super().__init__()
        self.setTitle('QSpinBox')
        self.init_ui()

    def init_ui(self):
        layout_group1 = self.group_int_spinbox()
        layout_group2 = self.group_double_spinbox()
        layout_group3 = self.group_date_spinbox()
        layout_group4 = self.group_time_spinbox()
        layout_group5 = self.group_datetime_spinbox()

        layout = QVBoxLayout()
        layout.addLayout(layout_group1)
        layout.addLayout(layout_group2)
        layout.addLayout(layout_group3)
        layout.addLayout(layout_group4)
        layout.addLayout(layout_group5)

        self.setLayout(layout)

    def group_datetime_spinbox(self):
        group2 = QGroupBox('QDateTimeEdit')
        lbl = QLabel('QDateTimeEdit')
        date_time_edit = QDateTimeEdit(self)
        date_time_edit.setDateTime(QDateTime.currentDateTime())
        date_time_edit.setDateTimeRange(QDateTime(1900, 1, 1, 00, 00, 00),
                                        QDateTime(2100, 1, 1, 00, 00, 00))
        date_time_edit.setDisplayFormat('yyyy-MM-dd hh:mm:ss')
        date_time_edit.dateTimeChanged.connect(self.datetime_value_change)
        self.lbl5 = QLabel(
            date_time_edit.dateTime().toString('yyyy-MM-dd hh:mm:ss'))
        layout_group5 = QHBoxLayout()
        layout_group5.addWidget(lbl)
        layout_group5.addWidget(date_time_edit)
        layout_group5.addWidget(self.lbl5)
        return layout_group5

    def group_time_spinbox(self):
        group2 = QGroupBox('QTimeEdit')
        lbl = QLabel('QTimeEdit')
        timeedit = QTimeEdit(self)
        timeedit.setTime(QTime.currentTime())
        timeedit.setTimeRange(QTime(3, 00, 00), QTime(23, 30, 00))
        timeedit.setDisplayFormat('hh:mm:ss')
        timeedit.timeChanged.connect(self.time_value_change)
        # dateedit.setDateRange(QDate(1900, 1, 1), QDate(2100, 12, 31))
        # self.lbl4 = QLabel(QTime.toString(timeedit.dateTime, 'hh:mm:ss'))
        self.lbl4 = QLabel(timeedit.time().toString('hh:mm:ss'))
        layout_group4 = QHBoxLayout()
        layout_group4.addWidget(lbl)
        layout_group4.addWidget(timeedit)
        layout_group4.addWidget(self.lbl4)
        return layout_group4

    def group_date_spinbox(self):
        lbl = QLabel('QDateEdit')
        group2 = QGroupBox('QDateEdit')
        self.dateedit = QDateEdit(self)
        self.dateedit.setDate(QDate.currentDate())
        self.dateedit.setMinimumDate(QDate(1900, 1, 1))
        self.dateedit.setMaximumDate(QDate(2100, 12, 31))
        self.dateedit.setDisplayFormat('yyyy-MM-dd')
        self.dateedit.dateChanged.connect(self.date_value_change)
        # dateedit.setDateRange(QDate(1900, 1, 1), QDate(2100, 12, 31))
        self.lbl3 = QLabel(QDate.toString(self.dateedit.date(), 'yyyy-MM-dd'))
        layout_group3 = QHBoxLayout()
        layout_group3.addWidget(lbl)
        layout_group3.addWidget(self.dateedit)
        layout_group3.addWidget(self.lbl3)
        return layout_group3

    def group_double_spinbox(self):
        group2 = QGroupBox('Double QSpinbox')
        lbl = QLabel('QDoubleSpinBox')
        self.dspinbox = QDoubleSpinBox()
        self.dspinbox.setRange(0, 100)
        self.dspinbox.setSingleStep(0.5)
        self.dspinbox.setPrefix('$ ')
        self.dspinbox.setDecimals(1)
        self.lbl2 = QLabel('$ 0.0')
        self.dspinbox.valueChanged.connect(self.double_value_changed)
        layout_group2 = QHBoxLayout()
        layout_group2.addWidget(lbl)
        layout_group2.addWidget(self.dspinbox)
        layout_group2.addWidget(self.lbl2)
        return layout_group2

    def group_int_spinbox(self):
        group1 = QGroupBox('Integer QSpinBox')
        lbl = QLabel('QSpinBox')
        self.spinbox = QSpinBox()
        self.spinbox.setMinimum(-10)
        self.spinbox.setMaximum(30)
        # self.spinbox.setRange(-10, 30)
        self.spinbox.setSingleStep(2)
        self.lbl1 = QLabel(str(self.spinbox.value()))
        self.spinbox.valueChanged.connect(self.int_value_changed)
        layout_group1 = QHBoxLayout()
        layout_group1.addWidget(lbl)
        layout_group1.addWidget(self.spinbox)
        layout_group1.addWidget(self.lbl1)
        return layout_group1

    def int_value_changed(self):
        self.lbl1.setText(str(self.spinbox.value()))

    def double_value_changed(self):
        self.lbl2.setText(str(self.dspinbox.value()))

    def date_value_change(self, t):
        self.lbl3.setText(QDate.toString(t, 'yyyy-MM-dd'))

    def time_value_change(self, t):
        self.lbl4.setText(t.toString('hh:mm:ss'))

    def datetime_value_change(self, dt):
        self.lbl5.setText(dt.toString('yyyy-MM-dd hh:mm:ss'))
Example #10
0
class ReportGen(PageWindow):
    def __init__(self):
        super().__init__()
        self.initUI()
        self.createWidgets()

    def initUI(self):
        self.setWindowTitle("Report Generation")
        self.setFixedSize(400, 590)
        # Set the central widget and the general layout
        self.generalLayout = QVBoxLayout()
        self._centralWidget = QWidget(self)
        self.setCentralWidget(self._centralWidget)
        self._centralWidget.setLayout(self.generalLayout)

    def createWidgets(self):
        self.logSelector=QComboBox(self)
        self.logSelector.resize(110,40)
        self.logSelector.move(140,40)
        self.logSelector.addItem("Resident Log")
        self.logSelector.addItem("Visitor Log")
        self.datepicker=QDateEdit(self)
        self.datepicker.setCalendarPopup(True)
        self.datepicker.move(145,120)
        
        self.datepicker.setDate(dt.today())
        self.startTime=QTimeEdit(self)
        self.startTime.move(65,200)
        self.endTime=QTimeEdit(self)
        self.endTime.move(225,200)
        self.genButton=QPushButton("Generate",self)
        self.genButton.move(145,280)
        self.backButton=QPushButton("Back",self)
        self.backButton.move(145,340)
        self.backButton.clicked.connect(self.goBack)
        self.genButton.clicked.connect(self.repGen)
    def goBack(self):
        self.goto("welcome")

    def repGen(self):
        #print("Hey")
        log=self.logSelector.currentText()
        date=str(self.datepicker.date().toPyDate())
        #print(date)
        start=str(self.startTime.time().toPyTime())
        end=str(self.endTime.time().toPyTime())
        vbox=QVBoxLayout()
        table=QTableWidget()
        #print("Heyo")
        #print(log+" "+date+" "+start+" "+end)
        repList=getRepData(log,date,start,end)
        rows=len(repList)
        print(repList)
        table.setRowCount(rows+1)
        if(log=="Resident Log"):
            #print("hey")
            table.setColumnCount(4)
            table.setItem(0,0,QTableWidgetItem("Vehicle No."))
            table.setItem(0,1,QTableWidgetItem("Flat No."))
            table.setItem(0,2,QTableWidgetItem("Entry Time"))
            table.setItem(0,3,QTableWidgetItem("Exit Time"))
            table.resize(650,400)
            
        else:
            table.setColumnCount(5)
            table.setItem(0,0,QTableWidgetItem("Vehicle No."))
            table.setItem(0,1,QTableWidgetItem("Visitor Name"))
            table.setItem(0,2,QTableWidgetItem("Flat No."))
            table.setItem(0,3,QTableWidgetItem("Entry Time"))
            table.setItem(0,4,QTableWidgetItem("Exit Time"))
            table.resize(800,400)

        try:
            i=1
            j=0
            for row in repList:
                for j in range(len(row)):
                    #print(j+" "+row[j])
                    table.setItem(i,j,QTableWidgetItem(row[j]))
                i+=1
        except Exception as e:
            print(e)
        
        table.horizontalHeader().setDefaultSectionSize(155)
        table.show()
        vbox.addWidget(table)
        self.setLayout(vbox)
Example #11
0
class HistWindowSelect(QGroupBox):
    """An extension of the QGroupBox widget. It allows the user to select a
    start date and end date for the historical window in the Monte Carlo VaR
    calculation application.
    
    The end date of the historical window is set to 22 days from the start date
    as a minimum. This restriction is implemented through the QDateEdit's set
    minimum date function.
    """
    end_signal = QtCore.pyqtSignal(dt.datetime)

    def __init__(self, parent=None):
        super(HistWindowSelect, self).__init__(parent)

        self.setTitle('Historical Window Select')
        grid = QGridLayout()

        lbl_start = QLabel('Start Date: ')
        lbl_end = QLabel('End Date: ')

        self.deStart = QDateEdit()
        self.deStart.setCalendarPopup(True)
        self.deStart.setMinimumDateTime(dt.datetime(2015, 1, 1))
        self.deStart.setMaximumDateTime(
            self.getWeekdaysBack(dt.datetime.now(), 22))
        self.deStart.dateChanged.connect(self.onStartDateChange)
        self.deEnd = QDateEdit()
        self.deEnd.setCalendarPopup(True)
        self.deEnd.setMaximumDateTime(dt.datetime.now())
        self.deEnd.dateChanged.connect(self.onEndDateChange)
        self.setEndDateMinimum()
        lbl_disc = QLabel(
            'Note: A minimum historical window length <br>of 22 business days has been imposed.'
        )

        grid.addWidget(lbl_start, 0, 0)
        grid.addWidget(lbl_end, 1, 0)
        grid.addWidget(self.deStart, 0, 1)
        grid.addWidget(self.deEnd, 1, 1)
        grid.addWidget(lbl_disc, 2, 1)

        self.setLayout(grid)

    def onStartDateChange(self):
        """Checks if new start date is a weekend. If so, it adds the 
        appropriate number of days to bring the start date to the following 
        Monday. After, it updates the minimum value of the end date, which must
        be 22 business days after the start date.
        """
        deStart = dt.datetime.combine(self.deStart.date().toPyDate(),
                                      dt.datetime.min.time())
        if deStart.weekday() == 5:
            deStart = deStart + timedelta(days=2)
        elif deStart.weekday() == 6:
            deStart = deStart + timedelta(days=1)

        self.deStart.setDate(deStart)
        self.setEndDateMinimum()

    def setEndDateMinimum(self):
        """Updates the minimum value of the end date, which must
        be 22 business days after the start date.
        """
        deStart = dt.datetime.combine(self.deStart.date().toPyDate(),
                                      dt.datetime.min.time())
        end_min = self.getWeekdaysOut(deStart, 22)
        self.deEnd.setMinimumDateTime(end_min)
        if self.deEnd.date() < end_min:
            self.deEnd.setDate(end_min)
            self.test_signal.emit(end_min)

    def onEndDateChange(self):
        """Checks if new end date is a weekend. If so, it adds the 
        appropriate number of days to bring the end date to the following 
        Monday. After, it emits a signal containing the new end date to be
        picked up by a slot in the PredWindowSelect widget.
        """
        deEnd = dt.datetime.combine(self.deEnd.date().toPyDate(),
                                    dt.datetime.min.time())
        if deEnd.weekday() == 5:
            deEnd = deEnd + timedelta(days=2)
        elif deEnd.weekday() == 6:
            deEnd = deEnd + timedelta(days=1)

        self.deEnd.setDate(deEnd)
        self.end_signal.emit(deEnd)

    def getWeekdaysOut(self, start_date, days_out):
        """Finds the date that is x weekdays later than the start date (where
        x = days_out).
        
        Args:
            
            start_date (datetime.datetime) - Start date from which to count 
            weekdays out.
            
            days_out (int) - Number of days out.
            
        Returns:
            
            curr_date (datetime.datetime) - the date that is days_out weekdays
            later than start_date.
        
        Raises Error:
            
            None
        
        """
        if start_date.weekday() == 5:
            start_date += timedelta(days=2)
        if start_date.weekday() == 6:
            start_date += timedelta(days=1)

        for i in range(days_out):
            if i == 0:
                curr_date = start_date
            next_date = curr_date + timedelta(days=1)
            if next_date.weekday() == 5:
                next_date = curr_date + timedelta(days=3)
            curr_date = next_date

        return (curr_date)

    def getWeekdaysBack(self, start_date, days_back):
        """Finds the date that is x weekdays earlier than the start date (where
        x = days_back).
        
        Args:
            
            start_date (datetime.datetime) - Start date from which to count 
            weekdays out.
            
            days_back (int) - Number of days back.
            
        Returns:
            
            curr_date (datetime.datetime) - the date that is days_back weekdays
            earlier than start_date.
        
        Raises Error:
            
            None
        
        """
        if start_date.weekday() == 5:
            start_date -= timedelta(days=1)
        if start_date.weekday() == 6:
            start_date -= timedelta(days=2)

        for i in range(days_back):
            if i == 0:
                curr_date = start_date
            next_date = curr_date - timedelta(days=1)
            if next_date.weekday() == 6:
                next_date = curr_date - timedelta(days=3)
            curr_date = next_date

        return (curr_date)

    def getDateWindow(self):
        """Getter function for the date window selected by the user.
        """
        start_date = dt.datetime.combine(self.deStart.date().toPyDate(),
                                         dt.datetime.min.time())
        end_date = dt.datetime.combine(self.deEnd.date().toPyDate(),
                                       dt.datetime.min.time())
        return start_date, end_date
Example #12
0
class PredWindowSelect(QGroupBox):
    """An extension of the QGroupBox widget. It allows the user to select a
    start date and end date for the prediction window in the Monte Carlo VaR
    calculation application.
    
    The start date of the prediction window is set to the end date of the 
    historical window. The end date of the prediction window is five days later
    than the start date of the prediction window as a minimum. These 
    restrictions are implemented through the QDateEdit widget's maximum and 
    minimum date functions.
    """
    def __init__(self, parent=None):
        super(PredWindowSelect, self).__init__(parent)

        self.setTitle('Prediction Window Select')
        grid = QGridLayout()

        lbl_start = QLabel('Start Date: ')
        lbl_end = QLabel('End Date: ')

        self.deStart = QDateEdit()
        self.deStart.setEnabled(False)
        self.deStart.setCalendarPopup(True)
        self.deStart.dateChanged.connect(self.setEndDateMinimum)
        self.deEnd = QDateEdit()
        self.deEnd.setCalendarPopup(True)
        self.deEnd.dateChanged.connect(self.onEndDateChange)
        self.setEndDateMinimum()
        lbl_disc = QLabel(
            'Note: A minimum prediction window length <br>of 5 business days has been imposed.'
        )

        grid.addWidget(lbl_start, 0, 0)
        grid.addWidget(lbl_end, 1, 0)
        grid.addWidget(self.deStart, 0, 1)
        grid.addWidget(self.deEnd, 1, 1)
        grid.addWidget(lbl_disc, 2, 1)

        self.setLayout(grid)

    @QtCore.pyqtSlot(dt.datetime)
    def setStart(self, date):
        """Slotted function to set the start date based on end date of the 
        historical window.
        """
        self.deStart.setDate(date)

    def onEndDateChange(self):
        """Checks if new end date is a weekend. If so, it adds the 
        appropriate number of days to bring the end date to the following 
        Monday.
        """
        deEnd = dt.datetime.combine(self.deEnd.date().toPyDate(),
                                    dt.datetime.min.time())
        if deEnd.weekday() == 5:
            deEnd = deEnd + timedelta(days=2)
        elif deEnd.weekday() == 6:
            deEnd = deEnd + timedelta(days=1)

        self.deEnd.setDate(deEnd)

    def setEndDateMinimum(self):
        """Updates the minimum value of the end date, which must
        be 5 business days after the start date.
        """
        deStart = dt.datetime.combine(self.deStart.date().toPyDate(),
                                      dt.datetime.min.time())
        end_min = self.getWeekdaysOut(deStart, 5)
        self.deEnd.setMinimumDateTime(end_min)
        if self.deEnd.date() < end_min:
            self.deEnd.setDate(end_min)

    def getWeekdaysOut(self, start_date, days_out):
        """Finds the date that is x weekdays later than the start date (where
        x = days_out).
        
        Args:
            
            start_date (datetime.datetime) - Start date from which to count 
            weekdays out.
            
            days_out (int) - Number of days out.
            
        Returns:
            
            curr_date (datetime.datetime) - the date that is days_out weekdays
            later than start_date.
        
        Raises Error:
            
            None
        
        """
        if start_date.weekday() == 5:
            start_date += timedelta(days=2)
        if start_date.weekday() == 6:
            start_date += timedelta(days=1)

        for i in range(days_out):
            if i == 0:
                curr_date = start_date
            next_date = curr_date + timedelta(days=1)
            if next_date.weekday() == 5:
                next_date = curr_date + timedelta(days=3)
            curr_date = next_date

        return (curr_date)

    def getDateWindow(self):
        """Getter function for the date window selected by the user.
        """
        start_date = dt.datetime.combine(self.deStart.date().toPyDate(),
                                         dt.datetime.min.time())
        end_date = dt.datetime.combine(self.deEnd.date().toPyDate(),
                                       dt.datetime.min.time())
        return start_date, end_date

    def getNumDays(self):
        """Getter function for the number of weekdays between the start and
        end dates."""
        start_date = dt.datetime.combine(self.deStart.date().toPyDate(),
                                         dt.datetime.min.time())
        end_date = dt.datetime.combine(self.deEnd.date().toPyDate(),
                                       dt.datetime.min.time())

        if start_date.weekday() == 5:
            start_date += timedelta(days=2)
        if start_date.weekday() == 6:
            start_date += timedelta(days=1)

        days = 0
        curr_date = start_date
        while curr_date != end_date:
            curr_date += timedelta(days=1)
            if curr_date.weekday() == 5:
                continue
            elif curr_date.weekday() == 6:
                continue
            else:
                days += 1

        return days
Example #13
0
class HomeScreen(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("Home Screen")
        self.resize(550, 461)
        self.setStyleSheet(Hariku_Style.get_window_stylesheet())
        self.centralWidget = QWidget()
        self.setCentralWidget(self.centralWidget)

        self.setupUI()

    def setupUI(self):
        self.setWindowIcon(Hariku_Style.getIcon())

        self.centralwidget = QWidget(self)
        self.setFocus()

        self.gridLayout = QGridLayout(self.centralwidget)
        self.gridLayout.setObjectName("gridLayout")

        self.topcenter_layout = QHBoxLayout()

        spacerItem = QSpacerItem(25, 20, QSizePolicy.MinimumExpanding,
                                 QSizePolicy.Minimum)
        self.topcenter_layout.addItem(spacerItem)

        self.monthFilter = QDateEdit(self.centralwidget)
        self.monthFilter.setCurrentSection(QDateTimeEdit.MonthSection)
        self.monthFilter.setButtonSymbols(QSpinBox.NoButtons)
        self.monthFilter.setDate(datetime.now())
        self.monthFilter.setDisplayFormat("MMMM/yyyy")
        self.monthFilter.setFont(Hariku_Style.get_font(10))
        self.monthFilter.setStyleSheet(Hariku_Style.get_dateedit_stylesheet())
        self.monthFilter.dateChanged.connect(self.filterDiaryByMonth)
        self.topcenter_layout.addWidget(self.monthFilter)

        self.showAllBtn = QPushButton("Remove Filter", self.centralwidget)
        self.showAllBtn.setFont(Hariku_Style.get_font(8))
        self.showAllBtn.clicked.connect(self.getDiaries)
        self.showAllBtn.setStyleSheet(
            Hariku_Style.get_moodBtn_stylesheet("rgb(38, 160, 173)",
                                                "rgb(8, 102, 112)"))
        self.topcenter_layout.addWidget(self.showAllBtn)

        spacerItem1 = QSpacerItem(25, 20, QSizePolicy.MinimumExpanding,
                                  QSizePolicy.Minimum)
        self.topcenter_layout.addItem(spacerItem1)

        self.gridLayout.addLayout(self.topcenter_layout, 1, 0, 1, 1)

        self.bottomLayout = QHBoxLayout()

        spacerItem2 = QSpacerItem(40, 20, QSizePolicy.Expanding,
                                  QSizePolicy.Minimum)
        self.bottomLayout.addItem(spacerItem2)

        self.createBtn = QPushButton("+ Add New Diary", self.centralwidget)
        self.createBtn.setFont(Hariku_Style.get_font(10))
        self.createBtn.clicked.connect(self.addNewDiary)
        self.createBtn.setStyleSheet(
            Hariku_Style.get_moodBtn_stylesheet("rgb(40, 186, 130)",
                                                "rgb(207, 207, 188)"))
        self.bottomLayout.addWidget(self.createBtn)

        self.gridLayout.addLayout(self.bottomLayout, 4, 0, 1, 1)

        self.contentScrollArea = QScrollArea(self.centralwidget)
        self.contentScrollArea.setEnabled(True)
        sizePolicy = QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(
            self.contentScrollArea.sizePolicy().hasHeightForWidth())
        self.contentScrollArea.setSizePolicy(sizePolicy)
        self.contentScrollArea.setStyleSheet(
            Hariku_Style.get_scrollarea_stylesheet())
        self.contentScrollArea.setWidgetResizable(True)
        self.contentScrollArea.setAlignment(QtCore.Qt.AlignLeading
                                            | QtCore.Qt.AlignLeft
                                            | QtCore.Qt.AlignTop)

        self.scrollAreaWidgetContents = QWidget()
        self.scrollAreaWidgetContents.setGeometry(QtCore.QRect(0, 0, 487, 321))
        self.scrollAreaLayout = QVBoxLayout(self.scrollAreaWidgetContents)

        self.getDiaries()

        self.contentScrollArea.setWidget(self.scrollAreaWidgetContents)

        self.gridLayout.addWidget(self.contentScrollArea, 2, 0, 1, 1)

        self.judul = QLabel("\nWelcome Home:)\n", self)
        self.judul.setFont(Hariku_Style.get_font(18))
        self.judul.setAlignment(QtCore.Qt.AlignCenter)
        self.gridLayout.addWidget(self.judul, 0, 0, 1, 1)

        self.setCentralWidget(self.centralwidget)

    def addNewDiary(self):
        dialog = DiaryScreen(self)
        dialog.show()
        self.hide()

    def clearScrollAreaLayout(self):
        # delete the diaries currently showind
        for i in reversed(range(self.scrollAreaLayout.count())):
            try:
                self.scrollAreaLayout.itemAt(i).widget().setParent(None)
            except AttributeError:
                self.scrollAreaLayout.removeItem(
                    self.scrollAreaLayout.itemAt(i))

    def filterDiaryByMonth(self):
        self.clearScrollAreaLayout()

        year = self.monthFilter.date().year()
        month = self.monthFilter.date().month()

        diaries = getDiaryByMonth(year, month)

        for i, diary in enumerate(diaries):
            self.diaryItem = QWidget(self.scrollAreaWidgetContents)
            sizePolicy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed)
            sizePolicy.setHeightForWidth(
                self.diaryItem.sizePolicy().hasHeightForWidth())
            self.diaryItem.setSizePolicy(sizePolicy)
            self.diaryItem.setMinimumSize(QtCore.QSize(0, 50))
            self.diaryItem.setStyleSheet(
                "background-color: rgba(227, 217, 163, 100%);\nborder-radius : 10px;"
            )
            self.diaryItem.setObjectName("diaryItem")
            self.itemLayout = QGridLayout(self.diaryItem)

            self.contentDateLayout = QVBoxLayout()
            self.contentDateLayout.setObjectName("contentDateLayout")

            self.content = QLabel(self.truncateString(diary.content),
                                  self.diaryItem)
            self.content.setFont(Hariku_Style.get_font(10))
            self.contentDateLayout.addWidget(self.content)

            self.date = QLabel(
                diary.date.strftime("%d %B %Y") +
                diary.time.strftime("  %I:%M %p"), self.diaryItem)
            self.date.setFont(Hariku_Style.get_font(8))
            self.contentDateLayout.addWidget(self.date)

            self.itemLayout.addLayout(self.contentDateLayout, 0, 0, 1, 1)

            self.buttons.append(i)
            self.buttons[i] = [
                QPushButton("⋗", self.diaryItem),
                QPushButton("×", self.diaryItem)
            ]

            self.buttons[i][0].clicked.connect(
                lambda checked, i=diary.diary_id: self.viewDiaryById(i))
            sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
            sizePolicy.setHorizontalStretch(0)
            sizePolicy.setVerticalStretch(0)
            sizePolicy.setHeightForWidth(
                self.buttons[i][0].sizePolicy().hasHeightForWidth())
            self.buttons[i][0].setSizePolicy(sizePolicy)
            self.buttons[i][0].setFont(Hariku_Style.get_font(9))
            self.buttons[i][0].setStyleSheet(
                Hariku_Style.get_moodBtn_stylesheet("rgb(145, 133, 63)",
                                                    "rgb(235, 224, 157)"))
            self.itemLayout.addWidget(self.buttons[i][0], 0, 1, 1, 1)

            # self.deleteBtn = QPushButton("×", self.diaryItem)
            self.buttons[i][1].clicked.connect(
                lambda checked, i=diary.diary_id: self.deleteDiaryById(i))
            sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
            sizePolicy.setHorizontalStretch(0)
            sizePolicy.setVerticalStretch(0)
            sizePolicy.setHeightForWidth(
                self.buttons[i][1].sizePolicy().hasHeightForWidth())
            self.buttons[i][1].setSizePolicy(sizePolicy)
            self.buttons[i][1].setFont(Hariku_Style.get_font(9))
            self.buttons[i][1].setStyleSheet(
                Hariku_Style.get_moodBtn_stylesheet("rgb(145, 63, 63)",
                                                    "rgb(235, 157, 157)"))
            self.itemLayout.addWidget(self.buttons[i][1], 0, 2, 1, 1)

            self.scrollAreaLayout.addWidget(self.diaryItem,
                                            alignment=QtCore.Qt.AlignTop)

        spacerItem2 = QSpacerItem(20, 40, QSizePolicy.Minimum,
                                  QSizePolicy.MinimumExpanding)
        self.scrollAreaLayout.addItem(spacerItem2)

    def getDiaries(self):
        diaries = getAllDiaries()

        self.monthFilter.setDate(datetime.now())
        self.clearScrollAreaLayout()

        self.buttons = []

        for i, diary in enumerate(diaries):
            self.diaryItem = QWidget(self.scrollAreaWidgetContents)
            sizePolicy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed)
            sizePolicy.setHeightForWidth(
                self.diaryItem.sizePolicy().hasHeightForWidth())
            self.diaryItem.setSizePolicy(sizePolicy)
            self.diaryItem.setMinimumSize(QtCore.QSize(0, 50))
            self.diaryItem.setStyleSheet(
                "background-color: rgba(227, 217, 163, 100%);\nborder-radius : 10px;"
            )
            self.diaryItem.setObjectName("diaryItem")
            self.itemLayout = QGridLayout(self.diaryItem)

            self.contentDateLayout = QVBoxLayout()
            self.contentDateLayout.setObjectName("contentDateLayout")

            self.content = QLabel(self.truncateString(diary.content),
                                  self.diaryItem)
            self.content.setFont(Hariku_Style.get_font(10))
            self.contentDateLayout.addWidget(self.content)

            self.date = QLabel(
                diary.date.strftime("%d %B %Y") +
                diary.time.strftime("  %I:%M %p"), self.diaryItem)
            self.date.setFont(Hariku_Style.get_font(8))
            self.contentDateLayout.addWidget(self.date)

            self.itemLayout.addLayout(self.contentDateLayout, 0, 0, 1, 1)

            self.buttons.append(i)
            self.buttons[i] = [
                QPushButton("⋗", self.diaryItem),
                QPushButton("×", self.diaryItem)
            ]

            self.buttons[i][0].clicked.connect(
                lambda checked, i=diary.diary_id: self.viewDiaryById(i))
            sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
            sizePolicy.setHorizontalStretch(0)
            sizePolicy.setVerticalStretch(0)
            sizePolicy.setHeightForWidth(
                self.buttons[i][0].sizePolicy().hasHeightForWidth())
            self.buttons[i][0].setSizePolicy(sizePolicy)
            self.buttons[i][0].setFont(Hariku_Style.get_font(9))
            self.buttons[i][0].setStyleSheet(
                Hariku_Style.get_moodBtn_stylesheet("rgb(145, 133, 63)",
                                                    "rgb(235, 224, 157)"))
            self.itemLayout.addWidget(self.buttons[i][0], 0, 1, 1, 1)

            # self.deleteBtn = QPushButton("×", self.diaryItem)
            self.buttons[i][1].clicked.connect(
                lambda checked, i=diary.diary_id: self.deleteDiaryById(i))
            sizePolicy = QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
            sizePolicy.setHorizontalStretch(0)
            sizePolicy.setVerticalStretch(0)
            sizePolicy.setHeightForWidth(
                self.buttons[i][1].sizePolicy().hasHeightForWidth())
            self.buttons[i][1].setSizePolicy(sizePolicy)
            self.buttons[i][1].setFont(Hariku_Style.get_font(9))
            self.buttons[i][1].setStyleSheet(
                Hariku_Style.get_moodBtn_stylesheet("rgb(145, 63, 63)",
                                                    "rgb(235, 157, 157)"))
            self.itemLayout.addWidget(self.buttons[i][1], 0, 2, 1, 1)

            self.scrollAreaLayout.addWidget(self.diaryItem,
                                            alignment=QtCore.Qt.AlignTop)

        spacerItem2 = QSpacerItem(20, 40, QSizePolicy.Minimum,
                                  QSizePolicy.MinimumExpanding)
        self.scrollAreaLayout.addItem(spacerItem2)

    def truncateString(self, string):
        try:
            string = string.replace('\n', ' ')
            return string[:45] + '...'
        except IndexError:
            return string

    def viewDiaryById(self, id):
        dialog = DiaryScreen(self, edit=False, id=id)
        dialog.show()
        self.hide()

    def deleteDiaryById(self, id):
        deleteDiaryById(id)
        self.clearScrollAreaLayout()
        self.getDiaries()
Example #14
0
class NewEntryDialog(QDialog):
    def __init__(self, parent):
        QDialog.__init__(self, parent)
        self.submitted = False
        self.cover_bytes = b''
        self.setWindowTitle('Add new entry')
        self.container = QWidget()
        self.horizontal_layout = QHBoxLayout()
        self.container_left_layout = QVBoxLayout()
        self.container_right_layout = QVBoxLayout()
        self.horizontal_layout.addLayout(self.container_left_layout)
        self.horizontal_layout.addLayout(self.container_right_layout)

        label_type = QLabel(_('Entry type:'))
        self.combo_type = QComboBox()
        label_type.setBuddy(self.combo_type)
        for entry in EntryType:
            self.combo_type.addItem(entry.value, entry)

        label_status = QLabel(_('Entry status:'))
        self.combo_status = QComboBox()
        label_status.setBuddy(self.combo_status)
        for entry in EntryStatus:
            self.combo_status.addItem(entry.value, entry)

        label_progress = QLabel(_('Progress status:'))
        self.combo_progress = QComboBox()
        label_progress.setBuddy(self.combo_progress)
        for entry in ProgressStatus:
            self.combo_progress.addItem(entry.value, entry)

        label_org_name = QLabel(_('Entry original name:'))
        self.line_org_name = QLineEdit()
        label_org_name.setBuddy(self.line_org_name)

        label_eng_name = QLabel(_('Entry english name:'))
        self.line_eng_name = QLineEdit()
        label_eng_name.setBuddy(self.line_eng_name)

        label_synonyms = QLabel(_('Synonym names:'))
        self.line_synonyms = QLineEdit()
        label_synonyms.setBuddy(self.line_synonyms)

        label_description = QLabel(_('Description:'))
        self.description_textbox = QPlainTextEdit()
        label_description.setBuddy(self.description_textbox)

        self.nsfw = QCheckBox(_('NSFW'))

        only_int = QIntValidator(bottom=0)
        label_current_progress = QLabel(_('Current progress:'))
        self.current_progress_textbox = QLineEdit()
        label_current_progress.setBuddy(self.current_progress_textbox)
        self.current_progress_textbox.setValidator(only_int)
        label_current_progress.setBuddy(self.current_progress_textbox)

        label_max_progress = QLabel(_('Max progress:'))
        self.max_progress_textbox = QLineEdit()
        label_max_progress.setBuddy(self.max_progress_textbox)
        self.max_progress_textbox.setValidator(only_int)
        label_max_progress.setBuddy(self.max_progress_textbox)

        label_release_date = QLabel(_('Release date:'))
        self.release_date1 = QDateEdit()
        self.release_date2 = QDateEdit()
        label_release_date.setBuddy(self.release_date1)
        label_release_date.setBuddy(self.release_date2)

        self.cover = QLabel("Cover:")
        self.load_cover_button = QPushButton(_('Load cover'))
        self.load_cover_button.clicked.connect(self.load_image)

        self.accept_button = QPushButton(_('Add'))

        self.container_left_layout.addWidget(self.cover)
        self.container_left_layout.addWidget(self.load_cover_button)

        self.container_right_layout.addWidget(label_type)
        self.container_right_layout.addWidget(self.combo_type)
        self.container_right_layout.addWidget(label_status)
        self.container_right_layout.addWidget(self.combo_status)
        self.container_right_layout.addWidget(label_progress)
        self.container_right_layout.addWidget(self.combo_progress)

        self.container_right_layout.addWidget(label_org_name)
        self.container_right_layout.addWidget(self.line_org_name)
        self.container_right_layout.addWidget(label_eng_name)
        self.container_right_layout.addWidget(self.line_eng_name)
        self.container_right_layout.addWidget(label_synonyms)
        self.container_right_layout.addWidget(self.line_synonyms)

        self.container_right_layout.addWidget(label_description)
        self.container_right_layout.addWidget(self.description_textbox)

        self.container_right_layout.addWidget(self.nsfw)

        self.container_right_layout.addWidget(label_current_progress)
        self.container_right_layout.addWidget(self.current_progress_textbox)
        self.container_right_layout.addWidget(label_max_progress)
        self.container_right_layout.addWidget(self.max_progress_textbox)

        self.container_right_layout.addWidget(label_release_date)
        date_layout = QHBoxLayout()
        date_layout.addWidget(self.release_date1)
        date_layout.addWidget(self.release_date2)
        self.container_right_layout.addLayout(date_layout)

        self.container_right_layout.addWidget(self.accept_button)

        self.root_layout = QVBoxLayout(self)
        self.main_layout = QVBoxLayout(self)
        self.root_layout.addLayout(self.main_layout)
        self.container.setLayout(self.horizontal_layout)
        self.main_layout.addWidget(self.container)
        self.setLayout(self.root_layout)

        self.accept_button.clicked.connect(self.submit)

    def submit(self):
        self.submitted = True
        self.close()

    def load_image(self):
        fname = QFileDialog.getOpenFileName(self, 'Select entry cover')
        image_path = fname[0]
        self.cover_bytes = open(image_path, 'rb').read()
        qp = QPixmap()
        qp.loadFromData(self.cover_bytes)
        self.cover.setPixmap(qp)
        self.cover.setMaximumHeight(500)
        self.cover.setMaximumWidth(500)

    def get_values(self):
        entry_status = self.combo_status.currentData()
        entry_type = self.combo_type.currentData()
        entry_progress = self.combo_progress.currentData()
        date1 = self.release_date1.date().toPyDate()
        date2 = self.release_date2.date().toPyDate()
        try:
            current_progress = int(self.current_progress_textbox.text())
        except:
            current_progress = 0
        try:
            max_progress = int(self.max_progress_textbox.text())
        except:
            max_progress = -1

        entry = GenericEntry(self.cover_bytes, self.line_eng_name.text(),
                             self.line_org_name.text(),
                             self.line_synonyms.text(), date1, date2,
                             entry_status,
                             self.description_textbox.toPlainText(),
                             self.nsfw.isChecked(), entry_type,
                             current_progress, max_progress, entry_progress)
        return entry
Example #15
0
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()
Example #16
0
class Filters(QWidget):
    def __init__(self, db, display={}):
        QWidget.__init__(self, None)
        self.db = db
        self.cursor = db.cursor
        self.sql = db.sql
        self.conf = db.config
        self.display = display

        self.gameName = {
            "27_1draw": _("Single Draw 2-7 Lowball"),
            "27_3draw": _("Triple Draw 2-7 Lowball"),
            "a5_3draw": _("Triple Draw A-5 Lowball"),
            "5_studhi": _("5 Card Stud"),
            "badugi": _("Badugi"),
            "fivedraw": _("5 Card Draw"),
            "holdem": _("Hold'em"),
            "omahahi": _("Omaha"),
            "omahahilo": _("Omaha Hi/Lo"),
            "razz": _("Razz"),
            "studhi": _("7 Card Stud"),
            "studhilo": _("7 Card Stud Hi/Lo"),
            "5_omahahi": _("5 Card Omaha"),
            "5_omaha8": _("5 Card Omaha Hi/Lo"),
            "cour_hi": _("Courchevel"),
            "cour_hilo": _("Courchevel Hi/Lo"),
            "2_holdem": _("Double hold'em"),
            "irish": _("Irish"),
            "6_omahahi": _("6 Card Omaha")
        }

        self.currencyName = {
            "USD": _("US Dollar"),
            "EUR": _("Euro"),
            "T$": _("Tournament Dollar"),
            "play": _("Play Money")
        }

        # text used on screen stored here so that it can be configured
        self.filterText = {
            'limitsall': _('All'),
            'limitsnone': _('None'),
            'limitsshow': _('Show Limits'),
            'gamesall': _('All'),
            'gamesnone': _('None'),
            'positionsall': _('All'),
            'positionsnone': _('None'),
            'currenciesall': _('All'),
            'currenciesnone': _('None'),
            'seatsbetween': _('Between:'),
            'seatsand': _('And:'),
            'seatsshow': _('Show Number of Players'),
            'playerstitle': _('Hero:'),
            'sitestitle': (_('Sites') + ':'),
            'gamestitle': (_('Games') + ':'),
            'limitstitle': _('Limits:'),
            'positionstitle': _('Positions:'),
            'seatstitle': _('Number of Players:'),
            'groupstitle': _('Grouping:'),
            'posnshow': _('Show Position Stats'),
            'datestitle': _('Date:'),
            'currenciestitle': (_('Currencies') + ':'),
            'groupsall': _('All Players'),
            'cardstitle': (_('Hole Cards') + ':'),
            'limitsFL': 'FL',
            'limitsNL': 'NL',
            'limitsPL': 'PL',
            'limitsCN': 'CAP',
            'ring': _('Ring'),
            'tour': _('Tourney'),
            'limitsHP': 'HP'
        }

        gen = self.conf.get_general_params()
        self.day_start = 0

        if 'day_start' in gen:
            self.day_start = float(gen['day_start'])

        self.setLayout(QVBoxLayout())

        self.callback = {}

        self.setStyleSheet(
            "QPushButton {padding-left:5;padding-right:5;padding-top:2;padding-bottom:2;}"
        )
        self.make_filter()

    def make_filter(self):
        self.siteid = {}
        self.cards = {}

        for site in self.conf.get_supported_sites():
            # Get db site id for filtering later
            self.cursor.execute(self.sql.query['getSiteId'], (site, ))
            result = self.db.cursor.fetchall()
            if len(result) == 1:
                self.siteid[site] = result[0][0]
            else:
                log.debug(_("Either 0 or more than one site matched for %s"),
                          site)

        # For use in date ranges.
        self.start_date = QDateEdit(QDate(1970, 1, 1))
        self.end_date = QDateEdit(QDate(2100, 1, 1))

        # For use in groups etc
        self.cbGroups = {}
        self.phands = None

        playerFrame = QGroupBox(self.filterText['playerstitle'])
        self.leHeroes = {}

        self.fillPlayerFrame(playerFrame, self.display)
        self.layout().addWidget(playerFrame)

        # Sites
        sitesFrame = QGroupBox(self.filterText['sitestitle'])
        self.cbSites = {}

        self.fillSitesFrame(sitesFrame)
        self.layout().addWidget(sitesFrame)

        # Game types
        gamesFrame = QGroupBox(self.filterText['gamestitle'])
        self.layout().addWidget(gamesFrame)
        self.cbGames = {}

        self.fillGamesFrame(gamesFrame)

        # Currencies
        currenciesFrame = QGroupBox(self.filterText['currenciestitle'])
        self.layout().addWidget(currenciesFrame)
        self.cbCurrencies = {}

        self.fillCurrenciesFrame(currenciesFrame)

        # Limits
        limitsFrame = QGroupBox(self.filterText['limitstitle'])
        self.layout().addWidget(limitsFrame)
        self.cbLimits = {}
        self.rb = {}  # radio buttons for ring/tour
        self.type = None  # ring/tour

        self.fillLimitsFrame(limitsFrame, self.display)

        # Positions
        positionsFrame = QGroupBox(self.filterText['positionstitle'])
        self.layout().addWidget(positionsFrame)

        self.cbPositions = {}

        self.fillPositionsFrame(positionsFrame, self.display)

        # GraphOps
        graphopsFrame = QGroupBox(_("Graphing Options:"))
        self.layout().addWidget(graphopsFrame)
        self.cbGraphops = {}

        self.fillGraphOpsFrame(graphopsFrame)

        # Seats
        seatsFrame = QGroupBox(self.filterText['seatstitle'])
        self.layout().addWidget(seatsFrame)
        self.sbSeats = {}

        self.fillSeatsFrame(seatsFrame)

        # Groups
        groupsFrame = QGroupBox(self.filterText['groupstitle'])
        self.layout().addWidget(groupsFrame)

        self.fillGroupsFrame(groupsFrame, self.display)

        # Date
        dateFrame = QGroupBox(self.filterText['datestitle'])
        self.layout().addWidget(dateFrame)

        self.fillDateFrame(dateFrame)

        # Hole cards
        cardsFrame = QGroupBox(self.filterText['cardstitle'])
        self.layout().addWidget(cardsFrame)

        self.fillHoleCardsFrame(cardsFrame)

        # Buttons
        self.Button1 = QPushButton("Unnamed 1")
        self.Button2 = QPushButton("Unnamed 2")
        self.layout().addWidget(self.Button1)
        self.layout().addWidget(self.Button2)

        # Should do this cleaner
        if "Heroes" not in self.display or self.display["Heroes"] is False:
            playerFrame.hide()
        if "Sites" not in self.display or self.display["Sites"] is False:
            sitesFrame.hide()
        if "Games" not in self.display or self.display["Games"] is False:
            gamesFrame.hide()
        if "Currencies" not in self.display or self.display[
                "Currencies"] is False:
            currenciesFrame.hide()
        if "Limits" not in self.display or self.display["Limits"] is False:
            limitsFrame.hide()
        if "Positions" not in self.display or self.display[
                "Positions"] is False:
            positionsFrame.hide()
        if "Seats" not in self.display or self.display["Seats"] is False:
            seatsFrame.hide()
        if "Groups" not in self.display or self.display["Groups"] is False:
            groupsFrame.hide()
        if "Dates" not in self.display or self.display["Dates"] is False:
            dateFrame.hide()
        if "GraphOps" not in self.display or self.display["GraphOps"] is False:
            graphopsFrame.hide()
        if "Cards" not in self.display or self.display["Cards"] is False:
            cardsFrame.hide()
        if "Button1" not in self.display or self.display["Button1"] is False:
            self.Button1.hide()
        if "Button2" not in self.display or self.display["Button2"] is False:
            self.Button2.hide()

        # make sure any locks on db are released:
        self.db.rollback()

    def getNumHands(self):
        if self.phands:
            return self.phands.value()
        return 0

    def getNumTourneys(self):
        return 0

    def getSites(self):
        return [s for s in self.cbSites if self.cbSites[s].isChecked()]

    def getPositions(self):
        return [p for p in self.cbPositions if self.cbPositions[p].isChecked()]

    def getTourneyTypes(self):
        return []

    def getGames(self):
        return [g for g in self.cbGames if self.cbGames[g].isChecked()]

    def getCards(self):
        return self.cards

    def getCurrencies(self):
        return [
            c for c in self.cbCurrencies if self.cbCurrencies[c].isChecked()
        ]

    def getSiteIds(self):
        return self.siteid

    def getHeroes(self):
        return dict([(site, unicode(self.leHeroes[site].text()))
                     for site in self.leHeroes])

    def getGraphOps(self):
        return [g for g in self.cbGraphops if self.cbGraphops[g].isChecked()]

    def getLimits(self):
        return [l for l in self.cbLimits if self.cbLimits[l].isChecked()]

    def getType(self):
        return (self.type)

    def getSeats(self):
        result = {}
        if 'from' in self.sbSeats:
            result['from'] = self.sbSeats['from'].value()
        if 'to' in self.sbSeats:
            result['to'] = self.sbSeats['to'].value()
        return result

    def getGroups(self):
        return [g for g in self.cbGroups if self.cbGroups[g].isChecked()]

    def getDates(self):
        # self.day_start gives user's start of day in hours
        offset = int(self.day_start * 3600)  # calc day_start in seconds

        t1 = self.start_date.date()
        t2 = self.end_date.date()

        adj_t1 = QDateTime(t1).addSecs(offset)
        adj_t2 = QDateTime(t2).addSecs(offset + 24 * 3600 - 1)

        return (adj_t1.toUTC().toString("yyyy-MM-dd HH:mm:ss"),
                adj_t2.toUTC().toString("yyyy-MM-dd HH:mm:ss"))

    def registerButton1Name(self, title):
        self.Button1.setText(title)

    def registerButton1Callback(self, callback):
        self.Button1.clicked.connect(callback)
        self.Button1.setEnabled(True)
        self.callback['button1'] = callback

    def registerButton2Name(self, title):
        self.Button2.setText(title)

    def registerButton2Callback(self, callback):
        self.Button2.clicked.connect(callback)
        self.Button2.setEnabled(True)
        self.callback['button2'] = callback

    def registerCardsCallback(self, callback):
        self.callback['cards'] = callback

    def __set_tourney_type_select(self, w, tourneyType):
        self.tourneyTypes[tourneyType] = w.get_active()
        log.debug("self.tourney_types[%s] set to %s", tourneyType,
                  self.tourneyTypes[tourneyType])

    def createTourneyTypeLine(self, hbox, tourneyType):
        cb = QCheckBox(str(tourneyType))
        cb.clicked.connect(
            partial(self.__set_tourney_type_select, tourneyType=tourneyType))
        hbox.addWidget(cb)
        cb.setChecked(True)

    def createCardsWidget(self, grid):
        grid.setSpacing(0)
        for i in range(0, 13):
            for j in range(0, 13):
                abbr = Card.card_map_abbr[j][i]
                b = QPushButton("")
                import platform
                if platform.system == "Darwin":
                    b.setStyleSheet(
                        "QPushButton {border-width:0;margin:6;padding:0;}")
                else:
                    b.setStyleSheet(
                        "QPushButton {border-width:0;margin:0;padding:0;}")
                b.clicked.connect(
                    partial(self.__toggle_card_select, widget=b, card=abbr))
                self.cards[
                    abbr] = False  # NOTE: This is flippped in __toggle_card_select below
                self.__toggle_card_select(False, widget=b, card=abbr)
                grid.addWidget(b, j, i)

    def createCardsControls(self, hbox):
        selections = ["All", "Suited", "Off Suit"]
        for s in selections:
            cb = QCheckBox(s)
            cb.clicked.connect(self.__set_cards)
            hbox.addWidget(cb)

    def __card_select_bgcolor(self, card, selected):
        s_on = "red"
        s_off = "orange"
        o_on = "white"
        o_off = "lightgrey"
        p_on = "blue"
        p_off = "lightblue"
        if len(card) == 2: return p_on if selected else p_off
        if card[2] == 's': return s_on if selected else s_off
        if card[2] == 'o': return o_on if selected else o_off

    def __toggle_card_select(self, checkState, widget, card):
        font = widget.font()
        font.setPointSize(10)
        widget.setFont(font)
        widget.setText(card)

        self.cards[card] = not self.cards[card]

        #        bg_color = self.__card_select_bgcolor(card, self.cards[card])

        #        style = w.get_style().copy()
        #        style.bg[gtk.STATE_NORMAL] = w.get_colormap().alloc(bg_color)
        #        w.set_style(style)
        if 'cards' in self.callback:
            self.callback['cards'](card)

    def __set_cards(self, checkState):
        pass

    def __set_checkboxes(self, checkState, checkBoxes, setState):
        for checkbox in checkBoxes.values():
            checkbox.setChecked(setState)

    def __select_limit(self, checkState, limit):
        for l, checkbox in self.cbLimits.items():
            if l.endswith(limit):
                checkbox.setChecked(True)

    def fillPlayerFrame(self, frame, display):
        vbox = QVBoxLayout()
        frame.setLayout(vbox)

        for site in self.conf.get_supported_sites():
            player = self.conf.supported_sites[site].screen_name
            _pname = Charset.to_gui(player)
            vbox.addWidget(QLabel(site + " id:"))

            self.leHeroes[site] = QLineEdit(_pname)
            vbox.addWidget(self.leHeroes[site])

            names = self.db.get_player_names(self.conf, self.siteid[site])
            completer = QCompleter([Charset.to_gui(n[0]) for n in names])
            self.leHeroes[site].setCompleter(completer)

        if "GroupsAll" in display and display["GroupsAll"]:
            hbox = QHBoxLayout()
            vbox.addLayout(hbox)
            self.cbGroups['allplayers'] = QCheckBox(
                self.filterText['groupsall'])
            hbox.addWidget(self.cbGroups['allplayers'])

            lbl = QLabel(_('Min # Hands:'))
            hbox.addWidget(lbl)

            self.phands = QSpinBox()
            self.phands.setMaximum(1e5)
            hbox.addWidget(self.phands)

    def fillSitesFrame(self, frame):
        vbox = QVBoxLayout()
        frame.setLayout(vbox)

        for site in self.conf.get_supported_sites():
            self.cbSites[site] = QCheckBox(site)
            self.cbSites[site].setChecked(True)
            vbox.addWidget(self.cbSites[site])

    def fillTourneyTypesFrame(self, vbox):
        vbox1 = QVBoxLayout()
        vbox.setLayout(vbox1)
        self.boxes['tourneyTypes'] = vbox1

        result = self.db.getTourneyTypesIds()
        if len(result) >= 1:
            for line in result:
                hbox = QHBoxLayout()
                vbox1.addLayout(hbox)
                self.createTourneyTypeLine(hbox, line[0])
        else:
            print _("INFO: No tourney types returned from database")
            log.info(_("No tourney types returned from database"))

    def fillGamesFrame(self, frame):
        vbox1 = QVBoxLayout()
        frame.setLayout(vbox1)

        self.cursor.execute(self.sql.query['getGames'])
        result = self.db.cursor.fetchall()
        if len(result) >= 1:
            for line in sorted(result,
                               key=lambda game: self.gameName[game[0]]):
                self.cbGames[line[0]] = QCheckBox(self.gameName[line[0]])
                self.cbGames[line[0]].setChecked(True)
                vbox1.addWidget(self.cbGames[line[0]])

            if len(result) >= 2:
                hbox = QHBoxLayout()
                vbox1.addLayout(hbox)
                hbox.addStretch()

                btnAll = QPushButton(self.filterText['gamesall'])
                btnAll.clicked.connect(
                    partial(self.__set_checkboxes,
                            checkBoxes=self.cbGames,
                            setState=True))
                hbox.addWidget(btnAll)

                btnNone = QPushButton(self.filterText['gamesnone'])
                btnNone.clicked.connect(
                    partial(self.__set_checkboxes,
                            checkBoxes=self.cbGames,
                            setState=False))
                hbox.addWidget(btnNone)
                hbox.addStretch()
        else:
            print _("INFO: No games returned from database")
            log.info(_("No games returned from database"))

    def fillPositionsFrame(self, frame, display):
        vbox1 = QVBoxLayout()
        frame.setLayout(vbox1)

        # the following is not the fastest query (as it querys a table with potentialy a lot of data), so dont execute it if not necessary
        if "Positions" not in display or display["Positions"] is False:
            return

        #This takes too long if there are a couple of 100k hands in the DB
        #self.cursor.execute(self.sql.query['getPositions'])
        #result = self.db.cursor.fetchall()
        result = [[0], [1], [2], [3], [4], [5], [6], [7], ['S'], ['B']]
        res_count = len(result)

        if res_count > 0:
            v_count = 0
            COL_COUNT = 4  #Number of columns
            hbox = None
            for line in result:
                if v_count == 0:  #start a new line when the vertical count is 0
                    hbox = QHBoxLayout()
                    vbox1.addLayout(hbox)

                line_str = str(line[0])
                self.cbPositions[line_str] = QCheckBox(line_str)
                self.cbPositions[line_str].setChecked(True)
                hbox.addWidget(self.cbPositions[line_str])

                v_count += 1
                if v_count == COL_COUNT:  #set the counter to 0 if the line is full
                    v_count = 0

            dif = res_count % COL_COUNT
            while dif > 0:  #fill the rest of the line with empy boxes, so that every line contains COL_COUNT elements
                fillbox = QVBoxLayout()
                hbox.addLayout(fillbox)
                dif -= 1

            if res_count > 1:
                hbox = QHBoxLayout()
                vbox1.addLayout(hbox)
                hbox.addStretch()

                btnAll = QPushButton(self.filterText['positionsall'])
                btnAll.clicked.connect(
                    partial(self.__set_checkboxes,
                            checkBoxes=self.cbPositions,
                            setState=True))
                hbox.addWidget(btnAll)

                btnNone = QPushButton(self.filterText['positionsnone'])
                btnNone.clicked.connect(
                    partial(self.__set_checkboxes,
                            checkBoxes=self.cbPositions,
                            setState=False))
                hbox.addWidget(btnNone)
                hbox.addStretch()
        else:
            print(_("INFO") + ": " + _("No positions returned from database"))
            log.info(_("No positions returned from database"))

    def fillHoleCardsFrame(self, frame):
        vbox1 = QVBoxLayout()
        frame.setLayout(vbox1)

        grid = QGridLayout()
        vbox1.addLayout(grid)
        self.createCardsWidget(grid)

        # Additional controls for bulk changing card selection
        hbox = QHBoxLayout()
        vbox1.addLayout(hbox)
        self.createCardsControls(hbox)

    def fillCurrenciesFrame(self, frame):
        vbox1 = QVBoxLayout()
        frame.setLayout(vbox1)

        self.cursor.execute(self.sql.query['getCurrencies'])
        result = self.db.cursor.fetchall()
        if len(result) >= 1:
            for line in result:
                if line[0] in self.currencyName:
                    cname = self.currencyName[line[0]]
                else:
                    cname = line[0]
                self.cbCurrencies[line[0]] = QCheckBox(cname)
                self.cbCurrencies[line[0]].setChecked(True)
                vbox1.addWidget(self.cbCurrencies[line[0]])

            if len(result) >= 2:
                hbox = QHBoxLayout()
                vbox1.addLayout(hbox)
                hbox.addStretch()

                btnAll = QPushButton(self.filterText['currenciesall'])
                btnAll.clicked.connect(
                    partial(self.__set_checkboxes,
                            checkBoxes=self.cbCurrencies,
                            setState=True))
                hbox.addWidget(btnAll)

                btnNone = QPushButton(self.filterText['currenciesnone'])
                btnNone.clicked.connect(
                    partial(self.__set_checkboxes,
                            checkBoxes=self.cbCurrencies,
                            setState=False))
                hbox.addWidget(btnNone)
                hbox.addStretch()
            else:
                # There is only one currency. Select it, even if it's Play Money.
                self.cbCurrencies[line[0]].setChecked(True)
        else:
            log.info(_("No currencies returned from database"))

    def fillLimitsFrame(self, frame, display):
        vbox1 = QVBoxLayout()
        frame.setLayout(vbox1)

        self.cursor.execute(self.sql.query['getCashLimits'])
        # selects  limitType, bigBlind
        result = self.db.cursor.fetchall()
        limits_found = set()
        types_found = set()

        if len(result) >= 1:
            hbox = QHBoxLayout()
            vbox1.addLayout(hbox)
            vbox2 = QVBoxLayout()
            hbox.addLayout(vbox2)
            vbox3 = QVBoxLayout()
            hbox.addLayout(vbox3)
            for i, line in enumerate(result):
                if "UseType" in self.display:
                    if line[0] != self.display["UseType"]:
                        continue
                hbox = QHBoxLayout()
                if i < (len(result) + 1) / 2:
                    vbox2.addLayout(hbox)
                else:
                    vbox3.addLayout(hbox)
                if True:  #line[0] == 'ring':
                    name = str(line[2]) + line[1]
                    limits_found.add(line[1])
                    self.cbLimits[name] = QCheckBox(name)
                    self.cbLimits[name].setChecked(True)
                    hbox.addWidget(self.cbLimits[name])
                types_found.add(line[0])  # type is ring/tour
                self.type = line[0]  # if only one type, set it now
            if "LimitSep" in display and display["LimitSep"] and len(
                    result) >= 2:
                hbox = QHBoxLayout()
                vbox1.addLayout(hbox)
                hbox.addStretch()

                btnAll = QPushButton(self.filterText['limitsall'])
                btnAll.clicked.connect(
                    partial(self.__set_checkboxes,
                            checkBoxes=self.cbLimits,
                            setState=True))
                hbox.addWidget(btnAll)

                btnNone = QPushButton(self.filterText['limitsnone'])
                btnNone.clicked.connect(
                    partial(self.__set_checkboxes,
                            checkBoxes=self.cbLimits,
                            setState=False))
                hbox.addWidget(btnNone)

                if "LimitType" in display and display["LimitType"] and len(
                        limits_found) > 1:
                    for limit in limits_found:
                        btn = QPushButton(self.filterText['limits' +
                                                          limit.upper()])
                        btn.clicked.connect(
                            partial(self.__select_limit, limit=limit))
                        hbox.addWidget(btn)

                hbox.addStretch()
        else:
            print _("INFO: No games returned from database")
            log.info(_("No games returned from database"))

        if "Type" in display and display[
                "Type"] and 'ring' in types_found and 'tour' in types_found:
            # rb1 = QRadioButton(frame, self.filterText['ring'])
            # rb1.clicked.connect(self.__set_limit_select)
            # rb2 = QRadioButton(frame, self.filterText['tour'])
            # rb2.clicked.connect(self.__set_limit_select)
            # top_hbox.addWidget(rb1)
            # top_hbox.addWidget(rb2)
            #
            # self.rb['ring'] = rb1
            # self.rb['tour'] = rb2
            # #print "about to set ring to true"
            # rb1.setChecked(True)
            # # set_active doesn't seem to call this for some reason so call manually:
            # self.__set_limit_select(rb1)
            self.type = 'ring'

    def fillGraphOpsFrame(self, frame):
        vbox1 = QVBoxLayout()
        frame.setLayout(vbox1)

        hbox1 = QHBoxLayout()
        vbox1.addLayout(hbox1)

        label = QLabel(_("Show Graph In:"))
        hbox1.addWidget(label)

        self.cbGraphops['$'] = QRadioButton("$$", frame)
        hbox1.addWidget(self.cbGraphops['$'])
        self.cbGraphops['$'].setChecked(True)

        self.cbGraphops['BB'] = QRadioButton("BB", frame)
        hbox1.addWidget(self.cbGraphops['BB'])

        self.cbGraphops['showdown'] = QCheckBox(_("Showdown Winnings"))
        vbox1.addWidget(self.cbGraphops['showdown'])

        self.cbGraphops['nonshowdown'] = QCheckBox(_("Non-Showdown Winnings"))
        vbox1.addWidget(self.cbGraphops['nonshowdown'])

        self.cbGraphops['ev'] = QCheckBox(_("EV"))
        vbox1.addWidget(self.cbGraphops['ev'])

    def fillSeatsFrame(self, frame):
        hbox = QHBoxLayout()
        frame.setLayout(hbox)

        lbl_from = QLabel(self.filterText['seatsbetween'])
        lbl_to = QLabel(self.filterText['seatsand'])

        adj1 = QSpinBox()
        adj1.setRange(2, 10)
        adj1.setValue(2)
        adj1.valueChanged.connect(partial(self.__seats_changed, 'from'))

        adj2 = QSpinBox()
        adj2.setRange(2, 10)
        adj2.setValue(10)
        adj2.valueChanged.connect(partial(self.__seats_changed, 'to'))

        hbox.addStretch()
        hbox.addWidget(lbl_from)
        hbox.addWidget(adj1)
        hbox.addWidget(lbl_to)
        hbox.addWidget(adj2)
        hbox.addStretch()

        self.sbSeats['from'] = adj1
        self.sbSeats['to'] = adj2

    def fillGroupsFrame(self, frame, display):
        vbox = QVBoxLayout()
        frame.setLayout(vbox)

        self.cbGroups['limits'] = QCheckBox(self.filterText['limitsshow'])
        vbox.addWidget(self.cbGroups['limits'])

        self.cbGroups['posn'] = QCheckBox(self.filterText['posnshow'])
        vbox.addWidget(self.cbGroups['posn'])

        if "SeatSep" in display and display["SeatSep"]:
            self.cbGroups['seats'] = QCheckBox(self.filterText['seatsshow'])
            vbox.addWidget(self.cbGroups['seats'])

    def fillDateFrame(self, frame):
        table = QGridLayout()
        frame.setLayout(table)

        lbl_start = QLabel(_('From:'))
        btn_start = QPushButton("Cal")
        btn_start.clicked.connect(
            partial(self.__calendar_dialog, dateEdit=self.start_date))
        clr_start = QPushButton("Reset")
        clr_start.clicked.connect(self.__clear_start_date)

        lbl_end = QLabel(_('To:'))
        btn_end = QPushButton("Cal")
        btn_end.clicked.connect(
            partial(self.__calendar_dialog, dateEdit=self.end_date))
        clr_end = QPushButton("Reset")
        clr_end.clicked.connect(self.__clear_end_date)

        table.addWidget(lbl_start, 0, 0)
        table.addWidget(btn_start, 0, 1)
        table.addWidget(self.start_date, 0, 2)
        table.addWidget(clr_start, 0, 3)

        table.addWidget(lbl_end, 1, 0)
        table.addWidget(btn_end, 1, 1)
        table.addWidget(self.end_date, 1, 2)
        table.addWidget(clr_end, 1, 3)

        table.setColumnStretch(0, 1)

    def get_limits_where_clause(self, limits):
        """Accepts a list of limits and returns a formatted SQL where clause starting with AND.
            Sql statement MUST link to gameType table and use the alias gt for that table."""
        where = ""
        lims = [int(x[0:-2]) for x in limits if len(x) > 2 and x[-2:] == 'fl']
        potlims = [
            int(x[0:-2]) for x in limits if len(x) > 2 and x[-2:] == 'pl'
        ]
        nolims = [
            int(x[0:-2]) for x in limits if len(x) > 2 and x[-2:] == 'nl'
        ]
        capnolims = [
            int(x[0:-2]) for x in limits if len(x) > 2 and x[-2:] == 'cn'
        ]
        hpnolims = [
            int(x[0:-2]) for x in limits if len(x) > 2 and x[-2:] == 'hp'
        ]

        where = "AND ( "

        if lims:
            clause = "(gt.limitType = 'fl' and gt.bigBlind in (%s))" % (
                ','.join(map(str, lims)))
        else:
            clause = "(gt.limitType = 'fl' and gt.bigBlind in (-1))"
        where = where + clause
        if potlims:
            clause = "or (gt.limitType = 'pl' and gt.bigBlind in (%s))" % (
                ','.join(map(str, potlims)))
        else:
            clause = "or (gt.limitType = 'pl' and gt.bigBlind in (-1))"
        where = where + clause
        if nolims:
            clause = "or (gt.limitType = 'nl' and gt.bigBlind in (%s))" % (
                ','.join(map(str, nolims)))
        else:
            clause = "or (gt.limitType = 'nl' and gt.bigBlind in (-1))"
        where = where + clause
        if hpnolims:
            clause = "or (gt.limitType = 'hp' and gt.bigBlind in (%s))" % (
                ','.join(map(str, hpnolims)))
        else:
            clause = "or (gt.limitType = 'hp' and gt.bigBlind in (-1))"
        where = where + clause
        if capnolims:
            clause = "or (gt.limitType = 'cp' and gt.bigBlind in (%s))" % (
                ','.join(map(str, capnolims)))
        else:
            clause = "or (gt.limitType = 'cp' and gt.bigBlind in (-1))"
        where = where + clause + ' )'

        return where

    def replace_placeholders_with_filter_values(self, query):
        """ Returnes given query with replaced placeholders by the filter values from self.
        
            List of Placeholders that are replaced and some infos how the statement has to look like:
            (whole clause means it starts with AND and contains the whole clause)
        
            Placeholders      table & alias or field     SQL usage          coresponding filter Name
            <player_test>     Players.Id                in <player_test>   Heroes
            <game_test>       GameType gt               whole clause       Game
            <limit_test>      GameType gt               whole clause       Limits, LimitSep, LimitType
            <position_test>   HandsPlayers hp           whole clause       Positions
        """

        if '<game_test>' in query:
            games = self.getGames()

            if len(games) > 0:
                gametest = str(tuple(games))
                gametest = gametest.replace("L", "")
                gametest = gametest.replace(",)", ")")
                gametest = gametest.replace("u'", "'")
                gametest = "and gt.category in %s" % gametest
            else:
                gametest = "and gt.category IS NULL"
            query = query.replace('<game_test>', gametest)

        if '<limit_test>' in query:  #copyed from GuiGraphView
            limits = self.getLimits()
            limittest = self.get_limits_where_clause(limits)
            query = query.replace('<limit_test>', limittest)

        if '<player_test>' in query:  #copyed from GuiGraphView
            sites = self.getSites()
            heroes = self.getHeroes()
            siteids = self.getSiteIds()
            sitenos = []
            playerids = []

            for site in sites:
                sitenos.append(siteids[site])
                _hname = Charset.to_utf8(heroes[site])
                result = self.db.get_player_id(self.conf, site, _hname)
                if result is not None:
                    playerids.append(str(result))

            query = query.replace('<player_test>',
                                  '(' + ','.join(playerids) + ')')

        if '<position_test>' in query:
            positions = self.getPositions()

            positiontest = "AND hp.position in ('" + "','".join(
                positions
            ) + "')"  #values must be set in '' because they can be strings as well as numbers
            query = query.replace('<position_test>', positiontest)

        return query

    def __calendar_dialog(self, checkState, dateEdit):
        d = QDialog()
        d.setWindowTitle(_('Pick a date'))

        vb = QVBoxLayout()
        d.setLayout(vb)
        cal = QCalendarWidget()
        vb.addWidget(cal)

        btn = QPushButton(_('Done'))
        btn.clicked.connect(
            partial(self.__get_date, dlg=d, calendar=cal, dateEdit=dateEdit))

        vb.addWidget(btn)

        d.exec_()

    def __clear_start_date(self, checkState):
        self.start_date.setDate(QDate(1970, 1, 1))

    def __clear_end_date(self, checkState):
        self.end_date.setDate(QDate(2100, 1, 1))

    def __get_date(self, checkState, dlg, calendar, dateEdit):
        newDate = calendar.selectedDate()
        dateEdit.setDate(newDate)

        # if the opposite date is set, and now the start date is later
        # than the end date, modify the one we didn't just set to be
        # the same as the one we did just set
        if dateEdit == self.start_date:
            end = self.end_date.date()
            if newDate > end:
                self.end_date.setDate(newDate)
        else:
            start = self.start_date.date()
            if newDate < start:
                self.start_date.setDate(newDate)
        dlg.accept()

    def __seats_changed(self, value, which):
        seats_from = self.sbSeats['from'].value()
        seats_to = self.sbSeats['to'].value()
        if seats_from > seats_to:
            if which == 'from':
                self.sbSeats['to'].setValue(seats_from)
            else:
                self.sbSeats['from'].setValue(seats_to)
Example #17
0
class PaymentDlg(QDialog):

    def __init__(self, parent=None):
        super(PaymentDlg, self).__init__(parent)

        forenameLabel = QLabel("&Forename:")
        self.forenameLineEdit = QLineEdit()
        forenameLabel.setBuddy(self.forenameLineEdit)
        surnameLabel = QLabel("&Surname:")
        self.surnameLineEdit = QLineEdit()
        surnameLabel.setBuddy(self.surnameLineEdit)
        invoiceLabel = QLabel("&Invoice No.:")
        self.invoiceSpinBox = QSpinBox()
        invoiceLabel.setBuddy(self.invoiceSpinBox)
        self.invoiceSpinBox.setRange(1, 10000000)
        self.invoiceSpinBox.setValue(100000)
        self.invoiceSpinBox.setAlignment(Qt.AlignRight|Qt.AlignVCenter)
        amountLabel = QLabel("&Amount:")
        self.amountSpinBox = QDoubleSpinBox()
        amountLabel.setBuddy(self.amountSpinBox)
        self.amountSpinBox.setRange(0, 5000.0)
        self.amountSpinBox.setPrefix("$ ")
        self.amountSpinBox.setAlignment(Qt.AlignRight|Qt.AlignVCenter)
        self.paidCheckBox = QCheckBox("&Paid")
        checkNumLabel = QLabel("Check &No.:")
        self.checkNumLineEdit = QLineEdit()
        checkNumLabel.setBuddy(self.checkNumLineEdit)
        bankLabel = QLabel("&Bank:")
        self.bankLineEdit = QLineEdit()
        bankLabel.setBuddy(self.bankLineEdit)
        accountNumLabel = QLabel("Acco&unt No.:")
        self.accountNumLineEdit = QLineEdit()
        accountNumLabel.setBuddy(self.accountNumLineEdit)
        sortCodeLabel = QLabel("Sort &Code:")
        self.sortCodeLineEdit = QLineEdit()
        sortCodeLabel.setBuddy(self.sortCodeLineEdit)
        creditCardLabel = QLabel("&Number:")
        self.creditCardLineEdit = QLineEdit()
        creditCardLabel.setBuddy(self.creditCardLineEdit)
        validFromLabel = QLabel("&Valid From:")
        self.validFromDateEdit = QDateEdit()
        validFromLabel.setBuddy(self.validFromDateEdit)
        self.validFromDateEdit.setDisplayFormat("MMM yyyy")
        self.validFromDateEdit.setAlignment(Qt.AlignRight|Qt.AlignVCenter)
        expiryLabel = QLabel("E&xpiry Date:")
        self.expiryDateEdit = QDateEdit()
        expiryLabel.setBuddy(self.expiryDateEdit)
        self.expiryDateEdit.setDisplayFormat("MMM yyyy")
        self.expiryDateEdit.setAlignment(Qt.AlignRight|Qt.AlignVCenter)
        self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok|
                                          QDialogButtonBox.Cancel)

        tabWidget = QTabWidget()
        cashWidget = QWidget()
        cashLayout = QHBoxLayout()
        cashLayout.addWidget(self.paidCheckBox)
        cashWidget.setLayout(cashLayout)
        tabWidget.addTab(cashWidget, "Cas&h")
        checkWidget = QWidget()
        checkLayout = QGridLayout()
        checkLayout.addWidget(checkNumLabel, 0, 0)
        checkLayout.addWidget(self.checkNumLineEdit, 0, 1)
        checkLayout.addWidget(bankLabel, 0, 2)
        checkLayout.addWidget(self.bankLineEdit, 0, 3)
        checkLayout.addWidget(accountNumLabel, 1, 0)
        checkLayout.addWidget(self.accountNumLineEdit, 1, 1)
        checkLayout.addWidget(sortCodeLabel, 1, 2)
        checkLayout.addWidget(self.sortCodeLineEdit, 1, 3)
        checkWidget.setLayout(checkLayout)
        tabWidget.addTab(checkWidget, "Chec&k")
        creditWidget = QWidget()
        creditLayout = QGridLayout()
        creditLayout.addWidget(creditCardLabel, 0, 0)
        creditLayout.addWidget(self.creditCardLineEdit, 0, 1, 1, 3)
        creditLayout.addWidget(validFromLabel, 1, 0)
        creditLayout.addWidget(self.validFromDateEdit, 1, 1)
        creditLayout.addWidget(expiryLabel, 1, 2)
        creditLayout.addWidget(self.expiryDateEdit, 1, 3)
        creditWidget.setLayout(creditLayout)
        tabWidget.addTab(creditWidget, "Credit Car&d")

        gridLayout = QGridLayout()
        gridLayout.addWidget(forenameLabel, 0, 0)
        gridLayout.addWidget(self.forenameLineEdit, 0, 1)
        gridLayout.addWidget(surnameLabel, 0, 2)
        gridLayout.addWidget(self.surnameLineEdit, 0, 3)
        gridLayout.addWidget(invoiceLabel, 1, 0)
        gridLayout.addWidget(self.invoiceSpinBox, 1, 1)
        gridLayout.addWidget(amountLabel, 1, 2)
        gridLayout.addWidget(self.amountSpinBox, 1, 3)
        layout = QVBoxLayout()
        layout.addLayout(gridLayout)
        layout.addWidget(tabWidget)
        layout.addWidget(self.buttonBox)
        self.setLayout(layout)

        for lineEdit in (self.forenameLineEdit, self.surnameLineEdit,
                self.checkNumLineEdit, self.accountNumLineEdit,
                self.bankLineEdit, self.sortCodeLineEdit,
                self.creditCardLineEdit):
            lineEdit.textEdited.connect(self.updateUi)
        for dateEdit in (self.validFromDateEdit, self.expiryDateEdit):
            dateEdit.dateChanged.connect(self.updateUi)

        self.paidCheckBox.clicked.connect(self.updateUi)
        self.buttonBox.accepted.connect(self.accept)
        self.buttonBox.rejected.connect(self.reject)

        self.updateUi()
        self.setWindowTitle("Payment Form")


    def updateUi(self):
        today = QDate.currentDate()
        enable = (self.forenameLineEdit.text() and
                       self.surnameLineEdit.text())
        if enable:
            enable = (self.paidCheckBox.isChecked() or
                  (self.checkNumLineEdit.text() and
                        self.accountNumLineEdit.text() and
                        self.bankLineEdit.text() and
                        self.sortCodeLineEdit.text()) or
                  (self.creditCardLineEdit.text() and
                   self.validFromDateEdit.date() <= today and
                   self.expiryDateEdit.date() >= today))
        self.buttonBox.button(QDialogButtonBox.Ok).setEnabled(bool(enable))
class ExportWindow(QDialog):
    """
    Class describing a dialog for exports of schedules.
    """
    def __init__(self, schedule: Schedule, parent: QWidget = None):
        super().__init__(parent)
        self._schedule_ref = schedule
        self._date_start_cache = None

        # window settings
        self.setWindowFlag(Qt.WindowContextHelpButtonHint, False)
        self.setWindowTitle(self.tr("Export window"))
        self.setMinimumWidth(800)

        # title, add_date, work mode
        self.layout_title_date_mode = QHBoxLayout()

        self.label_title = QLabel(self.tr("Title"))
        self.layout_title_date_mode.addWidget(self.label_title)

        self.line_edit_title = QLineEdit()
        self.layout_title_date_mode.addWidget(self.line_edit_title)

        self.check_box_add_date = QCheckBox(self.tr("Add date"))
        self.layout_title_date_mode.addWidget(self.check_box_add_date)

        self.combo_box_work_mode = QComboBox()
        self.layout_title_date_mode.addWidget(self.combo_box_work_mode)

        self.line_edit_title.setPlaceholderText(
            self.tr("My Group. A subgroup - green color, "
                    "B subgroup - yellow color. "))
        self.check_box_add_date.setChecked(True)

        self.combo_box_work_mode.addItem(self.tr("Weekly"))
        self.combo_box_work_mode.addItem(self.tr("Full"))

        # list widget with files
        self.layout_list_widget = QVBoxLayout()

        self.check_box_use_current = QCheckBox(self.tr("Use current schedule"))
        self.layout_list_widget.addWidget(self.check_box_use_current)
        self.check_box_use_current.setChecked(True)

        self.list_widget = QListWidget()
        self.layout_list_widget.addWidget(self.list_widget)
        self.list_widget.setSortingEnabled(True)
        self.list_widget.setEnabled(False)

        self.layout_open_folder = QHBoxLayout()
        self.layout_list_widget.addLayout(self.layout_open_folder)

        self.label_find = QLabel(self.tr("Schedules: ") + "0")
        self.layout_open_folder.addWidget(self.label_find)

        self.layout_open_folder.addStretch(1)

        self.push_button_open_folder = QToolButton()
        self.layout_open_folder.addWidget(self.push_button_open_folder)
        self.push_button_open_folder.setEnabled(False)

        self.push_button_open_folder.setText(self.tr("Open folder"))
        self.push_button_open_folder.setPopupMode(QToolButton.MenuButtonPopup)

        self.action_open_files = QAction(self.tr("Open files"))
        self.push_button_open_folder.addAction(self.action_open_files)

        # font edit
        self.group_box_font = QGroupBox(self.tr("Font settings"))
        self.form_layout_font = QFormLayout(self.group_box_font)

        self.label_font = QLabel(self.tr("Font"))
        self.form_layout_font.setWidget(0, QFormLayout.LabelRole,
                                        self.label_font)
        self.combo_box_font = QComboBox()
        self.form_layout_font.setWidget(0, QFormLayout.FieldRole,
                                        self.combo_box_font)

        self.label_encoding = QLabel(self.tr("Encoding"))
        self.form_layout_font.setWidget(1, QFormLayout.LabelRole,
                                        self.label_encoding)
        self.combo_box_encoding = QComboBox()
        self.form_layout_font.setWidget(1, QFormLayout.FieldRole,
                                        self.combo_box_encoding)

        for font_name, font_path in util.get_fonts():
            self.combo_box_font.addItem(font_name, font_path)

        self.combo_box_font.setCurrentText(qApp.font().family())
        self.combo_box_font.setEditable(True)

        self.combo_box_encoding.addItem("UTF-8")
        self.combo_box_encoding.addItem("Latin-1")
        self.combo_box_encoding.addItem("Windows-1252")

        # date edit
        self.group_box_date = QGroupBox(self.tr("Date settings"))
        self.form_layout_date = QFormLayout(self.group_box_date)

        self.label_date_start = QLabel(self.tr("Start"))
        self.form_layout_date.setWidget(0, QFormLayout.LabelRole,
                                        self.label_date_start)
        self.date_edit_start = QDateEdit()
        self.form_layout_date.setWidget(0, QFormLayout.FieldRole,
                                        self.date_edit_start)

        self.label_date_end = QLabel(self.tr("End"))
        self.form_layout_date.setWidget(1, QFormLayout.LabelRole,
                                        self.label_date_end)
        self.date_edit_end = QDateEdit()
        self.form_layout_date.setWidget(1, QFormLayout.FieldRole,
                                        self.date_edit_end)

        self.date_edit_start.setCalendarPopup(True)
        self.date_edit_end.setCalendarPopup(True)

        if QDate.currentDate().day() < (QDate.currentDate().dayOfYear() / 2):
            date = QDate(QDate.currentDate().year(), 2, 1)
        else:
            date = QDate(QDate.currentDate().year(), 9, 1)

        self._date_start_cache = date.addDays(8 - date.dayOfWeek())
        self.date_edit_start.setDate(self._date_start_cache)
        self.date_edit_end.setMinimumDate(self._date_start_cache.addDays(7))
        self.date_edit_end.setDate(self._date_start_cache.addDays(16 * 7))

        # subgroup edit
        self.group_box_subgroup = QGroupBox(self.tr("Subgroup settings"))
        self.form_layout_subgroup = QFormLayout(self.group_box_subgroup)

        self.label_color_a = QLabel(self.tr("Color A"))
        self.form_layout_subgroup.setWidget(0, QFormLayout.LabelRole,
                                            self.label_color_a)
        self.combo_box_color_a = QComboBox()
        self.form_layout_subgroup.setWidget(0, QFormLayout.FieldRole,
                                            self.combo_box_color_a)

        self.label_color_b = QLabel(self.tr("Color B"))
        self.form_layout_subgroup.setWidget(1, QFormLayout.LabelRole,
                                            self.label_color_b)
        self.combo_box_color_b = QComboBox()
        self.form_layout_subgroup.setWidget(1, QFormLayout.FieldRole,
                                            self.combo_box_color_b)

        self.label_pattern_a_b = QLabel(self.tr("Pattern A and B"))
        self.form_layout_subgroup.setWidget(2, QFormLayout.LabelRole,
                                            self.label_pattern_a_b)
        self.combo_box_pattern_a_b = QComboBox()
        self.form_layout_subgroup.setWidget(2, QFormLayout.FieldRole,
                                            self.combo_box_pattern_a_b)

        self.add_standard_colors(self.combo_box_color_a)
        self.add_standard_colors(self.combo_box_color_b)
        self.combo_box_color_a.setCurrentIndex(9)  # lime
        self.combo_box_color_b.setCurrentIndex(15)  # yellow

        self.combo_box_pattern_a_b.addItem(self.tr("Chess order"))
        self.combo_box_pattern_a_b.setEnabled(False)

        # navigate buttons
        self.layout_navigate = QHBoxLayout()

        self.layout_navigate.addStretch(1)

        self.push_button_export = QPushButton(self.tr("Export"))
        self.layout_navigate.addWidget(self.push_button_export)

        self.push_button_cancel = QPushButton(self.tr("Cancel"))
        self.layout_navigate.addWidget(self.push_button_cancel)

        # layout setup
        self.layout_right_setting = QVBoxLayout()
        self.layout_right_setting.addWidget(self.group_box_font)
        self.layout_right_setting.addWidget(self.group_box_date)
        self.layout_right_setting.addWidget(self.group_box_subgroup)
        self.layout_right_setting.addStretch(1)

        self.layout_center = QHBoxLayout()
        self.layout_center.addLayout(self.layout_list_widget)
        self.layout_center.addLayout(self.layout_right_setting)

        self.layout_main = QVBoxLayout()
        self.layout_main.addLayout(self.layout_title_date_mode)
        self.layout_main.addLayout(self.layout_center)
        self.layout_main.addLayout(self.layout_navigate)

        self.setLayout(self.layout_main)

        # connection
        self.check_box_use_current.clicked.connect(
            self.check_box_use_current_clicked)
        self.push_button_open_folder.clicked.connect(self.open_folder_clicked)
        self.action_open_files.triggered.connect(self.open_files_clicked)

        self.date_edit_start.dateChanged.connect(self.date_edit_start_changed)
        self.combo_box_color_a.activated.connect(
            self.combo_box_color_a_clicked)
        self.combo_box_color_b.activated.connect(
            self.combo_box_color_b_clicked)
        self.push_button_export.clicked.connect(self.export_to_pdf)
        self.push_button_cancel.clicked.connect(self.close)

    def add_standard_colors(self, combo_box: QComboBox) -> None:
        """
        Adds colors to the color selection menu.

        :param combo_box: Color selection menu
        """
        color_items = [(self.tr("Custom color"), QColor()),
                       (self.tr("Aqua"), QColor(0, 255, 255)),
                       (self.tr("Grey"), QColor(128, 128, 128)),
                       (self.tr("Navy"), QColor(0, 0, 192)),
                       (self.tr("Silver"), QColor(192, 192, 192)),
                       (self.tr("Black"), QColor(0, 0, 0)),
                       (self.tr("Green"), QColor(0, 128, 0)),
                       (self.tr("Olive"), QColor(192, 192, 0)),
                       (self.tr("Blue"), QColor(0, 0, 255)),
                       (self.tr("Lime"), QColor(0, 255, 0)),
                       (self.tr("Purple"), QColor(128, 0, 128)),
                       (self.tr("White"), QColor(255, 255, 255)),
                       (self.tr("Fuchsia"), QColor(255, 0, 255)),
                       (self.tr("Maroon"), QColor(128, 0, 0)),
                       (self.tr("Red"), QColor(255, 0, 0)),
                       (self.tr("Yellow"), QColor(255, 255, 0))]

        for name, data in color_items:
            combo_box.addItem(util.create_color_icon(data), name, data)

    def export_to_pdf(self) -> None:
        # select path

        paths = []

        if self.check_box_use_current.isChecked():
            path = QFileDialog.getSaveFileName(self, self.tr("Export to pdf"),
                                               ".", "PDF file (*.pdf)")[0]
            if path == "":
                return

            if not path.endswith(".pdf"):
                path += ".pdf"

            paths.append(path)
        else:
            for index in range(self.list_widget.count()):
                path = self.list_widget.item(index).data(Qt.UserRole)
                paths.append(path)

        # progress dialog
        progress = QProgressDialog(self.tr("Export to pdf"),
                                   self.tr("Abort exports"), 0, 100, self)
        progress.setWindowModality(Qt.WindowModal)
        progress.setMinimumDuration(2000)

        try:
            for index, path in enumerate(paths):

                if self.check_box_use_current.isChecked():
                    title_text = self.line_edit_title.text()
                    schedule = self._schedule_ref
                else:
                    title_text = QFileInfo(path).baseName()
                    schedule = Schedule()
                    schedule.load(path)
                    path = path[0:-5] + ".pdf"

                print(path)
                mode = self.combo_box_work_mode.currentIndex()
                if mode == 0:
                    export_weeks_to_pdf(
                        schedule, title_text,
                        self.check_box_add_date.isChecked(), path,
                        self.combo_box_font.currentText(),
                        self.combo_box_font.currentData(Qt.UserRole),
                        self.combo_box_encoding.currentText(),
                        self.date_edit_start.date().toPyDate(),
                        self.date_edit_end.date().toPyDate(),
                        self.combo_box_color_a.currentData(Qt.UserRole),
                        self.combo_box_color_b.currentData(Qt.UserRole),
                        progress
                        if self.check_box_use_current.isChecked() else None)
                else:
                    export_full_to_pdf(
                        schedule, title_text, path,
                        self.combo_box_font.currentText(),
                        self.combo_box_font.currentData(Qt.UserRole),
                        self.combo_box_encoding.currentText(), progress
                        if self.check_box_use_current.isChecked() else None)

                progress.setValue(int(index * 100 / len(paths)))

            # finish dialog
            progress.setValue(100)
            finish_msg_box = QMessageBox(QMessageBox.Information,
                                         self.tr("Export to pdf"),
                                         self.tr("Gone!"))
            open_folder_button = finish_msg_box.addButton(
                self.tr("Open folder"), QMessageBox.ActionRole)
            finish_msg_box.addButton(QMessageBox.Ok)
            finish_msg_box.exec_()

            if finish_msg_box.clickedButton() == open_folder_button:
                QDesktopServices.openUrl(
                    QUrl(
                        QFileInfo(paths[0] if len(paths) != 0 else ".").
                        absolutePath()))

        except UnicodeEncodeError as ex:
            QMessageBox.critical(self, self.tr("Encoding error"), str(ex))
        except Exception as ex:
            QMessageBox.critical(self, self.tr("Unknown error"), str(ex))
        progress.setValue(100)

    def check_box_use_current_clicked(self, checked: bool):
        if checked:
            self.list_widget.setEnabled(False)
            self.push_button_open_folder.setEnabled(False)
            self.line_edit_title.setEnabled(False)
        else:
            self.list_widget.setEnabled(True)
            self.push_button_open_folder.setEnabled(True)
            self.line_edit_title.setEnabled(True)

    def open_folder_clicked(self):
        path = QFileDialog.getExistingDirectory(self, self.tr("Select folder"))

        provider = QFileIconProvider()
        self.list_widget.clear()

        for dir_path, dir_names, file_names in os.walk(path):
            for file_name in file_names:
                if file_name.endswith(".json"):
                    item = QListWidgetItem()
                    item.setText(file_name[0:-5])
                    item.setData(Qt.UserRole, dir_path + os.sep + file_name)
                    item.setIcon(
                        provider.icon(QFileInfo(dir_path + os.sep +
                                                file_name)))

                    self.list_widget.addItem(item)

        self.label_find.setText(
            self.tr("Schedules: ") + str(self.list_widget.count()))

    def open_files_clicked(self):
        files = QFileDialog.getOpenFileNames(
            self, self.tr("Select files"), "",
            "JSON file (*.json) ;; All files (*.*)")[0]
        provider = QFileIconProvider()
        self.list_widget.clear()

        for file_path in files:
            file = QFileInfo(file_path)
            item = QListWidgetItem()
            item.setText(file.baseName())
            item.setData(Qt.UserRole, file_path)
            item.setIcon(provider.icon(file))
            self.list_widget.addItem(item)

        self.label_find.setText(
            self.tr("Schedules: ") + str(self.list_widget.count()))

    def combo_box_color_a_clicked(self) -> None:
        """
        Slot for color selection of A subgroup.
        """
        if self.combo_box_color_a.currentIndex() == 0:
            self.custom_color_selected(self.combo_box_color_a)

    def combo_box_color_b_clicked(self) -> None:
        """
        Slot for color selection of B subgroup.
        """
        if self.combo_box_color_b.currentIndex() == 0:
            self.custom_color_selected(self.combo_box_color_b)

    def custom_color_selected(self, combo_box: QComboBox) -> None:
        """
        Slot to select the color for the desired menu.

        :param combo_box: Menu
        """
        color = QColorDialog.getColor(combo_box.currentData(), self)
        if color.isValid():
            combo_box.setItemIcon(0, util.create_color_icon(color))
            combo_box.setItemData(0, color)

    def date_edit_start_changed(self, date: QDate):
        """
        Slot for changing the end of a range of dates.

        :param date: Start of the date range
        """
        end_date = self.date_edit_end.date().addDays(
            self._date_start_cache.daysTo(date))
        self.date_edit_end.setMinimumDate(date.addDays(7))
        self.date_edit_end.setDate(end_date)
        self._date_start_cache = QDate(date)
Example #19
0
class ImportWindow(QDialog):
    def __init__(self, parent: QWidget = None):
        super().__init__(parent)

        self._size: int = os.cpu_count()
        if self._size is None:
            self._size = 2

        self._processes_pool = []
        self._manager = ImportManager(self._size)
        self._max_progress: int = 0
        self._timer: QTimer = QTimer()
        self._confuser = ConfuseWindow(self)
        self._date_start_cache = None
        self._tesseract_path_cache = None
        self._poppler_path_cache = None

        # window settings
        self.setWindowFlag(Qt.WindowContextHelpButtonHint, False)
        self.setWindowTitle(self.tr("Import window"))

        # list widget with files
        self.list_widget = QListWidget()
        self.list_widget.setSortingEnabled(True)

        self.layout_open_folder = QHBoxLayout()
        self.label_find = QLabel(self.tr("Schedules: ") + "0")
        self.layout_open_folder.addWidget(self.label_find)

        self.layout_open_folder.addStretch(1)

        self.push_button_open_folder = QToolButton()
        self.layout_open_folder.addWidget(self.push_button_open_folder)

        self.push_button_open_folder.setText(self.tr("Open folder"))
        self.push_button_open_folder.setPopupMode(QToolButton.MenuButtonPopup)

        self.action_open_files = QAction(self.tr("Open files"))
        self.push_button_open_folder.addAction(self.action_open_files)

        # main progress
        self.group_box_main_progress = QGroupBox(self.tr("Main progress"))
        self.layout_main_progress = QVBoxLayout(self.group_box_main_progress)

        self.process_bar_main = QProgressBar()
        self.layout_main_progress.addWidget(self.process_bar_main)

        self.layout_start_process = QHBoxLayout()
        self.layout_start_process.addStretch(1)

        self.push_button_import = QPushButton(self.tr("Import"))
        self.layout_start_process.addWidget(self.push_button_import)

        self.push_button_stop = QPushButton(self.tr("Stop"))
        self.layout_start_process.addWidget(self.push_button_stop)

        self.push_button_stop.setEnabled(False)

        self.layout_main_progress.addLayout(self.layout_start_process)

        # threads process
        self.group_box_threads = QGroupBox(self.tr("Threads"))
        self.grid_layout_threads = QGridLayout(self.group_box_threads)

        self._progresses_bars = []
        rows = self._size // 2
        columns = 2
        for i in range(rows):
            for j in range(columns):
                progress_bar = QProgressBar()
                progress_bar.setTextVisible(True)
                self._progresses_bars.append(progress_bar)
                self.grid_layout_threads.addWidget(progress_bar, i, j)

        # options
        self.group_box_options = QGroupBox(self.tr("Options"))
        self.form_layout_options = QFormLayout(self.group_box_options)

        self.check_box_weekly = QCheckBox(self.tr("Create weekly schedule"))
        self.form_layout_options.addRow(self.check_box_weekly)

        self.check_box_full = QCheckBox(self.tr("Create full schedule"))
        self.form_layout_options.addRow(self.check_box_full)

        self.check_box_debug_img = QCheckBox(self.tr("Create debug image"))
        self.form_layout_options.addRow(self.check_box_debug_img)

        self.spin_box_dpi = QSpinBox()
        self.form_layout_options.addRow(self.tr("DPI"), self.spin_box_dpi)

        self.combo_box_tesseract_path = QComboBox()
        self.form_layout_options.addRow(self.tr("Tesseract path"),
                                        self.combo_box_tesseract_path)

        self.combo_box_poppler_path = QComboBox()
        self.form_layout_options.addRow(self.tr("Poppler path"),
                                        self.combo_box_poppler_path)

        self.check_box_debug_img.setChecked(True)
        self.check_box_debug_img.setEnabled(False)

        self.spin_box_dpi.setRange(200, 800)
        self.spin_box_dpi.setValue(500)

        self.combo_box_tesseract_path.addItem(
            self.tr("<select tesseract path>"))
        self.combo_box_tesseract_path.addItem("Default", "tesseract")
        self.combo_box_tesseract_path.setCurrentIndex(1)
        self._tesseract_path_cache = self.combo_box_tesseract_path.currentText(
        )

        self.combo_box_poppler_path.addItem(self.tr("<select poppler path>"))
        self.combo_box_poppler_path.addItem("Default", None)
        self.combo_box_poppler_path.setCurrentIndex(1)
        self._poppler_path_cache = self.combo_box_poppler_path.currentText()

        # font edit
        self.group_box_font = QGroupBox(self.tr("Font settings"))
        self.form_layout_font = QFormLayout(self.group_box_font)

        self.label_font = QLabel(self.tr("Font"))
        self.form_layout_font.setWidget(0, QFormLayout.LabelRole,
                                        self.label_font)
        self.combo_box_font = QComboBox()
        self.form_layout_font.setWidget(0, QFormLayout.FieldRole,
                                        self.combo_box_font)

        self.label_encoding = QLabel(self.tr("Encoding"))
        self.form_layout_font.setWidget(1, QFormLayout.LabelRole,
                                        self.label_encoding)
        self.combo_box_encoding = QComboBox()
        self.form_layout_font.setWidget(1, QFormLayout.FieldRole,
                                        self.combo_box_encoding)

        for font_name, font_path in util.get_fonts():
            self.combo_box_font.addItem(font_name, font_path)

        self.combo_box_font.setCurrentText(qApp.font().family())
        self.combo_box_font.setEditable(True)

        self.combo_box_encoding.addItem("UTF-8")
        self.combo_box_encoding.addItem("Latin-1")
        self.combo_box_encoding.addItem("Windows-1252")

        # date edit
        self.group_box_date = QGroupBox(self.tr("Date settings"))
        self.form_layout_date = QFormLayout(self.group_box_date)

        self.label_date_start = QLabel(self.tr("Start"))
        self.form_layout_date.setWidget(0, QFormLayout.LabelRole,
                                        self.label_date_start)
        self.date_edit_start = QDateEdit()
        self.form_layout_date.setWidget(0, QFormLayout.FieldRole,
                                        self.date_edit_start)

        self.label_date_end = QLabel(self.tr("End"))
        self.form_layout_date.setWidget(1, QFormLayout.LabelRole,
                                        self.label_date_end)
        self.date_edit_end = QDateEdit()
        self.form_layout_date.setWidget(1, QFormLayout.FieldRole,
                                        self.date_edit_end)

        self.date_edit_start.setCalendarPopup(True)
        self.date_edit_end.setCalendarPopup(True)

        if QDate.currentDate().day() < QDate.currentDate().dayOfYear() / 2:
            date = QDate(QDate.currentDate().year(), 2, 1)
        else:
            date = QDate(QDate.currentDate().year(), 9, 1)

        self._date_start_cache = date.addDays(8 - date.dayOfWeek())
        self.date_edit_start.setDate(self._date_start_cache)
        self.date_edit_end.setMinimumDate(self._date_start_cache.addDays(7))
        self.date_edit_end.setDate(self._date_start_cache.addDays(16 * 7))

        # subgroup edit
        self.group_box_subgroup = QGroupBox(self.tr("Subgroup settings"))
        self.form_layout_subgroup = QFormLayout(self.group_box_subgroup)

        self.label_color_a = QLabel(self.tr("Color A"))
        self.form_layout_subgroup.setWidget(0, QFormLayout.LabelRole,
                                            self.label_color_a)
        self.combo_box_color_a = QComboBox()
        self.form_layout_subgroup.setWidget(0, QFormLayout.FieldRole,
                                            self.combo_box_color_a)

        self.label_color_b = QLabel(self.tr("Color B"))
        self.form_layout_subgroup.setWidget(1, QFormLayout.LabelRole,
                                            self.label_color_b)
        self.combo_box_color_b = QComboBox()
        self.form_layout_subgroup.setWidget(1, QFormLayout.FieldRole,
                                            self.combo_box_color_b)

        self.label_pattern_a_b = QLabel(self.tr("Pattern A and B"))
        self.form_layout_subgroup.setWidget(2, QFormLayout.LabelRole,
                                            self.label_pattern_a_b)
        self.combo_box_pattern_a_b = QComboBox()
        self.form_layout_subgroup.setWidget(2, QFormLayout.FieldRole,
                                            self.combo_box_pattern_a_b)

        self.add_standard_colors(self.combo_box_color_a)
        self.add_standard_colors(self.combo_box_color_b)
        self.combo_box_color_a.setCurrentIndex(9)  # lime
        self.combo_box_color_b.setCurrentIndex(15)  # yellow

        self.combo_box_pattern_a_b.addItem(self.tr("Chess order"))
        self.combo_box_pattern_a_b.setEnabled(False)

        # navigate
        self.layout_navigate = QHBoxLayout()

        self.layout_navigate.addStretch(1)

        self.push_button_ok = QPushButton(self.tr("OK"))
        self.layout_navigate.addWidget(self.push_button_ok)

        self.push_button_cancel = QPushButton(self.tr("Cancel"))
        self.layout_navigate.addWidget(self.push_button_cancel)

        # layout setup
        self.layout_left = QVBoxLayout()
        self.layout_left.addWidget(self.list_widget)
        self.layout_left.addLayout(self.layout_open_folder)

        self.layout_right = QVBoxLayout()
        self.layout_right.addWidget(self.group_box_main_progress)
        self.layout_right.addWidget(self.group_box_threads)

        self.layout_down = QGridLayout()
        self.layout_down.addWidget(self.group_box_options, 0, 0)
        self.layout_down.addWidget(self.group_box_font, 1, 0)
        self.layout_down.addWidget(self.group_box_date, 0, 1)
        self.layout_down.addWidget(self.group_box_subgroup, 1, 1)

        self.layout_right.addLayout(self.layout_down)
        self.layout_right.addStretch(1)
        self.layout_right.addLayout(self.layout_navigate)

        self.layout_main = QHBoxLayout()
        self.layout_main.addLayout(self.layout_left, 1)
        self.layout_main.addLayout(self.layout_right, 2)

        self.setLayout(self.layout_main)

        # connections
        self._timer.timeout.connect(self.check_processes)

        self.push_button_open_folder.clicked.connect(self.open_folder_clicked)
        self.action_open_files.triggered.connect(self.open_files_clicked)

        self.push_button_import.clicked.connect(
            self.push_button_import_clicked)
        self.push_button_stop.clicked.connect(self.push_button_stop_clicked)

        self.check_box_weekly.clicked.connect(self.check_box_weekly_clicked)
        self.combo_box_tesseract_path.activated.connect(
            self.combo_box_tesseract_path_clicked)
        self.combo_box_poppler_path.activated.connect(
            self.combo_box_poppler_path_clicked)

        self.date_edit_start.dateChanged.connect(self.date_edit_start_changed)
        self.combo_box_color_a.activated.connect(
            self.combo_box_color_a_clicked)
        self.combo_box_color_b.activated.connect(
            self.combo_box_color_b_clicked)

        self.push_button_ok.clicked.connect(self.close)
        self.push_button_cancel.clicked.connect(self.close)

    def check_processes(self):
        work_processes = 0
        for index in range(self._size):
            if self._processes_pool[index].is_alive():
                work_processes += 1

            text = self._manager.progress_text_list[index]
            if text is not None and text != "":
                self._progresses_bars[index].setFormat(text)
                self._progresses_bars[index].setValue(
                    self._manager.progress_value_list[index])

            if self._manager.confuse_answer_list[
                    index] == ConfuseWindow.NeededSolution:
                if self._confuser.status == ConfuseWindow.Solved:
                    answer_index = self._confuser.index
                    self._manager.confuse_list[
                        answer_index] = self._confuser.answer
                    self._manager.confuse_answer_list[
                        answer_index] = ConfuseWindow.Solved
                    self._confuser.status = ConfuseWindow.Nothing
                elif self._confuser.status == ConfuseWindow.Nothing:
                    self._confuser.status = ConfuseWindow.Work
                    self._confuser.index = index
                    self._confuser.text_edit_confuse.setText(
                        self._manager.confuse_info[index])
                    self._confuser.text_edit_answer.setText(
                        self._manager.confuse_list[index])
                    self._confuser.set_image(
                        self._manager.confuse_file_path[index])
                    self._confuser.show()

        progress = self._max_progress - self._manager.queue.qsize(
        ) - work_processes
        self.process_bar_main.setValue(progress)

        if work_processes == 0:
            self.push_button_stop_clicked()
            return

        if not self._manager.flags["stop"]:
            self._timer.start(1000)

    def open_folder_clicked(self):
        path = QFileDialog.getExistingDirectory(self, self.tr("Select folder"))

        provider = QFileIconProvider()
        self.list_widget.clear()

        for dir_path, dir_names, file_names in os.walk(path):
            for file_name in file_names:
                if file_name.endswith(".pdf"):
                    item = QListWidgetItem()
                    item.setText(file_name[0:-4])
                    item.setData(Qt.UserRole, dir_path + os.sep + file_name)
                    item.setIcon(
                        provider.icon(QFileInfo(dir_path + os.sep +
                                                file_name)))

                    self.list_widget.addItem(item)

        self.label_find.setText(
            self.tr("Schedules: ") + str(self.list_widget.count()))

    def open_files_clicked(self):
        files = QFileDialog.getOpenFileNames(
            self, self.tr("Select files"), "",
            "PDF file (*.pdf) ;; All files (*.*)")[0]
        provider = QFileIconProvider()
        self.list_widget.clear()

        for file_path in files:
            file = QFileInfo(file_path)
            item = QListWidgetItem()
            item.setText(file.baseName())
            item.setData(Qt.UserRole, file_path)
            item.setIcon(provider.icon(file))
            self.list_widget.addItem(item)

        self.label_find.setText(
            self.tr("Schedules: ") + str(self.list_widget.count()))

    def push_button_import_clicked(self):
        self.group_box_options.setEnabled(False)
        self.group_box_font.setEnabled(False)
        self.group_box_date.setEnabled(False)
        self.group_box_subgroup.setEnabled(False)
        self.push_button_import.setEnabled(False)
        self.push_button_stop.setEnabled(True)
        self.push_button_ok.setEnabled(False)
        self.push_button_cancel.setEnabled(False)
        self.push_button_open_folder.setEnabled(False)

        for number in range(self.list_widget.count()):
            path = self.list_widget.item(number).data(Qt.UserRole)
            self._manager.queue.put(path)

        self._max_progress = self.list_widget.count()
        self.process_bar_main.setRange(0, self._max_progress)
        self.process_bar_main.setValue(0)

        self._manager.weekly = self.check_box_weekly.isChecked()
        self._manager.full = self.check_box_full.isChecked()
        self._manager.debug_image = self.check_box_debug_img.isChecked()

        self._manager.dpi = self.spin_box_dpi.value()
        self._manager.tesseract_path = self.combo_box_tesseract_path.currentData(
            Qt.UserRole)
        self._manager.poppler_path = self.combo_box_poppler_path.currentData(
            Qt.UserRole)

        self._manager.font_name = self.combo_box_font.currentText()
        self._manager.font_path = self.combo_box_font.currentData(Qt.UserRole)
        self._manager.encoding = self.combo_box_encoding.currentText()

        self._manager.start = self.date_edit_start.date().toPyDate()
        self._manager.end = self.date_edit_end.date().toPyDate()

        self._manager.color_a = self.combo_box_color_a.currentData(Qt.UserRole)
        self._manager.color_b = self.combo_box_color_b.currentData(Qt.UserRole)

        self._manager.flags["stop"] = False

        self._processes_pool.clear()
        for index in range(self._size):
            process = Process(target=import_from_pdf,
                              args=(index, self._manager),
                              daemon=True)
            process.start()
            self._processes_pool.append(process)

        self._timer.start(500)

    def push_button_stop_clicked(self):
        self.push_button_stop.setEnabled(False)

        self._manager.flags["stop"] = True

        self.group_box_options.setEnabled(True)
        self.group_box_font.setEnabled(True)
        self.group_box_date.setEnabled(True)
        self.group_box_subgroup.setEnabled(True)
        self.push_button_import.setEnabled(True)
        self.push_button_ok.setEnabled(True)
        self.push_button_cancel.setEnabled(True)
        self.push_button_open_folder.setEnabled(True)

    def check_box_weekly_clicked(self):
        if self.check_box_weekly.isChecked():
            self.group_box_date.setEnabled(True)
            self.group_box_subgroup.setEnabled(True)
        else:
            self.group_box_date.setEnabled(False)
            self.group_box_subgroup.setEnabled(False)

    def combo_box_tesseract_path_clicked(self, index):
        if index == 0:
            path = QFileDialog.getOpenFileName(self,
                                               self.tr("Select Tesseract"))[0]

            if path == "":
                self.combo_box_tesseract_path.setCurrentText(
                    self._tesseract_path_cache)
                return

            self.combo_box_tesseract_path.addItem(path, path)
            self.combo_box_tesseract_path.setCurrentText(path)
            self._tesseract_path_cache = path

    def combo_box_poppler_path_clicked(self, index):
        if index == 0:
            path = QFileDialog.getOpenFileName(self,
                                               self.tr("Select Poppler"))[0]

            if path == "":
                self.combo_box_poppler_path.setCurrentText(
                    self._poppler_path_cache)
                return

            self.combo_box_poppler_path.addItem(path, path)
            self.combo_box_poppler_path.setCurrentText(path)
            self._poppler_path_cache = path

    def add_standard_colors(self, combo_box: QComboBox) -> None:
        """
        Adds colors to the color selection menu.

        :param combo_box: Color selection menu
        """
        color_items = [(self.tr("Custom color"), QColor()),
                       (self.tr("Aqua"), QColor(0, 255, 255)),
                       (self.tr("Grey"), QColor(128, 128, 128)),
                       (self.tr("Navy"), QColor(0, 0, 192)),
                       (self.tr("Silver"), QColor(192, 192, 192)),
                       (self.tr("Black"), QColor(0, 0, 0)),
                       (self.tr("Green"), QColor(0, 128, 0)),
                       (self.tr("Olive"), QColor(192, 192, 0)),
                       (self.tr("Blue"), QColor(0, 0, 255)),
                       (self.tr("Lime"), QColor(0, 255, 0)),
                       (self.tr("Purple"), QColor(128, 0, 128)),
                       (self.tr("White"), QColor(255, 255, 255)),
                       (self.tr("Fuchsia"), QColor(255, 0, 255)),
                       (self.tr("Maroon"), QColor(128, 0, 0)),
                       (self.tr("Red"), QColor(255, 0, 0)),
                       (self.tr("Yellow"), QColor(255, 255, 0))]

        for name, data in color_items:
            combo_box.addItem(util.create_color_icon(data), name, data)

    def combo_box_color_a_clicked(self) -> None:
        """
        Slot for color selection of A subgroup.
        """
        if self.combo_box_color_a.currentIndex() == 0:
            self.custom_color_selected(self.combo_box_color_a)

    def combo_box_color_b_clicked(self) -> None:
        """
        Slot for color selection of B subgroup.
        """
        if self.combo_box_color_b.currentIndex() == 0:
            self.custom_color_selected(self.combo_box_color_b)

    def custom_color_selected(self, combo_box: QComboBox) -> None:
        """
        Slot to select the color for the desired menu.

        :param combo_box: Menu
        """
        color = QColorDialog.getColor(combo_box.currentData(), self)
        if color.isValid():
            combo_box.setItemIcon(0, util.create_color_icon(color))
            combo_box.setItemData(0, color)

    def date_edit_start_changed(self, date: QDate):
        """
        Slot for changing the end of a range of dates.

        :param date: Start of the date range
        """
        end_date = self.date_edit_end.date().addDays(
            self._date_start_cache.daysTo(date))
        self.date_edit_end.setMinimumDate(date.addDays(7))
        self.date_edit_end.setDate(end_date)
        self._date_start_cache = QDate(date)

    def closeEvent(self, event: QCloseEvent) -> None:
        for process in self._processes_pool:
            process.terminate()

        print("Processes terminate")
Example #20
0
class QStudyingView(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)

        self.time_label = QLabel("Время начала", self)
        self.time_edit = QTimeEdit()

        self.date_label = QLabel("Дата", parent=self)
        self.date_edit = QDateEdit(calendarPopup=True)

        self.subjects_label = QLabel("Темы", self)
        self.subjects_list = QListWidget(self)

        layout = QVBoxLayout()
        layout.addWidget(self.time_label)
        layout.addWidget(self.time_edit)
        layout.addWidget(self.date_label)
        layout.addWidget(self.date_edit)
        layout.addWidget(self.subjects_label)
        layout.addWidget(self.subjects_list)

        self.ok_btn = QPushButton('OK', parent=self)
        self.ok_btn.clicked.connect(self.ok)
        self.ok_cancel = QPushButton('Cancel', parent=self)
        self.ok_cancel.clicked.connect(self.cancel)

        btn_layout = QHBoxLayout()
        btn_layout.addWidget(self.ok_btn)
        btn_layout.addWidget(self.ok_cancel)

        layout.addLayout(btn_layout)
        layout.addStretch(0)

        self.setLayout(layout)

        self.presenter = StudyingPresenter(self)

    def set_subject_items(self, items: str):
        for i in items:
            item = QListWidgetItem(i)
            item.setCheckState(Qt.Unchecked)
            self.subjects_list.addItem(item)

    def set_subjects(self, subjects):
        if not subjects:
            return
        for i in subjects:
            self.subjects_list.findItems(i, Qt.MatchFixedString)[0].setData(
                Qt.CheckStateRole, Qt.Checked)

    def get_subjects(self):
        return [
            self.subjects_list.item(i).text()
            for i in range(self.subjects_list.count())
            if self.subjects_list.item(i).checkState() == Qt.Checked
        ]

    def get_time(self):
        return self.time_edit.time().toPyTime()

    def set_time(self, value):
        if value is not None:
            self.time_edit.setTime(value)

    def get_date(self):
        return self.date_edit.date().toPyDate()

    def set_date(self, value):
        if value is not None:
            self.date_edit.setTime(value)

    def ok(self):
        self.presenter.ok()

    def cancel(self):
        self.presenter.cancel()

    def get_presenter(self):
        return self.presenter
Example #21
0
class TaskAddEditor(QDialog):

    #initialize everything
    def __init__(self, dialog_name, button_name, identifier=None):
        super(TaskAddEditor, self).__init__()
        self.dialog_name = dialog_name
        self.button_name = button_name
        self.identifier = identifier

        self.setGeometry(50, 50, 300, 250)

        self.tabs = QTabWidget()
        self.tabs.tab_1 = QWidget()
        self.tabs.tab_2 = QWidget()

        self.tabs.addTab(self.tabs.tab_1, "Basic Info")
        self.tabs.addTab(self.tabs.tab_2, "Notifications")

        self.tab_1()
        self.tab_2()

        main_layout = QVBoxLayout()
        main_layout.addWidget(self.tabs)

        buttons = QHBoxLayout()

        button_ok = QPushButton(self.button_name)
        button_close = QPushButton("Cancel")
        button_ok.clicked.connect(self.dialog_button_click)
        button_close.clicked.connect(self.dialog_cancel_click)
        buttons.addWidget(button_ok)
        buttons.addWidget(button_close)

        main_layout.addLayout(buttons)

        self.setLayout(main_layout)

        self.setWindowTitle(dialog_name)
        self.exec_()

    def tab_1(self):
        # main layout
        layout = QVBoxLayout()

        task_name = QLabel('Task Name')
        due_date = QLabel('Due Date')
        due_time = QLabel('Due Time')

        if (self.button_name == "Add"):
            self.task_name_input = QLineEdit()
            self.due_date_input = QDateEdit()
            self.due_date_input.setMinimumDate(QDate.currentDate())
            self.due_time_input = QTimeEdit()

        else:

            task_info = user_tasks.get_task(self.identifier)

            self.task_name_input = QLineEdit(task_info[1])
            self.due_date_input = QDateEdit(task_info[2].date())
            self.due_date_input.setMinimumDate(QDate.currentDate())
            self.due_time_input = QTimeEdit(task_info[2].time())

        layout.addWidget(task_name)
        layout.addWidget(self.task_name_input)
        layout.addWidget(due_date)
        layout.addWidget(self.due_date_input)
        layout.addWidget(due_time)
        layout.addWidget(self.due_time_input)
        layout.addSpacing(20)

        self.tabs.tab_1.setLayout(layout)

    def tab_2(self):
        layout = QVBoxLayout()

        page_name = QLabel('Notification Settings')
        layout.addWidget(page_name)

        add_notification_area = QHBoxLayout()

        description = QLabel('Remind Me Everyday At: ')
        self.time_input = QTimeEdit()
        add_notification = QPushButton('+')
        add_notification.setFixedSize(30, 30)
        add_notification.clicked.connect(self.add_notification)

        add_notification_area.addWidget(description)
        add_notification_area.addWidget(self.time_input)
        add_notification_area.addWidget(add_notification)

        layout.addLayout(add_notification_area)

        your_notifications = QLabel('Your Notifications:')

        layout.addWidget(your_notifications)

        #create a scroll area to hold notifications
        notifications_area = QScrollArea(self)
        notifications_area.setWidgetResizable(True)
        widget = QWidget()
        notifications_area.setWidget(widget)
        self.notifications_layout = QVBoxLayout(widget)
        notifications_area.setAlignment(Qt.AlignTop)
        self.notifications_layout.setAlignment(Qt.AlignTop)

        layout.addWidget(notifications_area)

        if self.identifier is not None:

            #get a list of datetime objects
            notifications = user_tasks.get_notifications(self.identifier)

            #add notifications to the tab
            for notification_date in notifications:
                self.notifications_layout.addWidget(
                    Notification(notification_date))

        self.tabs.tab_2.setLayout(layout)

    def add_notification(self):
        # adds a notification to the layout of notifications
        for index in range(self.notifications_layout.count()):
            if ((self.notifications_layout.itemAt(
                    index).widget().notification_time) >
                (self.time_input.time().toPyTime())):
                self.notifications_layout.insertWidget(
                    index, Notification(self.time_input.time().toPyTime()))
                return
            elif (self.notifications_layout.itemAt(index).widget().
                  notification_time) == self.time_input.time().toPyTime():
                error = QMessageBox()
                error.setText("Time Already Set")
                error.exec_()
                return

        self.notifications_layout.addWidget(
            Notification(self.time_input.time().toPyTime()))

    def dialog_button_click(self):
        # when add is pressed
        if (input_error_box(self.due_time_input, self.due_date_input,
                            self.task_name_input)):

            notification_dates = []
            for notification in range(self.notifications_layout.count()):
                notification_dates.append(
                    self.notifications_layout.itemAt(
                        notification).widget().notification_time)

            if (self.button_name == 'Add'):
                print(notification_dates)
                user_tasks.add_task(
                    self.task_name_input.text(),
                    datetime.combine(self.due_date_input.date().toPyDate(),
                                     self.due_time_input.time().toPyTime()),
                    datetime.today(), str(uuid.uuid4()), notification_dates)
            else:
                print(notification_dates)
                user_tasks.edit_task(
                    self.identifier, self.task_name_input.text(),
                    datetime.combine(self.due_date_input.date().toPyDate(),
                                     self.due_time_input.time().toPyTime()),
                    notification_dates)

            self.reject()
            gui_window.refresh_tasks()

    def dialog_cancel_click(self):
        #used in the input window and closes it
        self.reject()
Example #22
0
class QSyllabusView(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)

        start_label = QLabel("Начало", self)
        self.start_edit = QDateEdit(calendarPopup=True)

        finish_label = QLabel("Конец", self)
        self.finish_edit = QDateEdit(calendarPopup=True)

        studyings_label = QLabel("Расписание", self)
        self.studyings_list = QListWidget(self)

        layout = QVBoxLayout()
        layout.addWidget(start_label)
        layout.addWidget(self.start_edit)
        layout.addWidget(finish_label)
        layout.addWidget(self.finish_edit)
        layout.addWidget(studyings_label)
        layout.addWidget(self.studyings_list)

        self.ok_btn = QPushButton('OK', parent=self)
        self.ok_btn.clicked.connect(self.ok)
        self.ok_cancel = QPushButton('Cancel', parent=self)
        self.ok_cancel.clicked.connect(self.cancel)

        btn_layout = QHBoxLayout()
        btn_layout.addWidget(self.ok_btn)
        btn_layout.addWidget(self.ok_cancel)

        layout.addLayout(btn_layout)
        layout.addStretch(0)

        self.setLayout(layout)

        self.presenter = SyllabusPresenter(self)

    def set_studying_items(self, items: str):
        for i in items:
            item = QListWidgetItem(i)
            item.setCheckState(Qt.Unchecked)
            self.studyings_list.addItem(item)

    def set_studyings(self, studyings):
        if not studyings:
            return
        for i in studyings:
            self.studyings_list.findItems(i, Qt.MatchFixedString)[0].setData(
                Qt.CheckStateRole, Qt.Checked)

    def get_studyings(self):
        return [
            self.studyings_list.item(i).text()
            for i in range(self.studyings_list.count())
            if self.studyings_list.item(i).checkState() == Qt.Checked
        ]

    def get_start(self):
        return self.start_edit.date().toPyDate()

    def set_start(self, value):
        if value is not None:
            self.start_edit.setDate(value)

    def get_finish(self):
        return self.finish_edit.date().toPyDate()

    def set_finish(self, value):
        if value is not None:
            self.finish_edit.setDate(value)

    def ok(self):
        self.presenter.ok()

    def cancel(self):
        self.presenter.cancel()

    def get_presenter(self):
        return self.presenter
Example #23
0
class YuToolsDailyPlan(QWidget):
    def __init__(self):
        super().__init__()
        ActionDao.auto_update_action()
        self.txt_content = QPlainTextEdit(self)
        self.txt_content.setGeometry(10, 10, 350, 50)

        self.rb_begin = QRadioButton(self)
        self.rb_begin.setText('Begin')
        self.rb_begin.setChecked(True)
        self.rb_begin.setGeometry(10, 70, 50, 22)

        self.de_begin = QDateEdit(self)
        self.de_begin.setDate(QDate.currentDate())
        self.de_begin.setGeometry(70, 70, 90, 22)

        self.rb_begin.clicked.connect(
            lambda: self.rb_select_date(self.de_begin))

        self.rb_deadline = QRadioButton(self)
        self.rb_deadline.setText("Deadline")
        self.rb_deadline.setGeometry(180, 70, 60, 22)

        self.de_deadline = QDateEdit(self)
        self.de_deadline.setDate(QDate.currentDate().addDays(7))
        self.de_deadline.setGeometry(250, 70, 90, 22)

        self.rb_deadline.clicked.connect(
            lambda: self.rb_select_date(self.de_deadline))

        self.calendar_select = QCalendarWidget(self)
        self.calendar_select.setGeometry(10, 100, 256, 190)
        self.calendar_select.clicked.connect(self.select_date)

        self.combo_frequency = QComboBox(self)
        self.combo_frequency.addItem(PlanFrequency.NoRepeat.name)
        self.combo_frequency.addItem(PlanFrequency.Day.name)
        self.combo_frequency.addItem(PlanFrequency.Week.name)
        self.combo_frequency.addItem(PlanFrequency.Month.name)
        self.combo_frequency.addItem(PlanFrequency.Quarter.name)
        self.combo_frequency.addItem(PlanFrequency.Year.name)
        self.combo_frequency.setGeometry(280, 100, 80, 26)

        self.sb_repeat = QSpinBox(self)
        self.sb_repeat.setMinimum(1)
        self.sb_repeat.setGeometry(280, 130, 80, 26)

        self.cb_include = QCheckBox(self)
        self.cb_include.setText("Include Begin")
        self.cb_include.setChecked(True)
        self.cb_include.setGeometry(280, 160, 80, 26)

        self.combo_importance = QComboBox(self)
        self.combo_importance.addItem('Important')
        self.combo_importance.addItem('Unimportant')
        self.combo_importance.setGeometry(280, 190, 80, 26)

        self.combo_urgency = QComboBox(self)
        self.combo_urgency.addItem('Urgent')
        self.combo_urgency.addItem('Non-Urgent')
        self.combo_urgency.setGeometry(280, 220, 80, 26)

        self.btn_save = QPushButton(self)
        self.btn_save.setGeometry(280, 260, 80, 26)
        self.btn_save.setText("Save")
        self.btn_save.clicked.connect(self.save_plan)

        self.tb_plan = QTableView(self)
        self.tb_plan.horizontalHeader().setStretchLastSection(True)
        self.tb_plan.horizontalHeader().setSectionResizeMode(
            QHeaderView.Custom)
        self.tb_plan.verticalHeader().hide()
        self.tb_plan.setGeometry(370, 10, 421, 281)

        self.line_importance = QFrame(self)
        self.line_importance.setGeometry(390, 295, 20, 435)
        self.line_importance.setFrameShape(QFrame.VLine)
        self.line_importance.setFrameShadow(QFrame.Sunken)

        self.line_urgency = QFrame(self)
        self.line_urgency.setGeometry(5, 480, 791, 16)
        self.line_urgency.setFrameShape(QFrame.HLine)
        self.line_urgency.setFrameShadow(QFrame.Sunken)

        self.combo_ac_list_filter = QComboBox(self)
        self.combo_ac_list_filter.addItem('Wait')
        self.combo_ac_list_filter.addItem('Going')
        self.combo_ac_list_filter.addItem('Done')
        self.combo_ac_list_filter.addItem('Cancel')
        self.combo_ac_list_filter.addItem('Expire')
        self.combo_ac_list_filter.addItem('Will')
        self.combo_ac_list_filter.addItem('All')
        self.combo_ac_list_filter.setCurrentIndex(1)
        self.combo_ac_list_filter.setGeometry(375, 478, 50, 20)
        self.combo_ac_list_filter.currentIndexChanged.connect(
            self.change_tb_ac_list)

        self.tb_ac_first = QTableView(self)
        self.tb_ac_first.horizontalHeader().setStretchLastSection(True)
        self.tb_ac_first.horizontalHeader().setSectionResizeMode(
            QHeaderView.Custom)
        self.tb_ac_first.verticalHeader().hide()
        self.tb_ac_first.setItemDelegateForColumn(
            3, ActionStatusDelegate(self.tb_ac_first))
        self.tb_ac_first.setGeometry(410, 300, 381, 178)

        self.tb_ac_second = QTableView(self)
        self.tb_ac_second.horizontalHeader().setStretchLastSection(True)
        self.tb_ac_second.horizontalHeader().setSectionResizeMode(
            QHeaderView.Custom)
        self.tb_ac_second.verticalHeader().hide()
        self.tb_ac_second.setItemDelegateForColumn(
            3, ActionStatusDelegate(self.tb_ac_second))
        self.tb_ac_second.setGeometry(10, 300, 381, 178)

        self.tb_ac_third = QTableView(self)
        self.tb_ac_third.horizontalHeader().setStretchLastSection(True)
        self.tb_ac_third.horizontalHeader().setSectionResizeMode(
            QHeaderView.Custom)
        self.tb_ac_third.verticalHeader().hide()
        self.tb_ac_third.setItemDelegateForColumn(
            3, ActionStatusDelegate(self.tb_ac_third))
        self.tb_ac_third.setGeometry(10, 498, 381, 178)

        self.tb_ac_fourth = QTableView(self)
        self.tb_ac_fourth.horizontalHeader().setStretchLastSection(True)
        self.tb_ac_fourth.horizontalHeader().setSectionResizeMode(
            QHeaderView.Custom)
        self.tb_ac_fourth.verticalHeader().hide()
        self.tb_ac_fourth.setItemDelegateForColumn(
            3, ActionStatusDelegate(self.tb_ac_fourth))
        self.tb_ac_fourth.setGeometry(410, 498, 381, 178)

        self.tb_acs = {
            1: self.tb_ac_first,
            2: self.tb_ac_second,
            3: self.tb_ac_third,
            4: self.tb_ac_fourth
        }

        self.refresh_tb_plan()

        for index in range(1, 5):
            self.refresh_tb_action(index)

    def rb_select_date(self, de_target):
        self.calendar_select.setSelectedDate(de_target.date())

    def select_date(self):
        date = self.calendar_select.selectedDate()
        if self.rb_begin.isChecked():
            self.de_begin.setDate(date)
        elif self.rb_deadline.isChecked():
            self.de_deadline.setDate(date)

    def save_plan(self):
        code, data = self.valid_check()
        if code == -1:
            QMessageBox.critical(self, 'Error', data)
            return

        code2, actions = self.generate_actions(data)
        if code2 == -1:
            QMessageBox.critical(self, 'Error', actions)
            return
        plan_id = PlanDao.add_plan(data)
        ActionDao.add_actions(actions, plan_id)

        self.txt_content.clear()

        self.refresh_tb_plan()
        self.refresh_tb_action(tb_index=code)

    def valid_check(self):
        content = self.txt_content.toPlainText().replace('\n', '.')
        if content.strip(' ').strip('.').strip(' ') == '':
            return -1, 'Content must be a normal string!'
        begin = self.de_begin.date()
        deadline = self.de_deadline.date()
        now = QDate.currentDate()
        diff_begin = now.daysTo(begin)
        diff_deadline = now.daysTo(deadline)
        if diff_begin < 0 or diff_deadline < 0 or diff_deadline < diff_begin:
            return -1, 'Deadline date must be farther than begin date and both of them must be farther than Now'
        begin_date = datetime.date(begin.year(), begin.month(), begin.day())
        deadline = datetime.date(deadline.year(), deadline.month(),
                                 deadline.day())
        frequency = self.combo_frequency.currentText()
        repeat = self.sb_repeat.value()
        importance = self.combo_importance.currentText()
        degree_importance = False if importance.lower().startswith(
            'un') else True
        urgent = self.combo_urgency.currentText()
        degree_urgent = False if urgent.lower().startswith('non') else True
        plan = Plan(content=content,
                    begin_date=begin_date,
                    deadline=deadline,
                    frequency=PlanFrequency[frequency],
                    repeat=repeat,
                    degree_importance=degree_importance,
                    degree_urgency=degree_urgent)
        if degree_importance and degree_urgent:
            code = 1
        elif degree_importance and not degree_urgent:
            code = 2
        elif not degree_importance and not degree_urgent:
            code = 3
        elif not degree_importance and degree_urgent:
            code = 4
        return code, plan

    def generate_actions(self, plan):
        action_list = []
        begin = QDate(plan.begin_date)
        deadline = QDate(plan.deadline)

        include = self.cb_include.isChecked()
        if plan.frequency == PlanFrequency.NoRepeat:
            days = begin.daysTo(deadline)
            if not include:
                if days == 0:
                    return -1, 'There is not time to complete the plan'
            for i in range(plan.repeat):
                action = Action(content=plan.content,
                                begin_date=plan.begin_date,
                                deadline=plan.deadline,
                                degree_importance=plan.degree_importance,
                                degree_urgency=plan.degree_urgency,
                                status=1)
                action_list.append(action)
        elif plan.frequency == PlanFrequency.Day:
            days = begin.daysTo(deadline)
            if not include:
                if days == 0:
                    return -1, 'There is not time to complete the plan'
            for day in range(days + 1):
                if not include and day == 0:
                    continue
                begin_date = begin.addDays(day)
                begin_date = datetime.date(begin_date.year(),
                                           begin_date.month(),
                                           begin_date.day())
                for i in range(plan.repeat):
                    action = Action(content=plan.content,
                                    begin_date=begin_date,
                                    deadline=begin_date,
                                    degree_importance=plan.degree_importance,
                                    degree_urgency=plan.degree_urgency,
                                    status=1)
                    action_list.append(action)
        elif plan.frequency == PlanFrequency.Week:
            begin_week, begin_year = begin.weekNumber()
            begin_day_of_week = begin.dayOfWeek()
            deadline_week, deadline_year = deadline.weekNumber()
            weeks = deadline_week + (deadline_year -
                                     begin_year) * 52 - begin_week
            if not include:
                if weeks == 0:
                    return -1, 'There is not time to complete the plan'
            current_week_deadline = begin.addDays(7 - begin_day_of_week)
            for week in range(weeks + 1):
                if not include and week == 0:
                    continue
                current_week_deadline = current_week_deadline.addDays(7 * week)
                current_week_begin = current_week_deadline.addDays(-6)
                if week == 0:
                    begin_date = plan.begin_date
                    if week == weeks:
                        deadline = plan.deadline
                    else:
                        deadline = datetime.date(current_week_deadline.year(),
                                                 current_week_deadline.month(),
                                                 current_week_deadline.day())
                elif week == weeks:
                    begin_date = datetime.date(current_week_begin.year(),
                                               current_week_begin.month(),
                                               current_week_begin.day())
                    deadline = plan.deadline
                else:
                    begin_date = datetime.date(current_week_begin.year(),
                                               current_week_begin.month(),
                                               current_week_begin.day())
                    deadline = datetime.date(current_week_deadline.year(),
                                             current_week_deadline.month(),
                                             current_week_deadline.day())
                for i in range(plan.repeat):
                    action = Action(content=plan.content,
                                    begin_date=begin_date,
                                    deadline=deadline,
                                    degree_importance=plan.degree_importance,
                                    degree_urgency=plan.degree_urgency,
                                    status=1)
                    action_list.append(action)
        elif plan.frequency == PlanFrequency.Month:
            begin_year = begin.year()
            deadline_year = deadline.year()
            years = deadline_year - begin_year
            begin_month = begin.month()
            deadline_month = deadline.month()
            months = deadline_month + 12 * years - begin_month
            if not include:
                if months == 0:
                    return -1, 'There is not time to complete the plan'
            current_year = begin_year
            for month in range(months + 1):
                if not include and month == 0:
                    continue
                current_month = begin_month + month
                if current_month > 12:
                    current_month -= 12
                    current_year += 1
                if month == 0:
                    begin_date = plan.begin_date
                    if month == months:
                        deadline = plan.deadline
                    else:
                        deadline = datetime.date(current_year, current_month,
                                                 begin.daysInMonth())
                elif month == months:
                    begin_date = datetime.date(current_year, current_month, 1)
                    deadline = plan.deadline
                else:
                    begin_date = datetime.date(current_year, current_month, 1)
                    deadline = datetime.date(current_year, current_month, 1)
                    deadline = datetime.date(
                        current_year, current_month,
                        QDate(deadline.year(), deadline.month(),
                              deadline.day()).daysInMonth())
                for i in range(plan.repeat):
                    action = Action(content=plan.content,
                                    begin_date=begin_date,
                                    deadline=deadline,
                                    degree_importance=plan.degree_importance,
                                    degree_urgency=plan.degree_urgency,
                                    status=1)
                    action_list.append(action)
        elif plan.frequency == PlanFrequency.Quarter:
            begin_year = begin.year()
            deadline_year = deadline.year()
            years = deadline_year - begin_year
            begin_month = begin.month()
            deadline_month = deadline.month()
            begin_quarter = (begin_month + 2) / 3
            deadline_quarter = (deadline_month + 2) / 3
            quarters = deadline_quarter + years * 4 - begin_quarter
            if not include:
                if quarters == 0:
                    return -1, 'There is not time to complete the plan'
            current_year = begin_year
            for quarter in range(quarters + 1):
                if not include and quarter == 0:
                    continue
                current_quarter = begin_quarter + quarter
                if current_quarter > 4:
                    current_quarter -= 4
                    current_year += 1
                begin_month = (current_quarter - 1) * 3 + 1
                deadline_month = begin_month + 2
                if quarter == 0:
                    begin_date = plan.begin_date
                    if quarter == quarters:
                        deadline = plan.deadline
                    else:
                        deadline = datetime.date(
                            current_year, deadline_month,
                            (30 if deadline_month == 4 else 31))
                elif quarter == quarters:
                    begin_date = datetime.date(current_year, begin_month, 1)
                    deadline = plan.deadline
                else:
                    begin_date = datetime.date(current_year, begin_month, 1)
                    deadline = datetime.date(
                        current_year, deadline_month,
                        (30 if deadline_month == 4 else 31))
                for i in range(plan.repeat):
                    action = Action(content=plan.content,
                                    begin_date=begin_date,
                                    deadline=deadline,
                                    degree_importance=plan.degree_importance,
                                    degree_urgency=plan.degree_urgency,
                                    status=1)
                    action_list.append(action)
        elif plan.frequency == PlanFrequency.Year:
            begin_year = begin.year()
            deadline_year = deadline.year()
            years = deadline_year - begin_year
            if not include:
                if years == 0:
                    return -1, 'There is not time to complete the plan'
            for year in range(years + 1):
                if not include and year == 0:
                    continue
                current_year = begin_year + year
                if year == 0:
                    begin_date = plan.begin_date
                    if year == years:
                        deadline = plan.deadline
                    else:
                        deadline = datetime.date(current_year, 12, 31)
                elif year == years:
                    begin_date = datetime.date(current_year, 1, 1)
                    deadline = plan.deadline
                else:
                    begin_date = datetime.date(current_year, 1, 1)
                    deadline = datetime.date(current_year, 12, 31)
                for i in range(plan.repeat):
                    action = Action(content=plan.content,
                                    begin_date=begin_date,
                                    deadline=deadline,
                                    degree_importance=plan.degree_importance,
                                    degree_urgency=plan.degree_urgency,
                                    status=1)
                    action_list.append(action)
        return 0, action_list

    def change_tb_ac_list(self):
        for index in range(1, 5):
            self.refresh_tb_action(index)

    def refresh_tb_plan(self):
        plans = PlanDao.query_plans()
        model = QStandardItemModel(len(plans), 3)
        model.setHorizontalHeaderLabels(['Content', 'Frequency', 'Flag'])
        row_index = 0
        for plan in plans:
            qsi_content = QStandardItem(plan.content)
            qsi_content.setEditable(False)
            qsi_frequency = QStandardItem(plan.frequency.name)
            qsi_frequency.setEditable(False)
            qsi_flag = QStandardItem('{},{}'.format(
                'Important' if plan.degree_importance else 'Unimportant',
                'Urgency' if plan.degree_urgency else 'Non-urgency'))
            qsi_flag.setEditable(False)
            model.setItem(row_index, 0, qsi_content)
            model.setItem(row_index, 1, qsi_frequency)
            model.setItem(row_index, 2, qsi_flag)
            row_index += 1
        self.tb_plan.setModel(model)
        self.tb_plan.setColumnWidth(0, 220)
        self.tb_plan.setColumnWidth(1, 70)
        self.tb_plan.setColumnWidth(2, 100)

    def refresh_tb_action(self, tb_index):
        tb_action = self.tb_acs[tb_index]
        ac_list_filter = self.combo_ac_list_filter.currentIndex()
        actions = ActionDao.query_actions(tb_index, ac_list_filter)
        model = QStandardItemModel(len(actions), 3)
        model.setHorizontalHeaderLabels(
            ['Content', 'Begin', 'Deadline', 'Status'])
        row_index = 0
        for action in actions:
            qsi_content = QStandardItem(action.content)
            qsi_content.setEditable(False)
            qsi_begin_date = QStandardItem(
                action.begin_date.strftime("%Y/%m/%d"))
            qsi_content.setEditable(False)
            qsi_deadline = QStandardItem(action.deadline.strftime("%Y/%m/%d"))
            qsi_deadline.setEditable(False)
            qsi_status = QStandardItem()
            qsi_status.setData({'id': action.id, 'status': action.status})
            qsi_status.setEditable(False)
            model.setItem(row_index, 0, qsi_content)
            model.setItem(row_index, 1, qsi_begin_date)
            model.setItem(row_index, 2, qsi_deadline)
            model.setItem(row_index, 3, qsi_status)
            row_index += 1
        tb_action.setModel(model)
        tb_action.setColumnWidth(0, 150)
        tb_action.setColumnWidth(1, 75)
        tb_action.setColumnWidth(2, 75)
        tb_action.setColumnWidth(3, 40)

    def change_status(self, tb_action, act_id, status):
        if status == 0:
            QMessageBox.information(self, 'Tip', 'Please wait for beginning')
        elif status == 1:
            menu = QMenu(tb_action)
            done_act = menu.addAction(QIcon('icons/daily_plan/done.png'),
                                      'Done')
            cancel_act = menu.addAction(QIcon('icons/daily_plan/cancel.png'),
                                        'Cancel')
            act = menu.exec_(
                tb_action.mapToGlobal(
                    QPoint(self.sender().x(),
                           self.sender().y() + 10)))
            refresh = False
            if act == done_act:
                ActionDao.update_action(act_id, 2)
                refresh = True
            elif act == cancel_act:
                ActionDao.update_action(act_id, 3)
                refresh = True
            if refresh:
                self.refresh_tb_action(
                    list(self.tb_acs.keys())[list(
                        self.tb_acs.values()).index(tb_action)])
        elif status == 2:
            QMessageBox.information(
                self, 'Tip', 'You are good that had completed the task')
        elif status == 3:
            QMessageBox.information(self, 'Tip',
                                    'It is sadly you had canceled this task')
        elif status == 4:
            QMessageBox.information(
                self, 'Tip',
                'It is sorry that this task had expired and you cannot operate it'
            )
Example #24
0
class Registration(QDialog):

    def __init__(self):
        super(Registration, self).__init__()
        self.createFormGroupBox()

        buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
        buttonBox.accepted.connect(self.clickSearch)
        #buttonBox.accepted.connect(self.close)
        buttonBox.rejected.connect(self.reject)

        mainLayout = QVBoxLayout()
        mainLayout.addWidget(self.formGroupBox)
        mainLayout.addWidget(buttonBox)
        self.setLayout(mainLayout)

        self.setWindowTitle("Registration")

    def createFormGroupBox(self):
        self.formGroupBox = QGroupBox("Registration Form")
        layout = QFormLayout(self)

        self.email = QLineEdit()
        layout.addRow(QLabel("*Email:"), self.email)
        self.confirmEmail = QLineEdit()
        layout.addRow(QLabel("*Confirm Email:"), self.confirmEmail)
        self.password = QLineEdit()
        self.password.setEchoMode(QLineEdit.Password)
        self.confirmPassword = QLineEdit()
        self.confirmPassword.setEchoMode(QLineEdit.Password)
        layout.addRow(QLabel("*Password:"******"*Confirm Password:"******"*First Name:"), self.firstName)
        self.lastName = QLineEdit()
        layout.addRow(QLabel("*Last Name:"), self.lastName)
        self.address1 = QLineEdit()
        layout.addRow(QLabel("*Address 1:"), self.address1)
        self.address2 = QLineEdit()
        layout.addRow(QLabel("Address 2:"), self.address2)
        self.city = QLineEdit()
        layout.addRow(QLabel("*City:"), self.city)
        self.state = QLineEdit()
        layout.addRow(QLabel("*State:"), self.state)
        self.postalCode = QLineEdit()
        layout.addRow(QLabel("*Postal Code:"), self.postalCode)

        self.combo = QComboBox(self)
        self.combo.addItem("AFG")
        self.combo.addItem("ALB")
        self.combo.addItem("DZA")
        self.combo.addItem("ASM")
        self.combo.addItem("AND")
        self.combo.addItem("AGO")
        self.combo.addItem("AIA")
        self.combo.addItem("ATA")
        self.combo.addItem("ATG")
        self.combo.addItem("ARG")
        self.combo.addItem("ARM")
        self.combo.addItem("ABW")
        self.combo.addItem("AUS")
        self.combo.addItem("AUT")
        self.combo.addItem("AZE")
        self.combo.addItem("BHS")
        self.combo.addItem("BHR")
        self.combo.addItem("BGD")
        self.combo.addItem("BRB")
        self.combo.addItem("BLR")
        self.combo.addItem("BEL")
        self.combo.addItem("BLZ")
        self.combo.addItem("BEN")
        self.combo.addItem("BMU")
        self.combo.addItem("BTN")
        self.combo.addItem("BOL")
        self.combo.addItem("BES")
        self.combo.addItem("BIH")
        self.combo.addItem("BWA")
        self.combo.addItem("BVT")
        self.combo.addItem("BRA")
        self.combo.addItem("IOT")
        self.combo.addItem("BRN")
        self.combo.addItem("BGR")
        self.combo.addItem("BFA")
        self.combo.addItem("BDI")
        self.combo.addItem("KHM")
        self.combo.addItem("CMR")
        self.combo.addItem("CAN")
        self.combo.addItem("CPV")
        self.combo.addItem("CYM")
        self.combo.addItem("CAF")
        self.combo.addItem("TCD")
        self.combo.addItem("CHL")
        self.combo.addItem("CHN")
        self.combo.addItem("CXR")
        self.combo.addItem("CCK")
        self.combo.addItem("COL")
        self.combo.addItem("COM")
        self.combo.addItem("COG")
        self.combo.addItem("COD")
        self.combo.addItem("C*K")
        self.combo.addItem("CRI")
        self.combo.addItem("HRV")
        self.combo.addItem("CUB")
        self.combo.addItem("CUW")
        self.combo.addItem("CYP")
        self.combo.addItem("CZE")
        self.combo.addItem("CIV")
        self.combo.addItem("DNK")
        self.combo.addItem("DJI")
        self.combo.addItem("DMA")
        self.combo.addItem("DOM")
        self.combo.addItem("ECU")
        self.combo.addItem("EGY")
        self.combo.addItem("SLV")
        self.combo.addItem("GNQ")
        self.combo.addItem("ERI")
        self.combo.addItem("EST")
        self.combo.addItem("ETH")
        self.combo.addItem("FLK")
        self.combo.addItem("FRO")
        self.combo.addItem("FJI")
        self.combo.addItem("FIN")
        self.combo.addItem("FRA")
        self.combo.addItem("GUF")
        self.combo.addItem("PYF")
        self.combo.addItem("ATF")
        self.combo.addItem("GAB")
        self.combo.addItem("GMB")
        self.combo.addItem("GEO")
        self.combo.addItem("DEU")
        self.combo.addItem("GHA")
        self.combo.addItem("GIB")
        self.combo.addItem("GRC")
        self.combo.addItem("GRL")
        self.combo.addItem("GRD")
        self.combo.addItem("GLP")
        self.combo.addItem("GUM")
        self.combo.addItem("GTM")
        self.combo.addItem("GGY")
        self.combo.addItem("GIN")
        self.combo.addItem("GNB")
        self.combo.addItem("GUY")
        self.combo.addItem("HTI")
        self.combo.addItem("HMD")
        self.combo.addItem("VAT")
        self.combo.addItem("HND")
        self.combo.addItem("HKG")
        self.combo.addItem("HUN")
        self.combo.addItem("ISL")
        self.combo.addItem("IND")
        self.combo.addItem("IDN")
        self.combo.addItem("IRN")
        self.combo.addItem("IRQ")
        self.combo.addItem("IRL")
        self.combo.addItem("IMN")
        self.combo.addItem("ISR")
        self.combo.addItem("ITA")
        self.combo.addItem("JAM")
        self.combo.addItem("JPN")
        self.combo.addItem("JEY")
        self.combo.addItem("JOR")
        self.combo.addItem("KAZ")
        self.combo.addItem("KEN")
        self.combo.addItem("KIR")
        self.combo.addItem("PRK")
        self.combo.addItem("KOR")
        self.combo.addItem("KWT")
        self.combo.addItem("KGZ")
        self.combo.addItem("LAO")
        self.combo.addItem("LVA")
        self.combo.addItem("LBN")
        self.combo.addItem("LSO")
        self.combo.addItem("LBR")
        self.combo.addItem("LBY")
        self.combo.addItem("LIE")
        self.combo.addItem("LTU")
        self.combo.addItem("LUX")
        self.combo.addItem("MAC")
        self.combo.addItem("MKD")
        self.combo.addItem("MDG")
        self.combo.addItem("MWI")
        self.combo.addItem("MYS")
        self.combo.addItem("MDV")
        self.combo.addItem("MLI")
        self.combo.addItem("MLT")
        self.combo.addItem("MHL")
        self.combo.addItem("MTQ")
        self.combo.addItem("MRT")
        self.combo.addItem("MUS")
        self.combo.addItem("MYT")
        self.combo.addItem("MEX")
        self.combo.addItem("FSM")
        self.combo.addItem("MDA")
        self.combo.addItem("MCO")
        self.combo.addItem("MNG")
        self.combo.addItem("MNE")
        self.combo.addItem("MSR")
        self.combo.addItem("MAR")
        self.combo.addItem("MOZ")
        self.combo.addItem("MMR")
        self.combo.addItem("NAM")
        self.combo.addItem("NRU")
        self.combo.addItem("NPL")
        self.combo.addItem("NLD")
        self.combo.addItem("NCL")
        self.combo.addItem("NZL")
        self.combo.addItem("NIC")
        self.combo.addItem("NER")
        self.combo.addItem("NGA")
        self.combo.addItem("NIU")
        self.combo.addItem("NFK")
        self.combo.addItem("MNP")
        self.combo.addItem("NOR")
        self.combo.addItem("OMN")
        self.combo.addItem("PAK")
        self.combo.addItem("PLW")
        self.combo.addItem("PSE")
        self.combo.addItem("PAN")
        self.combo.addItem("PNG")
        self.combo.addItem("PRY")
        self.combo.addItem("PER")
        self.combo.addItem("PHL")
        self.combo.addItem("PCN")
        self.combo.addItem("POL")
        self.combo.addItem("PRT")
        self.combo.addItem("PRI")
        self.combo.addItem("QAT")
        self.combo.addItem("ROU")
        self.combo.addItem("RUS")
        self.combo.addItem("RWA")
        self.combo.addItem("REU")
        self.combo.addItem("BLM")
        self.combo.addItem("SHN")
        self.combo.addItem("KNA")
        self.combo.addItem("LCA")
        self.combo.addItem("MAF")
        self.combo.addItem("SPM")
        self.combo.addItem("VCT")
        self.combo.addItem("WSM")
        self.combo.addItem("SMR")
        self.combo.addItem("STP")
        self.combo.addItem("SAU")
        self.combo.addItem("SEN")
        self.combo.addItem("SRB")
        self.combo.addItem("SYC")
        self.combo.addItem("SLE")
        self.combo.addItem("SGP")
        self.combo.addItem("SXM")
        self.combo.addItem("SVK")
        self.combo.addItem("SVN")
        self.combo.addItem("SLB")
        self.combo.addItem("SOM")
        self.combo.addItem("ZAF")
        self.combo.addItem("SGS")
        self.combo.addItem("SSD")
        self.combo.addItem("ESP")
        self.combo.addItem("LKA")
        self.combo.addItem("SDN")
        self.combo.addItem("SUR")
        self.combo.addItem("SJM")
        self.combo.addItem("SWZ")
        self.combo.addItem("SWE")
        self.combo.addItem("CHE")
        self.combo.addItem("SYR")
        self.combo.addItem("TWN")
        self.combo.addItem("TJK")
        self.combo.addItem("TZA")
        self.combo.addItem("THA")
        self.combo.addItem("TLS")
        self.combo.addItem("TGO")
        self.combo.addItem("TKL")
        self.combo.addItem("TON")
        self.combo.addItem("TTO")
        self.combo.addItem("TUN")
        self.combo.addItem("TUR")
        self.combo.addItem("TKM")
        self.combo.addItem("TCA")
        self.combo.addItem("TUV")
        self.combo.addItem("UGA")
        self.combo.addItem("UKR")
        self.combo.addItem("ARE")
        self.combo.addItem("GBR")
        self.combo.addItem("USA")
        self.combo.addItem("UMI")
        self.combo.addItem("URY")
        self.combo.addItem("UZB")
        self.combo.addItem("VUT")
        self.combo.addItem("VEN")
        self.combo.addItem("VNM")
        self.combo.addItem("VGB")
        self.combo.addItem("VIR")
        self.combo.addItem("WLF")
        self.combo.addItem("ESH")
        self.combo.addItem("YEM")
        self.combo.addItem("ZMB")
        self.combo.addItem("ZWE")
        layout.addRow(QLabel("*Country:"),self.combo)

        self.ccNum = QLineEdit()
        layout.addRow(QLabel("*Credit Card#:"), self.ccNum)

        default = QDate.currentDate().toPyDate()
        self.ccExpiry = QDateEdit(QDate(default.year, default.month, default.day))
        layout.addRow(QLabel("*CC Expiry:"), self.ccExpiry)

        default = QDate.currentDate().toPyDate()
        self.birthdate = QDateEdit(QDate(default.year, default.month, default.day))
        layout.addRow(QLabel("*Birth Date:"), self.birthdate)

        self.formGroupBox.setLayout(layout)

    def clickSearch(self):

        ccMonth = str(self.ccExpiry.date().month()).zfill(2)
        ccDay = str(self.ccExpiry.date().day()).zfill(2)
        ccYear = str(self.ccExpiry.date().year())
        ccDate = ccYear + ccMonth + ccDay
        #print(ccDate)

        bMonth = str(self.birthdate.date().month()).zfill(2)
        bDay = str(self.birthdate.date().day()).zfill(2)
        bYear = str(self.birthdate.date().year())
        bDate = bYear + bMonth + bDay

        if (self.email.text() == '' or self.password.text() == '' or self.firstName.text() == '' or self.lastName.text() == ''
            or self.address1.text() == '' or self.city.text() == '' or self.state.text() =='' or self.postalCode.text() == ''
            or self.combo.currentText() == '' or self.ccNum.text() == ''):

            QMessageBox.warning(self,
                    'Error', "Please fill out all required lines.")

        elif (self.email.text() != self.confirmEmail.text()):
            QMessageBox.warning(self,
                    'Error', "Emails do not match.")

        elif (self.password.text() != self.confirmPassword.text()):
            QMessageBox.warning(self,
                    'Error', "Passwords do not match.")

        else:
            self.hide()
            self._new_window = Search()
            self._new_window.show()

            userSQL = "insert into user(email,password,first_name,last_name) values(%s, %s, %s, %s);"
            cursor.execute(userSQL, (self.email.text(),self.password.text(), self.firstName.text(), self.lastName.text()))

            userIDSQL = "select user_id from user where email = %s and password = %s;"
            cursor.execute(userIDSQL, (self.email.text(), self.password.text()))
            dict1 = cursor.fetchall()[0]
            list1 = list(dict1.values())
            global userID
            userID = (list(dict1.values()))[0]


            addressSQL = "insert into address(line1,line2,city,state,post_code,country) values(%s,%s,%s,%s,%s,%s);"
            cursor.execute(addressSQL, (self.address1.text(), self.address2.text(), self.city.text(), self.state.text(), self.postalCode.text(), self.combo.currentText()))

            addressIDSQL = "select address_id from address where line1=%s and line2=%s and city=%s and state=%s and post_code=%s and country=%s;"
            cursor.execute(addressIDSQL, (self.address1.text(), self.address2.text(), self.city.text(), self.state.text(), self.postalCode.text(), self.combo.currentText()))
            dict2 = cursor.fetchall()[0]
            list2 = list(dict2.values())
            addressID = (list(dict2.values()))[0]


            customerSQL = "insert into customer(user_id, address_id, birthdate, credit_card_no, credit_card_expiry) values(%s, %s, %s, %s, %s);"
            cursor.execute(customerSQL, (str(userID), str(addressID), bDate, self.ccNum.text(),ccDate))
            connection.commit()
class AddTransDialog(QDialog):
    def __init__(self, parent=None, title='', item=None):
        super(AddTransDialog, self).__init__(parent)
        self.setFixedWidth(300)
        self.setWindowTitle(title)
        self.setWindowIcon(Icon('money.png'))
        self.showMessage = self.parent().mainWindow.showMessage
        self.createLayout(item)

    def createLayout(self, item):
        layout = QFormLayout()

        types = QGroupBox("Tipo", self)
        self.expense = QRadioButton("Despesa")
        self.expense.setChecked(True)
        self.expense.toggled.connect(lambda: changePrefix(self))
        self.income = QRadioButton("Receita")
        self.income.toggled.connect(lambda: changePrefix(self))

        hbox = QHBoxLayout()
        hbox.addWidget(self.expense)
        hbox.addWidget(self.income)
        types.setLayout(hbox)
        layout.addRow(types)

        self.date = QDateEdit()
        self.date.setDate(QDate.currentDate())
        self.date.setCalendarPopup(True)
        self.date.setFocusPolicy(Qt.StrongFocus)
        layout.addRow("Data", self.date)

        self.description = QLineEdit()
        self.description.setMaxLength(40)
        completer = QCompleter(DATABASE.getDescriptions())
        completer.setCaseSensitivity(Qt.CaseInsensitive)
        completer.setCompletionMode(QCompleter.InlineCompletion)
        self.description.setCompleter(completer)
        layout.addRow("Descrição", self.description)

        self.category = QComboBox()
        self.category.setEditable(True)
        self.category.completer().setCompletionMode(QCompleter.PopupCompletion)
        categories = DATABASE.getCategories()
        if not categories:
            DATABASE.populateCategories()
            categories = DATABASE.getCategories()
        for cat in categories:
            self.category.addItem(cat)
        layout.addRow("Categoria", self.category)

        self.account = QComboBox()
        self.account.setEditable(False)
        accounts = DATABASE.getAccounts()
        for acc in accounts:
            self.account.addItem(acc)
        layout.addRow("Conta", self.account)

        self.value = QDoubleSpinBox()
        self.value.setDecimals(2)
        self.value.setSingleStep(100)
        self.value.setRange(0, 1000000000)
        layout.addRow("Valor", self.value)

        divBox = QHBoxLayout()
        self.initial = QSpinBox()
        self.initial.setRange(1, 1000)
        label = QLabel(" de ")
        label.setAlignment(Qt.AlignCenter)
        self.subdivision = QSpinBox()
        self.subdivision.setRange(1, 1000)
        self.subdivision.setSuffix(" parcelas")
        self.subdivision.setAlignment(Qt.AlignCenter)
        divBox.addWidget(self.initial)
        divBox.addWidget(label)
        divBox.addWidget(self.subdivision)
        layout.addRow("Parcelas", divBox)

        sublayout = QHBoxLayout()
        self.ok = QPushButton("Adicionar")
        self.ok.clicked.connect(self.accept)
        if not accounts:
            self.ok.setEnabled(False)

        cancel = QPushButton("Cancelar")
        cancel.clicked.connect(self.reject)
        sublayout.addWidget(self.ok)
        sublayout.addWidget(cancel)
        layout.addRow(sublayout)

        if item:
            info = DATABASE.getTransactions(ident=item.ident)
            if info[-1] >= 0:
                self.income.setChecked(True)
                self.value.setPrefix("R$ ")
            else:
                self.expense.setChecked(True)
                self.value.setPrefix("R$ -")
            self.date.setDate(QDate(info[3], info[2], info[1]))
            self.description.setText(info[4])
            idx = self.category.findText(info[5], Qt.MatchExactly)
            self.category.setCurrentIndex(idx)
            idx = self.account.findText(info[7], Qt.MatchExactly)
            self.account.setCurrentIndex(idx)
            self.value.setValue(abs(info[8]))
            self.ok.setText("Editar")
            self.initial.setEnabled(False)
            label.setEnabled(False)
            self.subdivision.setEnabled(False)

        self.setLayout(layout)

    def process(self, item):
        if DATABASE.getCategories(self.category.currentText()):
            self.insertTransaction(item)
            self.parent().mainWindow.loadInfo()
        else:
            message = QMessageBox(
                QMessageBox.Warning, "Categoria Inexistente",
                "Deseja adicionar a categoria %s" %
                self.category.currentText(),
                QMessageBox.Ok | QMessageBox.Cancel)
            resultMsg = message.exec_()
            if resultMsg == QMessageBox.Ok:
                self.insertTransaction(item, True)
                self.parent().mainWindow.loadInfo()

    def insertTransaction(self, item, newCategory=False):
        if self.expense.isChecked():
            value = -self.value.value()
        else:
            value = self.value.value()

        if not item:
            value = value / self.subdivision.value()
            count = 0
            for i in range(self.initial.value(), self.subdivision.value() + 1):
                date = self.date.date().addMonths(count)
                transaction = [date.day(), date.month(), date.year()]
                if self.subdivision.value() > 1:
                    transaction += [
                        self.description.text() + " (%d/%d)" %
                        (i, self.subdivision.value())
                    ]
                else:
                    transaction += [self.description.text()]
                if newCategory:
                    transaction += [self.category.currentText(), None]
                else:
                    transaction += [
                        self.category.currentText(),
                        DATABASE.getCategories(self.category.currentText(),
                                               infos=True)[1]
                    ]
                transaction += [self.account.currentText(), value]
                DATABASE.addTransaction(transaction)
                self.showMessage("Transação Adicionada.")

                count += 1
        else:
            date = self.date.date()
            transaction = [date.day(), date.month(), date.year()]
            transaction += [self.description.text()]
            if newCategory:
                transaction += [self.category.currentText(), None]
            else:
                transaction += [
                    self.category.currentText(),
                    DATABASE.getCategories(self.category.currentText(),
                                           infos=True)[1]
                ]
            transaction += [self.account.currentText(), value, item.ident]
            DATABASE.updateTransaction(transaction)
            self.showMessage("Transação Editada.")
Example #26
0
class UserPopup(QWidget):
    """Super class for the two popups which allows users to be edited or added.
    They are so similar that it warrants one super class which creates the labels
    and entries."""
    def __init__(self, parent=None):
        super().__init__()
        self.controller = parent
        self.initUI()
        self.setWindowModality(Qt.ApplicationModal)
        self.show()

    def initUI(self):
        self.mainLayout = QVBoxLayout()
        lineEditsGroup = QGroupBox()
        grid = QGridLayout()

        #Create line edit labels for each field except user ID (non-editable)
        for i, key in enumerate(['Name', 'Birthday', 'Gender', 'Nationality']):
            grid.addWidget(QLabel(key + "*"), i, 0)

        #Create name line entry
        self.nameEntry = QLineEdit(self)
        grid.addWidget(self.nameEntry, 0, 1)

        #Create birthday entry
        self.birthdayEntry = QDateEdit(self)
        grid.addWidget(self.birthdayEntry, 1, 1)

        #Create gender selection
        self.genderBox = QComboBox(self)
        self.genderBox.addItem("Male")
        self.genderBox.addItem("Female")
        self.genderBox.addItem("Other")
        grid.addWidget(self.genderBox, 2, 1)

        #Add nationality
        self.nationEntry = QLineEdit(self)
        grid.addWidget(self.nationEntry, 3, 1)

        lineEditsGroup.setLayout(grid)
        self.mainLayout.addWidget(lineEditsGroup)

        self.setLayout(self.mainLayout)

    def verifyInputValidity(self):
        """Triggers when user tries to save changes. Checks all fields
        for correct data."""

        #Reset borders in case of earlier tries
        for field in [
                self.nameEntry, self.birthdayEntry, self.genderBox,
                self.nationEntry
        ]:
            field.setStyleSheet("border: 1px solid black")

        if self.nameEntry.text().strip() == "":
            self.nameEntry.setStyleSheet("border: 2px solid red")
            return 1

        if (self.birthdayEntry.date() >= QDate().currentDate()):
            self.birthdayEntry.setStyleSheet("border: 2px solid red")
            return 1

        if self.genderBox.currentText().strip() not in [
                "Male", "Female", "Other"
        ]:
            self.genderBox.setStyleSheet("border: 2px solid red")
            return 1

        if self.nationEntry.text().strip() == "":
            self.nationEntry.setStyleSheet("border: 2px solid red")
            return 1

        return 0
Example #27
0
class DateCreatorWindow(QDialog):
    """
    Dialog window for creation / editing date.
    """
    def __init__(self, parent: QWidget = None):
        super().__init__(parent)

        self._date = None
        self._date_delta = 7
        self._date_start_temp = QDate.currentDate()

        # window settings
        self.setWindowTitle(self.tr("Date creator"))

        # toggle and status
        self.check_box = QCheckBox(self.tr("Range date"))

        # date layout
        self.layout_date_edit = QFormLayout()

        # simple date layout
        self.label_simple_date = QLabel(self.tr("Date"))
        self.layout_date_edit.setWidget(0, QFormLayout.LabelRole,
                                        self.label_simple_date)
        self.date_edit_simple = QDateEdit()
        self.layout_date_edit.setWidget(0, QFormLayout.FieldRole,
                                        self.date_edit_simple)

        self.date_edit_simple.setCalendarPopup(True)
        self.date_edit_simple.setDisplayFormat("dd.MM.yyyy")
        self.date_edit_simple.setDate(QDate.currentDate())
        self.date_edit_simple.setDateRange(QDate.currentDate().addDays(-365),
                                           QDate.currentDate().addDays(365))

        # range date layout
        self.label_date_start = QLabel(self.tr("Start"))
        self.layout_date_edit.setWidget(1, QFormLayout.LabelRole,
                                        self.label_date_start)
        self.date_edit_start = QDateEdit()
        self.layout_date_edit.setWidget(1, QFormLayout.FieldRole,
                                        self.date_edit_start)

        self.label_date_end = QLabel(self.tr("End"))
        self.layout_date_edit.setWidget(2, QFormLayout.LabelRole,
                                        self.label_date_end)
        self.date_edit_end = QDateEdit()
        self.layout_date_edit.setWidget(2, QFormLayout.FieldRole,
                                        self.date_edit_end)

        self.label_date_frequency = QLabel(self.tr("Frequency"))
        self.layout_date_edit.setWidget(3, QFormLayout.LabelRole,
                                        self.label_date_frequency)
        self.combo_box_frequency = QComboBox()
        self.layout_date_edit.setWidget(3, QFormLayout.FieldRole,
                                        self.combo_box_frequency)

        self.date_edit_start.setCalendarPopup(True)
        self.date_edit_start.setDisplayFormat("dd.MM.yyyy")
        self.date_edit_start.setDate(QDate.currentDate())
        self.date_edit_start.setDateRange(QDate.currentDate().addDays(-365),
                                          QDate.currentDate().addDays(365))

        self.date_edit_end.setCalendarPopup(True)
        self.date_edit_end.setDisplayFormat("dd.MM.yyyy")
        self.date_edit_end.setDate(QDate.currentDate().addDays(
            self._date_delta))
        self.date_edit_end.setDateRange(
            QDate.currentDate().addDays(self._date_delta),
            QDate.currentDate().addDays(365))

        self.combo_box_frequency.addItem(str(FrequencyDate.Every),
                                         FrequencyDate.Every)
        self.combo_box_frequency.addItem(str(FrequencyDate.Throughout),
                                         FrequencyDate.Throughout)

        # navigate
        self.layout_navigate = QHBoxLayout()

        self.layout_navigate.addStretch(1)

        self.push_button_ok = QPushButton(self.tr("OK"))
        self.layout_navigate.addWidget(self.push_button_ok)

        self.push_button_apply = QPushButton(self.tr("Apply"))
        self.layout_navigate.addWidget(self.push_button_apply)

        self.push_button_cancel = QPushButton(self.tr("Cancel"))
        self.layout_navigate.addWidget(self.push_button_cancel)

        # layout setup
        self.layout_main = QVBoxLayout()
        self.layout_main.setAlignment(Qt.AlignCenter)

        self.layout_main.addWidget(self.check_box)
        self.layout_main.addLayout(self.layout_date_edit)
        self.layout_main.addStretch(1)
        self.layout_main.addLayout(self.layout_navigate)

        self.setLayout(self.layout_main)

        # connection
        self.check_box.clicked.connect(self.check_box_clicked)
        self.date_edit_start.dateChanged.connect(self.date_edit_start_change)
        self.date_edit_end.dateChanged.connect(self.date_range_validation)
        self.combo_box_frequency.currentIndexChanged.connect(
            self.combo_box_frequency_changed)
        self.push_button_ok.clicked.connect(self.push_button_ok_clicked)
        self.push_button_apply.clicked.connect(self.push_button_apply_clicked)
        self.push_button_cancel.clicked.connect(
            self.push_button_cancel_clicked)

        self.show_simple_date()

    def set_date(self, date_item) -> None:
        """
        Sets the date for editing.

        :param date_item: Set date
        """
        if isinstance(date_item, DateItem):
            self.show_simple_date()
            self.date_edit_simple.setDate(
                QDate.fromString(date_item.date, "yyyy.MM.dd"))
            self._date = date_item

        if isinstance(date_item, DateRange):
            self.check_box.setChecked(True)
            self.show_range_date()
            self.date_edit_start.setDate(
                QDate.fromString(date_item.date_from, "yyyy.MM.dd"))
            self.date_edit_end.setDate(
                QDate.fromString(date_item.date_to, "yyyy.MM.dd"))
            self.combo_box_frequency.setCurrentText(str(date_item.frequency))
            self._date = date_item

    def get_date(self) -> (DateItem, DateRange, None):
        """
        Returns the created date.
        """
        return self._date

    def show_simple_date(self) -> None:
        """
        Switches the window to simple date editing mode.
        """
        self.label_simple_date.setVisible(True)
        self.date_edit_simple.setVisible(True)

        self.label_date_start.setVisible(False)
        self.date_edit_start.setVisible(False)
        self.label_date_end.setVisible(False)
        self.date_edit_end.setVisible(False)
        self.label_date_frequency.setVisible(False)
        self.combo_box_frequency.setVisible(False)

    def show_range_date(self) -> None:
        """
        Switches the window to range date editing mode.
        """
        self.label_date_start.setVisible(True)
        self.date_edit_start.setVisible(True)
        self.label_date_end.setVisible(True)
        self.date_edit_end.setVisible(True)
        self.label_date_frequency.setVisible(True)
        self.combo_box_frequency.setVisible(True)

        self.label_simple_date.setVisible(False)
        self.date_edit_simple.setVisible(False)

    def date_edit_start_change(self, date: QDate) -> None:
        """
        Slot for changing the end of a range of dates.

        :param date: Start of the date range
        """
        end_date = self.date_edit_end.date().addDays(
            self._date_start_temp.daysTo(date))
        self.date_edit_end.setDateRange(date.addDays(self._date_delta),
                                        date.addDays(365))
        self.date_edit_end.setDate(end_date)
        self._date_start_temp = QDate(date)

    def combo_box_frequency_changed(self, index: int) -> None:
        """
        Slot for frequency combo box.

        :param index: Current index
        """
        if index == 0:
            self._date_delta = 7
        else:
            self._date_delta = 14

        self.date_edit_end.setDateRange(
            self.date_edit_start.date().addDays(self._date_delta),
            self.date_edit_start.date().addDays(365))
        self.date_range_validation()

    def date_range_validation(self) -> None:
        """
        Checks the correctness of the entered dates.
        """
        if self.date_edit_start.date().dayOfWeek() == self.date_edit_end.date(
        ).dayOfWeek():
            if self.date_edit_start.date().daysTo(
                    self.date_edit_end.date()) % self._date_delta == 0:
                msg = ""
            else:
                msg = self.tr("The number of days between "
                              "dates is not a multiple of {}").format(
                                  self._date_delta)
        else:
            msg = self.tr("Different days of the week at dates")

        if msg == "":
            self.push_button_ok.setEnabled(True)
            self.push_button_apply.setEnabled(True)
        else:
            self.push_button_ok.setEnabled(False)
            self.push_button_apply.setEnabled(False)

        self.date_edit_start.setToolTip(msg)
        self.date_edit_end.setToolTip(msg)

    def check_box_clicked(self, value: bool) -> None:
        """
        Slot for check box.

        :param value: Check box status
        """
        if value is False:
            # simple date
            self.show_simple_date()
        else:
            # range date
            self.show_range_date()

    def push_button_ok_clicked(self) -> None:
        """
        Slot for ok button.
        """
        if self.push_button_apply_clicked():
            self.close()

    def push_button_apply_clicked(self) -> bool:
        """
        Slot for apply button.
        """
        try:
            if self.check_box.isChecked() is False:
                # simple date
                self._date = DateItem(
                    self.date_edit_simple.date().toString("yyyy.MM.dd"))
            else:
                # range date
                self._date = DateRange(
                    self.date_edit_start.date().toString("yyyy.MM.dd"),
                    self.date_edit_end.date().toString("yyyy.MM.dd"),
                    self.combo_box_frequency.currentData(Qt.UserRole))
            return True
        except InvalidDatePair as pair_ex:
            QMessageBox.warning(self, self.tr("Date error"), str(pair_ex))

        except Exception as ex:
            QMessageBox.critical(self, self.tr("Unknown error"), str(ex))

        return False

    def push_button_cancel_clicked(self) -> None:
        """
        Slot for cancel button.
        """
        self._date = None
        self.close()
Example #28
0
class MainDialog(QWidget):
    """
    Main dialog of the loan calculator.
    """
    def __init__(self):
        super().__init__()

        self._vbox = None
        self._data_grid = None
        self._hbox_buttons = None
        self._hbox_close_button = None
        self._kredit_summe_edit = None
        self._tilgung_prozent_edit = None
        self._zins_prozent_edit = None
        self._start_month_edit = None
        self._monats_rate_label = None
        self._laufzeit_label = None
        self._kosten_label = None
        self._load_button = None
        self._save_button = None
        self._calc_button = None
        self._soti_button = None
        self._table_button = None
        self._table_button = None
        self._plot_button = None
        self._close_button = None

        self._window = None
        self._table_window = None

        self._current_project_file_name = None
        self._settings = None
        self._kredit_verlauf = []
        self._extra_payments = []
        
        self.init_ui()

        # Load/initialize settings
        self._credit_dir = os.path.join(pathlib.Path.home(), '.credit')
        self._credit_settings_file = os.path.join(self._credit_dir, 'settings.yaml')
        if not os.path.exists(self._credit_dir):
            os.makedirs(self._credit_dir)
        if not os.path.exists(self._credit_settings_file):
            self._settings = CreditSettings()
            self._save_settings(self._credit_settings_file)
        self._load_settings(self._credit_settings_file)

    def init_ui(self):
        self.setGeometry(300, 300, 300, 300)
        self.setWindowTitle('Annuity Loan Calculator')

        self.init_layout()
        self.init_project_buttons()
        self.init_input_fields()
        self.init_calc_buttons()
        self.init_output_fields()
        self.init_show_buttons()
        self.init_close_button()

        self._load_button.clicked.connect(self.load_button_pressed)
        self._save_button.clicked.connect(self.save_button_pressed)
        self._calc_button.clicked.connect(self.calc_button_pressed)
        self._soti_button.clicked.connect(self.soti_button_pressed)
        self._plot_button.clicked.connect(self.plot_button_pressed)
        self._table_button.clicked.connect(self.table_button_pressed)
        self._close_button.clicked.connect(self.close_button_pressed)

        self.show()

    def _load_settings(self, file_name):
        if os.path.exists(file_name):
            try:
                self._settings = yaml.load(open(file_name, 'r'))
                self._kredit_summe_edit.setText("{:.2f}".format(self._settings.kreditsumme))
                self._tilgung_prozent_edit.setText("{:.2f}".format(self._settings.tilgung))
                self._zins_prozent_edit.setText("{:.2f}".format(self._settings.zins))
                self._start_month_edit.lineEdit().setText(self._settings.start_date)
            except yaml.YAMLError as ex:
                log.LOGGER.error(ex)

    def _save_settings(self, file_name):
        save_dir = os.path.dirname(file_name)
        if os.path.exists(save_dir):
            try:
                self._settings.kreditsumme = float(self._kredit_summe_edit.text())
            except ValueError:
                self._settings.kreditsumme = 0.0
            try:
                self._settings.zins = float(self._zins_prozent_edit.text())
            except ValueError:
                self._settings.zins = 5.0
            try:
                self._settings.tilgung = float(self._tilgung_prozent_edit.text())
            except ValueError:
                self._settings.tilgung = 1.0
            try:
                self._settings.start_date = self._start_month_edit.lineEdit().text()
            except ValueError:
                self._settings.start_date = "2000-01-01"
            try:
                with open(file_name, mode='w') as file:
                    file.write(yaml.dump(self._settings))
            except yaml.YAMLError as ex:
                log.LOGGER.error(ex)
        else:
            QMessageBox.warning(
                self,
                "Project coud not be saved",
                "Target directory {} does not exist".format(save_dir))

    def init_layout(self):
        self._vbox = QVBoxLayout()
        self._data_grid = QGridLayout()
        self._hbox_buttons = QHBoxLayout()
        self._hbox_close_button = QHBoxLayout()

        self._vbox.addLayout(self._data_grid)
        self._vbox.addLayout(self._hbox_buttons)
        self._vbox.addLayout(self._hbox_close_button)
        self._vbox.addStretch(1)

        self.setLayout(self._vbox)

    def init_project_buttons(self):
        start_row = 0
        self._load_button = QPushButton("Load Project")
        self._save_button = QPushButton("Save Project")
        hbox = QHBoxLayout()
        hbox.addWidget(self._load_button)
        hbox.addWidget(self._save_button)
        self._data_grid.addLayout(hbox, start_row + 0, 0, 1, 2)

    def init_input_fields(self):
        start_row = 1
        self._data_grid.addWidget(QLabel("Loan Amount"), start_row + 0, 0)
        self._data_grid.addWidget(QLabel("Down Payment [%]"), start_row + 1, 0)
        self._data_grid.addWidget(QLabel("Nominal Interest [%]"), start_row + 2, 0)
        self._data_grid.addWidget(QLabel("Start Date"), start_row + 3, 0)
        self._kredit_summe_edit = QLineEdit()
        self._tilgung_prozent_edit = QLineEdit()
        self._zins_prozent_edit = QLineEdit()
        self._start_month_edit = QDateEdit(QDate.currentDate())
        self._start_month_edit.setDisplayFormat(conf.DATE_FORMAT)
        self._start_month_edit.currentSection = QDateTimeEdit.MonthSection
        # self._start_month_edit.setCalendarPopup(True)
        self._data_grid.addWidget(self._kredit_summe_edit, start_row + 0, 1)
        self._data_grid.addWidget(self._tilgung_prozent_edit, start_row + 1, 1)
        self._data_grid.addWidget(self._zins_prozent_edit, start_row + 2, 1)
        self._data_grid.addWidget(self._start_month_edit, start_row + 3, 1)

    def init_calc_buttons(self):
        start_row = 5
        self._calc_button = QPushButton("Calculate")
        self._soti_button = QPushButton("Extra Down Payments")
        hbox = QHBoxLayout()
        hbox.addWidget(self._calc_button)
        hbox.addWidget(self._soti_button)
        self._data_grid.addLayout(hbox, start_row + 0, 0, 1, 2)

    def init_output_fields(self):
        start_row = 6
        self._monats_rate_label = QLabel("...")
        self._laufzeit_label = QLabel("...")
        self._kosten_label = QLabel("...")
        self._data_grid.addWidget(QLabel("Monthly Rate:"), start_row + 0, 0)
        self._data_grid.addWidget(QLabel("Period:"), start_row + 1, 0)
        self._data_grid.addWidget(QLabel("Total Interest:"), start_row + 2, 0)
        self._data_grid.addWidget(self._monats_rate_label, start_row + 0, 1)
        self._data_grid.addWidget(self._laufzeit_label, start_row + 1, 1)
        self._data_grid.addWidget(self._kosten_label, start_row + 2, 1)

    def init_show_buttons(self):
        self._table_button = QPushButton("Show Schedue")
        self._plot_button = QPushButton("Show Chart")
        self._hbox_buttons.addWidget(self._table_button)
        self._hbox_buttons.addWidget(self._plot_button)

    def init_close_button(self):
        self._close_button = QPushButton("Close")
        self._hbox_close_button.addStretch(1)
        self._hbox_close_button.addWidget(self._close_button)

    @property
    def summe(self):
        """
        :returns loan amount
        """
        return float(self._kredit_summe_edit.text())

    @property
    def tilgung(self):
        """
        :returns redemption rate in %
        """
        return float(self._tilgung_prozent_edit.text())

    @property
    def zins(self):
        """
        :returns nominal interest in %
        """
        return float(self._zins_prozent_edit.text())

    @property
    def monatsrate(self):
        raise NotImplementedError("Setting is not allowed")

    @monatsrate.setter
    def monatsrate(self, x):
        self._monats_rate_label.setText("{0:.2f}".format(x))

    @property
    def laufzeit(self):
        raise NotImplementedError("Setting is not allowed")

    @laufzeit.setter
    def laufzeit(self, x):
        self._laufzeit_label.setText(str(x))

    @property
    def kosten(self):
        raise NotImplementedError("Setting is not allowed")

    @kosten.setter
    def kosten(self, x):
        """
        :param x (float): cost of the credit (sum of interest payments).
        """
        self._kosten_label.setText("{0:.2f}".format(x))

    def load_button_pressed(self, e):
        if self._current_project_file_name:
            start_file = self._current_project_file_name
        else:
            start_file = str(pathlib.Path.home())
        file_name = QFileDialog.getOpenFileName(
            self,
            "Open Project File",
            start_file,
            "Credit Project Files (*.yaml)")[0]
        self._load_settings(file_name)
        self._current_project_file_name = file_name

    def save_button_pressed(self, e):
        if self._current_project_file_name:
            start_file = self._current_project_file_name
        else:
            start_file = str(pathlib.Path.home())
        file_name = QFileDialog.getSaveFileName(
            self,
            "Save Project File",
            start_file,
            "Credit Project Files (*.yaml)")[0]
        self._save_settings(file_name)
        self._current_project_file_name = file_name

    def calc_button_pressed(self, e):
        kredit = AnnuitaetenKredit(self.summe, self.tilgung, self.zins)
        # Convert absolute to relative months
        extra_payments = {}
        for payment in self._settings.extra_payments:
            month = util.month_diff(
                QDate.fromString(payment[0], conf.DATE_FORMAT),
                QDate.fromString(self._settings.start_date, conf.DATE_FORMAT))
            extra_payments[month] = payment[1]
        self._kredit_verlauf = kredit.berechne_kreditverlauf(extra_payments)
        self.monatsrate = kredit.Monatsrate
        self.laufzeit = "{0:d} Years {1:d} Months".format(
            int(self._kredit_verlauf[-1].Monat) // 12,
            self._kredit_verlauf[-1].Monat % 12)
        self.kosten = kredit.GesamtKosten

    def soti_button_pressed(self, e):
        soti_dialog = SotiDialog(self, self._settings.extra_payments)
        ret = soti_dialog.exec()
        if ret == QDialog.Accepted:
            self._settings.extra_payments = soti_dialog.payments

    def table_button_pressed(self, e):
        if len(self._kredit_verlauf):
            table_dialog = TableDialog(self)
            table_dialog.show_table(self._kredit_verlauf, self._start_month_edit.date())
            table_dialog.exec()

    def plot_button_pressed(self, e):
        if len(self._kredit_verlauf):
            plot_dialog = PlotWindow(self)
            plot_dialog.plot(self._kredit_verlauf)
            plot_dialog.exec()

    def close_button_pressed(self):
        self._save_settings(self._credit_settings_file)
        self.close()
Example #29
0
class comic_meta_data_editor(QDialog):
    configGroup = "ComicsProjectManagementTools"

    # Translatable genre dictionary that has it's translated entries added to the genrelist and from which the untranslated items are taken.
    acbfGenreList = {
        "science_fiction": str(i18n("Science Fiction")),
        "fantasy": str(i18n("Fantasy")),
        "adventure": str(i18n("Adventure")),
        "horror": str(i18n("Horror")),
        "mystery": str(i18n("Mystery")),
        "crime": str(i18n("Crime")),
        "military": str(i18n("Military")),
        "real_life": str(i18n("Real Life")),
        "superhero": str(i18n("Superhero")),
        "humor": str(i18n("Humor")),
        "western": str(i18n("Western")),
        "manga": str(i18n("Manga")),
        "politics": str(i18n("Politics")),
        "caricature": str(i18n("Caricature")),
        "sports": str(i18n("Sports")),
        "history": str(i18n("History")),
        "biography": str(i18n("Biography")),
        "education": str(i18n("Education")),
        "computer": str(i18n("Computer")),
        "religion": str(i18n("Religion")),
        "romance": str(i18n("Romance")),
        "children": str(i18n("Children")),
        "non-fiction": str(i18n("Non Fiction")),
        "adult": str(i18n("Adult")),
        "alternative": str(i18n("Alternative")),
        "artbook": str(i18n("Artbook")),
        "other": str(i18n("Other"))
    }
    acbfAuthorRolesList = {
        "Writer": str(i18n("Writer")),
        "Adapter": str(i18n("Adapter")),
        "Artist": str(i18n("Artist")),
        "Penciller": str(i18n("Penciller")),
        "Inker": str(i18n("Inker")),
        "Colorist": str(i18n("Colorist")),
        "Letterer": str(i18n("Letterer")),
        "Cover Artist": str(i18n("Cover Artist")),
        "Photographer": str(i18n("Photographer")),
        "Editor": str(i18n("Editor")),
        "Assistant Editor": str(i18n("Assistant Editor")),
        "Designer": str(i18n("Designer")),
        "Translator": str(i18n("Translator")),
        "Other": str(i18n("Other"))
    }

    def __init__(self):
        super().__init__()
        # Get the keys for the autocompletion.
        self.genreKeysList = []
        self.characterKeysList = []
        self.ratingKeysList = {}
        self.formatKeysList = []
        self.otherKeysList = []
        self.authorRoleList = []
        for g in self.acbfGenreList.values():
            self.genreKeysList.append(g)
        for r in self.acbfAuthorRolesList.values():
            self.authorRoleList.append(r)
        mainP = Path(os.path.abspath(__file__)).parent
        self.get_auto_completion_keys(mainP)
        extraKeyP = Path(QDir.homePath()) / Application.readSetting(
            self.configGroup, "extraKeysLocation", str())
        self.get_auto_completion_keys(extraKeyP)

        # Setup the dialog.
        self.setLayout(QVBoxLayout())
        mainWidget = QTabWidget()
        self.layout().addWidget(mainWidget)
        self.setWindowTitle(i18n("Comic Metadata"))
        buttons = QDialogButtonBox(QDialogButtonBox.Ok
                                   | QDialogButtonBox.Cancel)
        self.layout().addWidget(buttons)
        buttons.accepted.connect(self.accept)
        buttons.rejected.connect(self.reject)

        # Title, concept, summary, genre, characters, format, rating, language, series, other keywords
        metadataPage = QWidget()
        mformLayout = QFormLayout()
        metadataPage.setLayout(mformLayout)

        self.lnTitle = QLineEdit()
        self.lnTitle.setToolTip(i18n("The proper title of the comic."))

        self.teSummary = QPlainTextEdit()
        self.teSummary.setToolTip(
            i18n("What will you tell others to entice them to read your comic?"
                 ))

        self.lnGenre = QLineEdit()
        genreCompletion = multi_entry_completer()
        genreCompletion.setModel(QStringListModel(self.genreKeysList))
        self.lnGenre.setCompleter(genreCompletion)
        genreCompletion.setCaseSensitivity(False)
        self.lnGenre.setToolTip(
            i18n(
                "The genre of the work. Prefilled values are from the ACBF, but you can fill in your own. Separate genres with commas. Try to limit the amount to about two or three"
            ))

        self.lnCharacters = QLineEdit()
        characterCompletion = multi_entry_completer()
        characterCompletion.setModel(QStringListModel(self.characterKeysList))
        characterCompletion.setCaseSensitivity(False)
        characterCompletion.setFilterMode(
            Qt.MatchContains
        )  # So that if there is a list of names with last names, people can type in a last name.
        self.lnCharacters.setCompleter(characterCompletion)
        self.lnCharacters.setToolTip(
            i18n(
                "The names of the characters that this comic revolves around. Comma-separated."
            ))

        self.lnFormat = QLineEdit()
        formatCompletion = multi_entry_completer()
        formatCompletion.setModel(QStringListModel(self.formatKeysList))
        formatCompletion.setCaseSensitivity(False)
        self.lnFormat.setCompleter(formatCompletion)

        ratingLayout = QHBoxLayout()
        self.cmbRatingSystem = QComboBox()
        self.cmbRatingSystem.addItems(self.ratingKeysList.keys())
        self.cmbRatingSystem.setEditable(True)
        self.cmbRating = QComboBox()
        self.cmbRating.setEditable(True)
        self.cmbRatingSystem.currentIndexChanged.connect(
            self.slot_refill_ratings)
        ratingLayout.addWidget(self.cmbRatingSystem)
        ratingLayout.addWidget(self.cmbRating)

        self.lnSeriesName = QLineEdit()
        self.lnSeriesName.setToolTip(
            i18n(
                "If this is part of a series, enter the name of the series and the number."
            ))
        self.spnSeriesNumber = QSpinBox()
        self.spnSeriesNumber.setPrefix("No. ")
        self.spnSeriesVol = QSpinBox()
        self.spnSeriesVol.setPrefix("Vol. ")
        seriesLayout = QHBoxLayout()
        seriesLayout.addWidget(self.lnSeriesName)
        seriesLayout.addWidget(self.spnSeriesVol)
        seriesLayout.addWidget(self.spnSeriesNumber)

        otherCompletion = multi_entry_completer()
        otherCompletion.setModel(QStringListModel(self.otherKeysList))
        otherCompletion.setCaseSensitivity(False)
        otherCompletion.setFilterMode(Qt.MatchContains)
        self.lnOtherKeywords = QLineEdit()
        self.lnOtherKeywords.setCompleter(otherCompletion)
        self.lnOtherKeywords.setToolTip(
            i18n(
                "Other keywords that don't fit in the previously mentioned sets. As always, comma-separated"
            ))

        self.cmbLanguage = language_combo_box()
        self.cmbReadingMode = QComboBox()
        self.cmbReadingMode.addItem(i18n("Left to Right"))
        self.cmbReadingMode.addItem(i18n("Right to Left"))

        self.cmbCoverPage = QComboBox()
        self.cmbCoverPage.setToolTip(
            i18n(
                "Which page is the cover page? This will be empty if there's no pages."
            ))

        mformLayout.addRow(i18n("Title:"), self.lnTitle)
        mformLayout.addRow(i18n("Cover Page:"), self.cmbCoverPage)
        mformLayout.addRow(i18n("Summary:"), self.teSummary)
        mformLayout.addRow(i18n("Language:"), self.cmbLanguage)
        mformLayout.addRow(i18n("Reading Direction:"), self.cmbReadingMode)
        mformLayout.addRow(i18n("Genre:"), self.lnGenre)
        mformLayout.addRow(i18n("Characters:"), self.lnCharacters)
        mformLayout.addRow(i18n("Format:"), self.lnFormat)
        mformLayout.addRow(i18n("Rating:"), ratingLayout)
        mformLayout.addRow(i18n("Series:"), seriesLayout)
        mformLayout.addRow(i18n("Other:"), self.lnOtherKeywords)

        mainWidget.addTab(metadataPage, i18n("Work"))

        # The page for the authors.
        authorPage = QWidget()
        authorPage.setLayout(QVBoxLayout())
        explanation = QLabel(
            i18n(
                "The following is a table of the authors that contributed to this comic. You can set their nickname, proper names (first, middle, last), Role (Penciller, Inker, etc), email and homepage."
            ))
        explanation.setWordWrap(True)
        self.authorModel = QStandardItemModel(0, 8)
        labels = [
            i18n("Nick Name"),
            i18n("Given Name"),
            i18n("Middle Name"),
            i18n("Family Name"),
            i18n("Role"),
            i18n("Email"),
            i18n("Homepage"),
            i18n("Language")
        ]
        self.authorModel.setHorizontalHeaderLabels(labels)
        self.authorTable = QTableView()
        self.authorTable.setModel(self.authorModel)
        self.authorTable.verticalHeader().setDragEnabled(True)
        self.authorTable.verticalHeader().setDropIndicatorShown(True)
        self.authorTable.verticalHeader().setSectionsMovable(True)
        self.authorTable.verticalHeader().sectionMoved.connect(
            self.slot_reset_author_row_visual)
        delegate = author_delegate()
        delegate.setCompleterData(self.authorRoleList, 4)
        delegate.setLanguageData(len(labels) - 1)
        self.authorTable.setItemDelegate(delegate)
        author_button_layout = QWidget()
        author_button_layout.setLayout(QHBoxLayout())
        btn_add_author = QPushButton(i18n("Add Author"))
        btn_add_author.clicked.connect(self.slot_add_author)
        btn_remove_author = QPushButton(i18n("Remove Author"))
        btn_remove_author.clicked.connect(self.slot_remove_author)
        author_button_layout.layout().addWidget(btn_add_author)
        author_button_layout.layout().addWidget(btn_remove_author)
        authorPage.layout().addWidget(explanation)
        authorPage.layout().addWidget(self.authorTable)
        authorPage.layout().addWidget(author_button_layout)
        mainWidget.addTab(authorPage, i18n("Authors"))

        # The page with publisher information.
        publisherPage = QWidget()
        publisherLayout = QFormLayout()
        publisherPage.setLayout(publisherLayout)
        self.publisherName = QLineEdit()
        self.publisherName.setToolTip(
            i18n(
                "The name of the company, group or person who is responsible for the final version the reader gets."
            ))
        publishDateLayout = QHBoxLayout()
        self.publishDate = QDateEdit()
        self.publishDate.setDisplayFormat(QLocale().system().dateFormat())
        currentDate = QPushButton(i18n("Set Today"))
        currentDate.setToolTip(
            i18n("Sets the publish date to the current date."))
        currentDate.clicked.connect(self.slot_set_date)
        publishDateLayout.addWidget(self.publishDate)
        publishDateLayout.addWidget(currentDate)
        self.publishCity = QLineEdit()
        self.publishCity.setToolTip(
            i18n(
                "Traditional publishers are always mentioned in source with the city they are located."
            ))
        self.isbn = QLineEdit()
        self.license = license_combo_box(
        )  # Maybe ought to make this a QLineEdit...
        self.license.setEditable(True)
        self.license.completer().setCompletionMode(QCompleter.PopupCompletion)
        dataBaseReference = QVBoxLayout()
        self.ln_database_name = QLineEdit()
        self.ln_database_name.setToolTip(
            i18n(
                "If there's an entry in a comics data base, that should be added here. It is unlikely to be a factor for comics from scratch, but useful when doing a conversion."
            ))
        self.cmb_entry_type = QComboBox()
        self.cmb_entry_type.addItems(["IssueID", "SeriesID", "URL"])
        self.cmb_entry_type.setEditable(True)
        self.ln_database_entry = QLineEdit()
        dbHorizontal = QHBoxLayout()
        dbHorizontal.addWidget(self.ln_database_name)
        dbHorizontal.addWidget(self.cmb_entry_type)
        dataBaseReference.addLayout(dbHorizontal)
        dataBaseReference.addWidget(self.ln_database_entry)
        publisherLayout.addRow(i18n("Name:"), self.publisherName)
        publisherLayout.addRow(i18n("City:"), self.publishCity)
        publisherLayout.addRow(i18n("Date:"), publishDateLayout)
        publisherLayout.addRow(i18n("ISBN:"), self.isbn)
        publisherLayout.addRow(i18n("License:"), self.license)
        publisherLayout.addRow(i18n("Database:"), dataBaseReference)

        mainWidget.addTab(publisherPage, i18n("Publisher"))

    """
    Ensure that the drag and drop of authors doesn't mess up the labels.
    """

    def slot_reset_author_row_visual(self):
        headerLabelList = []
        for i in range(self.authorTable.verticalHeader().count()):
            headerLabelList.append(str(i))
        for i in range(self.authorTable.verticalHeader().count()):
            logicalI = self.authorTable.verticalHeader().logicalIndex(i)
            headerLabelList[logicalI] = str(i + 1)
        self.authorModel.setVerticalHeaderLabels(headerLabelList)

    """
    Set the publish date to the current date.
    """

    def slot_set_date(self):
        self.publishDate.setDate(QDate().currentDate())

    """
    Append keys to autocompletion lists from the directory mainP.
    """

    def get_auto_completion_keys(self, mainP=Path()):
        genre = Path(mainP / "key_genre")
        characters = Path(mainP / "key_characters")
        rating = Path(mainP / "key_rating")
        format = Path(mainP / "key_format")
        keywords = Path(mainP / "key_other")
        authorRole = Path(mainP / "key_author_roles")
        if genre.exists():
            for t in list(genre.glob('**/*.txt')):
                file = open(str(t), "r", errors="replace")
                for l in file:
                    if str(l).strip("\n") not in self.genreKeysList:
                        self.genreKeysList.append(str(l).strip("\n"))
                file.close()
        if characters.exists():
            for t in list(characters.glob('**/*.txt')):
                file = open(str(t), "r", errors="replace")
                for l in file:
                    if str(l).strip("\n") not in self.characterKeysList:
                        self.characterKeysList.append(str(l).strip("\n"))
                file.close()
        if format.exists():
            for t in list(format.glob('**/*.txt')):
                file = open(str(t), "r", errors="replace")
                for l in file:
                    if str(l).strip("\n") not in self.formatKeysList:
                        self.formatKeysList.append(str(l).strip("\n"))
                file.close()
        if rating.exists():
            for t in list(rating.glob('**/*.csv')):
                file = open(str(t), "r", newline="", encoding="utf-8")
                ratings = csv.reader(file)
                title = os.path.basename(str(t))
                r = 0
                for row in ratings:
                    listItem = []
                    if r is 0:
                        title = row[1]
                    else:
                        listItem = self.ratingKeysList[title]
                        item = []
                        item.append(row[0])
                        item.append(row[1])
                        listItem.append(item)
                    self.ratingKeysList[title] = listItem
                    r += 1
                file.close()
        if keywords.exists():
            for t in list(keywords.glob('**/*.txt')):
                file = open(str(t), "r", errors="replace")
                for l in file:
                    if str(l).strip("\n") not in self.otherKeysList:
                        self.otherKeysList.append(str(l).strip("\n"))
                file.close()
        if authorRole.exists():
            for t in list(authorRole.glob('**/*.txt')):
                file = open(str(t), "r", errors="replace")
                for l in file:
                    if str(l).strip("\n") not in self.authorRoleList:
                        self.authorRoleList.append(str(l).strip("\n"))
                file.close()

    """
    Refill the ratings box.
    This is called whenever the rating system changes.
    """

    def slot_refill_ratings(self):
        if self.cmbRatingSystem.currentText() in self.ratingKeysList.keys():
            self.cmbRating.clear()
            model = QStandardItemModel()
            for i in self.ratingKeysList[self.cmbRatingSystem.currentText()]:
                item = QStandardItem()
                item.setText(i[0])
                item.setToolTip(i[1])
                model.appendRow(item)
            self.cmbRating.setModel(model)

    """
    Add an author with default values initialised.
    """

    def slot_add_author(self):
        listItems = []
        listItems.append(QStandardItem(i18n("Anon")))  # Nick name
        listItems.append(QStandardItem(i18n("John")))  # First name
        listItems.append(QStandardItem())  # Middle name
        listItems.append(QStandardItem(i18n("Doe")))  # Last name
        listItems.append(QStandardItem())  # role
        listItems.append(QStandardItem())  # email
        listItems.append(QStandardItem())  # homepage
        language = QLocale.system().name().split("_")[0]
        if language == "C":
            language = "en"
        listItems.append(QStandardItem(language))  # Language
        self.authorModel.appendRow(listItems)

    """
    Remove the selected author from the author list.
    """

    def slot_remove_author(self):
        self.authorModel.removeRow(self.authorTable.currentIndex().row())

    """
    Load the UI values from the config dictionary given.
    """

    def setConfig(self, config):

        if "title" in config.keys():
            self.lnTitle.setText(config["title"])
        self.teSummary.clear()
        if "pages" in config.keys():
            self.cmbCoverPage.clear()
            for page in config["pages"]:
                self.cmbCoverPage.addItem(page)
            if "cover" in config.keys():
                if config["cover"] in config["pages"]:
                    self.cmbCoverPage.setCurrentText(config["cover"])
        if "summary" in config.keys():
            self.teSummary.appendPlainText(config["summary"])
        if "genre" in config.keys():
            genreList = []
            genreListConf = config["genre"]
            totalMatch = 100
            if isinstance(config["genre"], dict):
                genreListConf = config["genre"].keys()
                totalMatch = 0
            for genre in genreListConf:
                genreKey = genre
                if genre in self.acbfGenreList:
                    genreKey = self.acbfGenreList[genre]
                if isinstance(config["genre"], dict):
                    genreValue = config["genre"][genre]
                    if genreValue > 0:
                        genreKey = str(genreKey + "(" + str(genreValue) + ")")
                genreList.append(genreKey)
            self.lnGenre.setText(", ".join(genreList))
        if "characters" in config.keys():
            self.lnCharacters.setText(", ".join(config["characters"]))
        if "format" in config.keys():
            self.lnFormat.setText(", ".join(config["format"]))
        if "rating" in config.keys():
            self.cmbRating.setCurrentText(config["rating"])
        else:
            self.cmbRating.setCurrentText("")
        if "ratingSystem" in config.keys():
            self.cmbRatingSystem.setCurrentText(config["ratingSystem"])
        else:
            self.cmbRatingSystem.setCurrentText("")
        if "otherKeywords" in config.keys():
            self.lnOtherKeywords.setText(", ".join(config["otherKeywords"]))
        if "seriesName" in config.keys():
            self.lnSeriesName.setText(config["seriesName"])
        if "seriesVolume" in config.keys():
            self.spnSeriesVol.setValue(config["seriesVolume"])
        if "seriesNumber" in config.keys():
            self.spnSeriesNumber.setValue(config["seriesNumber"])
        if "language" in config.keys():
            code = config["language"]
            if "_" in code:
                code = code.split("_")[0]
            self.cmbLanguage.setEntryToCode(code)
        if "readingDirection" in config.keys():
            if config["readingDirection"] is "leftToRight":
                self.cmbReadingMode.setCurrentIndex(int(Qt.LeftToRight))
            else:
                self.cmbReadingMode.setCurrentIndex(int(Qt.RightToLeft))
        else:
            self.cmbReadingMode.setCurrentIndex(
                QLocale(
                    self.cmbLanguage.codeForCurrentEntry()).textDirection())
        if "publisherName" in config.keys():
            self.publisherName.setText(config["publisherName"])
        if "publisherCity" in config.keys():
            self.publishCity.setText(config["publisherCity"])
        if "publishingDate" in config.keys():
            self.publishDate.setDate(
                QDate.fromString(config["publishingDate"], Qt.ISODate))
        if "isbn-number" in config.keys():
            self.isbn.setText(config["isbn-number"])
        if "license" in config.keys():
            self.license.setCurrentText(config["license"])
        else:
            self.license.setCurrentText(
                ""
            )  # I would like to keep it ambiguous whether the artist has thought about the license or not.
        if "authorList" in config.keys():
            authorList = config["authorList"]
            for i in range(len(authorList)):
                author = authorList[i]
                if len(author.keys()) > 0:
                    listItems = []
                    listItems = []
                    listItems.append(QStandardItem(author.get("nickname", "")))
                    listItems.append(
                        QStandardItem(author.get("first-name", "")))
                    listItems.append(QStandardItem(author.get("initials", "")))
                    listItems.append(QStandardItem(author.get("last-name",
                                                              "")))
                    role = author.get("role", "")
                    if role in self.acbfAuthorRolesList.keys():
                        role = self.acbfAuthorRolesList[role]
                    listItems.append(QStandardItem(role))
                    listItems.append(QStandardItem(author.get("email", "")))
                    listItems.append(QStandardItem(author.get("homepage", "")))
                    listItems.append(QStandardItem(author.get("language", "")))
                    self.authorModel.appendRow(listItems)
        else:
            self.slot_add_author()
        dbRef = config.get("databaseReference", {})
        self.ln_database_name.setText(dbRef.get("name", ""))
        self.ln_database_entry.setText(dbRef.get("entry", ""))
        stringCmbEntryType = self.cmb_entry_type.itemText(0)
        self.cmb_entry_type.setCurrentText(
            dbRef.get("type", stringCmbEntryType))

    """
    Store the GUI values into the config dictionary given.
    
    @return the config diactionary filled with new values.
    """

    def getConfig(self, config):

        text = self.lnTitle.text()
        if len(text) > 0 and text.isspace() is False:
            config["title"] = text
        elif "title" in config.keys():
            config.pop("title")
        config["cover"] = self.cmbCoverPage.currentText()
        listkeys = self.lnGenre.text()
        if len(listkeys) > 0 and listkeys.isspace() is False:
            preSplit = self.lnGenre.text().split(",")
            genreMatcher = re.compile(r'\((\d+)\)')
            genreList = {}
            totalValue = 0
            for key in preSplit:
                m = genreMatcher.search(key)
                if m:
                    genre = str(genreMatcher.sub("", key)).strip()
                    match = int(m.group()[:-1][1:])
                else:
                    genre = key.strip()
                    match = 0
                if genre in self.acbfGenreList.values():
                    i = list(self.acbfGenreList.values()).index(genre)
                    genreList[list(self.acbfGenreList.keys())[i]] = match
                else:
                    genreList[genre] = match
                totalValue += match
            # Normalize the values:
            for key in genreList.keys():
                if genreList[key] > 0:
                    genreList[key] = round(genreList[key] / totalValue * 100)
            config["genre"] = genreList
        elif "genre" in config.keys():
            config.pop("genre")
        listkeys = self.lnCharacters.text()
        if len(listkeys) > 0 and listkeys.isspace() is False:
            config["characters"] = self.lnCharacters.text().split(", ")
        elif "characters" in config.keys():
            config.pop("characters")
        listkeys = self.lnFormat.text()
        if len(listkeys) > 0 and listkeys.isspace() is False:
            config["format"] = self.lnFormat.text().split(", ")
        elif "format" in config.keys():
            config.pop("format")
        config["ratingSystem"] = self.cmbRatingSystem.currentText()
        config["rating"] = self.cmbRating.currentText()
        listkeys = self.lnOtherKeywords.text()
        if len(listkeys) > 0 and listkeys.isspace() is False:
            config["otherKeywords"] = self.lnOtherKeywords.text().split(", ")
        elif "otherKeywords" in config.keys():
            config.pop("otherKeywords")
        text = self.teSummary.toPlainText()
        if len(text) > 0 and text.isspace() is False:
            config["summary"] = text
        elif "summary" in config.keys():
            config.pop("summary")
        if len(self.lnSeriesName.text()) > 0:
            config["seriesName"] = self.lnSeriesName.text()
            config["seriesNumber"] = self.spnSeriesNumber.value()
            if self.spnSeriesVol.value() > 0:
                config["seriesVolume"] = self.spnSeriesVol.value()
        config["language"] = str(self.cmbLanguage.codeForCurrentEntry())
        if self.cmbReadingMode.currentIndex() is Qt.LeftToRight:
            config["readingDirection"] = "leftToRight"
        else:
            config["readingDirection"] = "rightToLeft"
        authorList = []
        for row in range(self.authorTable.verticalHeader().count()):
            logicalIndex = self.authorTable.verticalHeader().logicalIndex(row)
            listEntries = [
                "nickname", "first-name", "initials", "last-name", "role",
                "email", "homepage", "language"
            ]
            author = {}
            for i in range(len(listEntries)):
                entry = self.authorModel.data(
                    self.authorModel.index(logicalIndex, i))
                if entry is None:
                    entry = " "
                if entry.isspace() is False and len(entry) > 0:
                    if listEntries[i] == "role":
                        if entry in self.acbfAuthorRolesList.values():
                            entryI = list(
                                self.acbfAuthorRolesList.values()).index(entry)
                            entry = list(
                                self.acbfAuthorRolesList.keys())[entryI]
                    author[listEntries[i]] = entry
                elif listEntries[i] in author.keys():
                    author.pop(listEntries[i])
            authorList.append(author)
        config["authorList"] = authorList
        config["publisherName"] = self.publisherName.text()
        config["publisherCity"] = self.publishCity.text()
        config["publishingDate"] = self.publishDate.date().toString(Qt.ISODate)
        config["isbn-number"] = self.isbn.text()
        config["license"] = self.license.currentText()
        if self.ln_database_name.text().isalnum(
        ) and self.ln_database_entry.text().isalnum():
            dbRef = {}
            dbRef["name"] = self.ln_database_name.text()
            dbRef["entry"] = self.ln_database_entry.text()
            dbRef["type"] = self.cmb_entry_type.currentText()
            config["databaseReference"] = dbRef

        return config
Example #30
0
class Window(QWidget):
    def __init__(self):
        super(Window, self).__init__()
        self.setWindowTitle("Query Cocorahs")
        self.initUI()


    def initUI(self):
        self.createPreviewGroupBox()
        self.createDatesGroupBox()
        self.infoPanel()

        layout = QGridLayout()
        # layout.addWidget(self.previewGroupBox, 0, 0)
        layout.addWidget(self.datesGroupBox, 0, 1)
        layout.addWidget(self.infoPanelBox, 0, 2, 0, 1)
        layout.setSizeConstraint(QLayout.SetFixedSize)
        self.setLayout(layout)
        self.previewLayout.setRowMinimumHeight(0,
                self.calendar.sizeHint().height())
        self.previewLayout.setColumnMinimumWidth(0,
                self.calendar.sizeHint().width())


    def createPreviewGroupBox(self):
        self.previewGroupBox = QGroupBox("Calendar")
        self.calendar = QCalendarWidget()
        self.calendar.setMaximumDate(QDate(3000, 1, 1))
        self.calendar.setGridVisible(True)
        self.previewLayout = QGridLayout()
        self.previewLayout.addWidget(self.calendar, 0, 0)
        self.previewGroupBox.setLayout(self.previewLayout)


    def createDatesGroupBox(self):
        self.datesGroupBox = QGroupBox(self.tr("Selections"))

        # QUERY
        self.queryButton = QPushButton("Query Cocorahs Database")
        self.queryButton.clicked.connect(self.query_on_click)

        # START DATES
        self.currentDateEdit = QDateEdit()
        self.currentDateEdit.setDisplayFormat('dd MMM yyyy')
        self.currentDateEdit.setDate(self.calendar.selectedDate())
        self.currentDateEdit.setDateRange(self.calendar.minimumDate(),
                self.calendar.maximumDate())
        self.currentDateLabel = QLabel("&Date:")
        self.currentDateLabel.setBuddy(self.currentDateEdit)

        # END DATES
        self.maximumDateEdit = QDateEdit()
        self.maximumDateEdit.setDisplayFormat('dd MMM yyyy')
        self.maximumDateEdit.setDate(self.calendar.selectedDate())
        self.maximumDateEdit.setDateRange(self.calendar.minimumDate(),
                self.calendar.maximumDate())
        self.maximumDateLabel = QLabel("&End Date:")
        self.maximumDateLabel.setBuddy(self.maximumDateEdit)

        # LONGITUDE
        self.textboxLong = QLineEdit(self)
        self.textboxLongLabel = QLabel("Target Longitude:")

        # LATITUDE
        self.textboxLat = QLineEdit(self)
        self.textboxLatLabel = QLabel("Target Latitude:")

        # STATES
        self.textboxStates = QLineEdit(self)
        self.textboxStatesLabel = QLabel("State(s): e.g., 'CO,NE,WY'")

        dateBoxLayout = QGridLayout()
        dateBoxLayout.addWidget(self.currentDateLabel, 1, 0)
        dateBoxLayout.addWidget(self.currentDateEdit, 1, 1, 1, 2)
        # dateBoxLayout.addWidget(self.maximumDateLabel, 2, 0)
        # dateBoxLayout.addWidget(self.maximumDateEdit, 2, 1, 1, 2)
        dateBoxLayout.addWidget(self.textboxLatLabel, 3, 0)
        dateBoxLayout.addWidget(self.textboxLat, 3, 1, 1, 2)
        dateBoxLayout.addWidget(self.textboxLongLabel, 4, 0)
        dateBoxLayout.addWidget(self.textboxLong, 4, 1, 1, 2)
        dateBoxLayout.addWidget(self.textboxStatesLabel, 5, 0)
        dateBoxLayout.addWidget(self.textboxStates, 5, 1, 1, 2)
        dateBoxLayout.addWidget(self.queryButton, 6, 0,1,3)
        dateBoxLayout.setRowStretch(5, 1)
        self.datesGroupBox.setLayout(dateBoxLayout)


    def infoPanel(self):
        self.infoPanelBox = QGroupBox(self.tr("Info Console"))
        self.infoConsole = QTextEdit(self)
        infoPanelBoxLayout = QGridLayout()
        infoPanelBoxLayout.addWidget(self.infoConsole, 0, 0, 1, 1)
        self.infoPanelBox.setLayout(infoPanelBoxLayout)

    def query_on_click(self):
        long = self.textboxLong.text()
        lat = self.textboxLat.text()
        startDate = self.currentDateEdit.date()
        endDate = self.maximumDateEdit.date()
        states = self.textboxStates.text()
        date_range = list(range(startDate.month(), endDate.month() + 1))
        dateString = startDate.toString('MM/dd/yyyy')
        query(long=long, lat=lat, dateString=dateString, states=states)
Example #31
0
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()
Example #32
0
class WidgetGallery(QDialog):
    def __init__(self, parent=None):
        super(WidgetGallery, self).__init__(parent)

        self.localization = de
        self.srcFileString = ""
        self.targetFileString = ""
        self.truePath = None
        self.firstRun = True

        styleComboBox = QComboBox()
        styleComboBox.addItems(QStyleFactory.keys())

        self.createStartSection()
        self.createFileSelection()
        self.createDateSelection()
        self.createCheckboxArea()
        self.createInfoOutputSection()

        mainLayout = QGridLayout()
        mainLayout.addWidget(self.fileSelectionGroup, 1, 0)
        mainLayout.addWidget(self.dateSelectionGroupBox, 2, 0)
        mainLayout.addWidget(self.checkboxGroup, 3, 0)
        mainLayout.addWidget(self.startSection, 4, 0)
        mainLayout.addWidget(self.infoOutputSection, 5, 0)

        self.setLayout(mainLayout)

        self.setWindowTitle(self.localization.window_title)

    def createStartSection(self):
        '''Generate Aread containing the start button'''

        self.startSection = QGroupBox(self.localization.start_section)
        self.buttonGo = QPushButton(self.localization.button_go)
        self.buttonGo.setDisabled(True)
        self.buttonGo.clicked.connect(self.run)

        layout = QVBoxLayout()
        layout.addWidget(self.buttonGo)

        self.startSection.setLayout(layout)

    def createInfoOutputSection(self):
        '''Generate Aread containing progress, error and warning outputs'''

        self.infoOutputSection = QGroupBox(self.localization.infoOutput)
        self.infoTextBox = QTextBrowser()

        layout = QVBoxLayout()
        layout.addWidget(self.infoTextBox)

        self.infoOutputSection.setLayout(layout)

    def createFileSelection(self):
        '''Generate the area containing the file selectors and go button'''

        self.fileSelectionGroup = QGroupBox(self.localization.file_selection)

        # basic object #
        self.buttonSrcFile = QPushButton(self.localization.button_set_src_file)
        self.srcFileName = QLabel(self.localization.output_file)

        self.buttonTargetFile = QPushButton(
            self.localization.output_file_placeholder)
        self.boxUseSrcDir = QCheckBox(self.localization.button_use_src_dir)

        # connectors #
        self.buttonSrcFile.clicked.connect(self.selectSrcFile)
        self.buttonTargetFile.clicked.connect(self.selectTargetFile)
        self.boxUseSrcDir.stateChanged.connect(self.useSrcDir)
        self.boxUseSrcDir.setChecked(True)

        # layout #
        layout = QVBoxLayout()

        layout.addWidget(self.buttonSrcFile)
        layout.addWidget(self.srcFileName)

        layout.addWidget(self.buttonTargetFile)
        layout.addWidget(self.boxUseSrcDir)

        layout.addStretch(1)
        self.fileSelectionGroup.setLayout(layout)

    def createDateSelection(self):
        '''Generate the area containing the date selectors'''

        self.dateSelectionGroupBox = QGroupBox(
            self.localization.date_selection)

        layout = QGridLayout()

        self.startDateEdit = QDateEdit(calendarPopup=True)
        self.startDateEdit.setDisplayFormat("dd.MM.yyyy")
        self.startDateEdit.setReadOnly(True)
        self.startDateEdit.lineEdit().setDisabled(True)

        self.endDateEdit = QDateEdit(calendarPopup=True)
        self.endDateEdit.setDisplayFormat("dd.MM.yyyy")
        self.endDateEdit.setReadOnly(True)
        self.endDateEdit.lineEdit().setDisabled(True)

        self.startTimeEdit = QLineEdit("00:00")
        self.endTimeEdit = QLineEdit("23:59")
        self.startTimeEdit.setDisabled(True)
        self.endTimeEdit.setDisabled(True)

        layout.addWidget(self.startDateEdit, 0, 0)
        layout.addWidget(self.startTimeEdit, 0, 1)

        layout.addWidget(self.endDateEdit, 1, 0)
        layout.addWidget(self.endTimeEdit, 1, 1)

        layout.setColumnStretch(0, 1)
        layout.setColumnStretch(1, 1)

        self.dateSelectionGroupBox.setLayout(layout)

    def createCheckboxArea(self):
        '''Generate area  with configuration options'''

        self.checkboxGroup = QGroupBox(self.localization.options)

        self.boxOTemp = QCheckBox(self.localization.button_otemp)
        self.boxOHumidity = QCheckBox(self.localization.button_ohumidity)

        layout = QVBoxLayout()
        layout.addWidget(self.boxOTemp)
        layout.addWidget(self.boxOHumidity)
        layout.addStretch(1)
        self.checkboxGroup.setLayout(layout)

    def run(self):
        '''Run generation with selected file and options'''

        # set save target if nessesary #
        self.infoTextBox.clear()
        self.buttonGo.setText(self.localization.button_go_wait)
        self.buttonGo.setDisabled(True)
        self.repaint()

        if self.boxUseSrcDir.isChecked():
            target = self.srcFileString
            forcePath = False
        else:
            target = self.targetFileString
            forcePath = True

        # workaround for checkboxes changed #
        outsideDataNeeded = self.boxOTemp.isChecked(
        ) or self.boxOHumidity.isChecked()
        self.datapoints = input_backend.read_in_file(
            self.srcFileString,
            outsideData=outsideDataNeeded,
            plotOutsideTemp=self.boxOTemp.isChecked(),
            plotOutsideHum=self.boxOHumidity.isChecked(),
            qtTextBrowser=self.infoTextBox)

        # build dates #
        try:
            startTimeHelper = dt.datetime.strptime(self.startTimeEdit.text(),
                                                   "%H:%M")
            endTimeHelper = dt.datetime.strptime(self.endTimeEdit.text(),
                                                 "%H:%M")
        except ValueError as e:
            errorBox = QMessageBox(self)
            errorBox.setAttribute(PyQt5.QtCore.Qt.WA_DeleteOnClose)
            errorBox.setText(self.localization.bad_time)
            errorBox.setDetailedText(str(e))
            errorBox.show()
            self.buttonGo.setText(self.localization.button_go)
            self.buttonGo.setDisabled(False)
            return

        startTimeOffset = dt.timedelta(hours=startTimeHelper.hour,
                                       minutes=startTimeHelper.minute)
        endTimeOffset = dt.timedelta(hours=endTimeHelper.hour,
                                     minutes=endTimeHelper.minute)

        zeroTime = dt.time(0, 0)
        startDateTime = dt.datetime.combine(
            self.startDateEdit.date().toPyDate(), zeroTime)
        startDateTime += startTimeOffset
        endDateTime = dt.datetime.combine(self.endDateEdit.date().toPyDate(),
                                          zeroTime)
        endDateTime += endTimeOffset

        try:
            self.truePath = plot.plot(self.datapoints,
                                      path=target,
                                      date1=startDateTime,
                                      date2=endDateTime,
                                      forcePath=forcePath,
                                      qtTextBrowser=self.infoTextBox)
        except ValueError as e:
            self.infoTextBox.append("ERROR: " + str(e))
            self.buttonGo.setText(self.localization.button_go)
            return

        self.buttonGo.setText(self.localization.button_go)
        self.buttonGo.setDisabled(False)

        self.infoTextBox.append(self.localization.success)

        doneDialog = QMessageBox(self)
        doneDialog.setAttribute(PyQt5.QtCore.Qt.WA_DeleteOnClose)
        doneDialog.setText(self.localization.done_text)
        doneDialog.addButton(self.localization.open_pic, QMessageBox.YesRole)
        doneDialog.addButton(self.localization.close, QMessageBox.NoRole)
        doneDialog.buttonClicked.connect(self.openFile)
        doneDialog.show()

    def selectSrcFile(self):
        '''Function to select a src-file'''

        if not self.firstRun:
            targetDir = ""  # meaning the last one opened
        else:
            targetDir = cp.CFG("default_source_dir")

        self.srcFileString = QFileDialog.getOpenFileName(
            self, self.localization.src_file_dialog, targetDir,
            "Data-Files (*.txt *.csv *.dbf *.xls)")[0]
        self.srcFileName.setText(self.srcFileString)

        if not self.srcFileString:
            return

        self.infoTextBox.append(self.localization.testing_input)
        self.firstRun = False

        try:
            self.datapoints = input_backend.read_in_file(
                self.srcFileString,
                outsideData=False,
                plotOutsideTemp=False,
                plotOutsideHum=False,
                qtTextBrowser=self.infoTextBox)
        except Exception as e:
            errorBox = QMessageBox(self)
            errorBox.setStyleSheet("QLabel{min-width: 700px;}")
            errorBox.setAttribute(PyQt5.QtCore.Qt.WA_DeleteOnClose)
            errorBox.setText(self.localization.error_read_in)
            errorBox.setDetailedText(traceback.format_exc())
            errorBox.show()
            return

        start = self.datapoints[cp.CFG("plot_temperatur_key")].getFirstTime()
        self.startDateEdit.setDateTime(start)

        end = self.datapoints[cp.CFG("plot_temperatur_key")].getLastTime()
        self.endDateEdit.setDateTime(end)

        self.buttonGo.setDisabled(False)
        self.endDateEdit.setReadOnly(False)
        self.startDateEdit.setReadOnly(False)
        self.startDateEdit.lineEdit().setDisabled(False)
        self.endDateEdit.lineEdit().setDisabled(False)
        self.startTimeEdit.setDisabled(False)
        self.endTimeEdit.setDisabled(False)
        self.buttonGo.setFocus(PyQt5.QtCore.Qt.OtherFocusReason)

        self.infoTextBox.append(self.localization.testing_input_suc)

    def selectTargetFile(self):
        '''Function to select a target-file'''
        self.targetFileString = QFileDialog.getSaveFileName(
            self, self.localization.save_file_dialog)[0]
        if not self.targetFileString:
            return

        self.buttonTargetFile.setText(self.targetFileString)
        self.buttonGo.setDisabled(False)
        self.buttonGo.setFocus(PyQt5.QtCore.Qt.OtherFocusReason)

    def useSrcDir(self):
        '''Function to handle use src dir checkbox'''
        if self.boxUseSrcDir.isChecked():
            self.buttonTargetFile.setDisabled(True)
            if self.srcFileString:
                self.buttonGo.setDisabled(False)
                self.srcFileName.setText(self.srcFileString)
        else:
            self.buttonTargetFile.setDisabled(False)
            if self.targetFileString:
                self.buttonTargetFile.setText(self.targetFileString)
            else:
                self.buttonGo.setDisabled(True)

    def openFile(self, button):
        if button.text() == self.localization.open_pic and self.truePath:
            PyQt5.QtGui.QDesktopServices.openUrl(
                QUrl.fromLocalFile(self.truePath))
        else:
            pass
Example #33
0
class Invoice(QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setFixedSize(600, 650)
        self.setWindowTitle("Ver Fatura\Extrato: ")
        self.setWindowIcon(Icon('fatura.png'))

        layout = QFormLayout()
        self.account = QComboBox()
        accounts = DATABASE.getAccounts()
        for account in accounts:
            self.account.addItem(account)
        self.account.activated.connect(self.attPeriod)
        layout.addRow("Conta", self.account)

        self.period1 = QDateEdit()
        self.period1.setCalendarPopup(True)
        label = QLabel(" a ")
        label.setAlignment(Qt.AlignCenter)
        self.period2 = QDateEdit()
        self.period2.setCalendarPopup(True)
        dateLayout = QHBoxLayout()
        dateLayout.addWidget(self.period1, 1)
        dateLayout.addWidget(label)
        dateLayout.addWidget(self.period2, 1)
        layout.addRow("Periodo", dateLayout)

        infoBox = QHBoxLayout()
        infos = QFormLayout()
        self.accountView = QLabel()
        self.totalValue = QLabel()
        self.date1 = QLabel()
        label2 = QLabel(" a ")
        label2.setAlignment(Qt.AlignCenter)
        self.date2 = QLabel()
        dateLayout2 = QHBoxLayout()
        dateLayout2.addWidget(self.date1, 1)
        dateLayout2.addWidget(label2)
        dateLayout2.addWidget(self.date2, 1)
        infos.addRow("Conta", self.accountView)
        infos.addRow("Período ", dateLayout2)
        infos.addRow("Total", self.totalValue)
        infoBox.addLayout(infos)

        left = QToolButton()
        left.setArrowType(Qt.LeftArrow)
        left.clicked.connect(self.previousMonth)
        right = QToolButton()
        right.setArrowType(Qt.RightArrow)
        right.clicked.connect(self.nextMonth)
        infoBox.addWidget(left)
        infoBox.addWidget(right)
        infoBox.addStretch(1)
        layout.addRow(infoBox)

        self.table = Tree(4)
        self.table.setHeaderLabels(['Data', 'Descrição', 'Categoria', 'Valor'])
        self.table.setResizeColumn(2)
        self.table.itemDoubleClicked.connect(self.editItem)
        self.table.itemClicked.connect(self.alterSum)
        layout.addRow(self.table)

        self.attPeriod(0)
        self.period1.dateChanged.connect(self.showTable)
        self.period2.dateChanged.connect(self.showTable)
        self.setLayout(layout)

    def alterSum(self, item, column):
        if column == 1:
            suma = 0
            for itemTree in self.table.getChecked(1):
                if itemTree.checkState(1):
                    suma += float(itemTree.text(4)[3:])
            self.totalValue.setText("R$ %.2f" % suma)

    def attPeriod(self, index):
        info = DATABASE.getAccounts(name=self.account.itemText(index), info=True)
        currentDate = QDate.currentDate()
        if info[3]:
            currentDate.setDate(currentDate.year(), currentDate.month() - 1, info[3] + 1)
            self.period1.setDate(currentDate.addDays(-10))
            self.period2.setDate(currentDate.addMonths(1).addDays(-11))
            self.showTable()
        else:
            currentDate.setDate(currentDate.year(), currentDate.month(), 1)
            self.period1.setDate(currentDate)
            self.period2.setDate(QDate(currentDate.year(), currentDate.month(), currentDate.daysInMonth()))
            self.showTable(inverse=True)

    def editItem(self, item, column):
        self.parent().mainWindow.transWindow.editItem(item, column, invoice=True)
        self.showTable()

    def nextMonth(self):
        self.period1.setDate(self.period1.date().addMonths(1))
        self.period2.setDate(self.period2.date().addMonths(1))

    def previousMonth(self):
        self.period1.setDate(self.period1.date().addMonths(-1))
        self.period2.setDate(self.period2.date().addMonths(-1))

    def showTable(self, inverse=False):
        self.table.clear()
        self.table.setHeaderLabels(["#",'Data', 'Descrição', 'Categoria', 'Valor'])
        self.accountView.setText(self.account.currentText())
        self.date1.setText(self.period1.date().toString("dd/MM/yyyy"))
        self.date2.setText(self.period2.date().toString("dd/MM/yyyy"))
        transactions = DATABASE.getTransactionsFrom(self.period1.date(),
                                                    self.period2.date(),
                                                    self.account.currentText())
        suma = 0
        count = 1
        for trans in transactions:
            row = TreeItem(self.table, '')
            row.setIdent(trans[0])
            row.setData(0, Qt.DisplayRole, count)
            row.setData(1, Qt.DisplayRole, QDate(trans[3], trans[2], trans[1]), )
            row.setCheckState(1, Qt.Checked)
            row.setText(2, trans[4])
            row.setText(3, trans[5])
            if inverse:
                row.setText(4, "R$ %.2f" % trans[8])
                suma += trans[8]
            else:
                row.setText(4, "R$ %.2f" % -trans[8])
                suma -= trans[8]
            if trans[8] > 0:
                defineColor(row, trans[8], 2)
            count += 1

        self.totalValue.setText("R$ %.2f" % suma)
        self.table.resizeColumnToContents(0)
Example #34
0
class Addstocks(QWidget):

    def __init__(self, pf):
        self.counter = 0
        self.pf = pf
        super(Addstocks, self).__init__()
        self.setMinimumSize(QSize(300, 230))
        self.resize(550, 320)
        self.setWindowTitle("Add stocks")

        self.setAutoFillBackground(True)
        p = self.palette()
        p.setColor(self.backgroundRole(), Qt.darkCyan)  # darkcyan
        self.setPalette(p)

        label1 = QLabel("Enter a stock ticker:", self)
        self.ticker = QLineEdit(self)
        self.ticker.move(270, 20)
        self.ticker.resize(200, 32)
        label1.move(20, 25)

        label2 = QLabel("How many shares?", self)
        self.amount = QLineEdit(self)
        self.amount.move(270, 80)
        self.amount.resize(200, 32)
        label2.move(20, 85)

        label3 = QLabel("When you bought it?", self)
        self.date = QDateEdit(self)
        self.date.move(270, 140)
        self.date.resize(200, 32)
        self.date.setDate(QDate.currentDate())

        label3.move(20, 145)
        self.date.editingFinished.connect(self.date_method)

        pybutton = QPushButton('Add a stock', self)
        pybutton.clicked.connect(self.click)
        pybutton.resize(200, 32)
        pybutton.move(270, 200)

        pybutton2 = QPushButton('Finished', self)
        pybutton2.clicked.connect(self.click1)
        pybutton2.resize(200, 32)
        pybutton2.move(270, 260)

    def date_method(self):
        # Change the date received by the user into a correct form
        self.counter += 1
        value = self.date.date()
        self.day = value.toPyDate()

    def click(self):
        # Finds the ticker from Yahoo Finance and checks that the number of stocks owned is legit.
        # Also checks that the date chosen is a legitimate.
        # self.counter is used because editingFinished.connect does not work if the user does not touch the
        # date picker at all. Thus, the program needs to have a date even though the date_method has not been
        # activated.
        if self.counter == 0:
            value = QDate.currentDate()
            self.day = value.toPyDate()
        today = date.today()
        delta = today - self.day
        if delta.days < 0:
            QMessageBox.about(self, "Error", "The date you gave is incorrect.")
        else:
            self.stock = self.ticker.text()
            self.am = self.amount.text()
            tc = yf.Ticker(self.stock)
            pricedata = tc.history(period='5y')['Close']
            if len(pricedata) > 0:
                try:
                    self.am = float(self.am)
                    if self.am < 0.01:
                        QMessageBox.about(self, "Error", "Incorrect amount!")
                    else:
                        self.pf.add_stock(self.stock, self.am, self.day)
                        QMessageBox.about(self, "Success", "Stock added!")
                        self.amount.clear()
                        self.ticker.clear()
                except ValueError:
                    QMessageBox.about(self, "Error", "Incorrect amount!")

            else:
                QMessageBox.about(self, "Error", "Did not find any data for that stock.")

    def click1(self):
        #counts the different ratios for the portfolio and launches the new window
        self.pf.pf_value()
        self.pf.pf_returns()
        self.pf.get_greeks()
        self.pf.count_sharpe()
        self.next_window = Infopage(self.pf)
        self.next_window.show()
        self.close()
Example #35
0
class AddressForm:
    user_id = None

    def __init__(self, user=None):
        self.form_layout = QFormLayout()
        self.second_name = QLineEdit()
        self.first_name = QLineEdit()
        self.birthday = QDateEdit()
        self.notes = QTextEdit()
        self.phones = list()
        if user is not None and user['id'] is not None:
            self.user_id = user['id']
        if user is not None and user['second_name'] is not None:
            self.second_name.setText(user['second_name'])
        second_name_label = QLabel('Фамилия:')
        if user is not None and user['first_name'] is not None:
            self.first_name.setText(user['first_name'])
        first_name_label = QLabel('Имя:')
        self.birthday.setCalendarPopup(True)
        self.birthday.setDisplayFormat('dd MMMM yyyy')
        if user is not None and user['birthday'] is not None:
            self.birthday.setDate(
                QDate.fromString(user['birthday'], "d.M.yyyy"))
        birthday_label = QLabel('Дата рождения:')
        notes_label = QLabel('Примечание:')
        if user is not None and user['notes'] is not None:
            self.notes.setText(user['notes'])

        self.form_layout.addRow(second_name_label, self.second_name)
        self.form_layout.addRow(first_name_label, self.first_name)
        self.form_layout.addRow(birthday_label, self.birthday)
        self.form_layout.addRow(notes_label, self.notes)

        phone_label = QLabel('Телефон')
        self.form_layout.addRow(phone_label)
        if user is not None and user['phone'] is not None:
            for phone_row in user['phone']:
                phone = QLineEdit()
                phone.setText(phone_row['phone'])
                phone_type = QComboBox()
                phone_type.addItem('Домашний')
                phone_type.addItem('Рабочий')
                if phone_row['type'] == 'home':
                    phone_type.setCurrentIndex(0)
                if phone_row['type'] == 'work':
                    phone_type.setCurrentIndex(1)

                self.phones.append({'phone': phone, 'type': phone_type})
                self.form_layout.addRow(phone_type, phone)
        phone = QLineEdit()
        phone_type = QComboBox()
        phone_type.addItem('Домашний')
        phone_type.addItem('Рабочий')
        self.phones.append({'phone': phone, 'type': phone_type})

        self.form_layout.addRow(phone_type, phone)

    def add_row(self, *args):
        self.form_layout.addRow(*args)

    def get_layout(self):
        return self.form_layout

    def get_second_name(self):
        return self.second_name.text()

    def get_first_name(self):
        return self.first_name.text()

    def get_birthday(self):
        tmp_date = self.birthday.date()
        tmp_date = tmp_date.toPyDate()
        return '{0:%d.%m.%Y}'.format(tmp_date)

    def get_notes(self):
        return self.notes.toPlainText()

    def get_phones(self):
        return self.phones

    def get_user_id(self):
        return self.user_id

    def validate_form(self):
        errors = list()
Example #36
0
class DataWidget(QWidget):

    def __init__(self):
        super(DataWidget, self).__init__(None)
        self.read_data_file(config.HISTORIC_DATA)
        self.start_date = date(2016, 10, 1)
        self.end_date = date(2016, 11, 1)
        self.graph = GraphCanvas(self.data_frame)
        with open(config.LOGFILE, 'w', newline='') as logfile:
            logwriter = csv.writer(logfile)
            logwriter.writerow(config.headers)

        # options group box
        self.optionsGroupBox = QGroupBox("Options")
        options_layout = QVBoxLayout()
        date_range_layout = QFormLayout()
        start_date_label = QLabel("Start Date:")
        self.start_date_box = QDateEdit(self.start_date)
        self.start_date_box.setCalendarPopup(True)
        self.start_date_box.setDisplayFormat(config.DATE_DISPLAY_FORMAT)
        self.start_date_box.dateChanged.connect(self.plot)
        end_date_label = QLabel("End Date:")
        self.end_date_box = QDateEdit(self.end_date)
        self.end_date_box.setCalendarPopup(True)
        self.end_date_box.setDisplayFormat(config.DATE_DISPLAY_FORMAT)
        self.end_date_box.dateChanged.connect(self.plot)
        date_range_layout.addRow(start_date_label, self.start_date_box)
        date_range_layout.addRow(end_date_label, self.end_date_box)
        # days of week
        self.sundayCheckBox = QCheckBox("Sunday")
        self.mondayCheckBox = QCheckBox("Monday")
        self.tuesdayCheckBox = QCheckBox("Tuesday")
        self.wednesdayCheckBox = QCheckBox("Wednesday")
        self.thursdayCheckBox = QCheckBox("Thursday")
        self.fridayCheckBox = QCheckBox("Friday")
        self.saturdayCheckBox = QCheckBox("Saturday")
        self.sundayCheckBox.toggled.connect(self.plot)
        self.mondayCheckBox.toggled.connect(self.plot)
        self.tuesdayCheckBox.toggled.connect(self.plot)
        self.wednesdayCheckBox.toggled.connect(self.plot)
        self.thursdayCheckBox.toggled.connect(self.plot)
        self.fridayCheckBox.toggled.connect(self.plot)
        self.saturdayCheckBox.toggled.connect(self.plot)

        options_layout.addLayout(date_range_layout)
        options_layout.addWidget(self.sundayCheckBox)
        options_layout.addWidget(self.mondayCheckBox)
        options_layout.addWidget(self.tuesdayCheckBox)
        options_layout.addWidget(self.wednesdayCheckBox)
        options_layout.addWidget(self.thursdayCheckBox)
        options_layout.addWidget(self.fridayCheckBox)
        options_layout.addWidget(self.saturdayCheckBox)
        options_layout.addWidget(QPushButton("Button"))
        self.optionsGroupBox.setLayout(options_layout)

        # graph group box
        self.graphGroupBox = QGroupBox("Graph")
        graphLayout = QVBoxLayout()
        graphLayout.addWidget(self.graph)
        self.graphGroupBox.setLayout(graphLayout)

        # choice group box
        self.choiceGroupBox = QGroupBox("Choice")

        choice_layout = QVBoxLayout()

        choice_layout_1 = QHBoxLayout()
        choice_layout_1.addWidget(QLabel("A"))
        choice_layout_1.addWidget(QLabel("B"))
        choice_layout_1.addWidget(QLabel("C"))
        choice_layout_1.addWidget(QLabel("D"))

        choice_layout_2 = QHBoxLayout()
        self.decision_value_1 = QSpinBox()
        self.decision_value_2 = QSpinBox()
        self.decision_value_3 = QSpinBox()
        self.decision_value_4 = QSpinBox()
        choice_layout_2.addWidget(self.decision_value_1)
        choice_layout_2.addWidget(self.decision_value_2)
        choice_layout_2.addWidget(self.decision_value_3)
        choice_layout_2.addWidget(self.decision_value_4)

        choice_layout.addLayout(choice_layout_1)
        choice_layout.addLayout(choice_layout_2)

        self.decision_value_1.setValue(42)

        self.choiceGroupBox.setLayout(choice_layout)

        # count-down timer
        self.timerGroupBox = QGroupBox("Timer")
        timer_layout = QVBoxLayout()
        self.timerGroupBox.setLayout(timer_layout)
        self.count_down_timer = CountDownTimer()
        timer_layout.addWidget(self.count_down_timer.lcd)

        # central widget
        frame = QFrame(self)
        self.grid = QGridLayout(frame)
        self.grid.setSpacing(16)
        self.grid.setContentsMargins(16, 16, 16, 16)
        self.grid.addWidget(self.optionsGroupBox, 0, 0, 2, 1)
        self.grid.addWidget(self.graphGroupBox, 0, 1, 2, 1)
        self.grid.addWidget(self.timerGroupBox, 0, 2)
        self.grid.addWidget(self.choiceGroupBox, 2, 1)
        self.grid.setColumnStretch(0, 2)
        self.grid.setColumnStretch(1, 6)
        self.grid.setColumnStretch(2, 1)
        self.grid.setRowStretch(0, 1)
        self.grid.setRowStretch(1, 2)
        self.grid.setRowStretch(2, 2)
        self.setLayout(self.grid)

    def read_data_file(self, data_file):
        """read data_file and import it's content as pandas dataframe"""
        dateparse = lambda x: pd.datetime.strptime(x, '%Y-%m-%d')
        self.data_frame = pd.read_csv(data_file,
                                      index_col=0,
                                      parse_dates=True)

    def plot(self):
        """
        Method to update start / end dates upon selection. Fetch the start /
        end dates, convert the QTime datatype to DateTime.Date datatype, and
        plot the graph.
        """
        self.start_date = self.start_date_box.date().toPyDate()
        self.end_date = self.end_date_box.date().toPyDate()
        self.graph.plot(self.data_frame.loc[self.start_date : self.end_date])

    def add_log_row(self):
        """
        Write data in the log file
        :return:
        """
        new_row = [config.id, config.age, config.male, config.field,
                   'test_condition', datetime.now()]
        with open(config.LOGFILE, 'a', newline='') as logfile:
            logwriter = csv.writer(logfile)
            logwriter.writerow(new_row)