Refactor into modular widgets.

This commit is contained in:
Manu 2018-10-28 01:24:34 +08:00
parent 03f6286d7d
commit 5906a4b0c2
15 changed files with 861 additions and 829 deletions

View File

@ -1,149 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>AddRepository</class>
<widget class="QDialog" name="AddRepository">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>600</width>
<height>250</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<property name="modal">
<bool>true</bool>
</property>
<widget class="QWidget" name="formLayoutWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>20</y>
<width>591</width>
<height>271</height>
</rect>
</property>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<property name="leftMargin">
<number>20</number>
</property>
<property name="topMargin">
<number>20</number>
</property>
<property name="rightMargin">
<number>20</number>
</property>
<property name="bottomMargin">
<number>20</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Repository URL:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="repoURL">
<property name="placeholderText">
<string>csvis8xq@csvis8xq.repo.borgbase.com:repo</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="encryptionLabel">
<property name="text">
<string>Encryption:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="encryptionComboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>Select Encryption Mode</string>
</property>
</item>
</widget>
</item>
<item row="4" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QPushButton" name="saveButton">
<property name="text">
<string>Add</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="closeButton">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>SSH Key:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="sshComboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>Automatically choose SSH Key (default)</string>
</property>
</item>
</widget>
</item>
<item row="5" column="1">
<widget class="QLabel" name="errorText">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Password</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="passwordLineEdit">
<property name="enabled">
<bool>true</bool>
</property>
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -1,66 +0,0 @@
<?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>600</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<widget class="QWidget" name="verticalLayoutWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>601</width>
<height>301</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="leftMargin">
<number>10</number>
</property>
<property name="topMargin">
<number>10</number>
</property>
<property name="rightMargin">
<number>10</number>
</property>
<property name="bottomMargin">
<number>10</number>
</property>
<item>
<widget class="QPlainTextEdit" name="logText">
<property name="font">
<font>
<family>Courier</family>
<pointsize>12</pointsize>
</font>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
<property name="placeholderText">
<string>Logging output</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="closeButton">
<property name="text">
<string>Close</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -54,390 +54,28 @@
<item>
<widget class="QTabWidget" name="tabWidget">
<property name="currentIndex">
<number>0</number>
<number>2</number>
</property>
<widget class="QWidget" name="tab_2">
<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 class="QLabel" name="label_7">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>351</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string>Remote repository. The place to store your backups.</string>
</property>
</widget>
<widget class="QWidget" name="formLayoutWidget_2">
<property name="geometry">
<rect>
<x>0</x>
<y>240</y>
<width>771</width>
<height>171</height>
</rect>
</property>
<layout class="QFormLayout" name="formLayout_2">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<property name="formAlignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="leftMargin">
<number>10</number>
</property>
<property name="rightMargin">
<number>25</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_10">
<property name="text">
<string>Encryption:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="repoEncryption">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="Line" name="line">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="Line" name="line_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_11">
<property name="text">
<string>Original Size:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="sizeOriginal">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_13">
<property name="text">
<string>Deduplicated Size:</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_12">
<property name="text">
<string>Compressed Size:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLabel" name="sizeCompressed">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLabel" name="sizeDeduplicated">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</widget>
<widget class="QWidget" name="layoutWidget">
<property name="geometry">
<rect>
<x>0</x>
<y>30</y>
<width>769</width>
<height>197</height>
</rect>
</property>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<property name="leftMargin">
<number>10</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>25</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Repository:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="repoSelector">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>Select Backup Destination</string>
</property>
</item>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_5">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Need hosting for your Borg repository? &lt;a href=&quot;https://www.borgbackup.org/support/commercial.html&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;View providers&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_14">
<property name="text">
<string>SSH Key:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="sshComboBox">
<item>
<property name="text">
<string>Automatically choose SSH Key (default)</string>
</property>
</item>
<item>
<property name="text">
<string>Create New Key</string>
</property>
</item>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Compression:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QComboBox" name="repoCompression"/>
</item>
<item row="3" column="1">
<widget class="QLabel" name="label_2">
<property name="text">
<string>To access repository securely.</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="QWidget" name="tab">
<widget class="QWidget" name="sourceTabSlot">
<attribute name="title">
<string>Sources</string>
</attribute>
<widget class="QWidget" name="horizontalLayoutWidget">
<property name="geometry">
<rect>
<x>10</x>
<y>40</y>
<width>721</width>
<height>371</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QListWidget" name="sourceDirectoriesWidget"/>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPushButton" name="sourceAdd">
<property name="text">
<string>Add Folder</string>
</property>
</widget>
</item>
<item alignment="Qt::AlignTop">
<widget class="QPushButton" name="sourceRemove">
<property name="text">
<string>Remove Folder</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QLabel" name="label_6">
<property name="geometry">
<rect>
<x>20</x>
<y>10</y>
<width>361</width>
<height>16</height>
</rect>
</property>
<property name="text">
<string>Choose the folders to back up.</string>
</property>
</widget>
</widget>
<widget class="QWidget" name="tab_3">
<widget class="QWidget" name="snapshotTabSlot">
<attribute name="title">
<string>Snapshots</string>
</attribute>
<widget class="QWidget" name="verticalLayoutWidget_3">
<property name="geometry">
<rect>
<x>-10</x>
<y>0</y>
<width>791</width>
<height>401</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="leftMargin">
<number>10</number>
</property>
<property name="topMargin">
<number>10</number>
</property>
<property name="rightMargin">
<number>10</number>
</property>
<property name="bottomMargin">
<number>10</number>
</property>
<item>
<widget class="QTableWidget" name="snapshotTable">
<attribute name="horizontalHeaderVisible">
<bool>false</bool>
</attribute>
<attribute name="horizontalHeaderCascadingSectionResizes">
<bool>false</bool>
</attribute>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string>Name</string>
</property>
</column>
<column>
<property name="text">
<string>Date</string>
</property>
</column>
</widget>
</item>
<item>
<widget class="QLabel" name="mountErrors">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;To mount snapshots, first install &amp;quot;FUSE for macOS&amp;quot; from &lt;a href=&quot;https://osxfuse.github.io/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;here&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QPushButton" name="snapshotMountButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Mount</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="snapshotDeleteButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Delete</string>
</property>
</widget>
</item>
<item alignment="Qt::AlignLeft">
<widget class="QPushButton" name="snapshotRefreshButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Refresh</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
</widget>
</item>

