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
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 ;-)