This commit is contained in:
Sam 2024-04-11 06:32:38 +00:00 committed by GitHub
commit b8b5667157
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 199 additions and 2 deletions

View File

@ -725,6 +725,20 @@
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="preBackupScriptEditorButton">
<property name="toolTip">
<string> Open Pre-backup script editor</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/icons/edit.svg</normaloff>:/icons/edit.svg</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item>
@ -764,6 +778,20 @@
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="postBackupScriptEditorButton">
<property name="toolTip">
<string> Open Post-backup script editor</string>
</property>
<property name="text">
<string>...</string>
</property>
<property name="icon">
<iconset>
<normaloff>:/icons/edit.svg</normaloff>:/icons/edit.svg</iconset>
</property>
</widget>
</item>
</layout>
</item>
</layout>

View File

@ -0,0 +1,92 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ScriptEdit</class>
<widget class="QDialog" name="ScriptEdit">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>440</width>
<height>260</height>
</rect>
</property>
<property name="windowTitle">
<string>Edit Script</string>
</property>
<property name="modal">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="verticalSpacing">
<number>0</number>
</property>
<item row="1" column="0">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0">
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Pre/Post-Backup Script:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>5</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="0">
<widget class="QTextEdit" name="scriptEdit">
<property name="font">
<font>
<family>Monospace</family>
</font>
</property>
<property name="cursor" stdset="0">
<cursorShape>IBeamCursor</cursorShape>
</property>
<property name="lineWrapMode">
<enum>QTextEdit::NoWrap</enum>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Save</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -15,7 +15,13 @@ from typing import Any, Callable, Iterable, List, Optional, Tuple, TypeVar
import psutil
from PyQt6 import QtCore
from PyQt6.QtCore import QFileInfo, QThread, pyqtSignal
from PyQt6.QtWidgets import QApplication, QFileDialog, QSystemTrayIcon
from PyQt6.QtWidgets import (
QAbstractItemView,
QApplication,
QFileDialog,
QSystemTrayIcon,
QTreeView,
)
from vorta.borg._compatibility import BorgCompatibility
from vorta.log import logger
@ -166,12 +172,17 @@ def get_dict_from_list(dataDict, mapList):
return reduce(lambda d, k: d.setdefault(k, {}), mapList, dataDict)
def choose_file_dialog(parent, title, want_folder=True):
def choose_file_dialog(parent, title, want_folder=True, file_filter=None, single_selection=False):
dialog = QFileDialog(parent, title, os.path.expanduser('~'))
dialog.setFileMode(QFileDialog.FileMode.Directory if want_folder else QFileDialog.FileMode.ExistingFiles)
dialog.setParent(parent, QtCore.Qt.WindowType.Sheet)
if want_folder:
dialog.setOption(QFileDialog.Option.ShowDirsOnly)
elif file_filter:
dialog.setNameFilter(file_filter)
if single_selection:
tree_view = dialog.findChild(QTreeView)
tree_view.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
return dialog

View File

@ -13,6 +13,7 @@ from vorta.i18n import get_locale
from vorta.scheduler import ScheduleStatusType
from vorta.store.models import BackupProfileMixin, EventLogModel, WifiSettingModel
from vorta.utils import get_asset, get_sorted_wifis
from vorta.views.script_edit_dialog import ScriptEditWindow
from vorta.views.utils import get_colored_icon
uifile = get_asset('UI/scheduletab.ui')
@ -81,6 +82,8 @@ class ScheduleTab(ScheduleBase, ScheduleUI, BackupProfileMixin):
self.scheduleIntervalCount.valueChanged.connect(self.on_scheduler_change)
self.scheduleIntervalUnit.currentIndexChanged.connect(self.on_scheduler_change)
self.scheduleFixedTime.timeChanged.connect(self.on_scheduler_change)
self.preBackupScriptEditorButton.clicked.connect(lambda: self.launch_script_editor(context="pre"))
self.postBackupScriptEditorButton.clicked.connect(lambda: self.launch_script_editor(context="post"))
# Network and shell commands events
self.meteredNetworksCheckBox.stateChanged.connect(
@ -135,6 +138,8 @@ class ScheduleTab(ScheduleBase, ScheduleUI, BackupProfileMixin):
self.toolBox.setItemIcon(1, get_colored_icon('wifi'))
self.toolBox.setItemIcon(2, get_colored_icon('tasks'))
self.toolBox.setItemIcon(3, get_colored_icon('terminal'))
self.preBackupScriptEditorButton.setIcon(get_colored_icon('edit'))
self.postBackupScriptEditorButton.setIcon(get_colored_icon('edit'))
def populate_from_profile(self):
"""Populate current view with data from selected profile."""
@ -237,3 +242,8 @@ class ScheduleTab(ScheduleBase, ScheduleUI, BackupProfileMixin):
QTableWidgetItem(str(log_line.returncode)),
)
self.logTableWidget.setSortingEnabled(sorting) # restore sorting now that modifications are done
def launch_script_editor(self, context: str) -> None:
edit_window = ScriptEditWindow(context, profile=self.profile())
edit_window.exec()
self.populate_from_profile() # Refresh the view after the script has been edited.

View File

@ -0,0 +1,56 @@
from PyQt6 import QtCore, uic
from PyQt6.QtWidgets import QDialogButtonBox
from vorta.utils import get_asset
uifile = get_asset("UI/scriptedit.ui")
ScriptEditUI, ScriptEditBase = uic.loadUiType(uifile)
class ScriptEditWindow(ScriptEditUI, ScriptEditBase):
def __init__(self, context: str, profile, parent=None) -> None:
super().__init__(parent)
self.setupUi(self)
self.setAttribute(QtCore.Qt.WidgetAttribute.WA_DeleteOnClose)
self.context = context
if context == "pre":
self.setWindowTitle(self.tr("Edit Pre-Backup Script"))
self.label.setText(self.tr("Pre-Backup Script:"))
elif context == "post":
self.setWindowTitle(self.tr("Edit Post-Backup Script"))
self.label.setText(self.tr("Post-Backup Script:"))
self.buttonBox.button(QDialogButtonBox.StandardButton.Save).setText(self.tr("Save"))
self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).setText(self.tr("Cancel"))
self.profile = profile
self.buttonBox.button(QDialogButtonBox.StandardButton.Save).clicked.connect(self.save_script)
self.buttonBox.button(QDialogButtonBox.StandardButton.Cancel).clicked.connect(self.close)
# Populate data from profile
self.populate_from_profile()
def populate_from_profile(self):
"""Populate the script editor with the current profile's script."""
profile = self.profile
if self.context == "pre":
self.scriptEdit.setPlainText(profile.pre_backup_cmd)
elif self.context == "post":
self.scriptEdit.setPlainText(profile.post_backup_cmd)
def save_profile_attr(self, attr, new_value):
profile = self.profile
setattr(profile, attr, new_value)
profile.save()
def save_script(self):
script = self.scriptEdit.toPlainText()
profile = self.profile
if self.context == "pre":
self.save_profile_attr("pre_backup_cmd", script)
elif self.context == "post":
self.save_profile_attr("post_backup_cmd", script)
profile.save()
self.close()