143
vorta/UI/repoadd.ui Normal file
View File

@ -0,0 +1,143 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>AddRepository</class>
<widget class="QDialog" name="AddRepository">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>600</width>
<height>250</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<property name="modal">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<property name="leftMargin">
<number>20</number>
</property>
<property name="topMargin">
<number>20</number>
</property>
<property name="rightMargin">
<number>20</number>
</property>
<property name="bottomMargin">
<number>20</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Repository URL:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="repoURL">
<property name="placeholderText">
<string>csvis8xq@csvis8xq.repo.borgbase.com:repo</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="encryptionLabel">
<property name="text">
<string>Encryption:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="encryptionComboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>Select Encryption Mode</string>
</property>
</item>
</widget>
</item>
<item row="4" column="1">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QPushButton" name="saveButton">
<property name="text">
<string>Add</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="closeButton">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>SSH Key:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="sshComboBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>Automatically choose SSH Key (default)</string>
</property>
</item>
</widget>
</item>
<item row="5" column="1">
<widget class="QLabel" name="errorText">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Password</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="passwordLineEdit">
<property name="enabled">
<bool>true</bool>
</property>
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

233
vorta/UI/repotab.ui Normal file
View File

@ -0,0 +1,233 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="enabled">
<bool>true</bool>
</property>
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>831</width>
<height>461</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Ignored" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLabel" name="label_7">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Remote repository. The place to store your backups.</string>
</property>
</widget>
</item>
<item>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<property name="labelAlignment">
<set>Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing</set>
</property>
<property name="leftMargin">
<number>10</number>
</property>
<property name="topMargin">
<number>5</number>
</property>
<property name="rightMargin">
<number>25</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Repository:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="repoSelector">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<item>
<property name="text">
<string>Select Backup Destination</string>
</property>
</item>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="label_5">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Need hosting for your Borg repository? &lt;a href=&quot;https://www.borgbackup.org/support/commercial.html&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;View providers&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="openExternalLinks">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_14">
<property name="text">
<string>SSH Key:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="sshComboBox">
<item>
<property name="text">
<string>Automatically choose SSH Key (default)</string>
</property>
</item>
<item>
<property name="text">
<string>Create New Key</string>
</property>
</item>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Compression:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QComboBox" name="repoCompression"/>
</item>
<item row="3" column="1">
<widget class="QLabel" name="label_2">
<property name="text">
<string>To access repository securely.</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QFormLayout" name="formLayout_2">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<property name="labelAlignment">
<set>Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing</set>
</property>
<property name="formAlignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property>
<property name="leftMargin">
<number>10</number>
</property>
<property name="rightMargin">
<number>25</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label_10">
<property name="text">
<string>Encryption:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="repoEncryption">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="Line" name="line">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="Line" name="line_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_11">
<property name="text">
<string>Original Size:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="sizeOriginal">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_13">
<property name="text">
<string>Deduplicated Size:</string>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_12">
<property name="text">
<string>Compressed Size:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLabel" name="sizeCompressed">
<property name="text">
<string/>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLabel" name="sizeDeduplicated">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

