ruby-pass-qt 2.0.0 → 2.0.1

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.
@@ -1,243 +1,241 @@
1
- module PassQt
2
- class PassListWidget < RubyQt6::Bando::QWidget
3
- class TreeWidget < RubyQt6::Bando::QTreeWidget
4
- DataItem = Struct.new(:passname, :treewidgetitem)
5
-
6
- q_object do
7
- signal "store_changed(QString)"
8
- signal "passfile_selected(QString,QString)"
9
- signal "passfolder_selected(QString,QString)"
10
- slot "_on_item_clicked(QTreeWidgetItem*,int)"
11
- slot "_on_new_password_action_triggered()"
12
- slot "_on_new_otp_action_triggered()"
13
- slot "_on_delete_action_triggered()"
14
- slot "_on_refresh_action_triggered()"
15
- slot "_on_open_action_triggered()"
16
- end
1
+ class PassListWidget < RubyQt6::Bando::QWidget
2
+ class TreeWidget < RubyQt6::Bando::QTreeWidget
3
+ DataItem = Struct.new(:passname, :treewidgetitem)
4
+
5
+ q_object do
6
+ signal "store_changed(QString)"
7
+ signal "passfile_selected(QString,QString)"
8
+ signal "passfolder_selected(QString,QString)"
9
+ slot "_on_item_clicked(QTreeWidgetItem*,int)"
10
+ slot "_on_new_password_action_triggered()"
11
+ slot "_on_new_otp_action_triggered()"
12
+ slot "_on_delete_action_triggered()"
13
+ slot "_on_refresh_action_triggered()"
14
+ slot "_on_open_action_triggered()"
15
+ end
17
16
 
18
- def initialize
19
- super
17
+ def initialize
18
+ super
20
19
 
21
- @store = QString.new
22
- @dataitems = {}
20
+ @store = QString.new
21
+ @dataitems = {}
23
22
 
24
- initialize_actions
25
- initialize_fileiconprovider
23
+ initialize_actions
24
+ initialize_fileiconprovider
26
25
 
27
- item_clicked.connect(self, :_on_item_clicked)
28
- end
26
+ item_clicked.connect(self, :_on_item_clicked)
27
+ end
29
28
 
30
- def context_menu_event(evt)
31
- menu = QMenu.new("", self)
29
+ def context_menu_event(evt)
30
+ menu = QMenu.new("", self)
32
31
 
33
- menu.add_action(@new_password_action)
34
- menu.add_action(@new_otp_action)
35
- menu.add_action(@delete_action)
32
+ menu.add_action(@new_password_action)
33
+ menu.add_action(@new_otp_action)
34
+ menu.add_action(@delete_action)
36
35
 
37
- menu.add_separator
38
- menu.add_action(@refresh_action)
39
- menu.add_action(@open_action)
36
+ menu.add_separator
37
+ menu.add_action(@refresh_action)
38
+ menu.add_action(@open_action)
40
39
 
41
- enabled = !selected_items.empty?
42
- @delete_action.set_enabled(enabled)
40
+ enabled = !selected_items.empty?
41
+ @delete_action.set_enabled(enabled)
43
42
 
44
- menu.exec(evt.global_pos)
45
- end
43
+ menu.exec(evt.global_pos)
44
+ end
46
45
 
