Compare commits

...

19 Commits

Author SHA1 Message Date
Sam a362ec3227
Merge e070fda084 into 9b8dbcecfb 2024-04-01 21:21:29 +02:00
Sam e070fda084 minor changes: script editor dialog 2024-03-05 15:42:44 +05:30
Sam dae0ce153f minor changes: spacing between textedit and save button 2024-03-04 15:25:12 +05:30
Sam c5fc7c9c3f Not needed: Removed the add from file button/dialog. 2024-03-04 14:04:12 +05:30
Sam 2b55cd9866 feat: editor for pre and post backup cmd 2024-03-03 01:25:54 +05:30
Sam 384c57af57 feat: file selection dialog for selecting pre and post backup script in schedule tab 2024-02-28 23:22:27 +05:30
Sam 0c332780f8
Merge branch 'borgbase:master' into master 2024-02-22 15:53:15 +05:30
Sam e6faa54dee
Merge branch 'borgbase:master' into master 2024-01-11 15:17:44 +05:30
Sam 2f40b7c405
Merge branch 'borgbase:master' into master 2023-12-08 16:31:03 +05:30
Sam a5c6729064
Merge branch 'borgbase:master' into master 2023-11-17 18:38:16 +05:30
Sam 1d76358404
Merge branch 'borgbase:master' into master 2023-11-08 15:34:47 +05:30
Sam 767dcc126a
Merge branch 'borgbase:master' into master 2023-10-05 05:29:49 +00:00
Sam 4f03af6675
Merge branch 'borgbase:master' into master 2023-09-29 21:16:15 +05:30
Sam d21316b920
Merge branch 'borgbase:master' into master 2023-09-23 22:45:41 +05:30
Sam 4b299f9a4c
Merge branch 'borgbase:master' into master 2023-09-18 16:05:20 +05:30
Sam b4f2e64662
Merge branch 'borgbase:master' into master 2023-09-09 14:26:04 +05:30
Sam 5f07abd8d0
Merge branch 'borgbase:master' into master 2023-09-06 19:48:42 +05:30
Sam 7b800661c2 removed peewee from requirements: not necessary 2023-09-06 11:57:06 +05:30
Sam 6abd0f5862 added peewee to requirements.d/dev.txt 2023-09-01 23:13:17 +05:30
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()