Example #1
0
    def __init__(self, parent=None):
        from main_window_gui import Ui_table_window
        QtGui.QMainWindow.__init__(self, parent)

        self.ui = Ui_table_window()                                     # setting form
        self.ui.setupUi(self)

        itemlist = ['Да', 'Нет']
        self.ui.the_table.setItemDelegateForColumn(5, ComboDelegate(self.ui.the_table, itemlist))
        self.ui.the_table.setItemDelegateForColumn(6, ComboDelegate(self.ui.the_table, itemlist))

        self.ui.informedBox.setCurrentIndex(2)
        self.ui.beforeBox.setCurrentIndex(2)
        self.ui.afterBox.setCurrentIndex(2)
        self.ui.agreedBox.setCurrentIndex(0)
        self.ui.contractBox.setCurrentIndex(0)

        self.status_bar_refresh(init_dict)                              # setting initial period in status bar
        self.fill_in_table(search_db(init_dict))                        # initial table filling with init period's data

        self.connections()                                              # setting connections for this window
Example #2
0
class WindowMain(QtGui.QMainWindow):
    resize_signal = QtCore.pyqtSignal()                                 # new signal for window resize

    def __init__(self, parent=None):
        from main_window_gui import Ui_table_window
        QtGui.QMainWindow.__init__(self, parent)

        self.ui = Ui_table_window()                                     # setting form
        self.ui.setupUi(self)

        itemlist = ['Да', 'Нет']
        self.ui.the_table.setItemDelegateForColumn(5, ComboDelegate(self.ui.the_table, itemlist))
        self.ui.the_table.setItemDelegateForColumn(6, ComboDelegate(self.ui.the_table, itemlist))

        self.ui.informedBox.setCurrentIndex(2)
        self.ui.beforeBox.setCurrentIndex(2)
        self.ui.afterBox.setCurrentIndex(2)
        self.ui.agreedBox.setCurrentIndex(0)
        self.ui.contractBox.setCurrentIndex(0)

        self.status_bar_refresh(init_dict)                              # setting initial period in status bar
        self.fill_in_table(search_db(init_dict))                        # initial table filling with init period's data

        self.connections()                                              # setting connections for this window

    def connections(self):
        form = self.ui

        self.ui.menu_quit.setShortcut('Ctrl+Q')
        self.ui.menu_quit.triggered.connect(self.hide_window)

        search_button_press = QtGui.QAction(self)                           # This is a piece of magic
        search_button_press.setShortcut(QtGui.QKeySequence('Ctrl+return'))  # dunno how it works it's just a prayer
        self.connect(search_button_press, QtCore.SIGNAL("activated()"),     # of a lonely Cargo-cult adept
                     self.ui.searchButton, QtCore.SLOT("animateClick()"))   # this code just makes a search_button
        # search_button_press.connect(self.read_data)                       # TODO: find out why it's not working
        self.addAction(search_button_press)                                 # be clickable by a 'return' shortcut

        self.resize_signal.connect(self.align)
        form.searchButton.clicked.connect(self.read_data)
        form.p_dateButton.clicked.connect(lambda: self.set_search_period('p'))
        form.c_dateButton.clicked.connect(lambda: self.set_search_period('c'))
        form.informedBox.currentIndexChanged.connect(lambda: self.set_flags(form.informedBox.currentIndex(),
                                                                            'INFORMED'))
        form.beforeBox.currentIndexChanged.connect(lambda: self.set_flags(form.beforeBox.currentIndex(),
                                                                          'B_B'))
        form.afterBox.currentIndexChanged.connect(lambda: self.set_flags(form.afterBox.currentIndex(),
                                                                         'B_A'))
        form.agreedBox.currentIndexChanged.connect(lambda: self.set_flags(form.agreedBox.currentIndex(),
                                                                          'AGREED'))
        form.contractBox.currentIndexChanged.connect(lambda: self.set_flags(form.contractBox.currentIndex(),
                                                                            'CONTRACT'))
        form.the_table.itemChanged.connect(lambda: self.change_db_value(form.the_table.currentRow(),
                                                                        form.the_table.currentColumn()))
        form.the_table.horizontalHeader().sectionResized.connect(self.resize_widgets)

    def disconnections(self, b=True):
        form = self.ui
        if b:
            form.the_table.itemChanged.disconnect()
            form.informedBox.currentIndexChanged.disconnect()
            form.beforeBox.currentIndexChanged.disconnect()
            form.afterBox.currentIndexChanged.disconnect()
            form.agreedBox.currentIndexChanged.disconnect()
            form.contractBox.currentIndexChanged.disconnect()
        else:
            form.the_table.itemChanged.connect(lambda: self.change_db_value(self.ui.the_table.currentRow(),
                                                                            self.ui.the_table.currentColumn()))
            form.informedBox.currentIndexChanged.connect(lambda: self.set_flags(form.informedBox.currentIndex(),
                                                                                'INFORMED'))
            form.beforeBox.currentIndexChanged.connect(lambda: self.set_flags(form.beforeBox.currentIndex(),
                                                                              'B_B'))
            form.afterBox.currentIndexChanged.connect(lambda: self.set_flags(form.afterBox.currentIndex(),
                                                                             'B_A'))
            form.agreedBox.currentIndexChanged.connect(lambda: self.set_flags(form.agreedBox.currentIndex(),
                                                                             'agreed'))
            form.contractBox.currentIndexChanged.connect(lambda: self.set_flags(form.contractBox.currentIndex(),
                                                                                'CONTRACT'))

    def read_data(self):
        """sets global 'search_dict' values with current values of lineEdits"""
        global search_dict

        # without this every cell will be filled with random and written to the db:
        self.disconnections()
        # connecting this back in the end of method

        search_dict['NAME'] = self.ui.nameEdit.text()               # getting data from edit lines
        search_dict['PHONE'] = self.ui.phoneEdit.text()
        search_dict['COMMENT'] = self.ui.commentEdit.text()

        for k, i in search_dict.items():                            # looking through the dict
            if i:                                                   # if there is anything in the search_dict,
                self.fill_in_table(search_db())                     # then run a search in db and fill the table
                self.status_bar_refresh()                           # update status bar period

                self.ui.nameEdit.setText('')                        # return all our widgets
                self.ui.phoneEdit.setText('')                       # to primordial state
                self.ui.commentEdit.setText('')
                self.ui.informedBox.setCurrentIndex(2)
                self.ui.beforeBox.setCurrentIndex(2)
                self.ui.afterBox.setCurrentIndex(2)
                self.ui.agreedBox.setCurrentIndex(1)
                self.ui.contractBox.setCurrentIndex(0)
                self.change_button_text()
                self.status_bar_refresh()

                # now we need to connect table and db again and then exit method
                self.disconnections(False)

                # noinspection PyAssignmentToLoopOrWithParameter
                for k, i in search_dict.items():                    # this loop clears the search_dict of previous data
                    if i:
                        search_dict[k] = ''
                return
        # if the search_dict is empty, we use init_dict instead
        self.fill_in_table(search_db(init_dict))                    # fill the table with init period's data
        self.status_bar_refresh(init_dict)                          # update status bar with init period
        # and connect the table and db back again
        self.disconnections(False)

    def fill_in_table(self, data_rows):
        """takes a list as an arg and fills the table with its rows and columns"""
        from parsers import date_transform

        self.ui.the_table.setRowCount(len(data_rows))                       # setting row number by number of strings
        list_of_ids = []                                                    # the list is for table's vertical header
        # query_strings = '''SELECT NAME, PHONE, P_DATE, C_DATE, COMMENT, INFORMED, AGREED, CONTRACT, B_B, B_A, ID
        #               FROM NOTIFY NATURAL JOIN NAMES WHERE ''' + ' AND '.join(str(s) for s in query_strings)
        for row in range(0, len(data_rows)):                                # from first to last row:
            list_of_ids.append(str(data_rows[row][-1]))                     # add new purchase-id from current row
            data_rows[row] = [f for f in data_rows[row]]                    # changing the row from tuple to list TODO: use list()?
            data_rows[row][2] = date_transform(data_rows[row][2], '.', 0)   # transforming dates from SQLite format
            data_rows[row][3] = date_transform(data_rows[row][3], '.', 0)   # to human-readable format (dd-mm-yyyy)
            for column in range(0, 10):                                     # filling table loop
                item = QtGui.QTableWidgetItem(str(data_rows[row][column]))  # creating new item with text from db
                if (column < 4) or (column > 6):                            # setting columns 0-3 and 6-9
                    item.setFlags(QtCore.Qt.ItemIsEnabled)                  # user read-only
                self.ui.the_table.setItem(row, column, item)                # inserting a new item in a cell
        self.ui.the_table.setVerticalHeaderLabels(list_of_ids)              # filling vertical headers labels

    def change_db_value(self, row, column):
        if self.ui.the_table.selectedIndexes():
            try:
                id_number = self.ui.the_table.verticalHeaderItem(row).text()
                value = self.ui.the_table.item(row, column).text()
            except AttributeError:
                print('cell is not selected')
                return
            db_connection = sqlite3.connect(db_path_name)
            if column == 5:
                query_string = 'UPDATE NOTIFY SET INFORMED = ? WHERE ID == ?'
            else:
                id_number = db_connection.execute('SELECT CUSTOMER_ID FROM NOTIFY WHERE ID == ?',
                                                  (id_number,)).fetchone()[0]
                if column == 4:
                    query_string = 'UPDATE NAMES SET COMMENT = ? WHERE CUSTOMER_ID == ?'
                else:
                    query_string = 'UPDATE NAMES SET AGREED = ? WHERE CUSTOMER_ID == ?'
            db_connection.execute(query_string, (str(value), str(id_number)))
            db_connection.commit()
            db_connection.close()

    def set_search_period(self, date_type):
        """takes 'p' or 'c' as second argument, calls the date_set dialog
        and sets corresponding global 'search_dict' date values and button text"""
        global search_dict
        period_dlg = DateWindow(self)
        if period_dlg.exec_():
            values = period_dlg.return_period()
            if date_type == 'p':
                search_dict['P_DATE'] = values
                self.change_button_text('P_DATE')
            elif date_type == 'c':
                search_dict['C_DATE'] = values
                self.change_button_text('C_DATE')

    def resize_widgets(self):

        # calculating space left after resizing first five columns
        space_left = self.ui.the_table.geometry().width()
        for i in range(0, 5):
            space_left -= self.ui.the_table.columnWidth(i)
        # and dividing it on left five columns
        space_left /= 5
        for i in range(5, 10):
            self.ui.the_table.setColumnWidth(i, space_left - 20)    # without this '- 20' crutch last column runs away

        # setting widgets up accordingly to the corresponding column
        self.ui.nameEdit.setGeometry(self.ui.searchButton.geometry().right() + 5, 10,
                                     self.ui.the_table.columnWidth(0) - 5, 45)
        self.ui.phoneEdit.setGeometry(self.ui.nameEdit.geometry().right() + 6, 10,
                                      self.ui.the_table.columnWidth(1) - 5, 45)
        self.ui.p_dateButton.setGeometry(self.ui.phoneEdit.geometry().right() + 6, 10,
                                         self.ui.the_table.columnWidth(2) - 5, 45)
        self.ui.c_dateButton.setGeometry(self.ui.p_dateButton.geometry().right() + 6, 10,
                                         self.ui.the_table.columnWidth(3) - 5, 45)
        self.ui.commentEdit.setGeometry(self.ui.c_dateButton.geometry().right() + 6, 10,
                                        self.ui.the_table.columnWidth(4) - 5, 45)
        self.ui.informedBox.setGeometry(self.ui.commentEdit.geometry().right() + 6, 10,
                                        self.ui.the_table.columnWidth(5) - 5, 45)
        self.ui.agreedBox.setGeometry(self.ui.informedBox.geometry().right() + 6, 10,
                                      self.ui.the_table.columnWidth(6) - 5, 45)
        self.ui.contractBox.setGeometry(self.ui.agreedBox.geometry().right() + 6, 10,
                                        self.ui.the_table.columnWidth(7) - 5, 45)
        self.ui.beforeBox.setGeometry(self.ui.contractBox.geometry().right() + 6, 10,
                                      self.ui.the_table.columnWidth(8) - 5, 45)
        self.ui.afterBox.setGeometry(self.ui.beforeBox.geometry().right() + 6, 10,
                                     self.ui.the_table.columnWidth(9) - 5, 45)

    def status_bar_refresh(self, s_dict=search_dict):
        """Updates status bar text with chosen period"""
        from parsers import date_transform
        p = ''
        c = ''
        if s_dict['P_DATE']:
            l = list(s_dict['P_DATE'][1:])
            for i in range(0, len(l)):
                l[i] = date_transform(l[i], '.', 0)
            if len(l) == 2:
                p = 'период покупок c ' + l[0] + ' по ' + l[1]
            else:
                p = 'период покупок: ' + l[0]
        if s_dict['C_DATE']:
            l = list(s_dict['C_DATE'][1:])
            for i in range(0, len(l)):
                l[i] = date_transform(l[i], '.', 0)
            if len(l) == 2:
                c = 'период замены c ' + l[0] + ' по ' + l[1]
            else:
                c = 'период замены: ' + l[0]
        if p and c:
            self.setStatusTip('Выбран ' + p + ' и ' + c + '.')
        elif p:
            self.setStatusTip('Выбран ' + p + '.')
        elif c:
            self.setStatusTip('Выбран ' + c + '.')
        else:
            self.setStatusTip('Период не выбран')

    def align(self):
        """method aligns table geometry with window """

        self.ui.the_table.setGeometry(10, 60, self.geometry().width() - 20, self.geometry().height() - 90)
        self.ui.the_table.resizeColumnsToContents()
        self.ui.the_table.horizontalHeader().setStretchLastSection(True)
        self.ui.searchButton.setGeometry(10, 10, self.ui.the_table.verticalHeader().sectionSize(0) + 10, 45)
        # the last string is here just because i'm too lazy to find the button size. TODO: find this out

    def change_button_text(self, date=''):
        """changes text on date buttons depending on what period or date is set"""
        from parsers import date_transform
        if date:
            l = list(search_dict[date][1:])
            for i in range(0, len(l)):
                l[i] = date_transform(l[i], '.', 0)
            caption = '\n'.join(l)
            if date == 'P_DATE':
                self.ui.p_dateButton.setText(caption)
            elif date == 'C_DATE':
                self.ui.c_dateButton.setText(caption)
        else:
            self.ui.p_dateButton.setText('Дата\nпокупки')
            self.ui.c_dateButton.setText('Дата\nзамены')

    @staticmethod
    def set_flags(box_value, flag):
        if box_value == 0:
            search_dict[flag] = ''
        elif box_value == 1:
            search_dict[flag] = 'Да'
        else:
            search_dict[flag] = 'Нет'

    def hide_window(self):
        # kinda self-commenting method ;-)
        # but the only thing we need to do here is to keep tray icon's 'show\hide' menu in adorable condition
        self.parent().tray.menu.actions()[0].setChecked(False)
        self.hide()

    def closeEvent(self, event):
        self.hide_window()                              # redefined because we don't need it to actually be closed
        # self.deleteLater()                            # uncomment in case of strange behavior
        event.ignore()

    def changeEvent(self, event):
        if event.type() == QtCore.QEvent.WindowStateChange:             # hiding window on a minimize action
            if self.isMinimized():                                      # TODO: look for a better way
                self.hide_window()

    def resizeEvent(self, event):
        self.resize_signal.emit()                           # emitting our shiny brand new signal ;-)