├── .phones.sqlite3 ├── images └── phone.gif ├── requirements.txt ├── LICENSE ├── README.chinese.md ├── README.hindi.md ├── README.md ├── README.ru.md ├── gui.py ├── gui_draft.py └── main.py /.phones.sqlite3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BEPb/Phonebook/HEAD/.phones.sqlite3 -------------------------------------------------------------------------------- /images/phone.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BEPb/Phonebook/HEAD/images/phone.gif -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | PyQt5==5.15.1 2 | PyQt5-sip==12.8.1 3 | XlsxWriter==1.3.6 4 | xlrd==1.2.0 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Andrej Marinchenko 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.chinese.md: -------------------------------------------------------------------------------- 1 | # Phonebook 2 | 3 | Your own Phonebook written in python. 4 |

5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |

16 | 17 | 18 | 19 | Read in other languages: [English](README.md), [हिन्दी](README.hindi.md), [Russian](README.ru.md) 20 | 21 | 22 | 23 | ![GUI](images/phone.gif) 24 | 25 | 26 | ##如何安裝和運行 27 | ____ 28 | ### 克隆存儲庫 29 | 30 | ```sh 31 | $ cmd 32 | $ git clone https://github.com/BEPb/Browser 33 | $ cd Browser 34 | ``` 35 | 36 | ### 安裝必要的包(安裝依賴) 37 | ```sh 38 | $ pip install -r requirements.txt 39 | ``` 40 | 41 | ## 用法 42 | 要啟動 GUI: 43 | ``` 44 | python3 -m main 45 | ``` 46 | 47 | ## 項目發展 48 | 歡迎提出項目開發請求。 對於重大更改,請先打開一個問題,以便 49 | 討論你想改變什麼。 50 | ____ 51 | 52 | ## 執照 53 | 54 | 55 | [MIT](LICENSE.txt) 56 | 57 | ____ 58 | 59 | 60 | -------------------------------------------------------------------------------- /README.hindi.md: -------------------------------------------------------------------------------- 1 | # Phonebook 2 | 3 | Your own Phonebook written in python. 4 |

5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |

16 | 17 | 18 | 19 | Read in other languages: [English](README.md), [Russian](README.ru.md), [中國人](README.chinese.md) 20 | 21 | 22 | 23 | ![GUI](images/phone.gif) 24 | 25 | 26 | ## कैसे स्थापित करें और चलाएं 27 | ____ 28 | ### रिपॉजिटरी को क्लोन करें 29 | 30 | ```sh 31 | $ cmd 32 | $ git clone https://github.com/BEPb/Browser 33 | $ cd Browser 34 | ``` 35 | 36 | ### आवश्यक पैकेज स्थापित करें (निर्भरता स्थापित करें) 37 | ```sh 38 | $ pip install -r requirements.txt 39 | 40 | ``` 41 | 42 | ## उपयोग 43 | 要啟動 GUI: 44 | ``` 45 | python3 -m main 46 | ``` 47 | 48 | ## परियोजना का विकास 49 | परियोजना विकास अनुरोधों का स्वागत है। बड़े बदलावों के लिए, कृपया पहले एक मुद्दा खोलें ताकि 50 | चर्चा करें कि आप क्या बदलना चाहते हैं। 51 | ____ 52 | 53 | ## लाइसेंस 54 | 55 | [MIT](LICENSE.txt) 56 | 57 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Phonebook 2 | 3 | Your own Phonebook written in python. 4 |

5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |

16 | 17 | 18 | Read in other languages: [Russian](README.ru.md), [हिन्दी](README.hindi.md), [中國人](README.chinese.md) 19 | 20 | 21 | 22 | ![GUI](images/phone.gif) 23 | 24 | 25 | 26 | ## How to install and run 27 | ____ 28 | ### Clone the repository 29 | 30 | ```sh 31 | $ cmd 32 | $ git clone https://github.com/BEPb/Phonebook 33 | $ cd Phonebook 34 | ``` 35 | 36 | ### Install the necessary packages (Install dependencies) 37 | ```sh 38 | $ pip install -r requirements.txt 39 | ``` 40 | 41 | ## Usage 42 | To launch the GUI: 43 | ``` 44 | python3 -m main 45 | ``` 46 | ## Contributing 47 | Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. 48 | ____ 49 | 50 | ## License 51 | 52 | 53 | [MIT](LICENSE.txt) 54 | 55 | ____ 56 | 57 | 58 | -------------------------------------------------------------------------------- /README.ru.md: -------------------------------------------------------------------------------- 1 | # Phonebook 2 | 3 | Ваша собственный телефонный справочник написанный на питоне. 4 |

5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |

16 | 17 | 18 | 19 | Читать на других языках: [English](README.md), [हिन्दी](README.hindi.md), [中國人](README.chinese.md) 20 | 21 | 22 | 23 | ![GUI](images/phone.gif) 24 | 25 | 26 | ## Порядок установки и запуска 27 | ____ 28 | ### Клонируем репозиторий (Clone the repository) 29 | 30 | ```sh 31 | $ cmd 32 | $ git clone https://github.com/BEPb/Browser 33 | $ cd Browser 34 | ``` 35 | 36 | ### Устанавливаем необходимые пакеты (Install dependencies) 37 | ```sh 38 | $ pip install -r requirements.txt 39 | 40 | ``` 41 | 42 | ## Использование 43 | Чтобы запустить графический интерфейс: 44 | ``` 45 | python main.py 46 | ``` 47 | 48 | ## Развитие проекта 49 | Запросы на развитие проекта приветствуются. Для серьезных изменений, пожалуйста, сначала откройте вопрос, чтобы 50 | обсудить, что вы хотели бы изменить. 51 | ____ 52 | 53 | ## Лицензия 54 | [MIT](LICENSE.txt) 55 | 56 | -------------------------------------------------------------------------------- /gui.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Python 3.9 программа консольного приложения телефонного справочника 4 | Название файла gui.py 5 | 6 | Version: 0.1 7 | Author: Andrej Marinchenko 8 | Date: 2022-04-23 9 | """ 10 | 11 | from PyQt5 import QtCore, QtGui, QtWidgets 12 | 13 | 14 | class Ui_MainWindow(object): 15 | def setupUi(self, MainWindow): 16 | MainWindow.setObjectName("MainWindow") # создаем экземпляр объекта главного окна 17 | font = QtGui.QFont() # 18 | font.setFamily("Tahoma") # определяем шрифт 19 | MainWindow.setFont(font) # применяем шрифт для главного окна 20 | MainWindow.setLayoutDirection(QtCore.Qt.LeftToRight) # определяем порядок размещения кнопок слева на право 21 | MainWindow.setLocale(QtCore.QLocale(QtCore.QLocale.Russian, QtCore.QLocale.Russia)) # определяем язык и страну 22 | self.centralwidget = QtWidgets.QWidget(MainWindow) 23 | self.centralwidget.setObjectName("centralwidget") 24 | self.gridLayout = QtWidgets.QGridLayout(self.centralwidget) 25 | self.gridLayout.setObjectName("gridLayout") # тип размещения элементов сетка 26 | 27 | self.organization = QtWidgets.QLabel(self.centralwidget) 28 | self.organization.setObjectName("organization") 29 | self.gridLayout.addWidget(self.organization, 1, 1, 1, 1, QtCore.Qt.AlignRight) 30 | 31 | 32 | self.table = QtWidgets.QTableWidget(self.centralwidget) 33 | self.table.setShowGrid(True) 34 | self.table.setObjectName("table") 35 | self.table.setColumnCount(13) 36 | # self.table.setRowCount(1) 37 | 38 | 39 | 40 | item = QtWidgets.QTableWidgetItem() 41 | self.table.setHorizontalHeaderItem(0, item) 42 | item = QtWidgets.QTableWidgetItem() 43 | self.table.setHorizontalHeaderItem(1, item) 44 | item = QtWidgets.QTableWidgetItem() 45 | self.table.setHorizontalHeaderItem(2, item) 46 | item = QtWidgets.QTableWidgetItem() 47 | self.table.setHorizontalHeaderItem(3, item) 48 | item = QtWidgets.QTableWidgetItem() 49 | self.table.setHorizontalHeaderItem(4, item) 50 | item = QtWidgets.QTableWidgetItem() 51 | self.table.setHorizontalHeaderItem(5, item) 52 | item = QtWidgets.QTableWidgetItem() 53 | self.table.setHorizontalHeaderItem(6, item) 54 | item = QtWidgets.QTableWidgetItem() 55 | self.table.setHorizontalHeaderItem(7, item) 56 | item = QtWidgets.QTableWidgetItem() 57 | self.table.setHorizontalHeaderItem(8, item) 58 | item = QtWidgets.QTableWidgetItem() 59 | self.table.setHorizontalHeaderItem(9, item) 60 | item = QtWidgets.QTableWidgetItem() 61 | self.table.setHorizontalHeaderItem(10, item) 62 | item = QtWidgets.QTableWidgetItem() 63 | self.table.setHorizontalHeaderItem(11, item) 64 | item = QtWidgets.QTableWidgetItem() 65 | self.table.setHorizontalHeaderItem(12, item) 66 | item = QtWidgets.QTableWidgetItem() 67 | self.table.setHorizontalHeaderItem(13, item) 68 | 69 | # определяем положение таблицы в сетке 70 | self.gridLayout.addWidget(self.table, 0, 3, 15, 1) # строка=0, колонка=3, отступ строка=10, отступ колонка=1 71 | 72 | # подпись ячейки 73 | self.label_1 = QtWidgets.QLabel(self.centralwidget) 74 | self.label_1.setObjectName("label_1") 75 | self.gridLayout.addWidget(self.label_1, 0, 1, 1, 1) 76 | # ячейка ввода 77 | self.organization = QtWidgets.QLineEdit(self.centralwidget) 78 | self.organization.setObjectName("organization") 79 | self.gridLayout.addWidget(self.organization, 0, 2, 1, 1, QtCore.Qt.AlignLeft) 80 | 81 | # подпись ячейки 82 | self.label_2 = QtWidgets.QLabel(self.centralwidget) 83 | self.label_2.setObjectName("label_2") 84 | self.gridLayout.addWidget(self.label_2, 1, 1, 1, 1) 85 | # ячейка ввода 86 | self.division = QtWidgets.QLineEdit(self.centralwidget) 87 | self.division.setObjectName("division") 88 | self.gridLayout.addWidget(self.division, 1, 2, 1, 1, QtCore.Qt.AlignLeft) 89 | 90 | # подпись ячейки 91 | self.label_3 = QtWidgets.QLabel(self.centralwidget) 92 | self.label_3.setObjectName("label_3") 93 | self.gridLayout.addWidget(self.label_3, 2, 1, 1, 1) 94 | # ячейка ввода 95 | self.subdivision = QtWidgets.QLineEdit(self.centralwidget) 96 | self.subdivision.setObjectName("subdivision") 97 | self.gridLayout.addWidget(self.subdivision, 2, 2, 1, 1, QtCore.Qt.AlignLeft) 98 | 99 | # подпись ячейки 100 | self.label_4 = QtWidgets.QLabel(self.centralwidget) 101 | self.label_4.setObjectName("label_4") 102 | self.gridLayout.addWidget(self.label_4, 3, 1, 1, 1) 103 | # ячейка ввода 104 | self.subdivision_level1 = QtWidgets.QLineEdit(self.centralwidget) 105 | self.subdivision_level1.setObjectName("subdivision_level1") 106 | self.gridLayout.addWidget(self.subdivision_level1, 3, 2, 1, 1, QtCore.Qt.AlignLeft) 107 | 108 | # подпись ячейки 109 | self.label_5 = QtWidgets.QLabel(self.centralwidget) 110 | self.label_5.setObjectName("label_5") 111 | self.gridLayout.addWidget(self.label_5, 4, 1, 1, 1) 112 | # ячейка ввода 113 | self.subdivision_level2 = QtWidgets.QLineEdit(self.centralwidget) 114 | self.subdivision_level2.setObjectName("subdivision_level2") 115 | self.gridLayout.addWidget(self.subdivision_level2, 4, 2, 1, 1, QtCore.Qt.AlignLeft) 116 | 117 | # подпись ячейки 118 | self.label_6 = QtWidgets.QLabel(self.centralwidget) 119 | self.label_6.setObjectName("label_6") 120 | self.gridLayout.addWidget(self.label_6, 5, 1, 1, 1) 121 | # ячейка ввода 122 | self.position = QtWidgets.QLineEdit(self.centralwidget) 123 | self.position.setObjectName("position") 124 | self.gridLayout.addWidget(self.position, 5, 2, 1, 1, QtCore.Qt.AlignLeft) 125 | 126 | # подпись ячейки 127 | self.label_7 = QtWidgets.QLabel(self.centralwidget) 128 | self.label_7.setObjectName("label_7") 129 | self.gridLayout.addWidget(self.label_7, 6, 1, 1, 1) 130 | # ячейка ввода 131 | self.name = QtWidgets.QLineEdit(self.centralwidget) 132 | self.name.setObjectName("name") 133 | self.gridLayout.addWidget(self.name, 6, 2, 1, 1, QtCore.Qt.AlignLeft) 134 | 135 | # подпись ячейки 136 | self.label_8 = QtWidgets.QLabel(self.centralwidget) 137 | self.label_8.setObjectName("label_8") 138 | self.gridLayout.addWidget(self.label_8, 7, 1, 1, 1) 139 | # ячейка ввода 140 | self.family_name = QtWidgets.QLineEdit(self.centralwidget) 141 | self.family_name.setObjectName("family_name") 142 | self.gridLayout.addWidget(self.family_name, 7, 2, 1, 1, QtCore.Qt.AlignLeft) 143 | 144 | # подпись ячейки 145 | self.label_9 = QtWidgets.QLabel(self.centralwidget) 146 | self.label_9.setObjectName("label_9") 147 | self.gridLayout.addWidget(self.label_9, 8, 1, 1, 1) 148 | # ячейка ввода 149 | self.middle_name = QtWidgets.QLineEdit(self.centralwidget) 150 | self.middle_name.setObjectName("middle_name") 151 | self.gridLayout.addWidget(self.middle_name, 8, 2, 1, 1, QtCore.Qt.AlignLeft) 152 | 153 | # подпись ячейки 154 | self.label_10 = QtWidgets.QLabel(self.centralwidget) 155 | self.label_10.setObjectName("label_10") 156 | self.gridLayout.addWidget(self.label_10, 9, 1, 1, 1) 157 | # ячейка ввода 158 | self.work_number = QtWidgets.QLineEdit(self.centralwidget) 159 | self.work_number.setObjectName("work_number") 160 | self.gridLayout.addWidget(self.work_number, 9, 2, 1, 1, QtCore.Qt.AlignLeft) 161 | 162 | # подпись ячейки 163 | self.label_11 = QtWidgets.QLabel(self.centralwidget) 164 | self.label_11.setObjectName("label_11") 165 | self.gridLayout.addWidget(self.label_11, 10, 1, 1, 1) 166 | # ячейка ввода 167 | self.mobile_phone = QtWidgets.QLineEdit(self.centralwidget) 168 | self.mobile_phone.setObjectName("mobile_phone") 169 | self.gridLayout.addWidget(self.mobile_phone, 10, 2, 1, 1, QtCore.Qt.AlignLeft) 170 | 171 | # подпись ячейки 172 | self.label_12 = QtWidgets.QLabel(self.centralwidget) 173 | self.label_12.setObjectName("label_12") 174 | self.gridLayout.addWidget(self.label_12, 11, 1, 1, 1) 175 | # ячейка ввода 176 | self.city_phone = QtWidgets.QLineEdit(self.centralwidget) 177 | self.city_phone.setObjectName("city_phone") 178 | self.gridLayout.addWidget(self.city_phone, 11, 2, 1, 1, QtCore.Qt.AlignLeft) 179 | 180 | # подпись ячейки 181 | self.label_13 = QtWidgets.QLabel(self.centralwidget) 182 | self.label_13.setObjectName("label_13") 183 | self.gridLayout.addWidget(self.label_13, 12, 1, 1, 1) 184 | # ячейка ввода 185 | self.mark = QtWidgets.QLineEdit(self.centralwidget) 186 | self.mark.setObjectName("mark") 187 | self.gridLayout.addWidget(self.mark, 12, 2, 1, 1, QtCore.Qt.AlignLeft) 188 | 189 | # кнопка добавить 190 | self.add = QtWidgets.QPushButton(self.centralwidget) 191 | self.add.setObjectName("add") 192 | self.gridLayout.addWidget(self.add, 14, 0, 1, 3) 193 | 194 | # кнопка удалить 195 | self.remove = QtWidgets.QPushButton(self.centralwidget) 196 | self.remove.setObjectName("remove") 197 | self.gridLayout.addWidget(self.remove, 15, 0, 1, 3) 198 | 199 | # кнопка поиск 200 | self.search = QtWidgets.QPushButton(self.centralwidget) 201 | self.search.setObjectName("search") 202 | self.gridLayout.addWidget(self.search, 16, 0, 1, 3) 203 | 204 | MainWindow.setCentralWidget(self.centralwidget) 205 | self.retranslateUi(MainWindow) # подключаем подписи элементов таблицы 206 | QtCore.QMetaObject.connectSlotsByName(MainWindow) 207 | 208 | 209 | 210 | # прописываем виджеты и действия 211 | exitAction = QtWidgets.QAction('Выход', self) 212 | exitAction.triggered.connect(self.quit_safe) 213 | 214 | saveAction = QtWidgets.QAction('Сохранить', self) 215 | saveAction.triggered.connect(self.save) 216 | 217 | about_programerAction = QtWidgets.QAction('О производителе', self) 218 | about_programerAction.triggered.connect(self.about_programer) 219 | 220 | about_licencAction = QtWidgets.QAction('Лицензия на публикацию программы', self) 221 | about_licencAction.triggered.connect(self.about_licenc) 222 | 223 | excelMenu_import = QtWidgets.QAction('Импорт данных из Excel', self) 224 | excelMenu_import.triggered.connect(self.import_excel) 225 | 226 | excelMenu_export = QtWidgets.QAction('Экспорт в формат Excel', self) 227 | excelMenu_export.triggered.connect(self.export_excel) 228 | 229 | # прописываем менюбар 230 | menubar = self.menuBar() 231 | 232 | fileMenu = menubar.addMenu('Файл') # первая вкладка меню бара (ниже указано его содержание) 233 | fileMenu.addAction(saveAction) 234 | fileMenu.addAction(excelMenu_import) 235 | fileMenu.addAction(excelMenu_export) 236 | fileMenu.addAction(exitAction) 237 | 238 | aboutMenu = menubar.addMenu('О программе') # вторая вкладка меню бара (ниже указано его содержание) 239 | aboutMenu.addAction(about_programerAction) 240 | aboutMenu.addAction(about_licencAction) 241 | 242 | # Кнопки 243 | self.add.clicked.connect(self.add_button) 244 | self.search.clicked.connect(self.search_button) 245 | self.remove.clicked.connect(self.delete_button) 246 | 247 | def retranslateUi(self, MainWindow): 248 | _translate = QtCore.QCoreApplication.translate 249 | MainWindow.setWindowTitle(_translate("MainWindow", "Телефонная книга")) 250 | 251 | # подпись колонок таблицы 252 | item = self.table.horizontalHeaderItem(0) 253 | item.setText(_translate("MainWindow", "Организация")) 254 | item = self.table.horizontalHeaderItem(1) 255 | item.setText(_translate("MainWindow", "Управление")) 256 | item = self.table.horizontalHeaderItem(2) 257 | item.setText(_translate("MainWindow", "Подразделение")) 258 | item = self.table.horizontalHeaderItem(3) 259 | item.setText(_translate("MainWindow", "Подр-е ур.1")) 260 | item = self.table.horizontalHeaderItem(4) 261 | item.setText(_translate("MainWindow", "Подра-е ур.2")) 262 | item = self.table.horizontalHeaderItem(5) 263 | item.setText(_translate("MainWindow", "Должность")) 264 | item = self.table.horizontalHeaderItem(6) 265 | item.setText(_translate("MainWindow", "Имя")) 266 | item = self.table.horizontalHeaderItem(7) 267 | item.setText(_translate("MainWindow", "Отчество")) 268 | item = self.table.horizontalHeaderItem(8) 269 | item.setText(_translate("MainWindow", "Фамилия")) 270 | item = self.table.horizontalHeaderItem(9) 271 | item.setText(_translate("MainWindow", "Внутр. телефон")) 272 | item = self.table.horizontalHeaderItem(10) 273 | item.setText(_translate("MainWindow", "Мобильный телефон")) 274 | item = self.table.horizontalHeaderItem(11) 275 | item.setText(_translate("MainWindow", "Городской телефон")) 276 | item = self.table.horizontalHeaderItem(12) 277 | item.setText(_translate("MainWindow", "Примечание")) 278 | self.table.resizeColumnsToContents() # выравнивание ширины колонок по контенту 279 | 280 | # подписываем ячейки ввода данных 281 | self.label_1.setText(_translate("MainWindow", "Организация")) 282 | self.label_2.setText(_translate("MainWindow", "Управление")) 283 | self.label_3.setText(_translate("MainWindow", "Подразделение")) 284 | self.label_4.setText(_translate("MainWindow", "Подр. ур1")) 285 | self.label_5.setText(_translate("MainWindow", "Подр. ур2")) 286 | self.label_6.setText(_translate("MainWindow", "Должность")) 287 | self.label_7.setText(_translate("MainWindow", "Имя")) 288 | self.label_8.setText(_translate("MainWindow", "Отчество")) 289 | self.label_9.setText(_translate("MainWindow", "Фамилия")) 290 | self.label_10.setText(_translate("MainWindow", "Внутр. телефон")) 291 | self.label_11.setText(_translate("MainWindow", "Моб. телефон")) 292 | self.label_12.setText(_translate("MainWindow", "Гор. телефон")) 293 | self.label_13.setText(_translate("MainWindow", "Примечание")) 294 | 295 | # подпись кнопки 296 | self.add.setText(_translate("MainWindow", "Добавить")) 297 | self.search.setText(_translate("MainWindow", "Поиск")) 298 | self.remove.setText(_translate("MainWindow", "Удалить")) 299 | 300 | 301 | 302 | 303 | -------------------------------------------------------------------------------- /gui_draft.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | 4 | from PyQt5 import QtCore, QtGui, QtWidgets 5 | 6 | 7 | class Ui_MainWindow(object): 8 | def setupUi(self, MainWindow): 9 | MainWindow.setObjectName("MainWindow") 10 | font = QtGui.QFont() 11 | font.setFamily("Tahoma") 12 | MainWindow.setFont(font) 13 | MainWindow.setLayoutDirection(QtCore.Qt.RightToLeft) 14 | MainWindow.setLocale(QtCore.QLocale(QtCore.QLocale.Persian, QtCore.QLocale.Iran)) 15 | self.centralwidget = QtWidgets.QWidget(MainWindow) 16 | self.centralwidget.setObjectName("centralwidget") 17 | self.gridLayout = QtWidgets.QGridLayout(self.centralwidget) 18 | self.gridLayout.setObjectName("gridLayout") 19 | 20 | 21 | self.division = QtWidgets.QLabel(self.centralwidget) 22 | self.division.setObjectName("Организация") 23 | self.gridLayout.addWidget(self.division, 1, 1, 1, 1) 24 | 25 | self.subdivision = QtWidgets.QLabel(self.centralwidget) 26 | self.subdivision.setObjectName("подразделение") 27 | self.gridLayout.addWidget(self.subdivision, 0, 1, 1, 1) 28 | 29 | self.subdivision_level1 = QtWidgets.QLineEdit(self.centralwidget) 30 | self.subdivision_level1.setObjectName("подразделение ур.1") 31 | self.gridLayout.addWidget(self.subdivision_level1, 0, 0, 1, 1, QtCore.Qt.AlignLeft) 32 | 33 | self.subdivision_level2 = QtWidgets.QLabel(self.centralwidget) 34 | self.subdivision_level2.setObjectName("подразделение ур.2") 35 | self.gridLayout.addWidget(self.subdivision_level2, 3, 1, 1, 1) 36 | 37 | self.label_9 = QtWidgets.QLabel(self.centralwidget) 38 | self.label_9.setObjectName("label_9") 39 | self.gridLayout.addWidget(self.label_9, 4, 1, 1, 1) 40 | 41 | self.phone3 = QtWidgets.QLineEdit(self.centralwidget) 42 | self.phone3.setObjectName("phone3") 43 | self.gridLayout.addWidget(self.phone3, 4, 0, 1, 1, QtCore.Qt.AlignLeft) 44 | 45 | self.label_8 = QtWidgets.QLabel(self.centralwidget) 46 | self.label_8.setEnabled(True) 47 | self.label_8.setObjectName("label_8") 48 | self.gridLayout.addWidget(self.label_8, 5, 1, 1, 1, QtCore.Qt.AlignLeft) 49 | 50 | self.home1 = QtWidgets.QLineEdit(self.centralwidget) 51 | self.home1.setObjectName("home1") 52 | self.gridLayout.addWidget(self.home1, 5, 0, 1, 1, QtCore.Qt.AlignLeft) 53 | 54 | self.home2 = QtWidgets.QLineEdit(self.centralwidget) 55 | self.home2.setObjectName("home2") 56 | self.gridLayout.addWidget(self.home2, 6, 0, 1, 1, QtCore.Qt.AlignLeft) 57 | 58 | self.label_11 = QtWidgets.QLabel(self.centralwidget) 59 | self.label_11.setObjectName("label_11") 60 | self.gridLayout.addWidget(self.label_11, 2, 1, 1, 1) 61 | 62 | self.work_number = QtWidgets.QLineEdit(self.centralwidget) 63 | self.work_number.setObjectName("work_number") 64 | self.gridLayout.addWidget(self.work_number, 7, 0, 1, 1, QtCore.Qt.AlignLeft) 65 | 66 | self.table = QtWidgets.QTableWidget(self.centralwidget) 67 | self.table.setShowGrid(True) 68 | self.table.setObjectName("table") 69 | self.table.setColumnCount(16) 70 | self.table.setRowCount(0) 71 | 72 | 73 | item = QtWidgets.QTableWidgetItem() 74 | self.table.setHorizontalHeaderItem(0, item) 75 | item = QtWidgets.QTableWidgetItem() 76 | self.table.setHorizontalHeaderItem(1, item) 77 | item = QtWidgets.QTableWidgetItem() 78 | self.table.setHorizontalHeaderItem(2, item) 79 | item = QtWidgets.QTableWidgetItem() 80 | self.table.setHorizontalHeaderItem(3, item) 81 | item = QtWidgets.QTableWidgetItem() 82 | self.table.setHorizontalHeaderItem(4, item) 83 | item = QtWidgets.QTableWidgetItem() 84 | self.table.setHorizontalHeaderItem(5, item) 85 | item = QtWidgets.QTableWidgetItem() 86 | self.table.setHorizontalHeaderItem(6, item) 87 | item = QtWidgets.QTableWidgetItem() 88 | self.table.setHorizontalHeaderItem(7, item) 89 | item = QtWidgets.QTableWidgetItem() 90 | self.table.setHorizontalHeaderItem(8, item) 91 | item = QtWidgets.QTableWidgetItem() 92 | self.table.setHorizontalHeaderItem(9, item) 93 | item = QtWidgets.QTableWidgetItem() 94 | self.table.setHorizontalHeaderItem(10, item) 95 | item = QtWidgets.QTableWidgetItem() 96 | self.table.setHorizontalHeaderItem(11, item) 97 | item = QtWidgets.QTableWidgetItem() 98 | self.table.setHorizontalHeaderItem(12, item) 99 | item = QtWidgets.QTableWidgetItem() 100 | self.table.setHorizontalHeaderItem(13, item) 101 | 102 | 103 | 104 | self.gridLayout.addWidget(self.table, 0, 3, 18, 1) 105 | self.label_7 = QtWidgets.QLabel(self.centralwidget) 106 | self.label_7.setObjectName("label_7") 107 | self.gridLayout.addWidget(self.label_7, 6, 1, 1, 1) 108 | self.family = QtWidgets.QLineEdit(self.centralwidget) 109 | self.family.setObjectName("family") 110 | self.gridLayout.addWidget(self.family, 1, 0, 1, 1, QtCore.Qt.AlignLeft) 111 | self.phone1 = QtWidgets.QLineEdit(self.centralwidget) 112 | self.phone1.setObjectName("phone1") 113 | self.gridLayout.addWidget(self.phone1, 2, 0, 1, 1, QtCore.Qt.AlignLeft) 114 | self.label_6 = QtWidgets.QLabel(self.centralwidget) 115 | self.label_6.setObjectName("label_6") 116 | self.gridLayout.addWidget(self.label_6, 7, 1, 1, 1) 117 | self.label_5 = QtWidgets.QLabel(self.centralwidget) 118 | self.label_5.setObjectName("label_5") 119 | self.gridLayout.addWidget(self.label_5, 8, 1, 1, 1) 120 | self.phone2 = QtWidgets.QLineEdit(self.centralwidget) 121 | self.phone2.setObjectName("phone2") 122 | self.gridLayout.addWidget(self.phone2, 3, 0, 1, 1, QtCore.Qt.AlignLeft) 123 | self.website = QtWidgets.QLineEdit(self.centralwidget) 124 | self.website.setObjectName("website") 125 | self.gridLayout.addWidget(self.website, 10, 0, 1, 2) 126 | self.email = QtWidgets.QLineEdit(self.centralwidget) 127 | self.email.setObjectName("email") 128 | self.gridLayout.addWidget(self.email, 11, 0, 1, 2) 129 | self.messager = QtWidgets.QComboBox(self.centralwidget) 130 | self.messager.setMinimumSize(QtCore.QSize(70, 0)) 131 | self.messager.setObjectName("messager") 132 | self.messager.addItem("") 133 | self.messager.addItem("") 134 | self.messager.addItem("") 135 | self.messager.addItem("") 136 | self.messager.addItem("") 137 | 138 | 139 | self.gridLayout.addWidget(self.messager, 13, 0, 1, 1) 140 | self.label_2 = QtWidgets.QLabel(self.centralwidget) 141 | self.label_2.setObjectName("label_2") 142 | self.gridLayout.addWidget(self.label_2, 11, 2, 1, 1) 143 | self.remove = QtWidgets.QPushButton(self.centralwidget) 144 | self.remove.setObjectName("remove") 145 | self.gridLayout.addWidget(self.remove, 15, 0, 1, 3) 146 | self.search = QtWidgets.QPushButton(self.centralwidget) 147 | self.search.setObjectName("search") 148 | self.gridLayout.addWidget(self.search, 16, 0, 1, 3) 149 | self.fax = QtWidgets.QLineEdit(self.centralwidget) 150 | self.fax.setObjectName("fax") 151 | self.gridLayout.addWidget(self.fax, 8, 0, 1, 1, QtCore.Qt.AlignLeft) 152 | self.label_4 = QtWidgets.QLabel(self.centralwidget) 153 | self.label_4.setObjectName("label_4") 154 | self.gridLayout.addWidget(self.label_4, 9, 2, 1, 1) 155 | self.workpath_text = QtWidgets.QLabel(self.centralwidget) 156 | self.workpath_text.setLayoutDirection(QtCore.Qt.RightToLeft) 157 | self.workpath_text.setObjectName("workpath_text") 158 | self.gridLayout.addWidget(self.workpath_text, 12, 2, 1, 1) 159 | self.workpath = QtWidgets.QLineEdit(self.centralwidget) 160 | self.workpath.setObjectName("workpath") 161 | self.gridLayout.addWidget(self.workpath, 12, 0, 1, 2) 162 | self.home_path = QtWidgets.QLineEdit(self.centralwidget) 163 | self.home_path.setObjectName("home_path") 164 | self.gridLayout.addWidget(self.home_path, 9, 0, 1, 2) 165 | self.phone_msg = QtWidgets.QLineEdit(self.centralwidget) 166 | self.phone_msg.setObjectName("phone_msg") 167 | self.gridLayout.addWidget(self.phone_msg, 13, 1, 1, 1, QtCore.Qt.AlignLeft) 168 | self.label = QtWidgets.QLabel(self.centralwidget) 169 | self.label.setObjectName("label") 170 | self.gridLayout.addWidget(self.label, 13, 2, 1, 1, QtCore.Qt.AlignLeft) 171 | self.label_3 = QtWidgets.QLabel(self.centralwidget) 172 | self.label_3.setObjectName("label_3") 173 | self.gridLayout.addWidget(self.label_3, 10, 2, 1, 1) 174 | self.export_2 = QtWidgets.QPushButton(self.centralwidget) 175 | self.export_2.setObjectName("export_2") 176 | self.gridLayout.addWidget(self.export_2, 17, 0, 1, 3) 177 | self.add = QtWidgets.QPushButton(self.centralwidget) 178 | self.add.setObjectName("add") 179 | self.gridLayout.addWidget(self.add, 14, 0, 1, 3) 180 | MainWindow.setCentralWidget(self.centralwidget) 181 | 182 | self.retranslateUi(MainWindow) 183 | QtCore.QMetaObject.connectSlotsByName(MainWindow) 184 | #Buttons 185 | self.add.clicked.connect(self.add_button) 186 | self.search.clicked.connect(self.search_button) 187 | self.remove.clicked.connect(self.delete_button) 188 | self.export_2.clicked.connect(self.export) 189 | 190 | #Regex for persion 191 | persian_alpha_codepoints = '\u0621-\u0628\u062A-\u063A\u0641-\u0642\u0644-\u0648\u064E-\u0651\u0655\u067E\u0686\u0698\u06A9\u06AF\u06BE\u06CC' 192 | arabic_numbers_codepoints = '\u0660-\u0669' 193 | additional_arabic_characters_codepoints = '\u0629\u0643\u0649-\u064B\u064D\u06D5' 194 | punctuation_marks_codepoints = '\u060C\u061B\u061F\u0640\u066A\u066B\u066C' 195 | space_codepoints ='\u0020\u2000-\u200F\u2028-\u202F' 196 | persian_num_codepoints = '\u06F0-\u06F9' 197 | 198 | #OnlyInt part 199 | self.only_int = QtCore.QRegExp("[0-9" + persian_num_codepoints + arabic_numbers_codepoints + "]+") 200 | self.only_int_reg = QtGui.QRegExpValidator(self.only_int) 201 | self.home1.setValidator(self.only_int_reg) 202 | self.home2.setValidator(self.only_int_reg) 203 | self.work_number.setValidator(self.only_int_reg) 204 | self.phone1.setValidator(self.only_int_reg) 205 | self.phone2.setValidator(self.only_int_reg) 206 | self.phone3.setValidator(self.only_int_reg) 207 | self.fax.setValidator(self.only_int_reg) 208 | self.phone_msg.setValidator(self.only_int_reg) 209 | 210 | #Only al part 211 | self.only_english = QtCore.QRegExp('[A-Za-z0-9 0-9\\#\+\-\−\_@\.]+') 212 | self.only_persian = QtCore.QRegExp(r"[\s,"+persian_alpha_codepoints+additional_arabic_characters_codepoints 213 | +punctuation_marks_codepoints+space_codepoints+arabic_numbers_codepoints+persian_num_codepoints+r" 0-9\\#\+\-\−\_@\.]+") 214 | 215 | self.only_english_reg = QtGui.QRegExpValidator(self.only_english) 216 | self.only_persian_reg = QtGui.QRegExpValidator(self.only_persian) 217 | 218 | self.website.setValidator(self.only_english_reg) 219 | self.email.setValidator(self.only_english_reg) 220 | 221 | self.subdivision_level1.setValidator(self.only_persian_reg) 222 | self.family.setValidator(self.only_persian_reg) 223 | 224 | self.home_path.setValidator(self.only_persian_reg) 225 | self.workpath.setValidator(self.only_persian_reg) 226 | 227 | 228 | exitAction = QtWidgets.QAction('Выход', self) 229 | exitAction.triggered.connect(self.quit_safe) 230 | 231 | saveAction = QtWidgets.QAction('Сохранить', self) 232 | saveAction.triggered.connect(self.save) 233 | 234 | about_programerAction = QtWidgets.QAction('О производителе', self) 235 | about_programerAction.triggered.connect(self.about_programer) 236 | 237 | about_licencAction = QtWidgets.QAction('Лицензия на публикацию программы', self) 238 | about_licencAction.triggered.connect(self.about_licenc) 239 | 240 | about_licencAction = QtWidgets.QAction('Лицензия на публикацию программы', self) 241 | about_licencAction.triggered.connect(self.about_licenc) 242 | 243 | excelMenu_import = QtWidgets.QAction('Импорт данных из Excel', self) 244 | excelMenu_import.triggered.connect(self.import_excel) 245 | 246 | excelMenu_export = QtWidgets.QAction('Вывод в формате Excel', self) 247 | excelMenu_export.triggered.connect(self.export_excel) 248 | 249 | menubar = self.menuBar() 250 | 251 | fileMenu = menubar.addMenu('сохранить файл') 252 | fileMenu.addAction(saveAction) 253 | fileMenu.addAction(exitAction) 254 | 255 | excelMenu = menubar.addMenu('импорт эксель') 256 | excelMenu.addAction(excelMenu_import) 257 | excelMenu.addAction(excelMenu_export) 258 | 259 | aboutMenu = menubar.addMenu('о программе') 260 | aboutMenu.addAction(about_programerAction) 261 | aboutMenu.addAction(about_licencAction) 262 | 263 | def retranslateUi(self, MainWindow): 264 | _translate = QtCore.QCoreApplication.translate 265 | MainWindow.setWindowTitle(_translate("MainWindow", "Телефонная книга")) 266 | self.division.setText(_translate("MainWindow", "Организация")) 267 | self.subdivision.setText(_translate("MainWindow", "Подразделение")) 268 | # self.subdivision_level1.setText(_translate("MainWindow", "Подразделение ур1")) 269 | self.subdivision_level2.setText(_translate("MainWindow", "Подразделение ур2")) 270 | self.label_9.setText(_translate("MainWindow", "Номер телефона 3")) 271 | self.label_8.setText(_translate("MainWindow", "

