This commit is contained in:
2025-12-11 13:48:54 +03:00
commit fe28b9a58c
4 changed files with 10612 additions and 0 deletions

18
.gitignore vendored Normal file
View File

@@ -0,0 +1,18 @@
# Build artifacts
build/
dist/
*.spec
# Python
__pycache__/
*.pyc
*.pyo
venv/
.venv/
# macOS
.DS_Store
# IDE
.idea/
.vscode/

File diff suppressed because it is too large Load Diff

387
firstLabVisualProg/main.py Normal file
View File

@@ -0,0 +1,387 @@
import sys
import re
from PyQt5.QtWidgets import (
QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
QGroupBox, QListWidget, QTextEdit, QPushButton, QComboBox,
QRadioButton, QCheckBox, QLabel, QLineEdit, QFileDialog,
QMessageBox, QInputDialog, QButtonGroup, QFrame
)
from PyQt5.QtCore import Qt
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Лабораторная работа №1 - Обработка текста")
self.setMinimumSize(900, 700)
# Главный виджет
central_widget = QWidget()
self.setCentralWidget(central_widget)
main_layout = QVBoxLayout(central_widget)
# === Верхняя часть: работа с файлом и критерии ===
top_group = QGroupBox("Работа с файлом")
top_layout = QHBoxLayout(top_group)
# Кнопки файла
self.btn_open = QPushButton("Открыть файл")
self.btn_open.clicked.connect(self.open_file)
top_layout.addWidget(self.btn_open)
# Критерии отбора (RadioButton)
criteria_group = QGroupBox("Критерий отбора")
criteria_layout = QVBoxLayout(criteria_group)
self.radio_group = QButtonGroup()
self.radio_all = QRadioButton("Все")
self.radio_digits = QRadioButton("Содержащие цифры")
self.radio_email = QRadioButton("Содержащие e-mail")
self.radio_all.setChecked(True)
self.radio_group.addButton(self.radio_all, 0)
self.radio_group.addButton(self.radio_digits, 1)
self.radio_group.addButton(self.radio_email, 2)
criteria_layout.addWidget(self.radio_all)
criteria_layout.addWidget(self.radio_digits)
criteria_layout.addWidget(self.radio_email)
top_layout.addWidget(criteria_group)
# Кнопка "Начать"
self.btn_start = QPushButton("Начать")
self.btn_start.clicked.connect(self.process_text)
top_layout.addWidget(self.btn_start)
top_layout.addStretch()
main_layout.addWidget(top_group)
# === RichTextBox (QTextEdit) ===
text_group = QGroupBox("Исходный текст")
text_layout = QVBoxLayout(text_group)
self.text_edit = QTextEdit()
self.text_edit.setPlaceholderText("Откройте текстовый файл или введите текст...")
text_layout.addWidget(self.text_edit)
main_layout.addWidget(text_group)
# === Средняя часть: два раздела с панелью управления ===
middle_layout = QHBoxLayout()
# Раздел 1
section1_group = QGroupBox("Раздел 1")
section1_layout = QVBoxLayout(section1_group)
self.list1 = QListWidget()
self.list1.setSelectionMode(QListWidget.ExtendedSelection)
section1_layout.addWidget(self.list1)
# Сортировка для раздела 1
sort1_layout = QHBoxLayout()
sort1_layout.addWidget(QLabel("Сортировка:"))
self.combo_sort1 = QComboBox()
self.combo_sort1.addItems([
"По длине (возр.)",
"По длине (убыв.)",
"По алфавиту (возр.)",
"По алфавиту (убыв.)"
])
sort1_layout.addWidget(self.combo_sort1)
self.btn_sort1 = QPushButton("Сортировать")
self.btn_sort1.clicked.connect(lambda: self.sort_list(self.list1, self.combo_sort1))
sort1_layout.addWidget(self.btn_sort1)
section1_layout.addLayout(sort1_layout)
self.btn_clear1 = QPushButton("Очистить")
self.btn_clear1.clicked.connect(lambda: self.list1.clear())
section1_layout.addWidget(self.btn_clear1)
middle_layout.addWidget(section1_group)
# Панель управления (между разделами)
control_panel = QFrame()
control_panel.setFrameStyle(QFrame.StyledPanel)
control_layout = QVBoxLayout(control_panel)
self.btn_move_right = QPushButton("")
self.btn_move_right.setToolTip("Переместить выбранные в Раздел 2")
self.btn_move_right.clicked.connect(self.move_selected_right)
self.btn_move_all_right = QPushButton("")
self.btn_move_all_right.setToolTip("Переместить все в Раздел 2")
self.btn_move_all_right.clicked.connect(self.move_all_right)
self.btn_move_left = QPushButton("")
self.btn_move_left.setToolTip("Переместить выбранные в Раздел 1")
self.btn_move_left.clicked.connect(self.move_selected_left)
self.btn_move_all_left = QPushButton("")
self.btn_move_all_left.setToolTip("Переместить все в Раздел 1")
self.btn_move_all_left.clicked.connect(self.move_all_left)
self.btn_add = QPushButton("Добавить")
self.btn_add.clicked.connect(self.add_item)
self.btn_delete = QPushButton("Удалить")
self.btn_delete.clicked.connect(self.delete_selected)
control_layout.addStretch()
control_layout.addWidget(self.btn_move_right)
control_layout.addWidget(self.btn_move_all_right)
control_layout.addWidget(self.btn_move_left)
control_layout.addWidget(self.btn_move_all_left)
control_layout.addSpacing(20)
control_layout.addWidget(self.btn_add)
control_layout.addWidget(self.btn_delete)
control_layout.addStretch()
middle_layout.addWidget(control_panel)
# Раздел 2
section2_group = QGroupBox("Раздел 2")
section2_layout = QVBoxLayout(section2_group)
self.list2 = QListWidget()
self.list2.setSelectionMode(QListWidget.ExtendedSelection)
section2_layout.addWidget(self.list2)
# Сортировка для раздела 2
sort2_layout = QHBoxLayout()
sort2_layout.addWidget(QLabel("Сортировка:"))
self.combo_sort2 = QComboBox()
self.combo_sort2.addItems([
"По длине (возр.)",
"По длине (убыв.)",
"По алфавиту (возр.)",
"По алфавиту (убыв.)"
])
sort2_layout.addWidget(self.combo_sort2)
self.btn_sort2 = QPushButton("Сортировать")
self.btn_sort2.clicked.connect(lambda: self.sort_list(self.list2, self.combo_sort2))
sort2_layout.addWidget(self.btn_sort2)
section2_layout.addLayout(sort2_layout)
self.btn_clear2 = QPushButton("Очистить")
self.btn_clear2.clicked.connect(lambda: self.list2.clear())
section2_layout.addWidget(self.btn_clear2)
# Кнопка сохранения
self.btn_save = QPushButton("Сохранить в файл")
self.btn_save.clicked.connect(self.save_file)
section2_layout.addWidget(self.btn_save)
middle_layout.addWidget(section2_group)
main_layout.addLayout(middle_layout)
# === Нижняя часть: поиск ===
search_group = QGroupBox("Поиск")
search_layout = QHBoxLayout(search_group)
search_layout.addWidget(QLabel("Искать:"))
self.search_input = QLineEdit()
self.search_input.setPlaceholderText("Введите текст для поиска...")
search_layout.addWidget(self.search_input)
# CheckBox для выбора раздела поиска
self.check_search1 = QCheckBox("В разделе 1")
self.check_search1.setChecked(True)
self.check_search2 = QCheckBox("В разделе 2")
self.check_search2.setChecked(True)
search_layout.addWidget(self.check_search1)
search_layout.addWidget(self.check_search2)
self.btn_search = QPushButton("Найти")
self.btn_search.clicked.connect(self.search_items)
search_layout.addWidget(self.btn_search)
self.btn_reset_search = QPushButton("Сбросить")
self.btn_reset_search.clicked.connect(self.reset_search)
search_layout.addWidget(self.btn_reset_search)
main_layout.addWidget(search_group)
def open_file(self):
"""Открыть текстовый файл"""
file_path, _ = QFileDialog.getOpenFileName(
self, "Открыть файл", "", "Текстовые файлы (*.txt);;Все файлы (*)"
)
if file_path:
try:
with open(file_path, 'r', encoding='utf-8') as f:
self.text_edit.setText(f.read())
except Exception as e:
QMessageBox.critical(self, "Ошибка", f"Не удалось открыть файл:\n{e}")
def process_text(self):
"""Обработать текст и заполнить Раздел 1"""
text = self.text_edit.toPlainText()
if not text.strip():
QMessageBox.warning(self, "Внимание", "Текст пуст!")
return
# Разбиваем на слова
words = re.findall(r'\S+', text)
# Фильтруем по критерию
criteria = self.radio_group.checkedId()
filtered_words = []
for word in words:
if criteria == 0: # Все
filtered_words.append(word)
elif criteria == 1: # Содержащие цифры
if re.search(r'\d', word):
filtered_words.append(word)
elif criteria == 2: # Содержащие e-mail
if re.search(r'[\w.-]+@[\w.-]+\.\w+', word):
filtered_words.append(word)
# Заполняем ListBox
self.list1.clear()
self.list1.addItems(filtered_words)
QMessageBox.information(
self, "Готово",
f"Найдено слов: {len(filtered_words)}"
)
def move_selected_right(self):
"""Переместить выбранные элементы из Раздела 1 в Раздел 2"""
selected = self.list1.selectedItems()
for item in selected:
self.list2.addItem(item.text())
self.list1.takeItem(self.list1.row(item))
def move_all_right(self):
"""Переместить все элементы из Раздела 1 в Раздел 2"""
while self.list1.count() > 0:
item = self.list1.takeItem(0)
self.list2.addItem(item.text())
def move_selected_left(self):
"""Переместить выбранные элементы из Раздела 2 в Раздел 1"""
selected = self.list2.selectedItems()
for item in selected:
self.list1.addItem(item.text())
self.list2.takeItem(self.list2.row(item))
def move_all_left(self):
"""Переместить все элементы из Раздела 2 в Раздел 1"""
while self.list2.count() > 0:
item = self.list2.takeItem(0)
self.list1.addItem(item.text())
def add_item(self):
"""Добавить новый элемент"""
text, ok = QInputDialog.getText(self, "Добавить элемент", "Введите слово:")
if ok and text.strip():
# Спрашиваем куда добавить
items = ["Раздел 1", "Раздел 2"]
choice, ok = QInputDialog.getItem(
self, "Выбор раздела", "Куда добавить?", items, 0, False
)
if ok:
if choice == "Раздел 1":
self.list1.addItem(text.strip())
else:
self.list2.addItem(text.strip())
def delete_selected(self):
"""Удалить выбранные элементы из обоих разделов"""
# Удаляем из раздела 1
for item in self.list1.selectedItems():
self.list1.takeItem(self.list1.row(item))
# Удаляем из раздела 2
for item in self.list2.selectedItems():
self.list2.takeItem(self.list2.row(item))
def sort_list(self, list_widget, combo_box):
"""Сортировка списка выбранным алгоритмом (пузырьковая сортировка)"""
# Получаем все элементы
items = [list_widget.item(i).text() for i in range(list_widget.count())]
if not items:
return
sort_type = combo_box.currentIndex()
# Пузырьковая сортировка
n = len(items)
for i in range(n):
for j in range(0, n - i - 1):
should_swap = False
if sort_type == 0: # По длине (возр.)
should_swap = len(items[j]) > len(items[j + 1])
elif sort_type == 1: # По длине (убыв.)
should_swap = len(items[j]) < len(items[j + 1])
elif sort_type == 2: # По алфавиту (возр.)
should_swap = items[j].lower() > items[j + 1].lower()
elif sort_type == 3: # По алфавиту (убыв.)
should_swap = items[j].lower() < items[j + 1].lower()
if should_swap:
items[j], items[j + 1] = items[j + 1], items[j]
# Обновляем список
list_widget.clear()
list_widget.addItems(items)
def search_items(self):
"""Поиск элементов в разделах"""
search_text = self.search_input.text().lower()
if not search_text:
return
found_count = 0
# Поиск в разделе 1
if self.check_search1.isChecked():
for i in range(self.list1.count()):
item = self.list1.item(i)
if search_text in item.text().lower():
item.setSelected(True)
found_count += 1
else:
item.setSelected(False)
# Поиск в разделе 2
if self.check_search2.isChecked():
for i in range(self.list2.count()):
item = self.list2.item(i)
if search_text in item.text().lower():
item.setSelected(True)
found_count += 1
else:
item.setSelected(False)
QMessageBox.information(self, "Результат поиска", f"Найдено элементов: {found_count}")
def reset_search(self):
"""Сбросить поиск"""
self.search_input.clear()
self.list1.clearSelection()
self.list2.clearSelection()
def save_file(self):
"""Сохранить содержимое Раздела 2 в файл"""
if self.list2.count() == 0:
QMessageBox.warning(self, "Внимание", "Раздел 2 пуст!")
return
file_path, _ = QFileDialog.getSaveFileName(
self, "Сохранить файл", "", "Текстовые файлы (*.txt)"
)
if file_path:
try:
with open(file_path, 'w', encoding='utf-8') as f:
items = [self.list2.item(i).text() for i in range(self.list2.count())]
f.write('\n'.join(items))
QMessageBox.information(self, "Успех", "Файл сохранён!")
except Exception as e:
QMessageBox.critical(self, "Ошибка", f"Не удалось сохранить файл:\n{e}")
if __name__ == '__main__':
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())

View File

@@ -0,0 +1,44 @@
# -*- mode: python ; coding: utf-8 -*-
a = Analysis(
['main.py'],
pathex=[],
binaries=[],
datas=[],
hiddenimports=[],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
noarchive=False,
optimize=0,
)
pyz = PYZ(a.pure)
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.datas,
[],
name='main',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=False,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
)
app = BUNDLE(
exe,
name='main.app',
icon=None,
bundle_identifier=None,
)