ruby-pass-qt 2.0.6 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +4 -0
- data/lib/pass-qt/app/views/browsestoresdialog/ui.rb +77 -0
- data/lib/pass-qt/app/views/browsestoresdialog.rb +3 -69
- data/lib/pass-qt/app/{components → views/mainwindow/components}/passinfowidget/helpers.rb +1 -1
- data/lib/pass-qt/app/{components/passinfowidget.rb → views/mainwindow/components/passinfowidget/ui.rb} +30 -87
- data/lib/pass-qt/app/views/mainwindow/components/passinfowidget.rb +75 -0
- data/lib/pass-qt/app/{components → views/mainwindow/components}/passlistwidget/treewidget/helpers.rb +1 -1
- data/lib/pass-qt/app/{components → views/mainwindow/components}/passlistwidget/treewidget/treebuilder.rb +1 -1
- data/lib/pass-qt/app/{components → views/mainwindow/components}/passlistwidget/treewidget/treefilter.rb +1 -1
- data/lib/pass-qt/app/views/mainwindow/components/passlistwidget/treewidget/ui.rb +36 -0
- data/lib/pass-qt/app/{components → views/mainwindow/components}/passlistwidget/treewidget.rb +3 -30
- data/lib/pass-qt/app/{components/passlistwidget.rb → views/mainwindow/components/passlistwidget/ui.rb} +13 -47
- data/lib/pass-qt/app/views/mainwindow/components/passlistwidget.rb +45 -0
- data/lib/pass-qt/app/views/mainwindow/ui.rb +39 -0
- data/lib/pass-qt/app/views/mainwindow.rb +5 -61
- data/lib/pass-qt/app/views/newonetimepassworddialog/ui.rb +90 -0
- data/lib/pass-qt/app/views/newonetimepassworddialog.rb +15 -93
- data/lib/pass-qt/app/views/newpassworddialog/ui.rb +111 -0
- data/lib/pass-qt/app/views/newpassworddialog.rb +18 -117
- data/lib/pass-qt/app.rb +2 -2
- data/lib/pass-qt/config/initializers/qt6.rb +1 -1
- data/lib/pass-qt/lib/{contrib/sighandler.rb → ctrlc/handler.rb} +6 -4
- data/lib/pass-qt/lib/ctrlc.rb +1 -0
- data/lib/pass-qt/lib/pass/{clients → backend}/gopass.rb +4 -4
- data/lib/pass-qt/lib/pass/{clients → backend}/pass.rb +6 -6
- data/lib/pass-qt/lib/pass/backend.rb +2 -0
- data/lib/pass-qt/lib/{contrib → pass}/process.rb +1 -1
- data/lib/pass-qt/lib/pass.rb +13 -11
- data/lib/pass-qt/lib.rb +1 -1
- data/lib/pass-qt/version.rb +1 -1
- metadata +22 -17
- data/lib/pass-qt/app/assets/README.md +0 -5
- data/lib/pass-qt/app/assets/app.svg +0 -1
- data/lib/pass-qt/lib/contrib.rb +0 -2
- data/lib/pass-qt/lib/pass/clients.rb +0 -2
- /data/lib/pass-qt/app/{components.rb → views/mainwindow/components.rb} +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 0fb6805f75336a47b0d05fefce05aef65337a02726c03cae84d85587dc2ffe2c
|
|
4
|
+
data.tar.gz: dd7c0cad047c733a073bc301a8b57512da731888a62960d207015e8b1c2f0eab
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b6a0044d9db31fb3cdd5c76ab9ac3c22266e371d6c2c9f18a58ed4de480740849c3cfcd4713cbd2344ac815b670a4d43c84db7e20f9ff8fb826488232c182ca4
|
|
7
|
+
data.tar.gz: '069c63341c0129c3c5b113572055d579873fe58f9e95b16e74f80d1deabf01ee7e4503f0404f58682187fb0f03d52ce9bab176826947c3678bd8f9e6e0614a88'
|
data/.rubocop.yml
CHANGED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
class BrowseStoresDialog < RubyQt6::Bando::QDialog
|
|
2
|
+
private
|
|
3
|
+
|
|
4
|
+
def initialize_ui
|
|
5
|
+
initialize_toolbar
|
|
6
|
+
initialize_tablewidget
|
|
7
|
+
initialize_layout
|
|
8
|
+
|
|
9
|
+
set_attribute(Qt::WA_DeleteOnClose)
|
|
10
|
+
set_modal(true)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def initialize_toolbar
|
|
14
|
+
@toolbar = QWidget.new
|
|
15
|
+
|
|
16
|
+
btn = QPushButton.new(QIcon.from_theme(QIcon::ThemeIcon::ListAdd), "Add")
|
|
17
|
+
btn.clicked.connect(self, :_on_list_add_button_clicked)
|
|
18
|
+
|
|
19
|
+
qhboxlayout = QHBoxLayout.new(@toolbar)
|
|
20
|
+
qhboxlayout.add_widget(QLabel.new("Password Stores"))
|
|
21
|
+
qhboxlayout.add_stretch
|
|
22
|
+
qhboxlayout.add_widget(btn)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def initialize_tablewidget
|
|
26
|
+
@tablewidget = QWidget.new
|
|
27
|
+
@tablewidget.set_object_name("browsestoresdialog_tablewidget")
|
|
28
|
+
@tablewidget.set_style_sheet("
|
|
29
|
+
#browsestoresdialog_tablewidget {
|
|
30
|
+
min-width: 600px;
|
|
31
|
+
background: white;
|
|
32
|
+
}
|
|
33
|
+
")
|
|
34
|
+
|
|
35
|
+
QVBoxLayout.new(@tablewidget)
|
|
36
|
+
PassQt.settings.GET_stores.each do |store|
|
|
37
|
+
update_tablewidget_addtableitem(store["fullpath"])
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def initialize_layout
|
|
42
|
+
mainlayout = QVBoxLayout.new(self)
|
|
43
|
+
mainlayout.add_stretch
|
|
44
|
+
mainlayout.add_widget(@toolbar)
|
|
45
|
+
mainlayout.add_widget(@tablewidget)
|
|
46
|
+
mainlayout.add_stretch
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def update_tablewidget_addtableitem(fullpath)
|
|
50
|
+
tableitem = QWidget.new
|
|
51
|
+
tableitemlayout = QHBoxLayout.new(tableitem)
|
|
52
|
+
|
|
53
|
+
label = QLabel.new(fullpath)
|
|
54
|
+
tableitemlayout.add_widget(label)
|
|
55
|
+
tableitemlayout.add_stretch
|
|
56
|
+
|
|
57
|
+
btn = QPushButton.new(QIcon.from_theme(QIcon::ThemeIcon::ListRemove), "Remove")
|
|
58
|
+
btn.clicked.connect(self, :_on_list_remove_button_clicked)
|
|
59
|
+
tableitemlayout.add_widget(btn)
|
|
60
|
+
|
|
61
|
+
@dataitems[fullpath] = DataItem.new(tableitem)
|
|
62
|
+
@tablewidget.layout.add_widget(tableitem)
|
|
63
|
+
update_settings_stores
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def update_tablewidget_removetableitem(tableitem)
|
|
67
|
+
@dataitems.delete_if { |_, item| item.tablewidgetitem == tableitem }
|
|
68
|
+
tableitem.delete_now
|
|
69
|
+
update_settings_stores
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def update_settings_stores
|
|
73
|
+
stores = @dataitems.map { |fullpath, _| {"fullpath" => fullpath} }
|
|
74
|
+
PassQt.settings.PUT_stores(stores)
|
|
75
|
+
stores_changed.emit
|
|
76
|
+
end
|
|
77
|
+
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
require_relative "browsestoresdialog/ui"
|
|
2
|
+
|
|
1
3
|
class BrowseStoresDialog < RubyQt6::Bando::QDialog
|
|
2
4
|
DataItem = Struct.new(:tablewidgetitem)
|
|
3
5
|
|
|
@@ -11,77 +13,11 @@ class BrowseStoresDialog < RubyQt6::Bando::QDialog
|
|
|
11
13
|
super
|
|
12
14
|
|
|
13
15
|
@dataitems = {}
|
|
14
|
-
|
|
15
|
-
initialize_toolbar
|
|
16
|
-
initialize_tablewidget
|
|
17
|
-
|
|
18
|
-
mainlayout = QVBoxLayout.new(self)
|
|
19
|
-
mainlayout.add_stretch
|
|
20
|
-
mainlayout.add_widget(@toolbar)
|
|
21
|
-
mainlayout.add_widget(@tablewidget)
|
|
22
|
-
mainlayout.add_stretch
|
|
23
|
-
|
|
24
|
-
set_attribute(Qt::WA_DeleteOnClose)
|
|
25
|
-
set_modal(true)
|
|
16
|
+
initialize_ui
|
|
26
17
|
end
|
|
27
18
|
|
|
28
19
|
private
|
|
29
20
|
|
|
30
|
-
def initialize_toolbar
|
|
31
|
-
@toolbar = QWidget.new
|
|
32
|
-
|
|
33
|
-
btn = QPushButton.new(QIcon.from_theme(QIcon::ThemeIcon::ListAdd), "Add")
|
|
34
|
-
btn.clicked.connect(self, :_on_list_add_button_clicked)
|
|
35
|
-
|
|
36
|
-
qhboxlayout = QHBoxLayout.new(@toolbar)
|
|
37
|
-
qhboxlayout.add_widget(QLabel.new("Password Stores"))
|
|
38
|
-
qhboxlayout.add_stretch
|
|
39
|
-
qhboxlayout.add_widget(btn)
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def initialize_tablewidget
|
|
43
|
-
@tablewidget = QWidget.new
|
|
44
|
-
@tablewidget.set_object_name("browsestoresdialog_tablewidget")
|
|
45
|
-
@tablewidget.set_style_sheet("
|
|
46
|
-
#browsestoresdialog_tablewidget {
|
|
47
|
-
min-width: 600px;
|
|
48
|
-
background: white;
|
|
49
|
-
}
|
|
50
|
-
")
|
|
51
|
-
|
|
52
|
-
QVBoxLayout.new(@tablewidget)
|
|
53
|
-
PassQt.settings.GET_stores.each do |store|
|
|
54
|
-
update_tablewidget_addtableitem(store["fullpath"])
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
def update_tablewidget_addtableitem(fullpath)
|
|
59
|
-
tableitem = QWidget.new
|
|
60
|
-
tableitemlayout = QHBoxLayout.new(tableitem)
|
|
61
|
-
|
|
62
|
-
label = QLabel.new(fullpath)
|
|
63
|
-
tableitemlayout.add_widget(label)
|
|
64
|
-
tableitemlayout.add_stretch
|
|
65
|
-
|
|
66
|
-
btn = QPushButton.new(QIcon.from_theme(QIcon::ThemeIcon::ListRemove), "Remove")
|
|
67
|
-
btn.clicked.connect(self, :_on_list_remove_button_clicked)
|
|
68
|
-
tableitemlayout.add_widget(btn)
|
|
69
|
-
|
|
70
|
-
@dataitems[fullpath] = DataItem.new(tableitem)
|
|
71
|
-
@tablewidget.layout.add_widget(tableitem)
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
def update_tablewidget_removetableitem(tableitem)
|
|
75
|
-
@dataitems.delete_if { |_, item| item.tablewidgetitem == tableitem }
|
|
76
|
-
tableitem.delete_now
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
def update_settings_stores
|
|
80
|
-
stores = @dataitems.map { |fullpath, _| {"fullpath" => fullpath} }
|
|
81
|
-
PassQt.settings.PUT_stores(stores)
|
|
82
|
-
stores_changed.emit
|
|
83
|
-
end
|
|
84
|
-
|
|
85
21
|
def _on_list_add_button_clicked
|
|
86
22
|
dir = QFileDialog.get_existing_directory(self, "", QDir.home_path)
|
|
87
23
|
return if dir.empty?
|
|
@@ -99,11 +35,9 @@ class BrowseStoresDialog < RubyQt6::Bando::QDialog
|
|
|
99
35
|
end
|
|
100
36
|
|
|
101
37
|
update_tablewidget_addtableitem(dir)
|
|
102
|
-
update_settings_stores
|
|
103
38
|
end
|
|
104
39
|
|
|
105
40
|
def _on_list_remove_button_clicked
|
|
106
41
|
update_tablewidget_removetableitem(sender.parent)
|
|
107
|
-
update_settings_stores
|
|
108
42
|
end
|
|
109
43
|
end
|
|
@@ -1,69 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
class PassInfoWidget < RubyQt6::Bando::QWidget
|
|
4
|
-
q_object do
|
|
5
|
-
slot "_on_copy_action_triggered()"
|
|
6
|
-
slot "_on_copy_action_triggered_otpcode()"
|
|
7
|
-
slot "_on_view_action_triggered()"
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
def initialize
|
|
11
|
-
super
|
|
12
|
-
|
|
13
|
-
@store = QString.new
|
|
14
|
-
@passname = QString.new
|
|
1
|
+
class MainWindowPassInfoWidget < RubyQt6::Bando::QWidget
|
|
2
|
+
private
|
|
15
3
|
|
|
4
|
+
def initialize_ui
|
|
16
5
|
initialize_form
|
|
17
6
|
initialize_otpform
|
|
18
7
|
initialize_folderform
|
|
19
8
|
initialize_infoframe
|
|
20
|
-
|
|
21
|
-
@stackedlayout = QStackedLayout.new
|
|
22
|
-
@stackedlayout.add_widget(@form)
|
|
23
|
-
@stackedlayout.add_widget(@otpform)
|
|
24
|
-
@stackedlayout.add_widget(@folderform)
|
|
25
|
-
@stackedlayout.add_widget(@infoframe)
|
|
26
|
-
|
|
27
|
-
mainlayout = QVBoxLayout.new(self)
|
|
28
|
-
mainlayout.add_spacing(76)
|
|
29
|
-
mainlayout.add_layout(@stackedlayout)
|
|
30
|
-
|
|
31
|
-
use_infoframe
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def use_passfilecard(store, passname)
|
|
35
|
-
@store = store
|
|
36
|
-
@passname = passname
|
|
37
|
-
use_infoframe
|
|
38
|
-
|
|
39
|
-
Pass.show(@store, @passname, on_success: ->(data) {
|
|
40
|
-
formdata = Helpers.parse_passfile(data)
|
|
41
|
-
if formdata["password"].start_with?("otpauth:")
|
|
42
|
-
use_otpform(formdata)
|
|
43
|
-
else
|
|
44
|
-
use_form(formdata)
|
|
45
|
-
end
|
|
46
|
-
}, on_failure: ->(data) {
|
|
47
|
-
errinfo = data["stderr"]
|
|
48
|
-
use_infoframe_err(errinfo)
|
|
49
|
-
})
|
|
9
|
+
initialize_layout
|
|
50
10
|
end
|
|
51
11
|
|
|
52
|
-
def use_passfoldercard(store, passname)
|
|
53
|
-
@store = store
|
|
54
|
-
@passname = passname
|
|
55
|
-
use_infoframe
|
|
56
|
-
use_folderform
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def use_infocard
|
|
60
|
-
@store = QString.new
|
|
61
|
-
@passname = QString.new
|
|
62
|
-
use_infoframe
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
private
|
|
66
|
-
|
|
67
12
|
def initialize_form
|
|
68
13
|
@passnameinput = initialize_form_inputfield
|
|
69
14
|
initialize_form_inputfield_copyaction(@passnameinput)
|
|
@@ -94,6 +39,9 @@ class PassInfoWidget < RubyQt6::Bando::QWidget
|
|
|
94
39
|
initialize_form_inputfield_copyaction(@otppasswordinput)
|
|
95
40
|
initialize_form_inputfield_viewaction(@otppasswordinput)
|
|
96
41
|
|
|
42
|
+
@otpaccountinput = initialize_form_inputfield
|
|
43
|
+
initialize_form_inputfield_copyaction(@otpaccountinput)
|
|
44
|
+
|
|
97
45
|
@otpcodeinput = initialize_form_inputfield
|
|
98
46
|
action = @otpcodeinput.add_action(QIcon.from_theme(QIcon::ThemeIcon::EditCopy), QLineEdit::LeadingPosition)
|
|
99
47
|
action.triggered.connect(self, :_on_copy_action_triggered_otpcode)
|
|
@@ -102,7 +50,8 @@ class PassInfoWidget < RubyQt6::Bando::QWidget
|
|
|
102
50
|
otpformlayout = QFormLayout.new(@otpform)
|
|
103
51
|
otpformlayout.add_row(initialize_form_label("File"), @otppassnameinput)
|
|
104
52
|
otpformlayout.add_row(initialize_form_label("OTP URI"), @otppasswordinput)
|
|
105
|
-
otpformlayout.add_row(initialize_form_label("
|
|
53
|
+
otpformlayout.add_row(initialize_form_label("Account"), @otpaccountinput)
|
|
54
|
+
otpformlayout.add_row(initialize_form_label("Code"), @otpcodeinput)
|
|
106
55
|
end
|
|
107
56
|
|
|
108
57
|
def initialize_folderform
|
|
@@ -146,7 +95,19 @@ class PassInfoWidget < RubyQt6::Bando::QWidget
|
|
|
146
95
|
infoframelayout.add_stretch
|
|
147
96
|
end
|
|
148
97
|
|
|
149
|
-
def
|
|
98
|
+
def initialize_layout
|
|
99
|
+
@stackedlayout = QStackedLayout.new
|
|
100
|
+
@stackedlayout.add_widget(@form)
|
|
101
|
+
@stackedlayout.add_widget(@otpform)
|
|
102
|
+
@stackedlayout.add_widget(@folderform)
|
|
103
|
+
@stackedlayout.add_widget(@infoframe)
|
|
104
|
+
|
|
105
|
+
mainlayout = QVBoxLayout.new(self)
|
|
106
|
+
mainlayout.add_spacing(76)
|
|
107
|
+
mainlayout.add_layout(@stackedlayout)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def activate_form(formdata)
|
|
150
111
|
@passnameinput.set_text(@passname)
|
|
151
112
|
@passwordinput.set_text(formdata["password"])
|
|
152
113
|
@passwordinput.set_echo_mode(QLineEdit::Password)
|
|
@@ -156,12 +117,16 @@ class PassInfoWidget < RubyQt6::Bando::QWidget
|
|
|
156
117
|
@stackedlayout.set_current_widget(@form)
|
|
157
118
|
end
|
|
158
119
|
|
|
159
|
-
def
|
|
120
|
+
def activate_otpform(formdata)
|
|
160
121
|
@otppassnameinput.set_text(@passname)
|
|
161
122
|
@otppasswordinput.set_text(formdata["password"])
|
|
162
123
|
@otppasswordinput.set_cursor_position(0)
|
|
163
124
|
@otppasswordinput.set_echo_mode(QLineEdit::Password)
|
|
164
125
|
|
|
126
|
+
label = QUrl.new(formdata["password"]).path.to_s[1..]
|
|
127
|
+
account = label.split(":")[-1]
|
|
128
|
+
@otpaccountinput.set_text(account)
|
|
129
|
+
|
|
165
130
|
@otpcodeinput.set_text("")
|
|
166
131
|
@stackedlayout.set_current_widget(@otpform)
|
|
167
132
|
|
|
@@ -171,42 +136,20 @@ class PassInfoWidget < RubyQt6::Bando::QWidget
|
|
|
171
136
|
}, on_failure: ->(_) {})
|
|
172
137
|
end
|
|
173
138
|
|
|
174
|
-
def
|
|
139
|
+
def activate_folderform
|
|
175
140
|
@folderpassnameinput.set_text(@passname)
|
|
176
141
|
@stackedlayout.set_current_widget(@folderform)
|
|
177
142
|
end
|
|
178
143
|
|
|
179
|
-
def
|
|
144
|
+
def activate_infoframe(info = "")
|
|
180
145
|
@infolabel.set_style_sheet("color: black;")
|
|
181
146
|
@infolabel.set_text(info)
|
|
182
147
|
@stackedlayout.set_current_widget(@infoframe)
|
|
183
148
|
end
|
|
184
149
|
|
|
185
|
-
def
|
|
150
|
+
def activate_infoframe_err(info)
|
|
186
151
|
@infolabel.set_style_sheet("color: red;")
|
|
187
152
|
@infolabel.set_text(info)
|
|
188
153
|
@stackedlayout.set_current_widget(@infoframe)
|
|
189
154
|
end
|
|
190
|
-
|
|
191
|
-
def _on_copy_action_triggered
|
|
192
|
-
input = sender.parent
|
|
193
|
-
QApplication.clipboard.set_text(input.text)
|
|
194
|
-
end
|
|
195
|
-
|
|
196
|
-
def _on_copy_action_triggered_otpcode
|
|
197
|
-
Pass.otp(@store, @passname, on_success: ->(data) {
|
|
198
|
-
otpcode = data["stdout"].rstrip
|
|
199
|
-
@otpcodeinput.set_text(otpcode)
|
|
200
|
-
QApplication.clipboard.set_text(otpcode)
|
|
201
|
-
}, on_failure: ->(_) {})
|
|
202
|
-
end
|
|
203
|
-
|
|
204
|
-
def _on_view_action_triggered
|
|
205
|
-
input = sender.parent
|
|
206
|
-
case input.echo_mode
|
|
207
|
-
when QLineEdit::Normal then input.set_echo_mode(QLineEdit::Password)
|
|
208
|
-
when QLineEdit::Password then input.set_echo_mode(QLineEdit::Normal)
|
|
209
|
-
else raise "unreachable!"
|
|
210
|
-
end
|
|
211
|
-
end
|
|
212
155
|
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
require_relative "passinfowidget/helpers"
|
|
2
|
+
require_relative "passinfowidget/ui"
|
|
3
|
+
|
|
4
|
+
class MainWindowPassInfoWidget < RubyQt6::Bando::QWidget
|
|
5
|
+
q_object do
|
|
6
|
+
slot "activate_passfilecard(QString,QString)"
|
|
7
|
+
slot "activate_passfoldercard(QString,QString)"
|
|
8
|
+
slot "activate_infocard()"
|
|
9
|
+
slot "_on_copy_action_triggered()"
|
|
10
|
+
slot "_on_copy_action_triggered_otpcode()"
|
|
11
|
+
slot "_on_view_action_triggered()"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def initialize
|
|
15
|
+
super
|
|
16
|
+
|
|
17
|
+
initialize_ui
|
|
18
|
+
activate_infocard
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def activate_passfilecard(store, passname)
|
|
24
|
+
@store = store
|
|
25
|
+
@passname = passname
|
|
26
|
+
activate_infoframe
|
|
27
|
+
|
|
28
|
+
Pass.show(@store, @passname, on_success: ->(data) {
|
|
29
|
+
formdata = Helpers.parse_passfile(data)
|
|
30
|
+
if formdata["password"].start_with?("otpauth:")
|
|
31
|
+
activate_otpform(formdata)
|
|
32
|
+
else
|
|
33
|
+
activate_form(formdata)
|
|
34
|
+
end
|
|
35
|
+
}, on_failure: ->(data) {
|
|
36
|
+
errinfo = data["stderr"]
|
|
37
|
+
activate_infoframe_err(errinfo)
|
|
38
|
+
})
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def activate_passfoldercard(store, passname)
|
|
42
|
+
@store = store
|
|
43
|
+
@passname = passname
|
|
44
|
+
activate_infoframe
|
|
45
|
+
activate_folderform
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def activate_infocard
|
|
49
|
+
@store = QString.new
|
|
50
|
+
@passname = QString.new
|
|
51
|
+
activate_infoframe
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def _on_copy_action_triggered
|
|
55
|
+
input = sender.parent
|
|
56
|
+
QApplication.clipboard.set_text(input.text)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def _on_copy_action_triggered_otpcode
|
|
60
|
+
Pass.otp(@store, @passname, on_success: ->(data) {
|
|
61
|
+
otpcode = data["stdout"].rstrip
|
|
62
|
+
@otpcodeinput.set_text(otpcode)
|
|
63
|
+
QApplication.clipboard.set_text(otpcode)
|
|
64
|
+
}, on_failure: ->(_) {})
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def _on_view_action_triggered
|
|
68
|
+
input = sender.parent
|
|
69
|
+
case input.echo_mode
|
|
70
|
+
when QLineEdit::Normal then input.set_echo_mode(QLineEdit::Password)
|
|
71
|
+
when QLineEdit::Password then input.set_echo_mode(QLineEdit::Normal)
|
|
72
|
+
else raise "unreachable!"
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
class MainWindowPassListWidget < RubyQt6::Bando::QWidget
|
|
2
|
+
class TreeWidget < RubyQt6::Bando::QTreeWidget
|
|
3
|
+
private
|
|
4
|
+
|
|
5
|
+
def initialize_actions
|
|
6
|
+
@new_password_action = initialize_actions_act(QIcon::ThemeIcon::DocumentNew, "New Password", :_on_new_password_action_triggered)
|
|
7
|
+
@new_otp_action = initialize_actions_act(QIcon::ThemeIcon::DocumentNew, "New OTP", :_on_new_otp_action_triggered)
|
|
8
|
+
@delete_action = initialize_actions_act(QIcon::ThemeIcon::EditDelete, "Delete", :_on_delete_action_triggered)
|
|
9
|
+
@refresh_action = initialize_actions_act(QIcon::ThemeIcon::ViewRefresh, "Refresh", :_on_refresh_action_triggered)
|
|
10
|
+
@open_action = initialize_actions_act(QIcon::ThemeIcon::FolderVisiting, "Open Store With File Explorer", :_on_open_action_triggered)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def initialize_actions_act(icon, text, slot)
|
|
14
|
+
action = QAction.new(QIcon.from_theme(icon), text, self)
|
|
15
|
+
action.triggered.connect(self, slot)
|
|
16
|
+
action
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def initialize_context_menu
|
|
20
|
+
menu = QMenu.new("", self)
|
|
21
|
+
menu.set_attribute(Qt::WA_DeleteOnClose)
|
|
22
|
+
|
|
23
|
+
menu.add_action(@new_password_action)
|
|
24
|
+
menu.add_action(@new_otp_action)
|
|
25
|
+
menu.add_action(@delete_action)
|
|
26
|
+
menu.add_separator
|
|
27
|
+
menu.add_action(@refresh_action)
|
|
28
|
+
menu.add_action(@open_action)
|
|
29
|
+
|
|
30
|
+
enabled = !selected_items.empty?
|
|
31
|
+
@delete_action.set_enabled(enabled)
|
|
32
|
+
|
|
33
|
+
menu
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
data/lib/pass-qt/app/{components → views/mainwindow/components}/passlistwidget/treewidget.rb
RENAMED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
require_relative "treewidget/helpers"
|
|
2
2
|
require_relative "treewidget/treebuilder"
|
|
3
3
|
require_relative "treewidget/treefilter"
|
|
4
|
+
require_relative "treewidget/ui"
|
|
4
5
|
|
|
5
|
-
class
|
|
6
|
+
class MainWindowPassListWidget < RubyQt6::Bando::QWidget
|
|
6
7
|
class TreeWidget < RubyQt6::Bando::QTreeWidget
|
|
7
8
|
q_object do
|
|
8
9
|
signal "nil_selected(QString)"
|
|
@@ -23,25 +24,11 @@ class PassListWidget < RubyQt6::Bando::QWidget
|
|
|
23
24
|
@dataitems = {}
|
|
24
25
|
|
|
25
26
|
initialize_actions
|
|
26
|
-
|
|
27
27
|
current_item_changed.connect(self, :_on_current_item_changed)
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
def context_menu_event(evt)
|
|
31
|
-
menu =
|
|
32
|
-
menu.set_attribute(Qt::WA_DeleteOnClose)
|
|
33
|
-
|
|
34
|
-
menu.add_action(@new_password_action)
|
|
35
|
-
menu.add_action(@new_otp_action)
|
|
36
|
-
menu.add_action(@delete_action)
|
|
37
|
-
|
|
38
|
-
menu.add_separator
|
|
39
|
-
menu.add_action(@refresh_action)
|
|
40
|
-
menu.add_action(@open_action)
|
|
41
|
-
|
|
42
|
-
enabled = !selected_items.empty?
|
|
43
|
-
@delete_action.set_enabled(enabled)
|
|
44
|
-
|
|
31
|
+
menu = initialize_context_menu
|
|
45
32
|
menu.exec(evt.global_pos)
|
|
46
33
|
end
|
|
47
34
|
|
|
@@ -71,20 +58,6 @@ class PassListWidget < RubyQt6::Bando::QWidget
|
|
|
71
58
|
|
|
72
59
|
private
|
|
73
60
|
|
|
74
|
-
def initialize_actions
|
|
75
|
-
@new_password_action = initialize_actions_act(QIcon::ThemeIcon::DocumentNew, "New Password", :_on_new_password_action_triggered)
|
|
76
|
-
@new_otp_action = initialize_actions_act(QIcon::ThemeIcon::DocumentNew, "New OTP", :_on_new_otp_action_triggered)
|
|
77
|
-
@delete_action = initialize_actions_act(QIcon::ThemeIcon::EditDelete, "Delete", :_on_delete_action_triggered)
|
|
78
|
-
@refresh_action = initialize_actions_act(QIcon::ThemeIcon::ViewRefresh, "Refresh", :_on_refresh_action_triggered)
|
|
79
|
-
@open_action = initialize_actions_act(QIcon::ThemeIcon::FolderVisiting, "Open Store With File Explorer", :_on_open_action_triggered)
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
def initialize_actions_act(icon, text, slot)
|
|
83
|
-
action = QAction.new(QIcon.from_theme(icon), text, self)
|
|
84
|
-
action.triggered.connect(self, slot)
|
|
85
|
-
action
|
|
86
|
-
end
|
|
87
|
-
|
|
88
61
|
def _on_current_item_changed(curr, _prev)
|
|
89
62
|
if curr.nil?
|
|
90
63
|
nil_selected.emit(@store)
|
|
@@ -1,42 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
class PassListWidget < RubyQt6::Bando::QWidget
|
|
4
|
-
q_object do
|
|
5
|
-
signal "store_changed(QString)"
|
|
6
|
-
signal "nil_selected(QString)"
|
|
7
|
-
signal "passfile_selected(QString,QString)"
|
|
8
|
-
signal "passfolder_selected(QString,QString)"
|
|
9
|
-
slot "_on_combobox_current_text_changed(QString)"
|
|
10
|
-
slot "_on_searchbar_text_changed(QString)"
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def initialize
|
|
14
|
-
super
|
|
1
|
+
class MainWindowPassListWidget < RubyQt6::Bando::QWidget
|
|
2
|
+
private
|
|
15
3
|
|
|
4
|
+
def initialize_ui
|
|
16
5
|
initialize_combobox
|
|
17
6
|
initialize_searchbar
|
|
18
7
|
initialize_treewidget
|
|
8
|
+
initialize_layout
|
|
19
9
|
|
|
20
|
-
|
|
21
|
-
mainlayout.add_layout(@comboboxlayout)
|
|
22
|
-
mainlayout.add_widget(@searchbar)
|
|
23
|
-
mainlayout.add_widget(@treewidget)
|
|
24
|
-
|
|
25
|
-
update_combobox
|
|
10
|
+
update_combobox_using_settings_stores
|
|
26
11
|
end
|
|
27
12
|
|
|
28
|
-
def refresh
|
|
29
|
-
@combobox.block_signals(true).tap do |blocked|
|
|
30
|
-
@combobox.clear
|
|
31
|
-
ensure
|
|
32
|
-
@combobox.block_signals(blocked)
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
update_combobox
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
private
|
|
39
|
-
|
|
40
13
|
def initialize_combobox
|
|
41
14
|
@combobox = QComboBox.new
|
|
42
15
|
@combobox.current_text_changed.connect(self, :_on_combobox_current_text_changed)
|
|
@@ -63,24 +36,17 @@ class PassListWidget < RubyQt6::Bando::QWidget
|
|
|
63
36
|
@treewidget.passfolder_selected.connect(self, :passfolder_selected)
|
|
64
37
|
end
|
|
65
38
|
|
|
66
|
-
def
|
|
39
|
+
def initialize_layout
|
|
40
|
+
mainlayout = QVBoxLayout.new(self)
|
|
41
|
+
mainlayout.add_layout(@comboboxlayout)
|
|
42
|
+
mainlayout.add_widget(@searchbar)
|
|
43
|
+
mainlayout.add_widget(@treewidget)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def update_combobox_using_settings_stores
|
|
67
47
|
PassQt.settings.GET_stores.each do |store|
|
|
68
48
|
fileinfo = QFileInfo.new(store["fullpath"])
|
|
69
49
|
@combobox.add_item(fileinfo.file_name, QVariant.new(fileinfo.absolute_file_path))
|
|
70
50
|
end
|
|
71
51
|
end
|
|
72
|
-
|
|
73
|
-
def _on_combobox_current_text_changed(_text)
|
|
74
|
-
store = @combobox.current_data.value
|
|
75
|
-
store_changed.emit(store)
|
|
76
|
-
|
|
77
|
-
@searchbar.clear
|
|
78
|
-
QTimer.single_shot(0, @searchbar, :set_focus)
|
|
79
|
-
|
|
80
|
-
@treewidget.refresh(store)
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
def _on_searchbar_text_changed(text)
|
|
84
|
-
@treewidget.update_passname_filter(text)
|
|
85
|
-
end
|
|
86
52
|
end
|