From 62aa63f62f4edd4a40f2701c6205c8324fb21ea0 Mon Sep 17 00:00:00 2001 From: evgeniy Date: Thu, 27 Jun 2024 09:16:08 +0500 Subject: [PATCH] On branch main Your branch is up to date with 'origin/main'. Changes to be committed: modified: main.py modified: mainWindow.py new file: qt_markdown/__init__.py new file: qt_markdown/__pycache__/__init__.cpython-39.pyc new file: qt_markdown/__pycache__/qt_markdown.cpython-39.pyc new file: qt_markdown/qt_markdown.py new file: qt_markdown/text_formatter/__init__.py new file: qt_markdown/text_formatter/__pycache__/__init__.cpython-39.pyc new file: qt_markdown/text_formatter/__pycache__/header_formatter.cpython-39.pyc new file: qt_markdown/text_formatter/__pycache__/text_formatter.cpython-39.pyc new file: qt_markdown/text_formatter/__pycache__/text_style_formatter.cpython-39.pyc new file: qt_markdown/text_formatter/header_formatter.py new file: qt_markdown/text_formatter/text_formatter.py new file: qt_markdown/text_formatter/text_style_formatter.py new file: qt_markdown/toolbar/__init__.py new file: qt_markdown/toolbar/__pycache__/__init__.cpython-39.pyc new file: qt_markdown/toolbar/__pycache__/toolbar.cpython-39.pyc new file: qt_markdown/toolbar/toolbar.py modified: startWindow.py --- main.py | 40 ++++++-- mainWindow.py | 22 ++-- qt_markdown/__init__.py | 0 .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 157 bytes .../__pycache__/qt_markdown.cpython-39.pyc | Bin 0 -> 761 bytes qt_markdown/qt_markdown.py | 10 ++ qt_markdown/text_formatter/__init__.py | 0 .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 172 bytes .../header_formatter.cpython-39.pyc | Bin 0 -> 2060 bytes .../__pycache__/text_formatter.cpython-39.pyc | Bin 0 -> 3989 bytes .../text_style_formatter.cpython-39.pyc | Bin 0 -> 2742 bytes .../text_formatter/header_formatter.py | 45 +++++++++ qt_markdown/text_formatter/text_formatter.py | 69 +++++++++++++ .../text_formatter/text_style_formatter.py | 92 +++++++++++++++++ qt_markdown/toolbar/__init__.py | 0 .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 165 bytes .../__pycache__/toolbar.cpython-39.pyc | Bin 0 -> 3382 bytes qt_markdown/toolbar/toolbar.py | 94 ++++++++++++++++++ startWindow.py | 28 +++--- 19 files changed, 365 insertions(+), 35 deletions(-) create mode 100644 qt_markdown/__init__.py create mode 100644 qt_markdown/__pycache__/__init__.cpython-39.pyc create mode 100644 qt_markdown/__pycache__/qt_markdown.cpython-39.pyc create mode 100644 qt_markdown/qt_markdown.py create mode 100644 qt_markdown/text_formatter/__init__.py create mode 100644 qt_markdown/text_formatter/__pycache__/__init__.cpython-39.pyc create mode 100644 qt_markdown/text_formatter/__pycache__/header_formatter.cpython-39.pyc create mode 100644 qt_markdown/text_formatter/__pycache__/text_formatter.cpython-39.pyc create mode 100644 qt_markdown/text_formatter/__pycache__/text_style_formatter.cpython-39.pyc create mode 100644 qt_markdown/text_formatter/header_formatter.py create mode 100644 qt_markdown/text_formatter/text_formatter.py create mode 100644 qt_markdown/text_formatter/text_style_formatter.py create mode 100644 qt_markdown/toolbar/__init__.py create mode 100644 qt_markdown/toolbar/__pycache__/__init__.cpython-39.pyc create mode 100644 qt_markdown/toolbar/__pycache__/toolbar.cpython-39.pyc create mode 100644 qt_markdown/toolbar/toolbar.py diff --git a/main.py b/main.py index 8a4c87d..11d7f49 100644 --- a/main.py +++ b/main.py @@ -1,10 +1,13 @@ import sys import os import json -from PyQt5.QtWidgets import QApplication, QMainWindow, QFileDialog, QListWidgetItem, QLabel, QDesktopWidget -from PyQt5.QtCore import QDir, QFileSystemWatcher +from PyQt6.QtWidgets import QApplication, QMainWindow, QFileDialog, QListWidgetItem, QLabel +from PyQt6.QtCore import QDir, QFileSystemWatcher, Qt +from PyQt6.QtGui import QGuiApplication from startWindow import Ui_startWindow as Ui_StartWindow from mainWindow import Ui_MainWindow as Ui_MainWindow2 +from qt_markdown.qt_markdown import QtMarkDown + CONFIG_FILE = "catalogs.json" @@ -23,10 +26,11 @@ class StartWindow(QMainWindow): self.load_catalogs() def window_center(self): - qr = self.frameGeometry() - cp = QDesktopWidget().availableGeometry().center() - qr.moveCenter(cp) - self.move(qr.topLeft()) + screen = QGuiApplication.primaryScreen() + screen_geometry = screen.geometry() + window_geometry = self.frameGeometry() + window_geometry.moveCenter(screen_geometry.center()) + self.move(window_geometry.topLeft()) def create_catalog(self): folder_path = QFileDialog.getSaveFileName(self, "Create New Catalog", "", "All Files (*);;Directory")[0] @@ -88,6 +92,7 @@ class MainWindow(QMainWindow): self.create_file() self.ui.noteTitleEdit.textChanged.connect(self.save_note_title) self.ui.noteEdit.textChanged.connect(self.save_note_content) + self.show_note_edit_and_toolbar() else: self.show_default_label() @@ -97,6 +102,9 @@ class MainWindow(QMainWindow): self.file_watcher.addPath(self.folder_path) self.file_watcher.directoryChanged.connect(self.show_directory_files) + self.qt_markdown = QtMarkDown(self.ui.noteEdit) + + def load_selected_note(self, item): note_name = item.text() self.default_note_path = os.path.join(self.folder_path, note_name) @@ -104,9 +112,23 @@ class MainWindow(QMainWindow): self.ui.noteTitleEdit.setPlainText(note_name) self.ui.noteTitleEdit.show() self.ui.noteEdit.show() + self.show_note_edit_and_toolbar() + if hasattr(self, 'static_label'): self.static_label.hide() + # Подключаем сигналы для автосохранения + self.ui.noteTitleEdit.textChanged.connect(self.save_note_title) + self.ui.noteEdit.textChanged.connect(self.save_note_content) + + def show_note_edit_and_toolbar(self): + if not hasattr(self, 'toolbar'): + self.qt_markdown = QtMarkDown(self.ui.noteEdit) + self.toolbar = self.qt_markdown.get_toolbar() + + self.ui.noteEdit.show() + self.ui.verticalLayout.insertWidget(0, self.toolbar) + def create_file(self): base_name = "Без_Имени" extension = ".md" @@ -152,7 +174,7 @@ class MainWindow(QMainWindow): def show_directory_files(self): if os.path.exists(self.folder_path): self.ui.mainList.clear() - dir_content = QDir(self.folder_path).entryList(QDir.Files) + dir_content = QDir(self.folder_path).entryList(QDir.Filter.Files) for file_name in dir_content: item = QListWidgetItem(file_name) self.ui.mainList.addItem(item) @@ -160,6 +182,8 @@ class MainWindow(QMainWindow): def show_default_label(self): self.ui.noteTitleEdit.hide() self.ui.noteEdit.hide() + if hasattr(self, 'toolbar'): + self.toolbar.hide() if not hasattr(self, 'static_label'): self.static_label = QLabel("Выберите файл из списка или создайте новый") @@ -176,4 +200,4 @@ if __name__ == "__main__": app = QApplication(sys.argv) start_window = StartWindow() start_window.show() - sys.exit(app.exec_()) + sys.exit(app.exec()) diff --git a/mainWindow.py b/mainWindow.py index 76495d2..f771822 100644 --- a/mainWindow.py +++ b/mainWindow.py @@ -1,30 +1,28 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file '/home/merelden/Документы/NoteQt/mainWindow.ui' +# Form implementation generated from reading ui file '/home/evgeniy/Документы/Note_Qt/mainWindow.ui' # -# Created by: PyQt5 UI code generator 5.15.10 +# Created by: PyQt6 UI code generator 6.7.0 # -# WARNING: Any manual changes made to this file will be lost when pyuic5 is +# WARNING: Any manual changes made to this file will be lost when pyuic6 is # run again. Do not edit this file unless you know what you are doing. -from PyQt5 import QtCore, QtGui, QtWidgets +from PyQt6 import QtCore, QtGui, QtWidgets class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.resize(800, 600) - self.centralwidget = QtWidgets.QWidget(MainWindow) + self.centralwidget = QtWidgets.QWidget(parent=MainWindow) self.centralwidget.setObjectName("centralwidget") self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.centralwidget) self.verticalLayout_2.setObjectName("verticalLayout_2") self.horizontalLayout = QtWidgets.QHBoxLayout() self.horizontalLayout.setObjectName("horizontalLayout") - self.back = QtWidgets.QPushButton(self.centralwidget) + self.back = QtWidgets.QPushButton(parent=self.centralwidget) self.back.setObjectName("back") self.horizontalLayout.addWidget(self.back) - self.createFile = QtWidgets.QPushButton(self.centralwidget) + self.createFile = QtWidgets.QPushButton(parent=self.centralwidget) font = QtGui.QFont() font.setPointSize(10) self.createFile.setFont(font) @@ -33,17 +31,17 @@ class Ui_MainWindow(object): self.verticalLayout_2.addLayout(self.horizontalLayout) self.horizontalLayout_2 = QtWidgets.QHBoxLayout() self.horizontalLayout_2.setObjectName("horizontalLayout_2") - self.mainList = QtWidgets.QListWidget(self.centralwidget) + self.mainList = QtWidgets.QListWidget(parent=self.centralwidget) self.mainList.setMaximumSize(QtCore.QSize(150, 16777215)) self.mainList.setObjectName("mainList") self.horizontalLayout_2.addWidget(self.mainList) self.verticalLayout = QtWidgets.QVBoxLayout() self.verticalLayout.setObjectName("verticalLayout") - self.noteTitleEdit = QtWidgets.QTextEdit(self.centralwidget) + self.noteTitleEdit = QtWidgets.QTextEdit(parent=self.centralwidget) self.noteTitleEdit.setMaximumSize(QtCore.QSize(16777215, 30)) self.noteTitleEdit.setObjectName("noteTitleEdit") self.verticalLayout.addWidget(self.noteTitleEdit) - self.noteEdit = QtWidgets.QTextEdit(self.centralwidget) + self.noteEdit = QtWidgets.QTextEdit(parent=self.centralwidget) self.noteEdit.setObjectName("noteEdit") self.verticalLayout.addWidget(self.noteEdit) self.horizontalLayout_2.addLayout(self.verticalLayout) diff --git a/qt_markdown/__init__.py b/qt_markdown/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/qt_markdown/__pycache__/__init__.cpython-39.pyc b/qt_markdown/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ae3daea630f5be3e0ff291f85dee21e850db5ac2 GIT binary patch literal 157 zcmYe~<>g`k0_LSvX(0MBh(HF6K#l_t7qb9~6oz01O-8?!3`HPe1o71#$kort&rQ`& zElW?$%dFJDFy+F&3%f2hU)XbD>xI1+n=W?i=ca_D7MJK3mc-{K7G1DX99h#3GT(kmJO literal 0 HcmV?d00001 diff --git a/qt_markdown/__pycache__/qt_markdown.cpython-39.pyc b/qt_markdown/__pycache__/qt_markdown.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3937f798eac943ce613634e083e4b4ecb09962e5 GIT binary patch literal 761 zcmY*W&2G~`5T02(ZJH(^gv0^C1DHen0ti)rKtiHY)tr1;nd~MQ{6p8R-9E((BUgROX2IVRL3Y5PRk*|8E5bXV-ZV+HSn&>a~RbjH&T5ag!-Zn|{`J^b) zcd?mL<&Fu;j>yYL1R5e#5DA4!TtVbDquMd`;KaU-&BvF;=X}clwZ<{~3-a8w6*Razx>4d#GK{yrxN z-xrw<^~GH0$z@o5uYOfGn^kpNT~|LhUpL>vOigrY!!s*0VyuX9Hy(ewtou?Xd19sP zQNPkB036`r{(p_*wqnZrZH;4gCw7kl5=g=fw+Ybj4ITS*IJyn+!`Fv%ZRJ)UD=B#m zfQtv6k)4v`pvNThIMY(r11YmYou?cRr93;2)8>mgq$Xy_z)d^ALk$aKcMAL1_uUQk pjvnvsf4rMEZ*+G{cf38_Be@QpIc}^|*niq^e8vlM6Nfky{{Z?Vv`hd1 literal 0 HcmV?d00001 diff --git a/qt_markdown/qt_markdown.py b/qt_markdown/qt_markdown.py new file mode 100644 index 0000000..4a7a594 --- /dev/null +++ b/qt_markdown/qt_markdown.py @@ -0,0 +1,10 @@ +from .text_formatter.text_formatter import TextFormatter +from .toolbar.toolbar import FormattingToolbar + +class QtMarkDown: + def __init__(self, text_edit): + self.text_formatter = TextFormatter(text_edit) + self.toolbar = FormattingToolbar(self.text_formatter) + + def get_toolbar(self): + return self.toolbar \ No newline at end of file diff --git a/qt_markdown/text_formatter/__init__.py b/qt_markdown/text_formatter/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/qt_markdown/text_formatter/__pycache__/__init__.cpython-39.pyc b/qt_markdown/text_formatter/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b2499e62b1a8de0a32a7efb50c916c6142700c0d GIT binary patch literal 172 zcmYe~<>g`kg8bQ4X(0MBh(HF6K#l_t7qb9~6oz01O-8?!3`HPe1o71m$kort&rQ`& zElW?$%dFJDFy+F&3%f2hU)XbD>xI1+n=W?i=ca_D7MJK3mc-{K7G7U{>wXXa&=#K-FuRNmsS$<0qG%}KQbS@ju+830upF|q&v literal 0 HcmV?d00001 diff --git a/qt_markdown/text_formatter/__pycache__/header_formatter.cpython-39.pyc b/qt_markdown/text_formatter/__pycache__/header_formatter.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dd7e7bb29f4ce61c69e65244cc5cf239ac8ea9b9 GIT binary patch literal 2060 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[^<]+?)') + + def apply_text_formatting(self, cursor, text): + # Process bold and italic text + pos = 0 + bold_italic_positions = [] + while (match := self.regex_bold_italic.match(text, pos)).hasMatch(): + match_len = match.capturedLength() + start = match.capturedStart(0) + 3 # Start of text between asterisks + end = start + match_len - 6 # End of text between asterisks + + bold_italic_positions.append((start, end)) + + cursor.setPosition(start) + cursor.movePosition(QTextCursor.MoveOperation.Right, QTextCursor.MoveMode.KeepAnchor, match_len - 6) + + char_format = QTextCharFormat() + char_format.setFontWeight(QFont.Weight.Bold) + char_format.setFontItalic(True) + cursor.mergeCharFormat(char_format) + + pos = match.capturedEnd(0) + + # Process bold text + pos = 0 + bold_positions = [] + while (match := self.regex_bold.match(text, pos)).hasMatch(): + match_len = match.capturedLength() + start = match.capturedStart(0) + 2 # Start of text between asterisks + end = start + match_len - 4 # End of text between asterisks + + if not any(start < bi_end and end > bi_start for bi_start, bi_end in bold_italic_positions): + bold_positions.append((start, end)) + + cursor.setPosition(start) + cursor.movePosition(QTextCursor.MoveOperation.Right, QTextCursor.MoveMode.KeepAnchor, match_len - 4) + + char_format = QTextCharFormat() + char_format.setFontWeight(QFont.Weight.Bold) + cursor.mergeCharFormat(char_format) + + pos = match.capturedEnd(0) + + # Process italic text + pos = 0 + while (match := self.regex_italic.match(text, pos)).hasMatch(): + match_len = match.capturedLength() + start = match.capturedStart(0) + 1 # Start of text between asterisks + end = start + match_len - 2 # End of text between asterisks + + # Check for overlap with bold or bold and italic text + if not any(start < b_end and end > b_start for b_start, b_end in bold_positions) and \ + not any(start < bi_end and end > bi_start for bi_start, bi_end in bold_italic_positions): + cursor.setPosition(start) + cursor.movePosition(QTextCursor.MoveOperation.Right, QTextCursor.MoveMode.KeepAnchor, match_len - 2) + + char_format = QTextCharFormat() + char_format.setFontItalic(True) + cursor.mergeCharFormat(char_format) + + pos = match.capturedEnd(0) + + pos = 0 + while (match := self.regex_stroke.match(text, pos)).hasMatch(): + start = match.capturedStart(1) + end = match.capturedEnd(1) + cursor.setPosition(start) + cursor.movePosition(QTextCursor.MoveOperation.Right, QTextCursor.MoveMode.KeepAnchor, end - start) + char_format = QTextCharFormat() + char_format.setFontStrikeOut(True) + cursor.mergeCharFormat(char_format) + pos = match.capturedEnd(0) + + pos = 0 + while (match := self.regex_underline.match(text, pos)).hasMatch(): + start = match.capturedStart(1) + end = match.capturedEnd(1) + cursor.setPosition(start) + cursor.movePosition(QTextCursor.MoveOperation.Right, QTextCursor.MoveMode.KeepAnchor, end - start) + char_format = QTextCharFormat() + char_format.setFontUnderline(True) + cursor.mergeCharFormat(char_format) + pos = match.capturedEnd(0) \ No newline at end of file diff --git a/qt_markdown/toolbar/__init__.py b/qt_markdown/toolbar/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/qt_markdown/toolbar/__pycache__/__init__.cpython-39.pyc b/qt_markdown/toolbar/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..3165a2b07531e84e76c73e5540f93129ac01a67b GIT binary patch literal 165 zcmYe~<>g`kg7dSh(m?cM5P=LBfgA@QE@lA|DGb33nv8xc8Hzx{2;!?dkgK1OpPQ(p8ejl-~0K6&8AP_ z_xt{6bEiefuQ-_fIWTw&TK+b4oNyYGgff~~%t~x#Ck}Ix3ae1$S#dR~v0CCXH}RN9 z$-9Kx+_^)zBj}#Zd|p{6-Rf_!6X{lTZS9kY_l45+wT~}lJMV|P*$@X;X9w4Y`QXw} zsVvpr+T|?S$bj3mb$ji)*in}Up}dmGBviVxb|p)3xtSlzJd-_CH2bs5fpJC`Teh!5`JCeYU!p5l2G2@+3j>m74{!~7q@q11GcI_%d5~4>eDJ6J$=OE z#Y0nj6vfIPx{Pa$>vw>Iu764uh2ByYr+f4Z64+mmEqmf{YoAhr^j2k3HFtucKu5CCCm}!)prs1^qz@wlI^X*BePk84$T54!-9Wy)3;dpFKj)ROnL)T_#a|Wf1 z@usBx85v`FIo~$(bTU6K&vf#{*yuGOc5HQs@p$mfXl@e{=Im_|^#|(0!bTSJi@oyd zrXRe!d>1k`&gC2|yGLak zK8BXKnRb`sFxlYYN(V-NKqI49js{g3>Wj;9)(hi&1&Cr*;lQ_}OGzZnx2vKpuI5d#FRoKScJ9~9xFArBn&hpZ5 z<-d(U$TCJ~>*}k}&ULHu6wV=oSyx|!_Byol(B9~tkQgu$bxTZrR^Kq#9bj~^W-in^ z-q!j+2*qkWxUd_7>sl{MQ_)kbSxOgoIUVLoMmGfOl-#M)tX0koLYm1~4$uPcOh5(|q7`VK(y<-+d{WL$t3>>p`~2hD1-%+3_D6U zlI)hamgNybpl*HuqYt5AF^I_O>nfD$!_D^rlvo@4*^Mfg%G=t{Q7FG1se!IZu^op! z0r_E=Y)%SPP?%JxWPTBPg?f?lsUO`+kzCC(Ba3%OS0Q&^CtIgqGJ!Cf3*#0w(vIRoR7A@@44$q6+{e3qY|pfD2sB6rLoS-*t+ks6>cZ ztWlmwEN+QdVpcrt^YbwGF|^!;j!>62?1nvh;i!K{L9gp$d76fafb!H2f+XWZfW<&J zg5c&bj0=vb9wkDG0S1ZbX-t)W7l=4kKAZDfHVUfZ1)vfN5MnrBb-If+?1x JDbLV(>u>({K;HlW literal 0 HcmV?d00001 diff --git a/qt_markdown/toolbar/toolbar.py b/qt_markdown/toolbar/toolbar.py new file mode 100644 index 0000000..d6b3456 --- /dev/null +++ b/qt_markdown/toolbar/toolbar.py @@ -0,0 +1,94 @@ +from PyQt6.QtWidgets import QWidget, QVBoxLayout, QHBoxLayout, QPushButton, QComboBox +from PyQt6.QtGui import QTextCharFormat, QFont, QTextCursor + +class FormattingToolbar(QWidget): + def __init__(self, formatter): + super().__init__() + self.formatter = formatter + self.init_ui() + + def init_ui(self): + layout = QVBoxLayout() + toolbar_layout = QHBoxLayout() + + self.button_bold = QPushButton("Ж") + self.button_bold.setStyleSheet("font-weight: bold;") + self.button_bold.clicked.connect(lambda: self.formatter.toggle_special_symbols('**')) + + self.button_italic = QPushButton("К") + self.button_italic.setStyleSheet("font-style: italic;") + self.button_italic.clicked.connect(lambda: self.formatter.toggle_special_symbols('*')) + + self.button_strike = QPushButton("abc") + self.button_strike.setStyleSheet("text-decoration: line-through;") + self.button_strike.clicked.connect(lambda: self.formatter.toggle_special_symbols('~~')) + + self.button_underline = QPushButton("Ч") + self.button_underline.setStyleSheet("text-decoration: underline;") + self.button_underline.clicked.connect(lambda: self.formatter.toggle_special_symbols('', '')) + + self.button_header1 = QPushButton("H1") + self.button_header1.clicked.connect(self.insert_header1) + + self.button_header2 = QPushButton("H2") + self.button_header2.clicked.connect(self.insert_header2) + + self.header_drop = QComboBox() + self.header_drop.addItems(["H1", "H2", "H3", "H4", "H5", "H6"]) + self.header_drop.currentIndexChanged.connect(self.handle_header_drop) + + + toolbar_layout.addWidget(self.button_bold) + toolbar_layout.addWidget(self.button_italic) + toolbar_layout.addWidget(self.button_strike) + toolbar_layout.addWidget(self.button_underline) + toolbar_layout.addWidget(self.button_header1) + toolbar_layout.addWidget(self.button_header2) + toolbar_layout.addWidget(self.header_drop) + + + layout.addLayout(toolbar_layout) + self.setLayout(layout) + + def insert_header1(self): + self.insert_header('# ') + + def insert_header2(self): + self.insert_header('## ') + + def insert_header(self, header_symbol): + cursor = self.formatter.text_edit.textCursor() + cursor.beginEditBlock() + + # Get selected text or word under cursor + cursor.select(QTextCursor.SelectionType.WordUnderCursor) + selected_text = cursor.selectedText() + + # Check if there's already a header symbol at the beginning + cursor.movePosition(QTextCursor.MoveOperation.StartOfLine) + cursor.select(QTextCursor.SelectionType.LineUnderCursor) + line_text = cursor.selectedText().strip() + + if line_text.startswith('#'): + # Remove existing header symbol and space + line_text = line_text.replace('#', '', 1).lstrip() + + if selected_text: + # Replace the selected text with the header symbol + selected text + cursor.removeSelectedText() + cursor.insertText(header_symbol + selected_text) + else: + # If no word is selected, just insert the header symbol + cursor.insertText(header_symbol) + + cursor.endEditBlock() + + def handle_header_drop(self, index): + header_level = index + 1 # Since index starts from 0, but header levels start from 1 + header_symbol = '#' * header_level + ' ' + + # Set the correct index in the headerDrop ComboBox + self.header_drop.setCurrentIndex(index) + + # Call insert_header with the header_symbol + self.insert_header(header_symbol) \ No newline at end of file diff --git a/startWindow.py b/startWindow.py index f240fb9..11f75b2 100644 --- a/startWindow.py +++ b/startWindow.py @@ -1,21 +1,19 @@ -# -*- coding: utf-8 -*- - -# Form implementation generated from reading ui file '/home/merelden/Документы/NoteQt/startWindow.ui' +# Form implementation generated from reading ui file '/home/evgeniy/Документы/Note_Qt/startWindow.ui' # -# Created by: PyQt5 UI code generator 5.15.10 +# Created by: PyQt6 UI code generator 6.7.0 # -# WARNING: Any manual changes made to this file will be lost when pyuic5 is +# WARNING: Any manual changes made to this file will be lost when pyuic6 is # run again. Do not edit this file unless you know what you are doing. -from PyQt5 import QtCore, QtGui, QtWidgets +from PyQt6 import QtCore, QtGui, QtWidgets class Ui_startWindow(object): def setupUi(self, startWindow): startWindow.setObjectName("startWindow") startWindow.resize(800, 600) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Fixed, QtWidgets.QSizePolicy.Policy.Fixed) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(startWindow.sizePolicy().hasHeightForWidth()) @@ -24,32 +22,32 @@ class Ui_startWindow(object): startWindow.setMaximumSize(QtCore.QSize(800, 600)) startWindow.setBaseSize(QtCore.QSize(800, 600)) startWindow.setAutoFillBackground(False) - self.centralwidget = QtWidgets.QWidget(startWindow) + self.centralwidget = QtWidgets.QWidget(parent=startWindow) self.centralwidget.setObjectName("centralwidget") self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.centralwidget) self.verticalLayout_2.setObjectName("verticalLayout_2") self.horizontalLayout_3 = QtWidgets.QHBoxLayout() self.horizontalLayout_3.setObjectName("horizontalLayout_3") - self.startWindowList = QtWidgets.QListWidget(self.centralwidget) + self.startWindowList = QtWidgets.QListWidget(parent=self.centralwidget) self.startWindowList.setMinimumSize(QtCore.QSize(250, 0)) self.startWindowList.setMaximumSize(QtCore.QSize(252, 16777215)) self.startWindowList.setStyleSheet("max-width: 250") self.startWindowList.setObjectName("startWindowList") self.horizontalLayout_3.addWidget(self.startWindowList) self.verticalLayout = QtWidgets.QVBoxLayout() - self.verticalLayout.setSizeConstraint(QtWidgets.QLayout.SetMinimumSize) + self.verticalLayout.setSizeConstraint(QtWidgets.QLayout.SizeConstraint.SetMinimumSize) self.verticalLayout.setSpacing(0) self.verticalLayout.setObjectName("verticalLayout") self.horizontalLayout = QtWidgets.QHBoxLayout() self.horizontalLayout.setObjectName("horizontalLayout") - self.label = QtWidgets.QLabel(self.centralwidget) + self.label = QtWidgets.QLabel(parent=self.centralwidget) self.label.setMaximumSize(QtCore.QSize(16777215, 16777215)) font = QtGui.QFont() font.setPointSize(14) self.label.setFont(font) self.label.setObjectName("label") self.horizontalLayout.addWidget(self.label) - self.createCatalog = QtWidgets.QPushButton(self.centralwidget) + self.createCatalog = QtWidgets.QPushButton(parent=self.centralwidget) font = QtGui.QFont() font.setPointSize(14) self.createCatalog.setFont(font) @@ -58,8 +56,8 @@ class Ui_startWindow(object): self.verticalLayout.addLayout(self.horizontalLayout) self.horizontalLayout_2 = QtWidgets.QHBoxLayout() self.horizontalLayout_2.setObjectName("horizontalLayout_2") - self.label_2 = QtWidgets.QLabel(self.centralwidget) - sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) + self.label_2 = QtWidgets.QLabel(parent=self.centralwidget) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Policy.Preferred, QtWidgets.QSizePolicy.Policy.Preferred) sizePolicy.setHorizontalStretch(0) sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.label_2.sizePolicy().hasHeightForWidth()) @@ -70,7 +68,7 @@ class Ui_startWindow(object): self.label_2.setFont(font) self.label_2.setObjectName("label_2") self.horizontalLayout_2.addWidget(self.label_2) - self.openCatalog = QtWidgets.QPushButton(self.centralwidget) + self.openCatalog = QtWidgets.QPushButton(parent=self.centralwidget) font = QtGui.QFont() font.setPointSize(14) self.openCatalog.setFont(font)