ruby-pass-qt 1.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,240 +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
- filepath = entry.absolute_file_path
62
- next if @dataitems.key?(filepath)
63
-
64
- if entry.dir?
65
- dirs << filepath
66
- passname = store_root_path.relative_file_path(filepath)
67
- elsif entry.file?
68
- next unless h_passfile?(entry)
69
- passname = store_root_path.relative_file_path(filepath)
70
- passname = passname[0, passname.size - entry.suffix.size - 1]
71
- else
72
- next
73
- end
74
-
75
- item = QTreeWidgetItem.new(diritem, QStringList.new << entry.complete_base_name << filepath)
76
- item.set_icon(0, @fileiconprovider.icon(entry))
77
- @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
78
75
  end
79
- end
80
76
 
81
- expand_all
82
- 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
83
81
  end
84
82
 
85
- def update_passname_filter(text)
86
- if text.empty?
87
- @dataitems.each do |_, item|
88
- item.treewidgetitem.set_hidden(false)
89
- item.treewidgetitem.set_selected(false)
90
- end
91
- 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)
92
92
  end
93
+ return
94
+ end
93
95
 
94
- re_options = QRegularExpression::UnanchoredWildcardConversion | QRegularExpression::NonPathWildcardConversion
95
- re = QRegularExpression.from_wildcard(text, nil, re_options)
96
+ re_options = QRegularExpression::UnanchoredWildcardConversion | QRegularExpression::NonPathWildcardConversion
97
+ re = QRegularExpression.from_wildcard(text, nil, re_options)
96
98
 
97
- filepath_matched = Set.new
98
- filepath_matched_1st = nil
99
- @dataitems.each do |filepath, item|
100
- has_match = re.match(item.passname).has_match
101
- 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
102
104
 
103
- if filepath_matched_1st.nil?
104
- filepath_matched_1st = filepath if h_passfile?(filepath)
105
- end
106
-
107
- loop do
108
- filepath_matched << filepath
109
- filepath = QFileInfo.new(filepath).absolute_path
110
- break unless @dataitems.key?(filepath)
111
- end
105
+ if filepath_matched_1st.nil?
106
+ filepath_matched_1st = filepath if h_passfile?(filepath)
112
107
  end
113
108
 
114
- @dataitems.each do |filepath, item|
115
- visible = filepath_matched.include?(filepath)
116
- item.treewidgetitem.set_hidden(!visible)
117
-
118
- selected = filepath_matched_1st == filepath
119
- 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)
120
113
  end
121
114
  end
122
115
 
123
- private
116
+ @dataitems.each do |filepath, item|
117
+ visible = filepath_matched.include?(filepath)
118
+ item.treewidgetitem.set_hidden(!visible)
124
119
 
125
- def initialize_actions
126
- @new_password_action = initialize_actions_act(QIcon::ThemeIcon::DocumentNew, "New Password", :_on_new_password_action_triggered)
127
- @new_otp_action = initialize_actions_act(QIcon::ThemeIcon::DocumentNew, "New OTP", :_on_new_otp_action_triggered)
128
- @delete_action = initialize_actions_act(QIcon::ThemeIcon::EditDelete, "Delete", :_on_delete_action_triggered)
129
- @refresh_action = initialize_actions_act(QIcon::ThemeIcon::ViewRefresh, "Refresh", :_on_refresh_action_triggered)
130
- @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)
131
122
  end
123
+ end
132
124
 
133
- def initialize_actions_act(icon, text, slot)
134
- action = QAction.new(QIcon.from_theme(icon), text, self)
135
- action.triggered.connect(self, slot)
136
- action
137
- end
125
+ private
138
126
 
139
- def initialize_fileiconprovider
140
- @fileiconprovider = QFileIconProvider.new
141
- 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
142
134
 
143
- def reinitialize(selected_passname: "")
144
- 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
145
140
 