47
- def reinitialize_store(store)
48
- clear
49
-
50
- @store = store
51
- @dataitems = {}
52
-
53
- store_root_path = QDir.new(@store)
54
- dirs = [store]
55
- until dirs.empty?
56
- dir = dirs.shift
57
- diritem = @dataitems[dir]&.treewidgetitem || invisible_root_item
58
-
59
- entry_list = QDir.new(dir).entry_info_list(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot)
60
- entry_list.each do |entry|
61
- next if entry.hidden?
62
- next if entry.file_name.starts_with(".")
63
-
64
- filepath = entry.absolute_file_path
65
- next if @dataitems.key?(filepath)
66
-
67
- if entry.dir?
68
- dirs << filepath
69
- passname = store_root_path.relative_file_path(filepath)
70
- elsif entry.file?
71
- next unless h_passfile?(entry)
72
- passname = store_root_path.relative_file_path(filepath)
73
- passname = passname[0, passname.size - entry.suffix.size - 1]
74
- else
75
- next
76
- end
77
-
78
- item = QTreeWidgetItem.new(diritem, QStringList.new << entry.complete_base_name << filepath)
79
- item.set_icon(0, @fileiconprovider.icon(entry))
80
- @dataitems[filepath] = DataItem.new(passname, item)
46
+ def reinitialize_store(store)
47
+ clear
48
+
49
+ @store = store
50
+ @dataitems = {}
51
+
52
+ store_root_path = QDir.new(@store)
53
+ dirs = [store]
54
+ until dirs.empty?
55
+ dir = dirs.shift
56
+ diritem = @dataitems[dir]&.treewidgetitem || invisible_root_item
57
+
58
+ entry_list = QDir.new(dir).entry_info_list(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot)
59
+ entry_list.each do |entry|
60
+ next if entry.hidden?
61
+ next if entry.file_name.starts_with(".")
62
+
63
+ filepath = entry.absolute_file_path
64
+ next if @dataitems.key?(filepath)
65
+
66
+ if entry.dir?
67
+ dirs << filepath
68
+ passname = store_root_path.relative_file_path(filepath)
69
+ elsif entry.file?
70
+ next unless h_passfile?(entry)
71
+ passname = store_root_path.relative_file_path(filepath)
72
+ passname = passname[0, passname.size - entry.suffix.size - 1]
73
+ else
74
+ next
81
75
  end
82
- end
83
76
 
84
- expand_all
85
- store_changed.emit(@store)
77
+ item = QTreeWidgetItem.new(diritem, QStringList.new << entry.complete_base_name << filepath)
78
+ item.set_icon(0, @fileiconprovider.icon(entry))
79
+ @dataitems[filepath] = DataItem.new(passname, item)
80
+ end
86
81
  end
87
82
 
88
- def update_passname_filter(text)
89
- if text.empty?
90
- @dataitems.each do |_, item|
91
- item.treewidgetitem.set_hidden(false)
92
- item.treewidgetitem.set_selected(false)
93
- end
94
- return
83
+ expand_all
84
+ store_changed.emit(@store)
85
+ end
86
+
87
+ def update_passname_filter(text)
88
+ if text.empty?
89
+ @dataitems.each do |_, item|
90
+ item.treewidgetitem.set_hidden(false)
91
+ item.treewidgetitem.set_selected(false)
95
92
  end
93
+ return
94
+ end
96
95
 
97
- re_options = QRegularExpression::UnanchoredWildcardConversion | QRegularExpression::NonPathWildcardConversion
98
- re = QRegularExpression.from_wildcard(text, nil, re_options)
96
+ re_options = QRegularExpression::UnanchoredWildcardConversion | QRegularExpression::NonPathWildcardConversion
97
+ re = QRegularExpression.from_wildcard(text, nil, re_options)
99
98
 
100
- filepath_matched = Set.new
101
- filepath_matched_1st = nil
102
- @dataitems.each do |filepath, item|
103
- has_match = re.match(item.passname).has_match
104
- next unless has_match
99
+ filepath_matched = Set.new
100
+ filepath_matched_1st = nil
101
+ @dataitems.each do |filepath, item|
102
+ has_match = re.match(item.passname).has_match
103
+ next unless has_match
105
104
 
106
- if filepath_matched_1st.nil?
107
- filepath_matched_1st = filepath if h_passfile?(filepath)
108
- end
109
-
110
- loop do
111
- filepath_matched << filepath
112
- filepath = QFileInfo.new(filepath).absolute_path
113
- break unless @dataitems.key?(filepath)
114
- end
105
+ if filepath_matched_1st.nil?
106
+ filepath_matched_1st = filepath if h_passfile?(filepath)
115
107
  end
116
108
 