122
vorta/UI/snapshottab.ui Normal file
View File

@ -0,0 +1,122 @@
<?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>799</width>
<height>514</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<property name="leftMargin">
<number>10</number>
</property>
<property name="topMargin">
<number>10</number>
</property>
<property name="rightMargin">
<number>10</number>
</property>
<property name="bottomMargin">
<number>10</number>
</property>
<item>
<widget class="QTableWidget" name="snapshotTable">
<attribute name="horizontalHeaderVisible">
<bool>false</bool>
</attribute>
<attribute name="horizontalHeaderCascadingSectionResizes">
<bool>false</bool>
</attribute>
<attribute name="horizontalHeaderStretchLastSection">
<bool>true</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string>Name</string>
</property>
</column>
<column>
<property name="text">
<string>Date</string>
</property>
</column>
</widget>
</item>
<item>
<widget class="QLabel" name="mountErrors">
<property name="enabled">
<bool>true</bool>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;To mount snapshots, first install &amp;quot;FUSE for macOS&amp;quot; from &lt;a href=&quot;https://osxfuse.github.io/&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;here&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QPushButton" name="snapshotMountButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Mount</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="snapshotDeleteButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Delete</string>
</property>
</widget>
</item>
<item alignment="Qt::AlignLeft">
<widget class="QPushButton" name="snapshotRefreshButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Refresh</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

53
vorta/UI/sourcetab.ui Normal file
View File

@ -0,0 +1,53 @@
<?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="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="label_6">
<property name="text">
<string>Choose the folders to back up.</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QListWidget" name="sourceDirectoriesWidget"/>
</item>
<item>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QPushButton" name="sourceAdd">
<property name="text">
<string>Add Folder</string>
</property>
</widget>
</item>
<item alignment="Qt::AlignTop">
<widget class="QPushButton" name="sourceRemove">
<property name="text">
<string>Remove Folder</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -9,5 +9,5 @@ SETTINGS_DIR = appdirs.user_data_dir(APP_NAME, APP_AUTHOR)
if not os.path.exists(SETTINGS_DIR):
os.makedirs(SETTINGS_DIR)
def reset_app():
def remove_config():
shutil.rmtree(SETTINGS_DIR)

View File

