From 82faa4aa08459f93356d2130f6e06a5793f96ae4 Mon Sep 17 00:00:00 2001
From: Vandal <86826719+VandalByte@users.noreply.github.com>
Date: Tue, 24 Jun 2025 19:31:55 +0530
Subject: [PATCH 1/9] Do button testing
---
src/vorta/assets/UI/exclude_dialog.ui | 80 +++++++++++++--------------
1 file changed, 40 insertions(+), 40 deletions(-)
diff --git a/src/vorta/assets/UI/exclude_dialog.ui b/src/vorta/assets/UI/exclude_dialog.ui
index 793ad3fdc..ade897230 100644
--- a/src/vorta/assets/UI/exclude_dialog.ui
+++ b/src/vorta/assets/UI/exclude_dialog.ui
@@ -97,46 +97,46 @@
-
- Exclude If Present
-
-
- -
-
-
- true
-
-
-
- -
-
-
- -
-
-
-
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
- -
-
-
- -
-
-
-
-
-
-
-
+
+ Exclude If Present
+
+
+ -
+
+
+ true
+
+
+
+ -
+
+
+ -
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ -
+
+
+
+
+
+
+
Preview
From 156a4c725e2e62ec8db97ee17993bf67ac273a57 Mon Sep 17 00:00:00 2001
From: Vandal <86826719+VandalByte@users.noreply.github.com>
Date: Fri, 11 Jul 2025 20:08:55 +0530
Subject: [PATCH 2/9] Update layout design
---
src/vorta/assets/UI/exclude_dialog.ui | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/vorta/assets/UI/exclude_dialog.ui b/src/vorta/assets/UI/exclude_dialog.ui
index ade897230..370f2d973 100644
--- a/src/vorta/assets/UI/exclude_dialog.ui
+++ b/src/vorta/assets/UI/exclude_dialog.ui
@@ -52,6 +52,13 @@
+ -
+
+
+ Exclude Files/Folders
+
+
+
-
From 7c2d6a6443ef849ce57d0b941a549381195e07f8 Mon Sep 17 00:00:00 2001
From: Vandal <86826719+VandalByte@users.noreply.github.com>
Date: Sun, 20 Jul 2025 18:52:57 +0530
Subject: [PATCH 3/9] Connect file dialog to button
---
src/vorta/views/exclude_dialog.py | 20 +++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/src/vorta/views/exclude_dialog.py b/src/vorta/views/exclude_dialog.py
index 261d2667f..34dd6b1c9 100644
--- a/src/vorta/views/exclude_dialog.py
+++ b/src/vorta/views/exclude_dialog.py
@@ -1,14 +1,9 @@
from PyQt6 import uic
from PyQt6.QtCore import QModelIndex, QObject, Qt
from PyQt6.QtGui import QCursor, QStandardItem, QStandardItemModel
-from PyQt6.QtWidgets import (
- QAbstractItemView,
- QApplication,
- QMenu,
- QMessageBox,
- QStyledItemDelegate,
-)
+from PyQt6.QtWidgets import QAbstractItemView, QApplication, QMenu, QMessageBox, QStyledItemDelegate
+from vorta.filedialog import VortaFileSelector
from vorta.i18n import translate
from vorta.store.models import ExclusionModel
from vorta.utils import get_asset
@@ -87,6 +82,7 @@ def __init__(self, profile, parent=None):
self.bPreviewCopy.setIcon(get_colored_icon('copy'))
self.bAddPattern.clicked.connect(self.add_pattern_custom_exclusion)
self.bAddPattern.setIcon(get_colored_icon('plus'))
+ self.bOpenExcludeFD.clicked.connect(self.open_exclude_filedialog)
self.bAddPatternExcludeIfPresent.setIcon(get_colored_icon('plus'))
self.bAddPatternExcludeIfPresent.clicked.connect(self.add_pattern_exclude_if_present)
self.bRemovePatternExcludeIfPresent.setIcon(get_colored_icon('minus'))
@@ -447,3 +443,13 @@ def eventFilter(self, source, event):
self.remove_pattern()
return True
return QObject.eventFilter(self, source, event)
+
+ def open_exclude_filedialog(self):
+ file_dialog = VortaFileSelector(
+ self, window_title='Exclude Files and Folders', title='Select files and folders to exclude:'
+ )
+ paths = file_dialog.get_paths() # Selected paths from file dialog
+ if paths:
+ for path in paths:
+ # Add items to the list
+ print(path)
From e20fe6b188b011f728dd876fc52bc174b49fb9bc Mon Sep 17 00:00:00 2001
From: Vandal <86826719+VandalByte@users.noreply.github.com>
Date: Sun, 20 Jul 2025 19:36:08 +0530
Subject: [PATCH 4/9] Add the pattern to list
---
src/vorta/views/exclude_dialog.py | 35 ++++++++++++++++++++++++++++---
1 file changed, 32 insertions(+), 3 deletions(-)
diff --git a/src/vorta/views/exclude_dialog.py b/src/vorta/views/exclude_dialog.py
index 34dd6b1c9..57775b334 100644
--- a/src/vorta/views/exclude_dialog.py
+++ b/src/vorta/views/exclude_dialog.py
@@ -1,3 +1,6 @@
+from pathlib import Path
+from typing import List
+
from PyQt6 import uic
from PyQt6.QtCore import QModelIndex, QObject, Qt
from PyQt6.QtGui import QCursor, QStandardItem, QStandardItemModel
@@ -444,12 +447,38 @@ def eventFilter(self, source, event):
return True
return QObject.eventFilter(self, source, event)
+ def make_exclude_pattern_from_path(self, paths: List[str]):
+ '''
+ Create an exclusion pattern from a list of given paths.
+ '''
+ patterns = []
+ for path in paths:
+ if Path(path).is_file():
+ pattern = "fm:*" + path
+ patterns.append(pattern)
+ else: # folder
+ pattern = "fm:*" + path + "/*"
+ patterns.append(pattern)
+ return patterns
+
def open_exclude_filedialog(self):
file_dialog = VortaFileSelector(
self, window_title='Exclude Files and Folders', title='Select files and folders to exclude:'
)
paths = file_dialog.get_paths() # Selected paths from file dialog
if paths:
- for path in paths:
- # Add items to the list
- print(path)
+ patterns = self.make_exclude_pattern_from_path(paths)
+ for pattern in patterns:
+ # Check if the path already exists in the model
+ if not ExclusionModel.get_or_none(name=pattern, profile=self.profile):
+ # Create a new item in the list
+ item = QStandardItem(pattern)
+ item.setCheckable(True)
+ item.setCheckState(Qt.CheckState.Checked)
+ self.customExclusionsModel.appendRow(item)
+
+ # Add the item to database
+ ExclusionModel.create(
+ name=pattern, source=ExclusionModel.SourceFieldOptions.CUSTOM.value, profile=self.profile
+ )
+ self.populate_preview_tab()
From 45ca9a50c2d5d01150e965603af5da3008f16d7e Mon Sep 17 00:00:00 2001
From: Vandal <86826719+VandalByte@users.noreply.github.com>
Date: Wed, 23 Jul 2025 23:20:46 +0530
Subject: [PATCH 5/9] Add the proper pattern format
---
src/vorta/views/exclude_dialog.py | 13 +++++--------
1 file changed, 5 insertions(+), 8 deletions(-)
diff --git a/src/vorta/views/exclude_dialog.py b/src/vorta/views/exclude_dialog.py
index 57775b334..3d28030c2 100644
--- a/src/vorta/views/exclude_dialog.py
+++ b/src/vorta/views/exclude_dialog.py
@@ -447,18 +447,15 @@ def eventFilter(self, source, event):
return True
return QObject.eventFilter(self, source, event)
- def make_exclude_pattern_from_path(self, paths: List[str]):
+ def make_exclude_pattern_from_path(self, paths: List[str]) -> List[str]:
'''
- Create an exclusion pattern from a list of given paths.
+ Create exclusion patterns from a list of given paths.
'''
patterns = []
+ # Both files and folders use the same pattern format (fm:*/name),
+ # confirmed through testing to correctly exclude them during backup creation.
for path in paths:
- if Path(path).is_file():
- pattern = "fm:*" + path
- patterns.append(pattern)
- else: # folder
- pattern = "fm:*" + path + "/*"
- patterns.append(pattern)
+ patterns.append(f"fm:*/{Path(path).name}")
return patterns
def open_exclude_filedialog(self):
From 7fe6633731ec58335c1b78c831a991b61c4fd43c Mon Sep 17 00:00:00 2001
From: Vandal <86826719+VandalByte@users.noreply.github.com>
Date: Sun, 3 Aug 2025 20:56:21 +0530
Subject: [PATCH 6/9] Fix issue #2260
---
src/vorta/views/exclude_dialog.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/vorta/views/exclude_dialog.py b/src/vorta/views/exclude_dialog.py
index 3d28030c2..af179dc96 100644
--- a/src/vorta/views/exclude_dialog.py
+++ b/src/vorta/views/exclude_dialog.py
@@ -301,7 +301,7 @@ def text_editing_finished(self, model):
'''
for row in range(model.rowCount()):
item = model.item(row)
- if item.text() == '':
+ if item is not None and item.text() == '':
model.removeRow(row)
def custom_pattern_editing_finished(self, editor):
From 687a9bdaacf966ae0c385bc5c051161084e7d053 Mon Sep 17 00:00:00 2001
From: Vandal <86826719+VandalByte@users.noreply.github.com>
Date: Mon, 4 Aug 2025 21:22:21 +0530
Subject: [PATCH 7/9] Fix the incorrect model used
---
src/vorta/views/exclude_dialog.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/vorta/views/exclude_dialog.py b/src/vorta/views/exclude_dialog.py
index af179dc96..4ee10f3b1 100644
--- a/src/vorta/views/exclude_dialog.py
+++ b/src/vorta/views/exclude_dialog.py
@@ -301,7 +301,7 @@ def text_editing_finished(self, model):
'''
for row in range(model.rowCount()):
item = model.item(row)
- if item is not None and item.text() == '':
+ if item is not None and item.text().strip() == '':
model.removeRow(row)
def custom_pattern_editing_finished(self, editor):
@@ -371,7 +371,7 @@ def add_pattern_exclude_if_present(self):
self.save_exclude_if_present_patterns()
def exclude_if_present_pattern_editing_finished(self, editor):
- self.text_editing_finished(self.customExclusionsModel)
+ self.text_editing_finished(self.excludeIfPresentModel)
self.save_exclude_if_present_patterns()
def save_exclude_if_present_patterns(self):
From 978f31d2a5c01c4d1887bd64c8261656a06effbc Mon Sep 17 00:00:00 2001
From: Vandal <86826719+VandalByte@users.noreply.github.com>
Date: Sat, 23 Aug 2025 18:40:24 +0530
Subject: [PATCH 8/9] fix linting
---
src/vorta/borg/create.py | 11 +++--------
1 file changed, 3 insertions(+), 8 deletions(-)
diff --git a/src/vorta/borg/create.py b/src/vorta/borg/create.py
index 6f1f8c5b9..1fcf0671e 100644
--- a/src/vorta/borg/create.py
+++ b/src/vorta/borg/create.py
@@ -4,18 +4,13 @@
import tempfile
from datetime import datetime as dt
+from PyQt6.QtCore import QCoreApplication
+
from vorta import config
from vorta.i18n import trans_late, translate
-from vorta.store.models import (
- ArchiveModel,
- RepoModel,
- SourceFileModel,
- WifiSettingModel,
-)
+from vorta.store.models import ArchiveModel, RepoModel, SourceFileModel, WifiSettingModel
from vorta.utils import borg_compat, format_archive_name, get_network_status_monitor
-from PyQt6.QtCore import QCoreApplication
-
from .borg_job import BorgJob
From 4627fa7602e8af80c20847b67b9165a9eb65d67e Mon Sep 17 00:00:00 2001
From: Vandal <86826719+VandalByte@users.noreply.github.com>
Date: Fri, 29 Aug 2025 23:38:21 +0530
Subject: [PATCH 9/9] Change pattern format to 'pf'
---
src/vorta/views/exclude_dialog.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/vorta/views/exclude_dialog.py b/src/vorta/views/exclude_dialog.py
index 0eb68e36b..6cd7d1233 100644
--- a/src/vorta/views/exclude_dialog.py
+++ b/src/vorta/views/exclude_dialog.py
@@ -456,7 +456,7 @@ def make_exclude_pattern_from_path(self, paths: List[str]) -> List[str]:
# Both files and folders use the same pattern format (fm:*/name),
# confirmed through testing to correctly exclude them during backup creation.
for path in paths:
- patterns.append(f"fm:*/{Path(path).name}")
+ patterns.append(f"pf:{path}")
return patterns
def open_exclude_filedialog(self):