117
- @dataitems.each do |filepath, item|
118
- visible = filepath_matched.include?(filepath)
119
- item.treewidgetitem.set_hidden(!visible)
120
-
121
- selected = filepath_matched_1st == filepath
122
- item.treewidgetitem.set_selected(selected)
109
+ loop do
110
+ filepath_matched << filepath
111
+ filepath = QFileInfo.new(filepath).absolute_path
112
+ break unless @dataitems.key?(filepath)
123
113
  end
124
114
  end
125
115
 
126
- private
116
+ @dataitems.each do |filepath, item|
117
+ visible = filepath_matched.include?(filepath)
118
+ item.treewidgetitem.set_hidden(!visible)
127
119
 
128
- def initialize_actions
129
- @new_password_action = initialize_actions_act(QIcon::ThemeIcon::DocumentNew, "New Password", :_on_new_password_action_triggered)
130
- @new_otp_action = initialize_actions_act(QIcon::ThemeIcon::DocumentNew, "New OTP", :_on_new_otp_action_triggered)
131
- @delete_action = initialize_actions_act(QIcon::ThemeIcon::EditDelete, "Delete", :_on_delete_action_triggered)
132
- @refresh_action = initialize_actions_act(QIcon::ThemeIcon::ViewRefresh, "Refresh", :_on_refresh_action_triggered)
133
- @open_action = initialize_actions_act(QIcon::ThemeIcon::FolderVisiting, "Open Store With File Explorer", :_on_open_action_triggered)
120
+ selected = filepath_matched_1st == filepath
121
+ item.treewidgetitem.set_selected(selected)
134
122
  end
123
+ end
135
124
 
136
- def initialize_actions_act(icon, text, slot)
137
- action = QAction.new(QIcon.from_theme(icon), text, self)
138
- action.triggered.connect(self, slot)
139
- action
140
- end
125
+ private
141
126
 
142
- def initialize_fileiconprovider
143
- @fileiconprovider = QFileIconProvider.new
144
- end
127
+ def initialize_actions
128
+ @new_password_action = initialize_actions_act(QIcon::ThemeIcon::DocumentNew, "New Password", :_on_new_password_action_triggered)
129
+ @new_otp_action = initialize_actions_act(QIcon::ThemeIcon::DocumentNew, "New OTP", :_on_new_otp_action_triggered)
130
+ @delete_action = initialize_actions_act(QIcon::ThemeIcon::EditDelete, "Delete", :_on_delete_action_triggered)
131
+ @refresh_action = initialize_actions_act(QIcon::ThemeIcon::ViewRefresh, "Refresh", :_on_refresh_action_triggered)
132
+ @open_action = initialize_actions_act(QIcon::ThemeIcon::FolderVisiting, "Open Store With File Explorer", :_on_open_action_triggered)
133
+ end
145
134
 
146
- def reinitialize(selected_passname: "")
147
- reinitialize_store(@store)
135
+ def initialize_actions_act(icon, text, slot)
136
+ action = QAction.new(QIcon.from_theme(icon), text, self)
137
+ action.triggered.connect(self, slot)
138
+ action
139
+ end
148
140
 
149
- @dataitems.each do |_, item|
150
- if item.passname == selected_passname
151
- item.treewidgetitem.set_selected(true)
152
- break
153
- end
154
- end
155
- end
141
+ def initialize_fileiconprovider
142
+ @fileiconprovider = QFileIconProvider.new
143
+ end
156
144
 
157
- def h_passfile?(fileinfo)
158
- case fileinfo
159
- when QFileInfo then fileinfo.suffix.downcase == "gpg"
160
- when QString then fileinfo.ends_with(".gpg", Qt::CaseInsensitive)
161
- else raise "unreachable!"
145
+ def reinitialize(selected_passname: "")
146
+ reinitialize_store(@store)
147
+
148
+ @dataitems.each do |_, item|
149
+ if item.passname == selected_passname
150
+ item.treewidgetitem.set_selected(true)
151
+ break
162
152
  end
163
153
  end
154
+ end
164
155
 