@ -2,16 +2,15 @@ import os
import platform
from datetime import datetime as dt
from dateutil import parser
from PyQt5.QtWidgets import QApplication, QFileDialog, QTableWidgetItem, QTableView, QTableWidget
from PyQt5 import uic, QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QApplication
from PyQt5 import uic
from .repo_add import AddRepoWindow, ExistingRepoWindow
from .ssh_add import SSHAddWindow
from .config import APP_NAME, reset_app
from .models import RepoModel, SourceDirModel, SnapshotModel, BackupProfileModel
from .ssh_keys import get_private_keys
from .config import APP_NAME, remove_config
from .models import SnapshotModel, BackupProfileModel, SourceDirModel
from .borg_runner import BorgThread
from .utils import prettyByes
from .repo_tab import RepoTab
from .source_tab import SourceTab
from .snapshots_tab import SnapshotTab
uifile = os.path.join(os.path.dirname(__file__), 'UI/mainwindow.ui')
@ -24,11 +23,12 @@ class MainWindow(MainWindowBase, MainWindowUI):
self.setupUi(self)
self.setWindowTitle(APP_NAME)
self.profile = BackupProfileModel.get(id=1)
self.init_repo()
self.init_source()
self.init_snapshots()
self.init_compression()
self.init_ssh()
self.repoTab = RepoTab(self.repoTabSlot)
self.repoTab.repo_changed.connect(lambda: print('adf'))
self.sourceTab = SourceTab(self.sourceTabSlot)
self.snapshotTab = SnapshotTab(self.snapshotTabSlot)
self.createStartBtn.clicked.connect(self.create_action)
self.actionResetApp.triggered.connect(self.menu_reset)
@ -41,7 +41,7 @@ class MainWindow(MainWindowBase, MainWindowUI):
self.createProgressText.repaint()
def create_action(self):
n_backup_folders = self.sourceDirectoriesWidget.count()
n_backup_folders = SourceDirModel.select().count()
if n_backup_folders == 0:
self.set_status('Add some folders to back up first.')
return
@ -53,8 +53,8 @@ class MainWindow(MainWindowBase, MainWindowUI):
cmd = ['borg', 'create', '--list', '--info', '--log-json', '--json', '-C', self.profile.compression,
f'{repo.url}::{platform.node()}-{dt.now().isoformat()}'
]
for i in range(n_backup_folders):
cmd.append(self.sourceDirectoriesWidget.item(i).text())
for f in SourceDirModel.select():
cmd.append(f.dir)
thread = BorgThread(self, cmd, {})
thread.updated.connect(self.create_update_log)
@ -84,200 +84,8 @@ class MainWindow(MainWindowBase, MainWindowUI):
repo.unique_size = stats['unique_size']
repo.total_unique_chunks = stats['total_unique_chunks']
repo.save()
self.init_snapshots()
def init_source(self):
self.sourceAdd.clicked.connect(self.source_add)
self.sourceRemove.clicked.connect(self.source_remove)
for source in SourceDirModel.select():
self.sourceDirectoriesWidget.addItem(source.dir)
def init_ssh(self):
keys = get_private_keys()
for key in keys:
self.sshComboBox.addItem(f'{key["filename"]} ({key["format"]}:{key["fingerprint"]})', key['filename'])
self.sshComboBox.currentIndexChanged.connect(self.ssh_select_action)
def ssh_select_action(self, index):
if index == 1:
ssh_add_window = SSHAddWindow()
ssh_add_window.setParent(self, QtCore.Qt.Sheet)
ssh_add_window.show()
if ssh_add_window.exec_():
self.init_ssh()
else:
self.profile.ssh_key = self.sshComboBox.itemData(index)
self.profile.save()
print('set ssh key to', self.profile.ssh_key)
def init_snapshots(self):
if self.profile.repo:
snapshots = [s for s in self.profile.repo.snapshots.select()]
for row, snapshot in enumerate(snapshots):
self.snapshotTable.insertRow(row)
self.snapshotTable.setItem(row, 0, QTableWidgetItem(snapshot.name))
formatted_time = snapshot.time.strftime('%Y-%m-%d %H:%M')
self.snapshotTable.setItem(row, 1, QTableWidgetItem(formatted_time))
self.sizeCompressed.setText(prettyByes(self.profile.repo.unique_csize))
self.sizeDeduplicated.setText(prettyByes(self.profile.repo.unique_size))
self.sizeOriginal.setText(prettyByes(self.profile.repo.total_size))
self.repoEncryption.setText(str(self.profile.repo.encryption))
self.snapshotTable.setRowCount(len(snapshots))
header = self.snapshotTable.horizontalHeader()
header.setVisible(True)
header.setSectionResizeMode(0, QtWidgets.QHeaderView.Stretch)
header.setSectionResizeMode(1, QtWidgets.QHeaderView.ResizeToContents)
self.snapshotTable.setSelectionBehavior(QTableView.SelectRows)
self.snapshotTable.setEditTriggers(QTableView.NoEditTriggers)
self.snapshotMountButton.clicked.connect(self.snapshot_mount)
self.snapshotDeleteButton.clicked.connect(self.snapshot_mount)
self.snapshotRefreshButton.clicked.connect(self.snapshot_mount)
def snapshot_mount(self):
cmd = ['borg', 'mount', '--log-json']
row_selected = self.snapshotTable.selectionModel().selectedRows()
if row_selected:
snapshot_cell = self.snapshotTable.item(row_selected[0].row(), 0)
if snapshot_cell:
snapshot_name = snapshot_cell.text()
cmd.append(f'{self.profile.repo.url}::{snapshot_name}')
else:
cmd.append(f'{self.profile.repo.url}')
else:
cmd.append(f'{self.profile.repo.url}')
options = QFileDialog.Options()
options |= QFileDialog.ShowDirsOnly
options |= QFileDialog.DontUseNativeDialog
mountPoint = QFileDialog.getExistingDirectory(
self, "Choose Mount Point", "", options=options)
if mountPoint:
cmd.append(mountPoint)
self.set_status('Mounting snapshot into folder', 0)
thread = BorgThread(self, cmd, {})
thread.updated.connect(self.mount_update_log)
thread.result.connect(self.mount_get_result)
thread.start()
def mount_update_log(self, text):
self.mountErrors.setText(text)
def mount_get_result(self, result):
self.set_status(progress_max=100)
if result['returncode'] == 0:
self.set_status('Mounted successfully.')
def init_compression(self):
self.repoCompression.addItem('LZ4 (default)', 'lz4')
self.repoCompression.addItem('Zstandard (medium)', 'zstd')
self.repoCompression.addItem('LZMA (high)', 'lzma,6')
self.repoCompression.setCurrentIndex(self.repoCompression.findData(self.profile.compression))
self.repoCompression.currentIndexChanged.connect(self.compression_select_action)
def compression_select_action(self, index):
self.profile.compression = self.repoCompression.currentData()
self.profile.save()
def init_repo(self):
self.repoSelector.model().item(0).setEnabled(False)
self.repoSelector.addItem('Initialize New Repository', 'init')
self.repoSelector.addItem('Add Existing Repository', 'existing')
for repo in RepoModel.select():
self.repoSelector.addItem(repo.url, repo.id)
if self.profile.repo:
self.repoSelector.setCurrentIndex(self.repoSelector.findData(self.profile.repo.id))
self.repoSelector.currentIndexChanged.connect(self.repo_select_action)
def repo_select_action(self, index):
if index <= 2:
if index == 1:
repo_add_window = AddRepoWindow()
else:
repo_add_window = ExistingRepoWindow()
repo_add_window.setParent(self, QtCore.Qt.Sheet)
repo_add_window.show()
if repo_add_window.exec_():
params = repo_add_window.get_values()
if index == 1:
cmd = ["borg", "init", "--log-json", f"--encryption={params['encryption']}", params['repo_url']]
else:
cmd = ["borg", "list", "--json", params['repo_url']]
self.set_status('Connecting to repo...', 0)
thread = BorgThread(self, cmd, params)
thread.updated.connect(self.repo_add_update_log)
thread.result.connect(self.repo_add_result)
thread.start()
else:
self.profile.repo = self.repoSelector.currentData()
self.profile.save()
self.init_snapshots()
def repo_add_update_log(self, text):
self.set_status(text)
def repo_add_result(self, result):
if result['returncode'] == 0:
self.set_status('Successfully connected to repo.', 100)
new_repo, _ = RepoModel.get_or_create(
url=result['params']['repo_url'],
defaults={
'password': result['params']['password'],
# 'encryption': result['params'].get('encryption', '')
}
)
if 'cache' in result['data']:
stats = result['data']['cache']['stats']
new_repo.total_size = stats['total_size']
new_repo.unique_csize = stats['unique_csize']
new_repo.unique_size = stats['unique_size']
new_repo.total_unique_chunks = stats['total_unique_chunks']
new_repo.encryption = result['data']['encryption']['mode']
new_repo.save()
self.profile.repo = new_repo.id
self.profile.save()
if 'archives' in result['data'].keys():
for snapshot in result['data']['archives']:
new_snapshot, _ = SnapshotModel.get_or_create(
snapshot_id=snapshot['id'],
defaults={
'repo': new_repo.id,
'name': snapshot['name'],
'time': parser.parse(snapshot['time'])
}
)
new_snapshot.save()
self.repoSelector.addItem(new_repo.url, new_repo.id)
self.repoSelector.setCurrentIndex(self.repoSelector.count()-1)
self.init_snapshots()
def source_add(self):
options = QFileDialog.Options()
options |= QFileDialog.ShowDirsOnly
options |= QFileDialog.DontUseNativeDialog
fileName = QFileDialog.getExistingDirectory(
self, "Choose Backup Directory", "", options=options)
if fileName:
self.sourceDirectoriesWidget.addItem(fileName)
new_source = SourceDirModel(dir=fileName)
new_source.save()
def source_remove(self):
item = self.sourceDirectoriesWidget.takeItem(self.sourceDirectoriesWidget.currentRow())
db_item = SourceDirModel.get(dir=item.text())
db_item.delete_instance()
item = None
self.snapshotTab.populate()
def menu_reset(self):
reset_app()
remove_config()
QApplication.instance().quit()

