Profile sidebar and new setting interface. By @bigtedde (#1809)

This commit is contained in:
Ted Lawson 2023-10-24 01:36:50 -07:00 committed by GitHub
parent 60f9fc27b4
commit 071dd86ded
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 1262 additions and 331 deletions

View File

@ -173,7 +173,7 @@ class VortaApp(QtSingleApplication):
"""
if 'version' in result['data']:
borg_compat.set_version(result['data']['version'], result['data']['path'])
self.main_window.miscTab.set_borg_details(borg_compat.version, borg_compat.path)
self.main_window.aboutTab.set_borg_details(borg_compat.version, borg_compat.path)
self.main_window.repoTab.toggle_available_compression()
self.main_window.archiveTab.toggle_compact_button_visibility()
self.scheduler.reload_all_timers() # Start timer after Borg version is set.

View File

@ -0,0 +1,315 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>791</width>
<height>497</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="topMargin">
<number>12</number>
</property>
<property name="bottomMargin">
<number>12</number>
</property>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>5</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="alignment">
<set>Qt::AlignHCenter</set>
</property>
<property name="spacing">
<number>5</number>
</property>
<property name="topMargin">
<number>10</number>
</property>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Vorta Version:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="versionLabel">
<property name="text">
<string>0.0</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="alignment">
<set>Qt::AlignHCenter</set>
</property>
<property name="spacing">
<number>5</number>
</property>
<property name="topMargin">
<number>10</number>
</property>
<property name="bottomMargin">
<number>10</number>
</property>
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Borg Version:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="borgVersion">
<property name="text">
<string>1.1.8</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="bottomMargin">
<number>10</number>
</property>
<item>
<widget class="QLabel" name="borgPath">
<property name="text">
<string>/usr/bin/borg</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QFrame" name="seperator">
<property name="frameShape">
<enum>QFrame::HLine</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="alignment">
<set>Qt::AlignHCenter</set>
</property>
<property name="spacing">
<number>5</number>
</property>
<property name="topMargin">
<number>10</number>
</property>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/borgbase/vorta/issues/new/choose&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0984e3;&quot;&gt;Click here&lt;/span&gt;&lt;/a&gt; to report a bug.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="alignment">
<set>Qt::AlignHCenter</set>
</property>
<property name="topMargin">
<number>10</number>
</property>
<item>
<widget class="QLabel" name="logLink">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;file:///&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0984e3;&quot;&gt;View the logs&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="indent">
<number>0</number>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="alignment">
<set>Qt::AlignHCenter</set>
</property>
<property name="spacing">
<number>5</number>
</property>
<property name="topMargin">
<number>10</number>
</property>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;https://borgbackup.readthedocs.io/en/master/index.html&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0984e3;&quot;&gt; Click here&lt;/span&gt;&lt;/a&gt; to view the docs.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="alignment">
<set>Qt::AlignHCenter</set>
</property>
<property name="spacing">
<number>5</number>
</property>
<property name="topMargin">
<number>10</number>
</property>
<property name="bottomMargin">
<number>10</number>
</property>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;https://github.com/borgbase/vorta&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0984e3;&quot;&gt;Click here&lt;/span&gt;&lt;/a&gt; for view Git repo.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QFrame" name="seperator">
<property name="frameShape">
<enum>QFrame::HLine</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="alignment">
<set>Qt::AlignHCenter</set>
</property>
<property name="spacing">
<number>20</number>
</property>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>
Vorta is a cross-platform, open-source client designed to simplify the management of Borg backups.
Copyright (C) 2018-2020 Manuel Riel and Vorta contributors (see CONTRIBUTORS.md)
</string>
</property>
<property name="indent">
<number>0</number>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="topMargin">
<number>10</number>
</property>
<property name="bottomMargin">
<number>10</number>
</property>
<property name="spacing">
<number>20</number>
</property>
<property name="alignment">
<set>Qt::AlignHCenter</set>
</property>
<item>
<widget class="QLabel" name="gpl_logo"/>
</item>
<item>
<widget class="QLabel" name="python_logo"/>
</item>
</layout>
</item>
</layout>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -12,7 +12,7 @@
</property>
<property name="minimumSize">
<size>
<width>800</width>
<width>1000</width>
<height>600</height>
</size>
</property>
@ -23,28 +23,9 @@
<double>1.000000000000000</double>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="topMargin">
<number>12</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<layout class="QVBoxLayout" name="verticalLayoutSidebar">
<item>
<widget class="QLabel" name="label">
<property name="text">
@ -53,75 +34,142 @@
</widget>
</item>
<item>
<widget class="QComboBox" name="profileSelector">
<property name="minimumSize">
<widget class="QListWidget" name="profileSelector">
<property name="fixedSize">
<size>
<width>300</width>
<height>0</height>
<width>200</width>
<height>400</height>
</size>
</property>
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToContents</enum>
<property name="verticalScrollBarPolicy">
<enum>Qt::ScrollBarAsNeeded</enum>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="profileAddButton">
<property name="toolTip">
<string>Add a new profile (Dropdown: Import from file)</string>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<property name="popupMode">
<enum>QToolButton::MenuButtonPopup</enum>
</property>
</widget>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QToolButton" name="profileAddButton">
<property name="text">
<string/>
</property>
<property name="iconSize">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
<property name="popupMode">
<enum>QToolButton::InstantPopup</enum>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="profileDeleteButton">
<property name="toolTip">
<string>Delete current profile</string>
</property>
<property name="iconSize">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QToolButton" name="profileRenameButton">
<property name="toolTip">
<string>Rename current profile</string>
</property>
<property name="iconSize">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="profileExportButton">
<property name="toolTip">
<string>Export current profile</string>
</property>
<property name="iconSize">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QToolButton" name="profileRenameButton">
<property name="toolTip">
<string>Rename current profile</string>
</property>
<property name="iconSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="profileExportButton">
<property name="toolTip">
<string>Export current profile</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="profileDeleteButton">
<property name="toolTip">
<string>Delete current profile</string>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="miscButton">
<property name="text">
<string> Settings / About</string>
</property>
<property name="minimumSize">
<size>
<width>150</width>
<height>40</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="styleSheet">
<string notr="true">QPushButton:focus { border: none; outline: none; }</string>
</property>
<property name="flat">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<spacer name="bottomSpacer">
<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>20</height>
</size>
</property>
@ -130,106 +178,137 @@
</layout>
</item>
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="documentMode">
<bool>false</bool>
</property>
<property name="tabsClosable">
<bool>false</bool>
</property>
<widget class="QWidget" name="repoTabSlot">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<attribute name="title">
<string>Repository</string>
</attribute>
</widget>
<widget class="QWidget" name="sourceTabSlot">
<attribute name="title">
<string>Sources</string>
</attribute>
</widget>
<widget class="QWidget" name="scheduleTabSlot">
<attribute name="title">
<string>Schedule</string>
</attribute>
</widget>
<widget class="QWidget" name="archiveTabSlot">
<attribute name="title">
<string>Archives</string>
</attribute>
</widget>
<widget class="QWidget" name="miscTabSlot">
<attribute name="title">
<string>Misc</string>
</attribute>
</widget>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0" alignment="Qt::AlignTop">
<widget class="QPushButton" name="cancelButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>150</width>
<height>0</height>
</size>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="text">
<string>Cancel</string>
</property>
<property name="flat">
<bool>false</bool>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="progressText">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="1" alignment="Qt::AlignTop">
<widget class="QLabel" name="logText">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
<layout class="QVBoxLayout" name="verticalLayoutSidebar">
<item>
<widget class="QTabWidget" name="miscWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="documentMode">
<bool>false</bool>
</property>
<property name="tabsClosable">
<bool>false</bool>
</property>
<widget class="QWidget" name="SettingsTabSlot">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<attribute name="title">
<string>Settings</string>
</attribute>
</widget>
<widget class="QWidget" name="AboutTabSlot">
<attribute name="title">
<string>About</string>
</attribute>
</widget>
</widget>
</item>
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="documentMode">
<bool>false</bool>
</property>
<property name="tabsClosable">
<bool>false</bool>
</property>
<widget class="QWidget" name="repoTabSlot">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<attribute name="title">
<string>Repository</string>
</attribute>
</widget>
<widget class="QWidget" name="sourceTabSlot">
<attribute name="title">
<string>Sources</string>
</attribute>
</widget>
<widget class="QWidget" name="scheduleTabSlot">
<attribute name="title">
<string>Schedule</string>
</attribute>
</widget>
<widget class="QWidget" name="archiveTabSlot">
<attribute name="title">
<string>Archives</string>
</attribute>
</widget>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0" alignment="Qt::AlignTop">
<widget class="QPushButton" name="cancelButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>150</width>
<height>0</height>
</size>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="text">
<string>Cancel</string>
</property>
<property name="flat">
<bool>false</bool>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="progressText">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="1" alignment="Qt::AlignTop">
<widget class="QLabel" name="logText">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>

View File

@ -43,113 +43,6 @@
</property>
</spacer>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>5</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>Vorta Version:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="versionLabel">
<property name="text">
<string>0.0</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;| &lt;a href=&quot;https://github.com/borgbase/vorta/issues/new/choose&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0984e3;&quot;&gt;Report&lt;/span&gt;&lt;/a&gt; a Bug |&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="logLink">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&quot;file:///&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0984e3;&quot;&gt;Log&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="indent">
<number>0</number>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="spacing">
<number>5</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="label_3">
<property name="text">
<string>Borg Version:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="borgVersion">
<property name="text">
<string>1.1.8</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="borgPath">
<property name="text">
<string>/usr/bin/borg</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 108 KiB

View File

@ -0,0 +1,265 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
version="1.0"
id="svg2"
sodipodi:version="0.32"
inkscape:version="1.2.1 (9c6d41e410, 2022-07-14)"
sodipodi:docname="python-logo-only.svg"
width="83.371017pt"
height="101.00108pt"
inkscape:export-filename="python-logo-only.png"
inkscape:export-xdpi="232.44"
inkscape:export-ydpi="232.44"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<metadata
id="metadata371">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
inkscape:window-height="2080"
inkscape:window-width="1976"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
guidetolerance="10.0"
gridtolerance="10.0"
objecttolerance="10.0"
borderopacity="1.0"
bordercolor="#666666"
pagecolor="#ffffff"
id="base"
inkscape:zoom="2.1461642"
inkscape:cx="91.558698"
inkscape:cy="47.9926"
inkscape:window-x="1092"
inkscape:window-y="72"
inkscape:current-layer="svg2"
width="210mm"
height="40mm"
units="mm"
inkscape:showpageshadow="2"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="pt"
showgrid="false"
inkscape:window-maximized="0" />
<defs
id="defs4">
<linearGradient
id="linearGradient2795">
<stop
style="stop-color:#b8b8b8;stop-opacity:0.49803922;"
offset="0"
id="stop2797" />
<stop
style="stop-color:#7f7f7f;stop-opacity:0;"
offset="1"
id="stop2799" />
</linearGradient>
<linearGradient
id="linearGradient2787">
<stop
style="stop-color:#7f7f7f;stop-opacity:0.5;"
offset="0"
id="stop2789" />
<stop
style="stop-color:#7f7f7f;stop-opacity:0;"
offset="1"
id="stop2791" />
</linearGradient>
<linearGradient
id="linearGradient3676">
<stop
style="stop-color:#b2b2b2;stop-opacity:0.5;"
offset="0"
id="stop3678" />
<stop
style="stop-color:#b3b3b3;stop-opacity:0;"
offset="1"
id="stop3680" />
</linearGradient>
<linearGradient
id="linearGradient3236">
<stop
style="stop-color:#f4f4f4;stop-opacity:1"
offset="0"
id="stop3244" />
<stop
style="stop-color:white;stop-opacity:1"
offset="1"
id="stop3240" />
</linearGradient>
<linearGradient
id="linearGradient4671">
<stop
style="stop-color:#ffd43b;stop-opacity:1;"
offset="0"
id="stop4673" />
<stop
style="stop-color:#ffe873;stop-opacity:1"
offset="1"
id="stop4675" />
</linearGradient>
<linearGradient
id="linearGradient4689">
<stop
style="stop-color:#5a9fd4;stop-opacity:1;"
offset="0"
id="stop4691" />
<stop
style="stop-color:#306998;stop-opacity:1;"
offset="1"
id="stop4693" />
</linearGradient>
<linearGradient
x1="224.23996"
y1="144.75717"
x2="-65.308502"
y2="144.75717"
id="linearGradient2987"
xlink:href="#linearGradient4671"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(100.2702,99.61116)" />
<linearGradient
x1="172.94208"
y1="77.475983"
x2="26.670298"
y2="76.313133"
id="linearGradient2990"
xlink:href="#linearGradient4689"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(100.2702,99.61116)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4689"
id="linearGradient2587"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(100.2702,99.61116)"
x1="172.94208"
y1="77.475983"
x2="26.670298"
y2="76.313133" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4671"
id="linearGradient2589"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(100.2702,99.61116)"
x1="224.23996"
y1="144.75717"
x2="-65.308502"
y2="144.75717" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4689"
id="linearGradient2248"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(100.2702,99.61116)"
x1="172.94208"
y1="77.475983"
x2="26.670298"
y2="76.313133" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4671"
id="linearGradient2250"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(100.2702,99.61116)"
x1="224.23996"
y1="144.75717"
x2="-65.308502"
y2="144.75717" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4671"
id="linearGradient2255"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.562541,0,0,0.567972,-11.5974,-7.60954)"
x1="224.23996"
y1="144.75717"
x2="-65.308502"
y2="144.75717" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4689"
id="linearGradient2258"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.562541,0,0,0.567972,-11.5974,-7.60954)"
x1="172.94208"
y1="76.176224"
x2="26.670298"
y2="76.313133" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient2795"
id="radialGradient2801"
cx="61.518883"
cy="132.28575"
fx="61.518883"
fy="132.28575"
r="29.036913"
gradientTransform="matrix(1,0,0,0.177966,0,108.7434)"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4671"
id="linearGradient1475"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.562541,0,0,0.567972,-14.99112,-11.702371)"
x1="150.96111"
y1="192.35176"
x2="112.03144"
y2="137.27299" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4689"
id="linearGradient1478"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.562541,0,0,0.567972,-14.99112,-11.702371)"
x1="26.648937"
y1="20.603781"
x2="135.66525"
y2="114.39767" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient2795"
id="radialGradient1480"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.7490565e-8,-0.23994696,1.054668,3.7915457e-7,-83.7008,142.46201)"
cx="61.518883"
cy="132.28575"
fx="61.518883"
fy="132.28575"
r="29.036913" />
</defs>
<path
style="fill:url(#linearGradient1478);fill-opacity:1"
d="M 54.918785,9.1927421e-4 C 50.335132,0.02221727 45.957846,0.41313697 42.106285,1.0946693 30.760069,3.0991731 28.700036,7.2947714 28.700035,15.032169 v 10.21875 h 26.8125 v 3.40625 h -26.8125 -10.0625 c -7.792459,0 -14.6157588,4.683717 -16.7499998,13.59375 -2.46181998,10.212966 -2.57101508,16.586023 0,27.25 1.9059283,7.937852 6.4575432,13.593748 14.2499998,13.59375 h 9.21875 v -12.25 c 0,-8.849902 7.657144,-16.656248 16.75,-16.65625 h 26.78125 c 7.454951,0 13.406253,-6.138164 13.40625,-13.625 v -25.53125 c 0,-7.2663386 -6.12998,-12.7247771 -13.40625,-13.9374997 C 64.281548,0.32794397 59.502438,-0.02037903 54.918785,9.1927421e-4 Z m -14.5,8.21875012579 c 2.769547,0 5.03125,2.2986456 5.03125,5.1249996 -2e-6,2.816336 -2.261703,5.09375 -5.03125,5.09375 -2.779476,-1e-6 -5.03125,-2.277415 -5.03125,-5.09375 -10e-7,-2.826353 2.251774,-5.1249996 5.03125,-5.1249996 z"
id="path1948" />
<path
style="fill:url(#linearGradient1475);fill-opacity:1"
d="m 85.637535,28.657169 v 11.90625 c 0,9.230755 -7.825895,16.999999 -16.75,17 h -26.78125 c -7.335833,0 -13.406249,6.278483 -13.40625,13.625 v 25.531247 c 0,7.266344 6.318588,11.540324 13.40625,13.625004 8.487331,2.49561 16.626237,2.94663 26.78125,0 6.750155,-1.95439 13.406253,-5.88761 13.40625,-13.625004 V 86.500919 h -26.78125 v -3.40625 h 26.78125 13.406254 c 7.792461,0 10.696251,-5.435408 13.406241,-13.59375 2.79933,-8.398886 2.68022,-16.475776 0,-27.25 -1.92578,-7.757441 -5.60387,-13.59375 -13.406241,-13.59375 z m -15.0625,64.65625 c 2.779478,3e-6 5.03125,2.277417 5.03125,5.093747 -2e-6,2.826354 -2.251775,5.125004 -5.03125,5.125004 -2.76955,0 -5.03125,-2.29865 -5.03125,-5.125004 2e-6,-2.81633 2.261697,-5.093747 5.03125,-5.093747 z"
id="path1950" />
<ellipse
style="opacity:0.44382;fill:url(#radialGradient1480);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:15.4174;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path1894"
cx="55.816761"
cy="127.70079"
rx="35.930977"
ry="6.9673119" />
</svg>

After

Width:  |  Height:  |  Size: 9.4 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="m370-80-16-128q-13-5-24.5-12T307-235l-119 50L78-375l103-78q-1-7-1-13.5v-27q0-6.5 1-13.5L78-585l110-190 119 50q11-8 23-15t24-12l16-128h220l16 128q13 5 24.5 12t22.5 15l119-50 110 190-103 78q1 7 1 13.5v27q0 6.5-2 13.5l103 78-110 190-118-50q-11 8-23 15t-24 12L590-80H370Zm70-80h79l14-106q31-8 57.5-23.5T639-327l99 41 39-68-86-65q5-14 7-29.5t2-31.5q0-16-2-31.5t-7-29.5l86-65-39-68-99 42q-22-23-48.5-38.5T533-694l-13-106h-79l-14 106q-31 8-57.5 23.5T321-633l-99-41-39 68 86 64q-5 15-7 30t-2 32q0 16 2 31t7 30l-86 65 39 68 99-42q22 23 48.5 38.5T427-266l13 106Zm42-180q58 0 99-41t41-99q0-58-41-99t-99-41q-59 0-99.5 41T342-480q0 58 40.5 99t99.5 41Zm-2-140Z"/></svg>

After

Width:  |  Height:  |  Size: 753 B

View File

@ -0,0 +1,34 @@
import logging
from PyQt6 import QtCore, uic
from vorta import config
from vorta._version import __version__
from vorta.store.models import BackupProfileMixin
from vorta.utils import get_asset
from vorta.views.utils import get_colored_icon
uifile = get_asset('UI/abouttab.ui')
AboutTabUI, AboutTabBase = uic.loadUiType(uifile)
logger = logging.getLogger(__name__)
class AboutTab(AboutTabBase, AboutTabUI, BackupProfileMixin):
refresh_archive = QtCore.pyqtSignal()
def __init__(self, parent=None):
"""Init."""
super().__init__(parent)
self.setupUi(parent)
self.versionLabel.setText(__version__)
self.logLink.setText(
f'<a href="file://{config.LOG_DIR}"><span style="text-decoration:'
'underline; color:#0984e3;">Click here</span></a> to view the logs.'
)
self.gpl_logo.setPixmap(get_colored_icon('gpl_logo', scaled_height=40, return_qpixmap=True))
self.python_logo.setPixmap(get_colored_icon('python_logo', scaled_height=40, return_qpixmap=True))
def set_borg_details(self, version, path):
self.borgVersion.setText(version)
self.borgPath.setText(f"<center>Path to Borg: {path}</center>")

View File

@ -2,13 +2,13 @@ import logging
from pathlib import Path
from PyQt6 import QtCore, uic
from PyQt6.QtCore import QPoint
from PyQt6.QtCore import QPoint, Qt
from PyQt6.QtGui import QFontMetrics, QKeySequence, QShortcut
from PyQt6.QtWidgets import (
QApplication,
QCheckBox,
QFileDialog,
QMenu,
QListWidgetItem,
QMessageBox,
QToolTip,
)
@ -24,6 +24,7 @@ from vorta.utils import (
from vorta.views.partials.loading_button import LoadingButton
from vorta.views.utils import get_colored_icon
from .about_tab import AboutTab
from .archive_tab import ArchiveTab
from .export_window import ExportWindow
from .import_window import ImportWindow
@ -71,8 +72,10 @@ class MainWindow(MainWindowBase, MainWindowUI):
self.sourceTab = SourceTab(self.sourceTabSlot)
self.archiveTab = ArchiveTab(self.archiveTabSlot, app=self.app)
self.scheduleTab = ScheduleTab(self.scheduleTabSlot)
self.miscTab = MiscTab(self.miscTabSlot)
self.miscTab.set_borg_details(borg_compat.version, borg_compat.path)
self.miscTab = MiscTab(self.SettingsTabSlot)
self.aboutTab = AboutTab(self.AboutTabSlot)
self.aboutTab.set_borg_details(borg_compat.version, borg_compat.path)
self.miscWidget.hide()
self.tabWidget.setCurrentIndex(0)
self.repoTab.repo_changed.connect(self.archiveTab.populate_from_profile)
@ -80,6 +83,7 @@ class MainWindow(MainWindowBase, MainWindowUI):
self.repoTab.repo_added.connect(self.archiveTab.refresh_archive_list)
self.miscTab.refresh_archive.connect(self.archiveTab.populate_from_profile)
self.miscButton.clicked.connect(self.toggle_misc_visibility)
self.createStartBtn.clicked.connect(self.app.create_backup_action)
self.cancelButton.clicked.connect(self.app.backup_cancelled_event.emit)
@ -94,14 +98,13 @@ class MainWindow(MainWindowBase, MainWindowUI):
# Init profile list
self.populate_profile_selector()
self.profileSelector.currentIndexChanged.connect(self.profile_select_action)
self.profileSelector.itemClicked.connect(self.profile_clicked_action)
self.profileSelector.currentItemChanged.connect(self.profile_selection_changed_action)
self.profileRenameButton.clicked.connect(self.profile_rename_action)
self.profileExportButton.clicked.connect(self.profile_export_action)
self.profileDeleteButton.clicked.connect(self.profile_delete_action)
profile_add_menu = QMenu()
profile_add_menu.addAction(self.tr('Import from file…'), self.profile_import_action)
self.profileAddButton.setMenu(profile_add_menu)
self.profileAddButton.clicked.connect(self.profile_add_action)
self.profileAddButton.addAction(self.tr("Create new profile"), self.profile_add_action)
self.profileAddButton.addAction(self.tr("Import from file…"), self.profile_import_action)
# OS-specific startup options:
if not get_network_status_monitor().is_network_status_available():
@ -129,7 +132,8 @@ class MainWindow(MainWindowBase, MainWindowUI):
self.profileAddButton.setIcon(get_colored_icon('plus'))
self.profileRenameButton.setIcon(get_colored_icon('edit'))
self.profileExportButton.setIcon(get_colored_icon('file-import-solid'))
self.profileDeleteButton.setIcon(get_colored_icon('trash'))
self.profileDeleteButton.setIcon(get_colored_icon('minus'))
self.miscButton.setIcon(get_colored_icon('settings_wheel'))
def set_progress(self, text=''):
self.progressText.setText(text)
@ -150,14 +154,29 @@ class MainWindow(MainWindowBase, MainWindowUI):
self.cancelButton.repaint()
def populate_profile_selector(self):
# Clear the previous entries
self.profileSelector.clear()
for profile in BackupProfileModel.select().order_by(BackupProfileModel.name):
self.profileSelector.addItem(profile.name, profile.id)
current_profile_index = self.profileSelector.findData(self.current_profile.id)
self.profileSelector.setCurrentIndex(current_profile_index)
def profile_select_action(self, index):
backup_profile_id = self.profileSelector.currentData()
# Keep track of the current item to be selected (if any)
current_item = None
# Add items to the QListWidget
for profile in BackupProfileModel.select().order_by(BackupProfileModel.name):
item = QListWidgetItem(profile.name)
item.setData(Qt.ItemDataRole.UserRole, profile.id)
self.profileSelector.addItem(item)
if profile.id == self.current_profile.id:
current_item = item
# Set the current profile as selected
if current_item:
self.profileSelector.setCurrentItem(current_item)
def profile_selection_changed_action(self, index):
profile = self.profileSelector.currentItem()
backup_profile_id = profile.data(Qt.ItemDataRole.UserRole) if profile else None
if not backup_profile_id:
return
self.current_profile = BackupProfileModel.get(id=backup_profile_id)
@ -170,8 +189,13 @@ class MainWindow(MainWindowBase, MainWindowUI):
).execute()
self.archiveTab.toggle_compact_button_visibility()
def profile_clicked_action(self):
if self.miscWidget.isVisible():
self.toggle_misc_visibility()
def profile_rename_action(self):
window = EditProfileWindow(rename_existing_id=self.profileSelector.currentData())
backup_profile_id = self.profileSelector.currentItem().data(Qt.ItemDataRole.UserRole)
window = EditProfileWindow(rename_existing_id=backup_profile_id)
self.window = window # For tests
window.setParent(self, QtCore.Qt.WindowType.Sheet)
window.open()
@ -180,7 +204,7 @@ class MainWindow(MainWindowBase, MainWindowUI):
def profile_delete_action(self):
if self.profileSelector.count() > 1:
to_delete_id = self.profileSelector.currentData()
to_delete_id = self.profileSelector.currentItem().data(Qt.ItemDataRole.UserRole)
to_delete = BackupProfileModel.get(id=to_delete_id)
msg = self.tr("Are you sure you want to delete profile '{}'?".format(to_delete.name))
@ -195,8 +219,8 @@ class MainWindow(MainWindowBase, MainWindowUI):
if reply == QMessageBox.StandardButton.Yes:
to_delete.delete_instance(recursive=True)
self.app.scheduler.remove_job(to_delete_id) # Remove pending jobs
self.profileSelector.removeItem(self.profileSelector.currentIndex())
self.profile_select_action(0)
self.profileSelector.takeItem(self.profileSelector.currentRow())
self.profile_selection_changed_action(0)
else:
warn = self.tr("Cannot delete the last profile.")
@ -259,12 +283,26 @@ class MainWindow(MainWindowBase, MainWindowUI):
def profile_add_edit_result(self, profile_name, profile_id):
# Profile is renamed
if self.profileSelector.currentData() == profile_id:
self.profileSelector.setItemText(self.profileSelector.currentIndex(), profile_name)
if self.profileSelector.currentItem().data(Qt.ItemDataRole.UserRole) == profile_id:
self.profileSelector.currentItem().setText(profile_name)
# Profile is added
else:
self.profileSelector.addItem(profile_name, profile_id)
self.profileSelector.setCurrentIndex(self.profileSelector.count() - 1)
profile = QListWidgetItem(profile_name)
profile.setData(Qt.ItemDataRole.UserRole, profile_id)
self.profileSelector.addItem(profile)
self.profileSelector.setCurrentItem(profile)
def toggle_misc_visibility(self):
if self.miscWidget.isVisible():
self.miscWidget.hide()
self.tabWidget.setCurrentIndex(0)
self.miscButton.setStyleSheet("font-weight: normal;")
self.tabWidget.show()
else:
self.tabWidget.hide()
self.miscWidget.setCurrentIndex(0)
self.miscButton.setStyleSheet("font-weight: bold;")
self.miscWidget.show()
def backup_started_event(self):
self._toggle_buttons(create_enabled=False)

View File

@ -12,8 +12,6 @@ from PyQt6.QtWidgets import (
QSpacerItem,
)
from vorta import config
from vorta._version import __version__
from vorta.i18n import translate
from vorta.store.models import BackupProfileMixin, SettingsModel
from vorta.store.settings import get_misc_settings
@ -34,11 +32,6 @@ class MiscTab(MiscTabBase, MiscTabUI, BackupProfileMixin):
"""Init."""
super().__init__(parent)
self.setupUi(parent)
self.versionLabel.setText(__version__)
self.logLink.setText(
f'<a href="file://{config.LOG_DIR}"><span style="text-decoration:'
'underline; color:#0984e3;">Log</span></a>'
)
self.checkboxLayout = QFormLayout(self.frameSettings)
self.checkboxLayout.setSpacing(4)
@ -133,7 +126,3 @@ class MiscTab(MiscTabBase, MiscTabUI, BackupProfileMixin):
setting = SettingsModel.get(key=key)
setting.value = bool(new_value)
setting.save()
def set_borg_details(self, version, path):
self.borgVersion.setText(version)
self.borgPath.setText(path)

View File

@ -3,7 +3,7 @@ from PyQt6.QtGui import QIcon, QImage, QPixmap
from vorta.utils import get_asset, uses_dark_mode
def get_colored_icon(icon_name):
def get_colored_icon(icon_name, scaled_height=128, return_qpixmap=False):
"""
Return SVG icon in the correct color.
"""
@ -11,7 +11,9 @@ def get_colored_icon(icon_name):
svg_str = svg_file.read()
if uses_dark_mode():
svg_str = svg_str.replace(b'#000000', b'#ffffff')
# Reduce image size to 128 height
svg_img = QImage.fromData(svg_str).scaledToHeight(128)
svg_img = QImage.fromData(svg_str).scaledToHeight(scaled_height)
return QIcon(QPixmap(svg_img))
if return_qpixmap:
return QPixmap(svg_img)
else:
return QIcon(QPixmap(svg_img))

View File

@ -107,7 +107,7 @@ def test_enable_fixed_units(qapp, qtbot, mocker):
@pytest.mark.skipif(sys.platform != 'darwin', reason="Full Disk Access check only on Darwin")
def test_check_full_disk_access(qapp, qtbot, mocker):
def test_check_full_disk_access(qapp, mocker):
"""Tests if the full disk access warning is properly silenced with the setting enabled"""
# Set mocks for setting enabled

View File

@ -8,19 +8,19 @@ def test_profile_add_delete(qapp, qtbot, mocker):
main = qapp.main_window
# add profile and ensure it is created as intended
qtbot.mouseClick(main.profileAddButton, QtCore.Qt.MouseButton.LeftButton)
main.profile_add_action()
add_profile_window = main.window
qtbot.keyClicks(add_profile_window.profileNameField, 'Test Profile')
save_button = add_profile_window.buttonBox.button(QDialogButtonBox.StandardButton.Save)
qtbot.mouseClick(save_button, QtCore.Qt.MouseButton.LeftButton)
assert BackupProfileModel.get_or_none(name='Test Profile') is not None
assert main.profileSelector.currentText() == 'Test Profile'
assert main.profileSelector.currentItem().text() == 'Test Profile'
# delete the new profile and ensure it is no longer available.
mocker.patch.object(QMessageBox, 'question', return_value=QMessageBox.StandardButton.Yes)
qtbot.mouseClick(main.profileDeleteButton, QtCore.Qt.MouseButton.LeftButton)
assert BackupProfileModel.get_or_none(name='Test Profile') is None
assert main.profileSelector.currentText() == 'Default'
assert main.profileSelector.currentItem().text() == 'Default'
# attempt to delete the last remaining profile
# see that it cannot be deleted, a warning is displayed, and the profile remains
@ -28,7 +28,7 @@ def test_profile_add_delete(qapp, qtbot, mocker):
qtbot.mouseClick(main.profileDeleteButton, QtCore.Qt.MouseButton.LeftButton)
assert "Cannot delete the last profile." in warning.call_args[0][1]
assert BackupProfileModel.get_or_none(name='Default') is not None
assert main.profileSelector.currentText() == 'Default'
assert main.profileSelector.currentItem().text() == 'Default'
def test_profile_edit(qapp, qtbot):
@ -46,4 +46,4 @@ def test_profile_edit(qapp, qtbot):
# assert a profile by the old name no longer exists, and the newly named profile does exist and is selected.
assert BackupProfileModel.get_or_none(name='Default') is None
assert BackupProfileModel.get_or_none(name='Test Profile') is not None
assert main.profileSelector.currentText() == 'Test Profile'
assert main.profileSelector.currentItem().text() == 'Test Profile'