165
- def h_folderpath(fileinfo)
166
- folder = fileinfo.dir? ? fileinfo.absolute_file_path : fileinfo.absolute_path
167
- QDir.new(@store).relative_file_path(folder)
156
+ def h_passfile?(fileinfo)
157
+ case fileinfo
158
+ when QFileInfo then fileinfo.suffix.downcase == "gpg"
159
+ when QString then fileinfo.ends_with(".gpg", Qt::CaseInsensitive)
160
+ else raise "unreachable!"
168
161
  end
162
+ end
169
163
 
170
- def _on_item_clicked(item, _column)
171
- filepath = item.data(1, Qt::DisplayRole).value
172
- dataitem = @dataitems[filepath]
173
- h_passfile?(filepath) ?
174
- passfile_selected.emit(@store, dataitem.passname) :
175
- passfolder_selected.emit(@store, dataitem.passname)
176
- end
164
+ def h_folderpath(fileinfo)
165
+ folder = fileinfo.dir? ? fileinfo.absolute_file_path : fileinfo.absolute_path
166
+ QDir.new(@store).relative_file_path(folder)
167
+ end
177
168
 
178
- def _on_new_password_action_triggered
179
- item = selected_items[0]
180
- if item
181
- filepath = item.data(1, Qt::DisplayRole).value
182
- folder = h_folderpath(QFileInfo.new(filepath))
183
- folder = "" if folder == "."
184
- else
185
- folder = ""
186
- end
169
+ def _on_item_clicked(item, _column)
170
+ filepath = item.data(1, Qt::DisplayRole).value
171
+ dataitem = @dataitems[filepath]
172
+ h_passfile?(filepath) ?
173
+ passfile_selected.emit(@store, dataitem.passname) :
174
+ passfolder_selected.emit(@store, dataitem.passname)
175
+ end
187
176
 
188
- dialog = NewPasswordDialog.new(@store, folder, on_success: ->(passname) {
189
- reinitialize(selected_passname: passname)
190
- })
191
- dialog.show
177
+ def _on_new_password_action_triggered
178
+ item = selected_items[0]
179
+ if item
180
+ filepath = item.data(1, Qt::DisplayRole).value
181
+ folder = h_folderpath(QFileInfo.new(filepath))
182
+ folder = "" if folder == "."
183
+ else
184
+ folder = ""
192
185
  end
193
186
 
194
- def _on_new_otp_action_triggered
195
- item = selected_items[0]
196
- if item
197
- filepath = item.data(1, Qt::DisplayRole).value
198
- folder = h_folderpath(QFileInfo.new(filepath))
199
- folder = "" if folder == "."
200
- else
201
- folder = ""
202
- end
187
+ dialog = NewPasswordDialog.new(@store, folder, on_success: ->(passname) {
188
+ reinitialize(selected_passname: passname)
189
+ })
190
+ dialog.show
191
+ end
203
192
 
204
- dialog = NewOneTimePasswordDialog.new(@store, folder, on_success: ->(passname) {
205
- reinitialize(selected_passname: passname)
206
- })
207
- dialog.show
193
+ def _on_new_otp_action_triggered
194
+ item = selected_items[0]
195
+ if item
196
+ filepath = item.data(1, Qt::DisplayRole).value
197
+ folder = h_folderpath(QFileInfo.new(filepath))
198
+ folder = "" if folder == "."
199
+ else
200
+ folder = ""
208
201
  end
209
202
 
210
- def _on_delete_action_triggered
211
- item = selected_items[0]
212
- filepath = item.data(1, Qt::DisplayRole).value
213
- dataitem = @dataitems[filepath]
203
+ dialog = NewOneTimePasswordDialog.new(@store, folder, on_success: ->(passname) {
204
+ reinitialize(selected_passname: passname)
205
+ })
206
+ dialog.show
207
+ end
214
208
 
215
- message = "<p>Do you really want to delete this item?</p>#{dataitem.passname}"
216
- reply = QMessageBox.question(self, "", message)
217
- return if reply == QMessageBox::No
209
+ def _on_delete_action_triggered
210
+ item = selected_items[0]
211
+ filepath = item.data(1, Qt::DisplayRole).value
212
+ dataitem = @dataitems[filepath]
218
213
 