View File

@ -1,8 +1,8 @@
import os
from PyQt5 import uic
from .ssh_keys import get_private_keys
from .utils import get_private_keys
uifile = os.path.join(os.path.dirname(__file__), 'UI/addrepo.ui')
uifile = os.path.join(os.path.dirname(__file__), 'UI/repoadd.ui')
AddRepoUI, AddRepoBase = uic.loadUiType(uifile)

136
vorta/repo_tab.py Normal file
View File

@ -0,0 +1,136 @@
import os
from dateutil import parser
from PyQt5 import uic, QtCore
from .models import RepoModel, SourceDirModel, SnapshotModel, BackupProfileModel
from .repo_add import AddRepoWindow, ExistingRepoWindow
from .borg_runner import BorgThread
from .utils import prettyBytes, get_private_keys
from .ssh_add import SSHAddWindow
uifile = os.path.join(os.path.dirname(__file__), 'UI/repotab.ui')
RepoUI, RepoBase = uic.loadUiType(uifile)
class RepoTab(RepoBase, RepoUI):
repo_changed = QtCore.pyqtSignal(int)
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(parent)
self.profile = self.window().profile
self.repoSelector.model().item(0).setEnabled(False)
self.repoSelector.addItem('Initialize New Repository', 'init')
self.repoSelector.addItem('Add Existing Repository', 'existing')
for repo in RepoModel.select():
self.repoSelector.addItem(repo.url, repo.id)
if self.profile.repo:
self.repoSelector.setCurrentIndex(self.repoSelector.findData(self.profile.repo.id))
self.repoSelector.currentIndexChanged.connect(self.repo_select_action)
self.repoCompression.addItem('LZ4 (default)', 'lz4')
self.repoCompression.addItem('Zstandard (medium)', 'zstd')
self.repoCompression.addItem('LZMA (high)', 'lzma,6')
self.repoCompression.setCurrentIndex(self.repoCompression.findData(self.profile.compression))
self.repoCompression.currentIndexChanged.connect(self.compression_select_action)
self.init_ssh()
self.init_repo_stats()
def init_repo_stats(self):
self.sizeCompressed.setText(prettyBytes(self.profile.repo.unique_csize))
self.sizeDeduplicated.setText(prettyBytes(self.profile.repo.unique_size))
self.sizeOriginal.setText(prettyBytes(self.profile.repo.total_size))
self.repoEncryption.setText(str(self.profile.repo.encryption))
self.repo_changed.emit(self.profile.repo.id)
def init_ssh(self):
keys = get_private_keys()
for key in keys:
self.sshComboBox.addItem(f'{key["filename"]} ({key["format"]}:{key["fingerprint"]})', key['filename'])
self.sshComboBox.currentIndexChanged.connect(self.ssh_select_action)
def ssh_select_action(self, index):
if index == 1:
ssh_add_window = SSHAddWindow()
ssh_add_window.setParent(self, QtCore.Qt.Sheet)
ssh_add_window.show()
if ssh_add_window.exec_():
self.init_ssh()
else:
self.profile.ssh_key = self.sshComboBox.itemData(index)
self.profile.save()
print('set ssh key to', self.profile.ssh_key)
def compression_select_action(self, index):
self.profile.compression = self.repoCompression.currentData()
self.profile.save()
def repo_select_action(self, index):
if index <= 2:
if index == 1:
repo_add_window = AddRepoWindow()
else:
repo_add_window = ExistingRepoWindow()
repo_add_window.setParent(self, QtCore.Qt.Sheet)
repo_add_window.show()
if repo_add_window.exec_():
params = repo_add_window.get_values()
if index == 1:
cmd = ["borg", "init", "--log-json", f"--encryption={params['encryption']}", params['repo_url']]
else:
cmd = ["borg", "list", "--json", params['repo_url']]
self.set_status('Connecting to repo...', 0)
thread = BorgThread(self, cmd, params)
thread.updated.connect(self.repo_add_update_log)
thread.result.connect(self.repo_add_result)
thread.start()
else:
self.profile.repo = self.repoSelector.currentData()
self.profile.save()
self.init_repo_stats()
def repo_add_update_log(self, text):
self.set_status(text)
def repo_add_result(self, result):
if result['returncode'] == 0:
self.set_status('Successfully connected to repo.', 100)
new_repo, _ = RepoModel.get_or_create(
url=result['params']['repo_url'],
defaults={
'password': result['params']['password'],
# 'encryption': result['params'].get('encryption', '')
}
)
if 'cache' in result['data']:
stats = result['data']['cache']['stats']
new_repo.total_size = stats['total_size']
new_repo.unique_csize = stats['unique_csize']
new_repo.unique_size = stats['unique_size']
new_repo.total_unique_chunks = stats['total_unique_chunks']
new_repo.encryption = result['data']['encryption']['mode']
new_repo.save()
self.profile.repo = new_repo.id
self.profile.save()
if 'archives' in result['data'].keys():
for snapshot in result['data']['archives']:
new_snapshot, _ = SnapshotModel.get_or_create(
snapshot_id=snapshot['id'],
defaults={
'repo': new_repo.id,
'name': snapshot['name'],
'time': parser.parse(snapshot['time'])
}
)
new_snapshot.save()
self.repoSelector.addItem(new_repo.url, new_repo.id)
self.repoSelector.setCurrentIndex(self.repoSelector.count()-1)
self.init_snapshots()