146
- @dataitems.each do |_, item|
147
- if item.passname == selected_passname
148
- item.treewidgetitem.set_selected(true)
149
- break
150
- end
151
- end
152
- end
141
+ def initialize_fileiconprovider
142
+ @fileiconprovider = QFileIconProvider.new
143
+ end
153
144
 
154
- def h_passfile?(fileinfo)
155
- case fileinfo
156
- when QFileInfo then fileinfo.suffix.downcase == "gpg"
157
- when QString then fileinfo.ends_with(".gpg", Qt::CaseInsensitive)
158
- 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
159
152
  end
160
153
  end
154
+ end
161
155
 
162
- def h_folderpath(fileinfo)
163
- folder = fileinfo.dir? ? fileinfo.absolute_file_path : fileinfo.absolute_path
164
- 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!"
165
161
  end
162
+ end
166
163
 
167
- def _on_item_clicked(item, _column)
168
- filepath = item.data(1, Qt::DisplayRole).value
169
- dataitem = @dataitems[filepath]
170
- h_passfile?(filepath) ?
171
- passfile_selected.emit(@store, dataitem.passname) :
172
- passfolder_selected.emit(@store, dataitem.passname)
173
- 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
174
168
 
175
- def _on_new_password_action_triggered
176
- item = selected_items[0]
177
- if item
178
- filepath = item.data(1, Qt::DisplayRole).value
179
- folder = h_folderpath(QFileInfo.new(filepath))
180
- folder = "" if folder == "."
181
- else
182
- folder = ""
183
- 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
184
176
 
185
- dialog = NewPasswordDialog.new(@store, folder, on_success: ->(passname) {
186
- reinitialize(selected_passname: passname)
187
- })
188
- 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 = ""
189
185
  end
190
186
 
191
- def _on_new_otp_action_triggered
192
- item = selected_items[0]
193
- if item
194
- filepath = item.data(1, Qt::DisplayRole).value
195
- folder = h_folderpath(QFileInfo.new(filepath))
196
- folder = "" if folder == "."
197
- else
198
- folder = ""
199
- end
187
+ dialog = NewPasswordDialog.new(@store, folder, on_success: ->(passname) {
188
+ reinitialize(selected_passname: passname)
189
+ })
190
+ dialog.show
191
+ end
200
192
 
201
- dialog = NewOneTimePasswordDialog.new(@store, folder, on_success: ->(passname) {
202
- reinitialize(selected_passname: passname)
203
- })
204
- 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 = ""
205
201
  end
206
202
 
207
- def _on_delete_action_triggered
208
- item = selected_items[0]
209
- filepath = item.data(1, Qt::DisplayRole).value
210
- dataitem = @dataitems[filepath]
203
+ dialog = NewOneTimePasswordDialog.new(@store, folder, on_success: ->(passname) {
204
+ reinitialize(selected_passname: passname)
205
+ })
206
+ dialog.show
207
+ end
211
208
 
212
- message = "<p>Do you really want to delete this item?</p>#{dataitem.passname}"
213
- reply = QMessageBox.question(self, "", message)
214
- 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]
215
213
 
216
- file = QFile.new(filepath)
217
- file.move_to_trash
218
- reinitialize
219
- 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
220
217
 
221
- def _on_refresh_action_triggered
222
- item = selected_items[0]
223
- if item
224
- filepath = item.data(1, Qt::DisplayRole).value
225
- dataitem = @dataitems[filepath]
226
- passname = dataitem.passname
227
- else
228
- passname = ""
229
- end
218
+ file = QFile.new(filepath)
219
+ file.move_to_trash
220
+ reinitialize
221
+ end
230
222
 
231
- 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 = ""
232
231
  end
233
232
 
234
- def _on_open_action_triggered
235
- url = QUrl.from_local_file(@store)
236
- QDesktopServices.open_url(url)
237
- 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)
238
239
  end
239
240
  end
240
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