219
- file = QFile.new(filepath)
220
- file.move_to_trash
221
- reinitialize
222
- end
214
+ message = "<p>Do you really want to delete this item?</p>#{dataitem.passname}"
215
+ reply = QMessageBox.question(self, "", message)
216
+ return if reply == QMessageBox::No
223
217
 
224
- def _on_refresh_action_triggered
225
- item = selected_items[0]
226
- if item
227
- filepath = item.data(1, Qt::DisplayRole).value
228
- dataitem = @dataitems[filepath]
229
- passname = dataitem.passname
230
- else
231
- passname = ""
232
- end
218
+ file = QFile.new(filepath)
219
+ file.move_to_trash
220
+ reinitialize
221
+ end
233
222
 
234
- reinitialize(selected_passname: passname)
223
+ def _on_refresh_action_triggered
224
+ item = selected_items[0]
225
+ if item
226
+ filepath = item.data(1, Qt::DisplayRole).value
227
+ dataitem = @dataitems[filepath]
228
+ passname = dataitem.passname
229
+ else
230
+ passname = ""
235
231
  end
236
232
 
237
- def _on_open_action_triggered
238
- url = QUrl.from_local_file(@store)
239
- QDesktopServices.open_url(url)
240
- end
233
+ reinitialize(selected_passname: passname)
234
+ end
235
+
236
+ def _on_open_action_triggered
237
+ url = QUrl.from_local_file(@store)
238
+ QDesktopServices.open_url(url)
241
239
  end
242
240
  end
243
241
  end
@@ -1,91 +1,89 @@
1
1
  require_relative "passlistwidget/treewidget"
2
2
 
3
- module PassQt
4
- class PassListWidget < RubyQt6::Bando::QWidget
5
- q_object do
6
- signal "store_changed(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
- slot "_on_treewidget_store_changed(QString)"
12
- end
3
+ class PassListWidget < RubyQt6::Bando::QWidget
4
+ q_object do
5
+ signal "store_changed(QString)"
6
+ signal "passfile_selected(QString,QString)"
7
+ signal "passfolder_selected(QString,QString)"
8
+ slot "_on_combobox_current_text_changed(QString)"
9
+ slot "_on_searchbar_text_changed(QString)"
10
+ slot "_on_treewidget_store_changed(QString)"
11
+ end
13
12
 
14
- def initialize
15
- super
13
+ def initialize
14
+ super
16
15
 
17
- initialize_combobox
18
- initialize_searchbar
19
- initialize_treewidget
16
+ initialize_combobox
17
+ initialize_searchbar
18
+ initialize_treewidget
20
19
 
21
- mainlayout = QVBoxLayout.new(self)
22
- mainlayout.add_layout(@comboboxlayout)
23
- mainlayout.add_widget(@searchbar)
24
- mainlayout.add_widget(@treewidget)
20
+ mainlayout = QVBoxLayout.new(self)
21
+ mainlayout.add_layout(@comboboxlayout)
22
+ mainlayout.add_widget(@searchbar)
23
+ mainlayout.add_widget(@treewidget)
25
24
 
26
- update_combobox
27
- end
28
-
29
- def reinitialize_stores
30
- @combobox.block_signals(true).tap do |blocked|
31
- @combobox.clear
32
- ensure
33
- @combobox.block_signals(blocked)
34
- end
25
+ update_combobox
26
+ end
35
27
 
36
- update_combobox
28
+ def reinitialize_stores
29
+ @combobox.block_signals(true).tap do |blocked|
30
+ @combobox.clear
31
+ ensure
32
+ @combobox.block_signals(blocked)
37
33
  end
38
34
 
39
- private
35
+ update_combobox
36
+ end
40
37
 
41
- def initialize_combobox
42
- @combobox = QComboBox.new
43
- @combobox.current_text_changed.connect(self, :_on_combobox_current_text_changed)
38
+ private
44
39
 