75
vorta/snapshots_tab.py Normal file
View File

@ -0,0 +1,75 @@
import os
from PyQt5 import uic, QtCore
from PyQt5.QtWidgets import QFileDialog, QTableWidgetItem, QTableView, QHeaderView
from .borg_runner import BorgThread
uifile = os.path.join(os.path.dirname(__file__), 'UI/snapshottab.ui')
SnapshotUI, SnapshotBase = uic.loadUiType(uifile)
class SnapshotTab(SnapshotBase, SnapshotUI):
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(parent)
self.profile = self.window().profile
header = self.snapshotTable.horizontalHeader()
header.setVisible(True)
header.setSectionResizeMode(0, QHeaderView.Stretch)
header.setSectionResizeMode(1, QHeaderView.ResizeToContents)
self.snapshotTable.setSelectionBehavior(QTableView.SelectRows)
self.snapshotTable.setEditTriggers(QTableView.NoEditTriggers)
self.snapshotMountButton.clicked.connect(self.snapshot_mount)
self.snapshotDeleteButton.clicked.connect(self.snapshot_mount)
self.snapshotRefreshButton.clicked.connect(self.snapshot_mount)
self.populate()
def populate(self):
if self.profile.repo:
snapshots = [s for s in self.profile.repo.snapshots.select()]
for row, snapshot in enumerate(snapshots):
self.snapshotTable.insertRow(row)
self.snapshotTable.setItem(row, 0, QTableWidgetItem(snapshot.name))
formatted_time = snapshot.time.strftime('%Y-%m-%d %H:%M')
self.snapshotTable.setItem(row, 1, QTableWidgetItem(formatted_time))
self.snapshotTable.setRowCount(len(snapshots))
def snapshot_mount(self):
cmd = ['borg', 'mount', '--log-json']
row_selected = self.snapshotTable.selectionModel().selectedRows()
if row_selected:
snapshot_cell = self.snapshotTable.item(row_selected[0].row(), 0)
if snapshot_cell:
snapshot_name = snapshot_cell.text()
cmd.append(f'{self.profile.repo.url}::{snapshot_name}')
else:
cmd.append(f'{self.profile.repo.url}')
else:
cmd.append(f'{self.profile.repo.url}')
options = QFileDialog.Options()
options |= QFileDialog.ShowDirsOnly
options |= QFileDialog.DontUseNativeDialog
mountPoint = QFileDialog.getExistingDirectory(
self, "Choose Mount Point", "", options=options)
if mountPoint:
cmd.append(mountPoint)
self.set_status('Mounting snapshot into folder', 0)
thread = BorgThread(self, cmd, {})
thread.updated.connect(self.mount_update_log)
thread.result.connect(self.mount_get_result)
thread.start()
def mount_update_log(self, text):
self.mountErrors.setText(text)
def mount_get_result(self, result):
self.set_status(progress_max=100)
if result['returncode'] == 0:
self.set_status('Mounted successfully.')