Номер домашнего телефона

")) 272 | self.label_11.setText(_translate("MainWindow", "телефонный номер 1")) 273 | item = self.table.horizontalHeaderItem(0) 274 | item.setText(_translate("MainWindow", "название")) 275 | item = self.table.horizontalHeaderItem(1) 276 | item.setText(_translate("MainWindow", "фамилия")) 277 | item = self.table.horizontalHeaderItem(2) 278 | item.setText(_translate("MainWindow", "телефонный номер 1")) 279 | item = self.table.horizontalHeaderItem(3) 280 | item.setText(_translate("MainWindow", "телефонный номер 2")) 281 | item = self.table.horizontalHeaderItem(4) 282 | item.setText(_translate("MainWindow", "телефонный номер 3")) 283 | item = self.table.horizontalHeaderItem(5) 284 | item.setText(_translate("MainWindow", "Номер домашнего телефона 1")) 285 | item = self.table.horizontalHeaderItem(6) 286 | item.setText(_translate("MainWindow", "Номер домашнего телефона 2")) 287 | item = self.table.horizontalHeaderItem(7) 288 | item.setText(_translate("MainWindow", "Номер рабочего места")) 289 | item = self.table.horizontalHeaderItem(8) 290 | item.setText(_translate("MainWindow", "текст 8")) 291 | item = self.table.horizontalHeaderItem(9) 292 | item.setText(_translate("MainWindow", "текст 9")) 293 | item = self.table.horizontalHeaderItem(10) 294 | item.setText(_translate("MainWindow", "текст 10")) 295 | item = self.table.horizontalHeaderItem(11) 296 | item.setText(_translate("MainWindow", "текст 11")) 297 | item = self.table.horizontalHeaderItem(12) 298 | item.setText(_translate("MainWindow", "текст 12")) 299 | item = self.table.horizontalHeaderItem(13) 300 | item.setText(_translate("MainWindow", "текст 13")) 301 | 302 | self.label_7.setText(_translate("MainWindow", "Номер домашнего телефона 2")) 303 | self.label_6.setText(_translate("MainWindow", "Номер рабочего места")) 304 | self.label_5.setText(_translate("MainWindow", "факс")) 305 | self.messager.setItemText(0, _translate("MainWindow", "«Эта»")) 306 | self.messager.setItemText(1, _translate("MainWindow", "«Соруш»")) 307 | self.messager.setItemText(2, _translate("MainWindow", "«WhatsApp»")) 308 | self.messager.setItemText(3, _translate("MainWindow", "«Telegram»")) 309 | self.messager.setItemText(4, _translate("MainWindow", "«Другие мессенджеры»")) 310 | self.label_2.setText(_translate("MainWindow", "Эл. адрес")) 311 | self.remove.setText(_translate("MainWindow", "Цель")) 312 | self.search.setText(_translate("MainWindow", "Поиск")) 313 | self.label_4.setText(_translate("MainWindow", "Домашний адрес")) 314 | self.workpath_text.setText(_translate("MainWindow", "рабочий адрес")) 315 | self.label.setText(_translate("MainWindow", "виртуальный номер телефона")) 316 | self.label_3.setText(_translate("MainWindow", "интернет сайт")) 317 | self.export_2.setText(_translate("MainWindow", "Вывод в Excel")) 318 | self.add.setText(_translate("MainWindow", "Добавлять")) 319 | self.all_messager_types = ['«Эта»', '«Соруш»', '«WhatsApp»', '«Telegram»', '«Другие мессенджеры»'] 320 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ 4 | Python 3.9 программа консольного приложения телефонного справочника 5 | Название файла main.py 6 | 7 | Version: 0.1 8 | Author: Andrej Marinchenko 9 | Date: 2022-04-23 10 | """ 11 | 12 | 13 | import gui # подключаем свой модуль класс 14 | import sqlite3 as db 15 | import xlsxwriter 16 | import xlrd 17 | from PyQt5 import QtCore, QtWidgets 18 | from PyQt5.QtWidgets import QApplication, QMessageBox, QFileDialog 19 | from PyQt5.QtCore import pyqtSlot, QObject, QThread, pyqtSignal 20 | from sys import argv 21 | 22 | 23 | class load_worker(QObject): 24 | finished = pyqtSignal() 25 | def __init__(self, sql): 26 | super().__init__() 27 | self.sql = sql 28 | 29 | def run(self): 30 | global database_data 31 | database_data = None 32 | database_data = LoadData(self.sql) 33 | self.finished.emit() 34 | 35 | 36 | class delete_worker(QObject): 37 | finished = pyqtSignal() 38 | def __init__(self, target): 39 | super().__init__() 40 | self.target = target 41 | 42 | def run(self): 43 | con = db.connect('.phones.sqlite3') 44 | for index in sorted(self.target.table.selectionModel().selectedRows()): 45 | row = index.row() 46 | sql = "DELETE FROM Phones WHERE name LIKE '%{0}%' AND middle_name LIKE '%{1}%' AND family_name LIKE '%{2}%'".format( 47 | self.target.table.model().data(self.target.table.model().index(row, 6)), 48 | self.target.table.model().data(self.target.table.model().index(row, 7)), 49 | self.target.table.model().data(self.target.table.model().index(row, 8)) 50 | ) 51 | # print(self.target.table.model().data(self.target.table.model().index(row, 6))) 52 | # print(self.target.table.model().data(self.target.table.model().index(row, 7))) 53 | # print(self.target.table.model().data(self.target.table.model().index(row, 8))) 54 | cur = con.cursor() 55 | cur.execute(sql) 56 | con.commit() 57 | 58 | self.target.clear_table() # очистка таблицы 59 | self.target.load_table('SELECT * FROM Phones') # чтение таблицы 60 | 61 | # класс создания графического приложения 62 | class App(QtWidgets.QMainWindow, gui.Ui_MainWindow): # на входе библиотека виджета и подключенный собств. модуль 63 | def __init__(self, parent=None): # инициализация класса 64 | super(App, self).__init__(parent) 65 | self.setupUi(self) 66 | self.load_table('SELECT * FROM phones') 67 | self.showMaximized() 68 | 69 | # функция сохранения данных 70 | def save(self): 71 | cur = con.cursor() 72 | for i in range(self.table.rowCount()): # перебираем все строки 73 | column = [] 74 | for j in range(self.table.columnCount()): # перебираем все колонки 75 | if j != 12: 76 | column.append(self.table.model().data(self.table.model().index(i, j))) 77 | else: 78 | column.append(self.table.cellWidget(i,j).currentText()) 79 | 80 | sql = """UPDATE Phones 81 | SET organization = '%s', 82 | division = '%s', 83 | subdivision = '%s', 84 | subdivision_level1 = '%s', 85 | subdivision_level2 = '%s', 86 | position = '%s', 87 | name = '%s', 88 | middle_name = '%s', 89 | family_name = '%s', 90 | work_number = '%s', 91 | mobile_phone = '%s', 92 | city_phone = '%s', 93 | mark = '%s', 94 | WHERE id = %s;""" % tuple(column) 95 | cur.execute(sql) 96 | con.commit() 97 | 98 | def clear_table(self): 99 | self.table.setRowCount(0) 100 | 101 | # функция чтения данных 102 | def load_table(self, sql): 103 | global database_data 104 | database_data = None 105 | self.thread = QThread(self) 106 | self.worker = load_worker(sql) 107 | self.worker.moveToThread(self.thread) 108 | self.thread.started.connect(self.worker.run) 109 | self.worker.finished.connect(self.thread.quit) 110 | self.worker.finished.connect(self.worker.deleteLater) 111 | self.thread.finished.connect(self.thread.deleteLater) 112 | self.thread.start() 113 | self.thread.finished.connect(self.load_table_thread_callback) 114 | 115 | def load_table_thread_callback(self): 116 | global database_data 117 | if database_data == []: 118 | return False 119 | 120 | for row in database_data: 121 | row_pos = self.table.rowCount() 122 | self.table.insertRow(row_pos) 123 | for i, column in enumerate(row, 0): 124 | normal_widget_item = True 125 | item = QtWidgets.QTableWidgetItem(str(column)) 126 | # if i == 12: 127 | # item = QtWidgets.QComboBox() 128 | # item.addItems(self.all_messager_types) 129 | # item.setCurrentIndex(self.all_messager_types.index(column)) 130 | # normal_widget_item = False 131 | # 132 | if i == 12: 133 | flags = QtCore.Qt.ItemFlags() 134 | flags != QtCore.Qt.ItemIsEnabled 135 | item.setFlags(flags) 136 | 137 | if normal_widget_item: 138 | self.table.setItem(row_pos, i, item) 139 | else: 140 | self.table.setCellWidget(row_pos,i,item) 141 | 142 | self.table.resizeColumnsToContents() 143 | 144 | def error(self, text, title = "Проблема"): 145 | msg = QMessageBox() 146 | msg.setIcon(QMessageBox.Critical) 147 | msg.setText(text) 148 | msg.setWindowTitle("Проблема") 149 | msg.exec_() 150 | del msg 151 | 152 | def info(self, text, title = "Информация"): 153 | msg = QMessageBox() 154 | msg.setIcon(QMessageBox.Information) 155 | msg.setText(text) 156 | msg.setWindowTitle("Информация") 157 | msg.exec_() 158 | del msg 159 | 160 | def question(self,title,text): 161 | buttonReply = QMessageBox.question(self, title, text, QMessageBox.Yes | QMessageBox.No, QMessageBox.No) 162 | if buttonReply == QMessageBox.Yes: 163 | del buttonReply 164 | return True 165 | else: 166 | del buttonReply 167 | return False 168 | 169 | 170 | def export_excel(self): 171 | options = QFileDialog.Options() 172 | options |= QFileDialog.DontUseNativeDialog 173 | fileName, _ = QFileDialog.getSaveFileName(self,"Export", "","Xls Files (*.xlsx)", options=options) 174 | if fileName: 175 | workbook = xlsxwriter.Workbook(fileName) 176 | worksheet = workbook.add_worksheet() 177 | 178 | for i in range(self.table.columnCount()): 179 | text = self.table.horizontalHeaderItem(i).text() 180 | worksheet.write(0, i,text) 181 | 182 | for i in range(self.table.columnCount()): 183 | for j in range(self.table.rowCount()): 184 | if i != 12: 185 | text = self.table.item(j, i).text() 186 | else: 187 | text = self.table.cellWidget(j,i).currentText() 188 | # text = self.table.cellWidget(j, i).currentText() 189 | worksheet.write(j + 1, i,text) 190 | workbook.close() 191 | self.info('Вывод успешно создан!') 192 | 193 | def import_excel(self): 194 | options = QFileDialog.Options() 195 | options = QFileDialog.DontUseNativeDialog 196 | user_file, _ = QFileDialog.getOpenFileName(self,"Please select a file", "","Excel File (*.xlsx)", options=options) 197 | if user_file: 198 | wb = xlrd.open_workbook(user_file) 199 | sheet = wb.sheet_by_index(0) 200 | 201 | for i,row in enumerate(range(sheet.nrows)): 202 | if i == 0: 203 | continue 204 | row_data = [] 205 | for j,col in enumerate(range(sheet.ncols)): 206 | if j == 12: 207 | continue 208 | row_data.append(sheet.cell_value(row, col)) 209 | try: 210 | AddData(row_data) 211 | self.load_table('SELECT * FROM Phones') 212 | self.info('Информация введена успешно!') 213 | 214 | except db.IntegrityError: 215 | self.error('Пользователь {0} доступен!'.format(i)) 216 | 217 | except db.ProgrammingError: 218 | self.error('Файл Excel был изменен. Пользователь {0} не добавлен в базу данных.'.format(i)) 219 | 220 | def quit_safe(self): 221 | self.save() 222 | exit(0) 223 | 224 | def closeEvent(self, event): 225 | self.quit_safe() 226 | event.accept() 227 | 228 | def about_programer(self): 229 | self.info("Эта программа была создана Андреем Маринченко. \n Вы можете использовать адрес электронной почты " 230 | "andrej.marinchenko@gmail.com чтобы связаться") 231 | 232 | def about_licenc(self): 233 | self.info('Эта программа выпущена под лицензией GPL версии 3.') 234 | 235 | def reset_textboxs(self): 236 | self.clear_table() 237 | self.load_table('SELECT * FROM phones') 238 | self.organization.setText("") 239 | self.division.setText("") 240 | self.subdivision.setText("") 241 | self.subdivision_level1.setText("") 242 | self.subdivision_level2.setText("") 243 | self.position.setText("") 244 | self.name.setText("") 245 | self.family_name.setText("") 246 | self.middle_name.setText("") 247 | self.work_number.setText("") 248 | self.mobile_phone.setText("") 249 | self.city_phone.setText("") 250 | self.mark.setText("") 251 | 252 | # функция добавления данных в таблицу 253 | @pyqtSlot() 254 | def add_button(self): 255 | datas = { 256 | 'organization' : self.organization.text(), 257 | 'division' : self.division.text(), 258 | 'subdivision' : self.subdivision.text(), 259 | 'subdivision_level1' : self.subdivision_level1.text(), 260 | 'subdivision_level2' : self.subdivision_level2.text(), 261 | 'position' : self.position.text(), 262 | 'name' : self.name.text(), 263 | 'family_name' : self.family_name.text(), 264 | 'middle_name' : self.middle_name.text(), 265 | 'work_number' : self.work_number.text(), 266 | 'mobile_phone' : self.mobile_phone.text(), 267 | 'city_phone' : self.city_phone.text(), 268 | 'mark' : self.mark.text() 269 | } 270 | if datas['name'] and datas['family_name']: 271 | try: 272 | AddData(list(datas.values())) 273 | self.reset_textboxs() 274 | row_pos = self.table.rowCount() 275 | self.table.insertRow(row_pos) 276 | for i, column in enumerate(datas.values(), 0): 277 | normal_widget_item = True 278 | item = QtWidgets.QTableWidgetItem(str(column)) 279 | # if i == 12: 280 | # item = QtWidgets.QComboBox() 281 | # item.addItems(self.all_messager_types) 282 | # item.setCurrentIndex(self.all_messager_types.index(column)) 283 | # normal_widget_item = False 284 | 285 | if i == 12: 286 | flags = QtCore.Qt.ItemFlags() 287 | flags != QtCore.Qt.ItemIsEnabled 288 | item.setFlags(flags) 289 | 290 | if normal_widget_item: 291 | self.table.setItem(row_pos, i, item) 292 | else: 293 | self.table.setCellWidget(row_pos, i, item) 294 | 295 | self.table.resizeColumnsToContents() 296 | except db.IntegrityError: 297 | self.error('Необходимая информация доступна в базе данных') 298 | else: 299 | self.error('Пожалуйста, заполните имя и фамилию') 300 | 301 | # функция поиска в каждой ячейке 302 | @pyqtSlot() 303 | def search_button(self): 304 | datas = { 305 | 'organization' : self.organization.text(), 306 | 'division' : self.division.text(), 307 | 'subdivision' : self.subdivision.text(), 308 | 'subdivision_level1' : self.subdivision_level1.text(), 309 | 'subdivision_level2' : self.subdivision_level2.text(), 310 | 'position' : self.position.text(), 311 | 'name' : self.name.text(), 312 | 'family_name' : self.family_name.text(), 313 | 'middle_name' : self.middle_name.text(), 314 | 'work_number' : self.work_number.text(), 315 | 'mobile_phone' : self.mobile_phone.text(), 316 | 'city_phone' : self.city_phone.text(), 317 | 'mark' : self.mark.text() 318 | } 319 | sql = """ 320 | SELECT * FROM Phones WHERE 321 | organization LIKE '%{0}%' AND 322 | division LIKE '%{1}%' AND 323 | subdivision LIKE '%{2}%' AND 324 | subdivision_level1 LIKE '%{3}%' AND 325 | subdivision_level2 LIKE '%{4}%' AND 326 | position LIKE '%{5}%' AND 327 | name LIKE '%{6}%' AND 328 | family_name LIKE '%{7}%' AND 329 | middle_name LIKE '%{8}%' AND 330 | work_number LIKE '%{9}%' AND 331 | mobile_phone LIKE '%{10}%' AND 332 | city_phone LIKE '%{11}%' AND 333 | mark LIKE '%{12}%' 334 | """.format( 335 | datas['organization'], 336 | datas['division'], 337 | datas['subdivision'], 338 | datas['subdivision_level1'], 339 | datas['subdivision_level2'], 340 | datas['position'], 341 | datas['name'], 342 | datas['family_name'], 343 | datas['middle_name'], 344 | datas['work_number'], 345 | datas['mobile_phone'], 346 | datas['city_phone'], 347 | datas['mark'] 348 | ) 349 | self.clear_table() 350 | if self.load_table(sql) == False: 351 | self.error("Ошибка чтения") 352 | 353 | # функция удаления строки данных 354 | @pyqtSlot() 355 | def delete_button(self): 356 | if self.table.selectionModel().selectedRows() == []: # если строка данных не выбрана 357 | self.error("Пожалуйста, выберите пользователя для удаления") 358 | return False 359 | 360 | if self.question("Удалить пользователя", "Уверены ли вы?"): # окно подтверждения удаления строки пользователя 361 | 362 | self.del_thread = QThread(self) 363 | self.worker = delete_worker(self) 364 | self.worker.moveToThread(self.del_thread) 365 | self.del_thread.started.connect(self.worker.run) 366 | self.worker.finished.connect(self.thread.quit) 367 | self.worker.finished.connect(self.worker.deleteLater) 368 | self.del_thread.finished.connect(self.del_thread.deleteLater) 369 | self.del_thread.start() 370 | 371 | @pyqtSlot() 372 | def export(self): 373 | self.export_excel() 374 | 375 | # функция создания таблицы данных телефонного справочника 376 | def CreateTable(): 377 | global con # глобальная переменная 378 | cur = con.cursor() # курсор подключения к базе данных 379 | cur.execute(''' 380 | CREATE TABLE IF NOT EXISTS `phones`( 381 | organization TEXT, 382 | division TEXT, 383 | subdivision TEXT, 384 | subdivision_level1 TEXT, 385 | subdivision_level2 TEXT, 386 | position TEXT, 387 | name TEXT, 388 | family_name TEXT, 389 | middle_name TEXT, 390 | work_number TEXT, 391 | mobile_phone TEXT, 392 | city_phone TEXT, 393 | mark TEXT, 394 | id INTEGER PRIMARY KEY AUTOINCREMENT 395 | ) 396 | ''') 397 | return True # создание базы данных успешно 398 | 399 | # функция чтения базы данных 400 | def LoadData(sql): 401 | con = db.connect('.phones.sqlite3') # глобальная переменная 402 | cur = con.cursor() 403 | cur.execute(sql) 404 | return cur.fetchall() 405 | 406 | # функция добавления данных в базу 407 | def AddData(values): 408 | cur = con.cursor() 409 | cur.execute(''' 410 | INSERT INTO `phones`(organization, division, subdivision, subdivision_level1, subdivision_level2, position, name, family_name, middle_name, work_number, mobile_phone, city_phone, mark) 411 | VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?) 412 | ''',values) 413 | con.commit() 414 | return True 415 | 416 | # главная функция 417 | def main(): 418 | global con, mainWindow # определяем глобальные переменные 419 | con = db.connect('.phones.sqlite3') # подключение к базе данных 420 | CreateTable() # создание таблицы (определены все колонки, на выходе истина) 421 | mainApp = QApplication(argv) # главное окно 422 | mainWindow = App() # 423 | mainApp.exec_() # 424 | con.close() # 425 | 426 | # проверка на запуск главной программы 427 | if __name__ == "__main__" : main() 428 | --------------------------------------------------------------------------------