45
- @comboboxlayout = QHBoxLayout.new
46
- @comboboxlayout.add_widget(QLabel.new("Current Store"))
47
- @comboboxlayout.add_widget(@combobox)
48
- @comboboxlayout.set_stretch(0, 2)
49
- @comboboxlayout.set_stretch(1, 3)
50
- end
40
+ def initialize_combobox
41
+ @combobox = QComboBox.new
42
+ @combobox.current_text_changed.connect(self, :_on_combobox_current_text_changed)
51
43
 
52
- def initialize_searchbar
53
- @searchbar = QLineEdit.new
54
- @searchbar.set_clear_button_enabled(true)
55
- @searchbar.set_placeholder_text("List passwords that match passname...")
56
- @searchbar.text_changed.connect(self, :_on_searchbar_text_changed)
57
- end
44
+ @comboboxlayout = QHBoxLayout.new
45
+ @comboboxlayout.add_widget(QLabel.new("Current Store"))
46
+ @comboboxlayout.add_widget(@combobox)
47
+ @comboboxlayout.set_stretch(0, 2)
48
+ @comboboxlayout.set_stretch(1, 3)
49
+ end
58
50
 
59
- def initialize_treewidget
60
- @treewidget = TreeWidget.new
61
- @treewidget.set_header_hidden(true)
62
- @treewidget.store_changed.connect(self, :_on_treewidget_store_changed)
63
- @treewidget.passfile_selected.connect(self, :passfile_selected)
64
- @treewidget.passfolder_selected.connect(self, :passfolder_selected)
65
- end
51
+ def initialize_searchbar
52
+ @searchbar = QLineEdit.new
53
+ @searchbar.set_clear_button_enabled(true)
54
+ @searchbar.set_placeholder_text("List passwords that match passname...")
55
+ @searchbar.text_changed.connect(self, :_on_searchbar_text_changed)
56
+ end
57
+
58
+ def initialize_treewidget
59
+ @treewidget = TreeWidget.new
60
+ @treewidget.set_header_hidden(true)
61
+ @treewidget.store_changed.connect(self, :_on_treewidget_store_changed)
62
+ @treewidget.passfile_selected.connect(self, :passfile_selected)
63
+ @treewidget.passfolder_selected.connect(self, :passfolder_selected)
64
+ end
66
65
 
67
- def update_combobox
68
- PassQt.settings.GET_stores.each do |store|
69
- fileinfo = QFileInfo.new(store["fullpath"])
70
- @combobox.add_item(fileinfo.file_name, QVariant.new(fileinfo.absolute_file_path))
71
- end
66
+ def update_combobox
67
+ PassQt.settings.GET_stores.each do |store|
68
+ fileinfo = QFileInfo.new(store["fullpath"])
69
+ @combobox.add_item(fileinfo.file_name, QVariant.new(fileinfo.absolute_file_path))
72
70
  end
71
+ end
73
72
 
74
- def _on_combobox_current_text_changed(_text)
75
- store = @combobox.current_data.value
76
- @treewidget.reinitialize_store(store)
73
+ def _on_combobox_current_text_changed(_text)
74
+ store = @combobox.current_data.value
75
+ @treewidget.reinitialize_store(store)
77
76
 
78
- @searchbar.clear
79
- QTimer.single_shot(0, @searchbar, :set_focus)
80
- end
77
+ @searchbar.clear
78
+ QTimer.single_shot(0, @searchbar, :set_focus)
79
+ end
81
80
 
82
- def _on_searchbar_text_changed(text)
83
- @treewidget.update_passname_filter(text)
84
- end
81
+ def _on_searchbar_text_changed(text)
82
+ @treewidget.update_passname_filter(text)
83
+ end
85
84
 
86
- def _on_treewidget_store_changed(store)
87
- @searchbar.clear
88
- store_changed.emit(store)
89
- end
85
+ def _on_treewidget_store_changed(store)
86
+ @searchbar.clear
87
+ store_changed.emit(store)
90
88
  end
91
89
  end