36
vorta/source_tab.py Normal file
View File

@ -0,0 +1,36 @@
import os
from PyQt5 import uic, QtCore
from PyQt5.QtWidgets import QFileDialog
from .models import SourceDirModel
uifile = os.path.join(os.path.dirname(__file__), 'UI/sourcetab.ui')
SourceUI, SourceBase = uic.loadUiType(uifile)
class SourceTab(SourceBase, SourceUI):
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(parent)
self.profile = self.window().profile
self.sourceAdd.clicked.connect(self.source_add)
self.sourceRemove.clicked.connect(self.source_remove)
for source in SourceDirModel.select():
self.sourceDirectoriesWidget.addItem(source.dir)
def source_add(self):
options = QFileDialog.Options()
options |= QFileDialog.ShowDirsOnly
options |= QFileDialog.DontUseNativeDialog
fileName = QFileDialog.getExistingDirectory(
self, "Choose Backup Directory", "", options=options)
if fileName:
self.sourceDirectoriesWidget.addItem(fileName)
new_source = SourceDirModel(dir=fileName)
new_source.save()
def source_remove(self):
item = self.sourceDirectoriesWidget.takeItem(self.sourceDirectoriesWidget.currentRow())
db_item = SourceDirModel.get(dir=item.text())
db_item.delete_instance()
item = None

