Files
2025-12-11 15:39:41 +03:00

388 lines
16 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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_())