From fb45ffde86da0463b8e1ba3847c47dda2de0bda7 Mon Sep 17 00:00:00 2001
From: berkaygediz <121058050+berkaygediz@users.noreply.github.com>
Date: Tue, 19 Nov 2024 03:55:20 +0300
Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A5=E2=9C=8F=EF=B8=8Fcode=20cleanup,?=
=?UTF-8?q?=20title,=20defining=20statistics,=20file=20opening=20argument,?=
=?UTF-8?q?=20toolbar=20translations,=20llm=20consent,=20function=20names,?=
=?UTF-8?q?=20hebrew=20language,=20readme?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
README.md | 6 +-
RichSpan.py | 347 +++++++++++++++++++++++----------------------
modules/globals.py | 131 ++++++++++++++++-
3 files changed, 308 insertions(+), 176 deletions(-)
diff --git a/README.md b/README.md
index 5f96838..2c59110 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
# RichSpan - A Supercharged Word Processor
-
+
@@ -31,7 +31,7 @@ RichSpan is a supercharged word processor offering a powerful alternative to tra
- [x] **Base64 Image Support**: Embed images in documents using Base64 encoding.
- [x] **Customizable Toolbar**: Personalize the user interface toolbar to suit your workflow.
- [x] **Performance**: Fast and lightweight with threading support and hardware acceleration.
-- [x] **Multilingual Support**: Available in multiple languages including English, Deutsch, Español, Türkçe, Azərbaycanca, Uzbek, 中文 (Chinese), 한국어 (Korean), 日本語 (Japanese), العربية (Arabic), Русский (Russian), Français, Ελληνικά (Greek).
+- [x] **Multilingual Support**: Available in multiple languages including English, Deutsch, Español, Türkçe, Azərbaycanca, Uzbek, 中文 (Chinese), 한국어 (Korean), 日本語 (Japanese), العربية (Arabic), Русский (Russian), Français, Ελληνικά (Greek), Hebrew (עברית).
- [x] **Lists**: Create numbered or bulleted lists.
- [x] **Adaptive Power Saving**: Optimized for power efficiency with hybrid ultra and standard power saving modes.
- [x] **Offline AI Chat**: Offline AI chat powered by a local language model, enabling direct interaction for questions and content generation, with automatic language detection, assisted by a context menu for enhanced user experience.
@@ -68,7 +68,7 @@ RichSpan is a supercharged word processor offering a powerful alternative to tra
pyinstaller --noconfirm --onefile --windowed --icon ".\richspan_icon.ico" --name "RichSpan" --clean --optimize "2" "RichSpan.py"
```
-- Command for CUDA Support
+- Command for CUDA
```bash
pyinstaller --noconfirm --onefile --windowed --icon ".\richspan_icon.ico" --name "RichSpan" --clean --optimize "2" --add-data "path\RichSpan\.venv\Lib\site-packages\llama_cpp\lib\;." ".\RichSpan.py"
diff --git a/RichSpan.py b/RichSpan.py
index 5a463c5..5411a57 100644
--- a/RichSpan.py
+++ b/RichSpan.py
@@ -285,32 +285,32 @@ def showContextMenu(self, pos):
{
"name": "bold",
"text": translations[lang]["bold"],
- "function": self.ContentBold,
+ "function": self.contentBold,
},
{
"name": "italic",
"text": translations[lang]["italic"],
- "function": self.ContentItalic,
+ "function": self.contentItalic,
},
{
"name": "underline",
"text": translations[lang]["underline"],
- "function": self.ContentUnderline,
+ "function": self.contentUnderline,
},
{
"name": "color",
"text": translations[lang]["font_color"],
- "function": self.ContentColor,
+ "function": self.contentColor,
},
{
"name": "backgroundcolor",
"text": translations[lang]["contentBackgroundColor"],
- "function": self.ContentBGColor,
+ "function": self.contentBGColor,
},
{
"name": "fontfamily",
"text": translations[lang]["font"],
- "function": self.ContentFont,
+ "function": self.contentFont,
},
]
@@ -413,7 +413,6 @@ def closeEvent(self, event):
event.accept()
def changeLanguage(self):
- settings = QSettings("berkaygediz", "RichSpan")
settings.setValue("appLanguage", self.language_combobox.currentData())
settings.sync()
self.updateTitle()
@@ -421,18 +420,16 @@ def changeLanguage(self):
self.toolbarTranslate()
def updateTitle(self):
+ lang = settings.value("appLanguage")
+
file = self.file_name if self.file_name else translations[lang]["new"]
- if file.endswith(".docx"):
- textMode = " - Read Only"
- else:
- textMode = ""
+ textMode = translations[lang]["readonly"] if file.endswith(".docx") else ""
+
if len(textMode) == 0:
- if self.is_saved == True:
- asterisk = ""
- else:
- asterisk = "*"
+ asterisk = "*" if not self.is_saved else ""
else:
asterisk = ""
+
self.setWindowTitle(
f"{file}{asterisk}{textMode} — {app.applicationDisplayName()}"
)
@@ -446,14 +443,36 @@ def textChanged(self):
if not self.text_changed_timer.isActive():
self.text_changed_timer.start()
- def updateStatistics(self, lang=lang):
+ def updateStatistics(self):
self.text_changed_timer.stop()
self.thread_running = False
text = self.DocumentArea.toPlainText()
+
character_count = len(text)
word_count = len(text.split())
line_count = text.count("\n") + 1
+ avg_word_length = avg_line_length = uppercase_count = lowercase_count = None
+ detected_language = None
+ lang = settings.value("appLanguage")
+
+ if word_count > 0 and line_count > 0 and character_count > 0 and text != "":
+ avg_word_length = sum(len(word) for word in text.split()) / word_count
+ formatted_avg_word_length = "{:.1f}".format(avg_word_length)
+
+ avg_line_length = (character_count / line_count) - 1
+ formatted_avg_line_length = "{:.1f}".format(avg_line_length)
+
+ uppercase_count = sum(1 for char in text if char.isupper())
+ lowercase_count = sum(1 for char in text if char.islower())
+
+ if word_count > 20:
+ try:
+ DetectorFactory.seed = 0
+ detected_language = detect(text)
+ except Exception:
+ detected_language = None
+
statistics = f"
"
+
statistics += ""
- if word_count > 0 and line_count > 0 and character_count > 0 and text != "":
+
+ if avg_word_length is not None:
statistics += f"{translations[lang]['analysis']} | "
- avg_word_length = sum(len(word) for word in text.split()) / word_count
- formatted_avg_word_length = "{:.1f}".format(avg_word_length)
statistics += f"{translations[lang]['analysis_message_1'].format(formatted_avg_word_length)} | "
- avg_line_length = character_count / line_count - 1
- formatted_avg_line_length = "{:.1f}".format(avg_line_length)
statistics += f"{translations[lang]['analysis_message_2'].format(formatted_avg_line_length)} | "
- uppercase_count = sum(1 for char in text if char.isupper())
- lowercase_count = sum(1 for char in text if char.islower())
statistics += f"{translations[lang]['analysis_message_3'].format(uppercase_count)} | "
statistics += f"{translations[lang]['analysis_message_4'].format(lowercase_count)} | "
- if word_count > 20:
- try:
- DetectorFactory.seed = 0
- langdetect = detect(text)
- statistics += f"{translations[lang]['analysis_message_5'].format(langdetect)} | "
- except:
- None
+ if detected_language:
+ statistics += f"{translations[lang]['analysis_message_5'].format(detected_language)} | "
else:
self.DocumentArea.setFontFamily(fallbackValues["fontFamily"])
@@ -496,6 +506,7 @@ def updateStatistics(self, lang=lang):
self.DocumentArea.setTextBackgroundColor(
QColor(fallbackValues["contentBackgroundColor"])
)
+
statistics += f"{translations[lang]['statistic']} | "
statistics += (
f"{translations[lang]['statistic_message_1'].format(line_count)} | "
@@ -504,16 +515,22 @@ def updateStatistics(self, lang=lang):
f"{translations[lang]['statistic_message_2'].format(word_count)} | "
)
statistics += f"{translations[lang]['statistic_message_3'].format(character_count)} | "
+
statistics += f"{app.applicationDisplayName()} | "
+
statistics += "
"
self.statistics_label.setText(statistics)
+
self.status_bar.addPermanentWidget(self.statistics_label)
+
self.new_text = self.DocumentArea.toPlainText()
+
if self.new_text != fallbackValues["content"]:
self.is_saved = False
else:
self.is_saved = True
+
self.updateTitle()
def saveState(self):
@@ -535,7 +552,6 @@ def saveState(self):
def restoreState(self):
self.geometry = settings.value("windowScale")
self.directory = settings.value("defaultDirectory", self.default_directory)
- self.file_name = settings.value("fileName")
self.DocumentArea.setHtml(settings.value("content"))
self.is_saved = settings.value("isSaved")
index = self.language_combobox.findData(lang)
@@ -544,34 +560,20 @@ def restoreState(self):
if self.geometry is not None:
self.restoreGeometry(self.geometry)
- if self.file_name and os.path.exists(self.file_name):
- try:
- automaticEncoding = RS_Workspace.detectEncoding(self.file_name)
- except Exception as e:
- automaticEncoding = "utf-8"
-
- if self.file_name.endswith(".docx"):
- with open(
- self.file_name,
- "rb",
- ) as file:
- try:
- conversionLayer = mammoth.convert_to_html(file)
- self.DocumentArea.setHtml(conversionLayer.value)
- except:
- None
-
+ if len(sys.argv) > 1:
+ file_to_open = os.path.abspath(sys.argv[1])
+ if os.path.exists(file_to_open):
+ self.file_name = file_to_open
else:
- with open(self.file_name, "r", encoding=automaticEncoding) as file:
- if self.file_name.endswith((".rsdoc")):
- self.DocumentArea.setHtml(file.read())
- elif self.file_name.endswith((".html", ".htm")):
- self.DocumentArea.setHtml(file.read())
+ QMessageBox.warning(
+ self, "File Not Found", f"The file '{file_to_open}' does not exist."
+ )
+ return
+ else:
+ self.file_name = settings.value("fileName")
- elif self.file_name.endswith((".md")):
- self.DocumentArea.setMarkdown(file.read())
- else:
- self.DocumentArea.setPlainText(file.read())
+ if self.file_name and os.path.exists(self.file_name):
+ self.openFile(self.file_name)
scroll_position = settings.value("scrollPosition")
if scroll_position is not None:
@@ -579,10 +581,7 @@ def restoreState(self):
else:
self.DocumentArea.verticalScrollBar().setValue(0)
- if self.file_name:
- self.is_saved = True
- else:
- self.is_saved = False
+ self.is_saved = bool(self.file_name)
self.adaptiveResponse = settings.value("adaptiveResponse")
self.restoreTheme()
@@ -641,62 +640,46 @@ def toolbarTheme(self):
def toolbarTranslate(self):
lang = settings.value("appLanguage")
- self.newaction.setText(translations[lang]["new"])
- self.newaction.setStatusTip(translations[lang]["new_message"])
- self.openaction.setText(translations[lang]["open"])
- self.openaction.setStatusTip(translations[lang]["open_message"])
- self.saveaction.setText(translations[lang]["save"])
- self.saveaction.setStatusTip(translations[lang]["save_message"])
- self.saveasaction.setText(translations[lang]["save_as"])
- self.saveasaction.setStatusTip(translations[lang]["save_as_message"])
- self.printaction.setText(translations[lang]["print"])
- self.printaction.setStatusTip(translations[lang]["print_message"])
- self.undoaction.setText(translations[lang]["undo"])
- self.undoaction.setStatusTip(translations[lang]["undo_message"])
- self.redoaction.setText(translations[lang]["redo"])
- self.redoaction.setStatusTip(translations[lang]["redo_message"])
- self.theme_action.setText(translations[lang]["darklight"])
- self.theme_action.setStatusTip(translations[lang]["darklight_message"])
- self.powersaveraction.setText(translations[lang]["powersaver"])
- self.powersaveraction.setStatusTip(translations[lang]["powersaver_message"])
- self.hide_ai_dock.setText("AI")
- self.hide_ai_dock.setStatusTip("AI")
- self.findaction.setText(translations[lang]["find"])
- self.findaction.setStatusTip(translations[lang]["find_message"])
- self.replaceaction.setText(translations[lang]["replace"])
- self.replaceaction.setStatusTip(translations[lang]["replace_message"])
- self.helpAction.setText(translations[lang]["help"])
- self.helpAction.setStatusTip(translations[lang]["help"])
- self.aboutAction.setText(translations[lang]["about"])
- self.aboutAction.setStatusTip(translations[lang]["about"])
- self.alignrightevent.setText(translations[lang]["right"])
- self.alignrightevent.setStatusTip(translations[lang]["right_message"])
- self.aligncenterevent.setText(translations[lang]["center"])
- self.aligncenterevent.setStatusTip(translations[lang]["center_message"])
- self.alignleftevent.setText(translations[lang]["left"])
- self.alignleftevent.setStatusTip(translations[lang]["left_message"])
- self.alignjustifiedevent.setText(translations[lang]["justify"])
- self.alignjustifiedevent.setStatusTip(translations[lang]["justify_message"])
- self.bold.setText(translations[lang]["bold"])
- self.bold.setStatusTip(translations[lang]["bold_message"])
- self.italic.setText(translations[lang]["italic"])
- self.italic.setStatusTip(translations[lang]["italic_message"])
- self.underline.setText(translations[lang]["underline"])
- self.underline.setStatusTip(translations[lang]["underline_message"])
- self.bulletevent.setText(translations[lang]["bullet"])
- self.bulletevent.setStatusTip(translations[lang]["bullet"])
- self.numberedevent.setText(translations[lang]["numbered"])
- self.numberedevent.setStatusTip(translations[lang]["numbered"])
- self.color.setText(translations[lang]["font_color"])
- self.color.setStatusTip(translations[lang]["font_color_message"])
- self.backgroundcolor.setText(translations[lang]["contentBackgroundColor"])
- self.backgroundcolor.setStatusTip(
- translations[lang]["contentBackgroundColor_message"]
- )
- self.fontfamily.setText(translations[lang]["font"])
- self.fontfamily.setStatusTip(translations[lang]["font_message"])
- self.addimage.setText(translations[lang]["image"])
- self.addimage.setStatusTip(translations[lang]["image_message"])
+
+ actions = {
+ self.newaction: ("new", "new_message"),
+ self.openaction: ("open", "open_message"),
+ self.saveaction: ("save", "save_message"),
+ self.saveasaction: ("save_as", "save_as_message"),
+ self.printaction: ("print", "print_message"),
+ self.undoaction: ("undo", "undo_message"),
+ self.redoaction: ("redo", "redo_message"),
+ self.theme_action: ("darklight", "darklight_message"),
+ self.powersaveraction: ("powersaver", "powersaver_message"),
+ self.findaction: ("find", "find_message"),
+ self.replaceaction: ("replace", "replace_message"),
+ self.helpAction: ("help", "help"),
+ self.aboutAction: ("about", "about"),
+ self.alignrightevent: ("right", "right_message"),
+ self.aligncenterevent: ("center", "center_message"),
+ self.alignleftevent: ("left", "left_message"),
+ self.alignjustifiedevent: ("justify", "justify_message"),
+ self.bold: ("bold", "bold_message"),
+ self.italic: ("italic", "italic_message"),
+ self.underline: ("underline", "underline_message"),
+ self.bulletevent: ("bullet", "bullet"),
+ self.numberedevent: (
+ "numbered",
+ "numbered",
+ ),
+ self.color: ("font_color", "font_color_message"),
+ self.backgroundcolor: (
+ "contentBackgroundColor",
+ "contentBackgroundColor_message",
+ ),
+ self.fontfamily: ("font", "font_message"),
+ self.addimage: ("image", "image_message"),
+ }
+
+ for action, (text_key, status_key) in actions.items():
+ action.setText(translations[lang][text_key])
+ action.setStatusTip(translations[lang][status_key])
+
self.ai_widget.setWindowTitle("AI")
def initArea(self):
@@ -714,6 +697,26 @@ def initArea(self):
self.DocumentArea.document().setDocumentMargin(self.width() * 0.25)
def loadLLM(self):
+ # Consent
+ if settings.value("load_llm") is None or settings.value("load_llm") is True:
+ reply = QMessageBox.question(
+ None,
+ "Load LLM",
+ "Do you want to load the LLM model?",
+ QMessageBox.Yes | QMessageBox.No,
+ QMessageBox.Yes,
+ )
+
+ if reply == QMessageBox.Yes:
+ settings.setValue("load_llm", True)
+ self._load_model()
+ else:
+ settings.setValue("load_llm", False)
+ self.ai_widget.setWidget(QLabel("LLM not available."))
+ else:
+ self.ai_widget.setWidget(QLabel("LLM not available."))
+
+ def _load_model(self):
try:
model_filename, _ = QFileDialog.getOpenFileName(
None,
@@ -972,35 +975,35 @@ def initActions(self):
"name": "newaction",
"text": translations[lang]["new"],
"status_tip": translations[lang]["new_message"],
- "function": self.New,
+ "function": self.newFile,
"shortcut": QKeySequence.New,
},
{
"name": "openaction",
"text": translations[lang]["open"],
"status_tip": translations[lang]["open_message"],
- "function": self.Open,
+ "function": self.openFile,
"shortcut": QKeySequence.Open,
},
{
"name": "saveaction",
"text": translations[lang]["save"],
"status_tip": translations[lang]["save_message"],
- "function": self.Save,
+ "function": self.saveFile,
"shortcut": QKeySequence.Save,
},
{
"name": "saveasaction",
"text": translations[lang]["save_as"],
"status_tip": translations[lang]["save_as_message"],
- "function": self.SaveAs,
+ "function": self.saveAs,
"shortcut": QKeySequence.SaveAs,
},
{
"name": "printaction",
"text": translations[lang]["print"],
"status_tip": translations[lang]["print_message"],
- "function": self.PrintDocument,
+ "function": self.printDocument,
"shortcut": QKeySequence.Print,
},
{
@@ -1035,84 +1038,84 @@ def initActions(self):
"name": "alignrightevent",
"text": translations[lang]["right"],
"status_tip": translations[lang]["right_message"],
- "function": lambda: self.Align(Qt.AlignRight),
+ "function": lambda: self.contentAlign(Qt.AlignRight),
"shortcut": "",
},
{
"name": "alignleftevent",
"text": translations[lang]["left"],
"status_tip": translations[lang]["left_message"],
- "function": lambda: self.Align(Qt.AlignLeft),
+ "function": lambda: self.contentAlign(Qt.AlignLeft),
"shortcut": "",
},
{
"name": "aligncenterevent",
"text": translations[lang]["center"],
"status_tip": translations[lang]["center_message"],
- "function": lambda: self.Align(Qt.AlignCenter),
+ "function": lambda: self.contentAlign(Qt.AlignCenter),
"shortcut": "",
},
{
"name": "alignjustifiedevent",
"text": translations[lang]["justify"],
"status_tip": translations[lang]["justify_message"],
- "function": lambda: self.Align(Qt.AlignJustify),
+ "function": lambda: self.contentAlign(Qt.AlignJustify),
"shortcut": "",
},
{
"name": "bulletevent",
"text": translations[lang]["bullet"],
"status_tip": "",
- "function": self.Bullet,
+ "function": self.bulletList,
"shortcut": QKeySequence("Ctrl+Shift+U"),
},
{
"name": "numberedevent",
"text": translations[lang]["numbered"],
"status_tip": "",
- "function": self.Numbered,
+ "function": self.numberedList,
"shortcut": QKeySequence("Ctrl+Shift+O"),
},
{
"name": "bold",
"text": translations[lang]["bold"],
"status_tip": translations[lang]["bold_message"],
- "function": self.ContentBold,
+ "function": self.contentBold,
"shortcut": QKeySequence.Bold,
},
{
"name": "italic",
"text": translations[lang]["italic"],
"status_tip": translations[lang]["italic_message"],
- "function": self.ContentItalic,
+ "function": self.contentItalic,
"shortcut": QKeySequence.Italic,
},
{
"name": "underline",
"text": translations[lang]["underline"],
"status_tip": translations[lang]["underline_message"],
- "function": self.ContentUnderline,
+ "function": self.contentUnderline,
"shortcut": QKeySequence.Underline,
},
{
"name": "color",
"text": translations[lang]["font_color"],
"status_tip": translations[lang]["font_color_message"],
- "function": self.ContentColor,
+ "function": self.contentColor,
"shortcut": QKeySequence("Ctrl+Shift+C"),
},
{
"name": "backgroundcolor",
"text": translations[lang]["contentBackgroundColor"],
"status_tip": translations[lang]["contentBackgroundColor_message"],
- "function": self.ContentBGColor,
+ "function": self.contentBGColor,
"shortcut": QKeySequence("Ctrl+Shift+B"),
},
{
"name": "fontfamily",
"text": translations[lang]["font"],
"status_tip": translations[lang]["font_message"],
- "function": self.ContentFont,
+ "function": self.contentFont,
"shortcut": QKeySequence("Ctrl+Shift+F"),
},
{
@@ -1323,7 +1326,7 @@ def detectEncoding(file_path):
detector.close()
return detector.result["encoding"]
- def New(self):
+ def newFile(self):
if self.is_saved == True:
self.DocumentArea.clear()
self.DocumentArea.setFontFamily(fallbackValues["fontFamily"])
@@ -1370,31 +1373,34 @@ def New(self):
else:
pass
- def Open(self):
+ def openFile(self, file_to_open=None):
options = QFileDialog.Options()
options |= QFileDialog.ReadOnly
- selected_file, _ = QFileDialog.getOpenFileName(
- self,
- translations[lang]["open"] + f" — {app.applicationDisplayName()} ",
- self.directory,
- fallbackValues["readFilter"],
- options=options,
- )
+
+ if file_to_open:
+ selected_file = file_to_open
+ else:
+ selected_file, _ = QFileDialog.getOpenFileName(
+ self,
+ translations[lang]["open"] + f" — {app.applicationDisplayName()} ",
+ self.directory,
+ fallbackValues["readFilter"],
+ options=options,
+ )
+
if selected_file:
self.file_name = selected_file
try:
- automaticEncoding = RS_Workspace.detectEncoding(self.selected_file)
+ automaticEncoding = RS_Workspace.detectEncoding(self.file_name)
except Exception as e:
automaticEncoding = "utf-8"
+
if self.file_name.endswith(".docx"):
- with open(
- self.file_name,
- "rb",
- ) as file:
+ with open(self.file_name, "rb") as file:
try:
conversionLayer = mammoth.convert_to_html(file)
self.DocumentArea.setHtml(conversionLayer.value)
- except:
+ except Exception as e:
QMessageBox.warning(self, None, "Conversion failed.")
else:
with open(self.file_name, "r", encoding=automaticEncoding) as file:
@@ -1402,7 +1408,6 @@ def Open(self):
self.DocumentArea.setHtml(file.read())
elif self.file_name.endswith((".html", ".htm")):
self.DocumentArea.setHtml(file.read())
-
elif self.file_name.endswith((".md")):
self.DocumentArea.setMarkdown(file.read())
else:
@@ -1411,18 +1416,16 @@ def Open(self):
self.directory = os.path.dirname(self.file_name)
self.is_saved = True
self.updateTitle()
- else:
- pass
- def Save(self):
+ def saveFile(self):
if self.is_saved == False:
- self.SaveProcess()
+ self.saveProcess()
elif self.file_name == None:
- self.SaveAs()
+ self.saveAs()
else:
- self.SaveProcess()
+ self.saveProcess()
- def SaveAs(self):
+ def saveAs(self):
options = QFileDialog.Options()
options |= QFileDialog.ReadOnly
selected_file, _ = QFileDialog.getSaveFileName(
@@ -1435,14 +1438,14 @@ def SaveAs(self):
if selected_file:
self.file_name = selected_file
self.directory = os.path.dirname(self.file_name)
- self.SaveProcess()
+ self.saveProcess()
return True
else:
return False
- def SaveProcess(self):
+ def saveProcess(self):
if not self.file_name:
- self.SaveAs()
+ self.saveAs()
else:
try:
automaticEncoding = RS_Workspace.detectEncoding(self.file_name)
@@ -1465,7 +1468,7 @@ def SaveProcess(self):
self.is_saved = True
self.updateTitle()
- def PrintDocument(self):
+ def printDocument(self):
printer = QPrinter(QPrinter.HighResolution)
printer.setPageOrientation(QPageLayout.Orientation.Portrait)
printer.setPageMargins(QMargins(10, 10, 10, 10), QPageLayout.Millimeter)
@@ -1506,10 +1509,7 @@ def viewHelp(self):
help_window = RS_Help(self)
help_window.show()
- def Align(self, alignment):
- self.DocumentArea.setAlignment(alignment)
-
- def Bullet(self):
+ def bulletList(self):
cursor = self.DocumentArea.textCursor()
cursor.beginEditBlock()
selected_text = cursor.selectedText()
@@ -1522,7 +1522,7 @@ def Bullet(self):
new_cursor.mergeCharFormat(char_format)
cursor.endEditBlock()
- def Numbered(self):
+ def numberedList(self):
cursor = self.DocumentArea.textCursor()
cursor.beginEditBlock()
selected_text = cursor.selectedText()
@@ -1535,30 +1535,33 @@ def Numbered(self):
new_cursor.mergeCharFormat(char_format)
cursor.endEditBlock()
- def ContentBold(self):
+ def contentAlign(self, alignment):
+ self.DocumentArea.setAlignment(alignment)
+
+ def contentBold(self):
font = self.DocumentArea.currentFont()
font.setBold(not font.bold())
self.DocumentArea.setCurrentFont(font)
- def ContentItalic(self):
+ def contentItalic(self):
font = self.DocumentArea.currentFont()
font.setItalic(not font.italic())
self.DocumentArea.setCurrentFont(font)
- def ContentUnderline(self):
+ def contentUnderline(self):
font = self.DocumentArea.currentFont()
font.setUnderline(not font.underline())
self.DocumentArea.setCurrentFont(font)
- def ContentColor(self):
+ def contentColor(self):
color = QColorDialog.getColor()
self.DocumentArea.setTextColor(color)
- def ContentBGColor(self):
+ def contentBGColor(self):
color = QColorDialog.getColor()
self.DocumentArea.setTextBackgroundColor(color)
- def ContentFont(self):
+ def contentFont(self):
# 'ok' (bool), 'font' (QFont)
ok, font = QFontDialog.getFont(
self.DocumentArea.currentFont(), self.DocumentArea
diff --git a/modules/globals.py b/modules/globals.py
index 51bbff2..096d5ca 100644
--- a/modules/globals.py
+++ b/modules/globals.py
@@ -5,7 +5,7 @@
"fontFamily": "Segoe UI",
"fontSize": 9,
"bold": False,
- "italic": False,
+ "italic": False,
"underline": False,
"contentAlign": Qt.AlignmentFlag.AlignLeft,
"contentColor": "#FFFFFF",
@@ -40,6 +40,7 @@
"1049": "Русский", # Russia
"1036": "Français",
"1032": "Ελληνικά", # Greek
+ "1037": "Hebrew (עברית)",
}
translations = {
@@ -156,6 +157,7 @@
"list": "List",
"powersaver": "Power Saver",
"powersaver_message": "Hybrid (Ultra/Standard) power saver",
+ "readonly": " — Read Only",
},
"1055": {
"new": "Yeni",
@@ -271,6 +273,7 @@
"list": "Liste",
"powersaver": "Güç Tasarrufu",
"powersaver_message": "Hibrit (Ultra/Standart) güç tasarrufu.",
+ "readonly": " — Sadece Okunabilir",
},
"1068": {
"new": "Yeni",
@@ -386,6 +389,7 @@
"list": "Siyahı",
"powersaver": "Enerji qənaəti",
"powersaver_message": "Hibrid (Ultra/Standart) enerji qənaəti",
+ "readonly": " — Yalnız Oxunabilir",
},
"1031": {
"new": "Neu",
@@ -501,6 +505,7 @@
"list": "Liste",
"powersaver": "Energiesparmodus",
"powersaver_message": "Hybrid (Ultra/Standard) Energiesparmodus",
+ "readonly": " — Nur Lesen",
},
"1034": {
"new": "Nuevo",
@@ -615,6 +620,7 @@
"list": "Lista",
"powersaver": "Ahorro de energía",
"powersaver_message": "Ahorro de energía híbrido (Ultra/Estándar).",
+ "readonly": " — Solo Lectura",
},
"2052": {
"new": "新建",
@@ -720,6 +726,7 @@
"list": "列表",
"powersaver": "节能",
"powersaver_message": "混合(超高效/标准)节能",
+ "readonly": " — 仅限阅读",
},
"1042": {
"new": "새로 만들기",
@@ -825,6 +832,7 @@
"list": "목록",
"powersaver": "전력 절약",
"powersaver_message": "하이브리드 (울트라/표준) 전력 절약",
+ "readonly": " — 읽기 전용",
},
"1041": {
"new": "新規",
@@ -930,6 +938,7 @@
"list": "リスト",
"powersaver": "省エネルギー",
"powersaver_message": "ハイブリッド(ウルトラ/スタンダード)省エネルギー",
+ "readonly": " — 読み取り専用",
},
"1025": {
"new": "جديد",
@@ -1035,6 +1044,7 @@
"list": "قائمة",
"powersaver": "توفير الطاقة",
"powersaver_message": "توفير الطاقة الهجين (ألترا/قياسي)",
+ "readonly": " — للقراءة فقط",
},
"1091": {
"new": "Yangi",
@@ -1140,6 +1150,7 @@
"list": "Ro'yxat",
"powersaver": "Quvvat tejash",
"powersaver_message": "Gibrid (Ultra/Standart) quvvat tejash.",
+ "readonly": " — Faqat o'qish",
},
"1049": {
"new": "Новый",
@@ -1245,6 +1256,7 @@
"list": "Список",
"powersaver": "Энергосбережение",
"powersaver_message": "Гибридное (Ультра/Стандартное) энергосбережение.",
+ "readonly": " — Только для чтения",
},
"1036": {
"new": "Nouveau",
@@ -1350,6 +1362,7 @@
"list": "Liste",
"powersaver": "Économie d'énergie",
"powersaver_message": "Économie d'énergie hybride (Ultra/Standard).",
+ "readonly": " — Lecture seule",
},
"1032": {
"new": "Νέο",
@@ -1455,5 +1468,121 @@
"list": "Λίστα",
"powersaver": "Εξοικονόμηση ενέργειας",
"powersaver_message": "Υβριδική (Ultra/Κανονική) εξοικονόμηση ενέργειας.",
+ "readonly": " — Μόνο Ανάγνωση",
+ },
+ "1037": {
+ "new": "חדש",
+ "open": "פתח",
+ "save": "שמור",
+ "save_as": "שמור בשם",
+ "print": "הדפס",
+ "exit": "יציאה",
+ "file": "קובץ",
+ "interface": "ממשק",
+ "ui": "ממשק משתמש",
+ "format": "פורמט",
+ "alignment": "יישור",
+ "color": "צבע",
+ "multimedia": "מדיה מרובה",
+ "darklight": "כהה/בהיר",
+ "darklight_message": "שנה תמה",
+ "edit": "ערוך",
+ "view": "תצוגה",
+ "viewmode": "מצב תצוגה",
+ "viewmode_message": "שנה מצב תצוגה",
+ "help": "עזרה",
+ "help_message": "עזרה",
+ "help_shortcut": "קיצורי דרך",
+ "help_description": "תיאור",
+ "about": "אודות",
+ "new": "חדש",
+ "new_message": "מסמך חדש",
+ "open": "פתח",
+ "open_message": "פתח מסמך",
+ "save": "שמור",
+ "save_message": "שמור מסמך",
+ "save_as": "שמור בשם",
+ "save_as_message": "שמור מסמך בשם",
+ "print": "הדפס",
+ "print_message": "הדפס מסמך",
+ "find": "חפש",
+ "find_message": "חפש טקסט",
+ "replace": "החלף",
+ "replace_message": "החלף טקסט",
+ "undo": "ביטול",
+ "undo_message": "ביטול פעולה",
+ "redo": "בצע מחדש",
+ "redo_message": "בצע מחדש פעולה",
+ "right": "ימין",
+ "right_message": "יישר טקסט לימין",
+ "center": "מרכז",
+ "center_message": "יישר טקסט למרכז",
+ "left": "שמאל",
+ "left_message": "יישר טקסט לשמאל",
+ "justify": "מותאם",
+ "justify_message": "מותאם טקסט",
+ "font": "גופן",
+ "font_message": "שנה גופן",
+ "font_size": "גודל גופן",
+ "font_size_message": "שנה גודל גופן",
+ "font_color": "צבע גופן",
+ "font_color_message": "שנה צבע גופן",
+ "contentBackgroundColor": "צבע רקע",
+ "contentBackgroundColor_message": "שנה צבע רקע",
+ "bold": "מודגש",
+ "bold_message": "טקסט מודגש",
+ "italic": "נטוי",
+ "italic_message": "טקסט נטוי",
+ "underline": "קו תחתון",
+ "underline_message": "קו תחתון לטקסט",
+ "inc_font_message": "הגדל גודל גופן",
+ "dec_font_message": "הקטן גודל גופן",
+ "image": "תמונה",
+ "image_message": "הוסף תמונה",
+ "find": "חפש",
+ "replace": "החלף",
+ "find": "חפש",
+ "untitled": "ללא שם",
+ "statistic": "סטטיסטיקה",
+ "statistic_message_1": "שורות: {0}",
+ "statistic_message_2": "מילים: {0}",
+ "statistic_message_3": "תווים: {0}",
+ "statistic_message_4": "דפים: {0}",
+ "analysis": "ניתוח",
+ "analysis_message_1": "ממוצע מילים: {0}",
+ "analysis_message_2": "ממוצע שורות: {0}",
+ "analysis_message_3": "אותיות רישיות: {0}",
+ "analysis_message_4": "אותיות קטנות: {0}",
+ "analysis_message_5": "שפה: {0}",
+ "exit": "יציאה",
+ "exit_message": "האם אתה בטוח שברצונך לצאת?",
+ "cancel": "ביטול",
+ "rsdoc": "מסמך RichSpan",
+ "connection_verified": "החיבור אומת",
+ "connection_denied": "החיבור נדחה",
+ "logout": "התנתק",
+ "sync_settings": "סנכרן הגדרות",
+ "welcome-title": "ברוך הבא — RichSpan",
+ "intro": "התחבר או הירשם עם חשבון BG Ecosystem כדי להמשיך.",
+ "wrong_password": "סיסמא שגויה",
+ "no_account": "אין לך חשבון.",
+ "email": "אימייל",
+ "password": "סיסמה",
+ "login": "התחבר",
+ "register": "הרשם",
+ "error": "שגיאה",
+ "fill_all": "אנא מלא את כל השדות.",
+ "login_success": "ההתחברות הצליחה, מפנים...",
+ "wrong_credentials": "פרטי התחברות שגויים",
+ "register_success": "ההרשמה הצליחה, בבקשה התחבר.",
+ "already_registered": "כבר רשום",
+ "invalid_email": "אימייל לא תקין",
+ "bullet": "נקודה",
+ "numbered": "ממוספר",
+ "account": "חשבון",
+ "list": "רשימה",
+ "powersaver": "חסכון בחשמל",
+ "powersaver_message": "חסכון בחשמל היברידי (אולטרה/סטנדרטי)",
+ "readonly": " — קריאה בלבד",
},
}