View File

@ -1,28 +0,0 @@
import os
from paramiko.rsakey import RSAKey
from paramiko.ecdsakey import ECDSAKey
from paramiko.ed25519key import Ed25519Key
from paramiko import SSHException
def get_private_keys():
key_formats = [RSAKey, ECDSAKey, Ed25519Key]
ssh_folder = os.path.expanduser('~/.ssh')
available_private_keys = []
for key in os.listdir(ssh_folder):
for key_format in key_formats:
try:
parsed_key = key_format.from_private_key_file(os.path.join(ssh_folder, key))
key_details = {
'filename': key,
'format': parsed_key.get_name(),
'bits': parsed_key.get_bits(),
'fingerprint': parsed_key.get_fingerprint().hex()
}
available_private_keys.append(key_details)
except (SSHException, UnicodeDecodeError, IsADirectoryError):
continue
return available_private_keys

View File

@ -1,5 +1,36 @@
import os
from paramiko.rsakey import RSAKey
from paramiko.ecdsakey import ECDSAKey
from paramiko.ed25519key import Ed25519Key
from paramiko import SSHException
def prettyByes(size):
def get_private_keys():
"""Find SSH keys in standard folder."""
key_formats = [RSAKey, ECDSAKey, Ed25519Key]
ssh_folder = os.path.expanduser('~/.ssh')
available_private_keys = []
if os.path.isdir(ssh_folder):
for key in os.listdir(ssh_folder):
for key_format in key_formats:
try:
parsed_key = key_format.from_private_key_file(os.path.join(ssh_folder, key))
key_details = {
'filename': key,
'format': parsed_key.get_name(),
'bits': parsed_key.get_bits(),
'fingerprint': parsed_key.get_fingerprint().hex()
}
available_private_keys.append(key_details)
except (SSHException, UnicodeDecodeError, IsADirectoryError):
continue
return available_private_keys
def prettyBytes(size):
"""from https://stackoverflow.com/questions/12523586/
python-format-size-application-converting-b-to-kb-mb-gb-tb/37423778"""
if type(size) != int: