Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
mat2
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Model registry
Operate
Environments
Monitor
Incidents
Service Desk
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
tails
mat2
Commits
b32ba9f7
Commit
b32ba9f7
authored
6 years ago
by
Julien (jvoisin) Voisin
Browse files
Options
Downloads
Patches
Plain Diff
Improve a bit nautilus' popup
parent
e9f28edf
No related branches found
No related tags found
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
.gitlab-ci.yml
+1
-1
1 addition, 1 deletion
.gitlab-ci.yml
nautilus/nautilus_mat2.py
+57
-34
57 additions, 34 deletions
nautilus/nautilus_mat2.py
with
58 additions
and
35 deletions
.gitlab-ci.yml
+
1
−
1
View file @
b32ba9f7
...
@@ -10,7 +10,7 @@ bandit:
...
@@ -10,7 +10,7 @@ bandit:
-
apt-get -qqy update
-
apt-get -qqy update
-
apt-get -qqy install --no-install-recommends python3-bandit
-
apt-get -qqy install --no-install-recommends python3-bandit
-
bandit ./mat2 --format txt
-
bandit ./mat2 --format txt
-
bandit -r ./nautilus/ --format txt
-
bandit -r ./nautilus/ --format txt
--skip B101
-
bandit -r ./libmat2 --format txt --skip B101,B404,B603,B405,B314
-
bandit -r ./libmat2 --format txt --skip B101,B404,B603,B405,B314
pylint
:
pylint
:
...
...
This diff is collapsed.
Click to expand it.
nautilus/nautilus_mat2.py
+
57
−
34
View file @
b32ba9f7
#!/usr/bin/env python3
#!/usr/bin/env python3
# pylint: disable=unused-argument,arguments-differ,no-self-use,no-name-in-module,import-error
"""
"""
Because writing GUI is non-trivial (cf. https://0xacab.org/jvoisin/mat2/issues/3),
Because writing GUI is non-trivial (cf. https://0xacab.org/jvoisin/mat2/issues/3),
we decided to write a Nautilus extensions instead
we decided to write a Nautilus extensions instead
...
@@ -12,18 +10,24 @@ so we're not allowed to call anything Gtk-related outside of the main
...
@@ -12,18 +10,24 @@ so we're not allowed to call anything Gtk-related outside of the main
thread, so we
'
ll have to resort to using a `queue` to pass
"
messages
"
around.
thread, so we
'
ll have to resort to using a `queue` to pass
"
messages
"
around.
"""
"""
import
os
# pylint: disable=no-name-in-module,unused-argument,no-self-use,import-error
import
queue
import
queue
import
threading
import
threading
from
typing
import
Tuple
from
urllib.parse
import
unquote
from
urllib.parse
import
unquote
import
gi
import
gi
gi
.
require_version
(
'
Nautilus
'
,
'
3.0
'
)
gi
.
require_version
(
'
Nautilus
'
,
'
3.0
'
)
gi
.
require_version
(
'
Gtk
'
,
'
3.0
'
)
gi
.
require_version
(
'
Gtk
'
,
'
3.0
'
)
from
gi.repository
import
Nautilus
,
GObject
,
Gtk
,
Gio
,
GLib
gi
.
require_version
(
'
GdkPixbuf
'
,
'
2.0
'
)
from
gi.repository
import
Nautilus
,
GObject
,
Gtk
,
Gio
,
GLib
,
GdkPixbuf
from
libmat2
import
parser_factory
from
libmat2
import
parser_factory
# make pyflakes happy
assert
Tuple
def
_remove_metadata
(
fpath
):
def
_remove_metadata
(
fpath
):
"""
This is a simple wrapper around libmat2, because it
'
s
"""
This is a simple wrapper around libmat2, because it
'
s
easier and cleaner this way.
easier and cleaner this way.
...
@@ -35,6 +39,7 @@ def _remove_metadata(fpath):
...
@@ -35,6 +39,7 @@ def _remove_metadata(fpath):
class
ColumnExtension
(
GObject
.
GObject
,
Nautilus
.
MenuProvider
,
Nautilus
.
LocationWidgetProvider
):
class
ColumnExtension
(
GObject
.
GObject
,
Nautilus
.
MenuProvider
,
Nautilus
.
LocationWidgetProvider
):
"""
This class adds an item to the right-clic menu in Nautilus.
"""
"""
This class adds an item to the right-clic menu in Nautilus.
"""
def
__init__
(
self
):
def
__init__
(
self
):
super
().
__init__
()
super
().
__init__
()
self
.
infobar_hbox
=
None
self
.
infobar_hbox
=
None
...
@@ -96,38 +101,55 @@ class ColumnExtension(GObject.GObject, Nautilus.MenuProvider, Nautilus.LocationW
...
@@ -96,38 +101,55 @@ class ColumnExtension(GObject.GObject, Nautilus.MenuProvider, Nautilus.LocationW
box
=
Gtk
.
Box
(
orientation
=
Gtk
.
Orientation
.
VERTICAL
)
box
=
Gtk
.
Box
(
orientation
=
Gtk
.
Orientation
.
VERTICAL
)
window
.
add
(
box
)
window
.
add
(
box
)
listbox
=
Gtk
.
ListBox
()
box
.
add
(
self
.
__create_treeview
())
listbox
.
set_selection_mode
(
Gtk
.
SelectionMode
.
NONE
)
window
.
show_all
()
box
.
pack_start
(
listbox
,
True
,
True
,
0
)
for
fname
,
mtype
in
self
.
failed_items
:
row
=
Gtk
.
ListBoxRow
()
hbox
=
Gtk
.
Box
(
orientation
=
Gtk
.
Orientation
.
HORIZONTAL
)
row
.
add
(
hbox
)
icon
=
Gio
.
content_type_get_icon
(
'
text/plain
'
if
not
mtype
else
mtype
)
@staticmethod
select_image
=
Gtk
.
Image
.
new_from_gicon
(
icon
,
Gtk
.
IconSize
.
BUTTON
)
def
__validate
(
fileinfo
)
->
Tuple
[
bool
,
str
]:
hbox
.
pack_start
(
select_image
,
False
,
False
,
0
)
"""
Validate if a given file FileInfo `fileinfo` can be processed.
Returns a boolean, and a textreason why
"""
if
fileinfo
.
get_uri_scheme
()
!=
"
file
"
or
fileinfo
.
is_directory
():
return
False
,
"
Not a file
"
elif
not
fileinfo
.
can_write
():
return
False
,
"
Not writeable
"
return
True
,
""
label
=
Gtk
.
Label
(
os
.
path
.
basename
(
fname
))
hbox
.
pack_start
(
label
,
True
,
False
,
0
)
listbox
.
add
(
row
)
def
__create_treeview
(
self
)
->
Gtk
.
TreeView
:
liststore
=
Gtk
.
ListStore
(
GdkPixbuf
.
Pixbuf
,
str
,
str
)
treeview
=
Gtk
.
TreeView
(
model
=
liststore
)
listbox
.
show_all
()
renderer_pixbuf
=
Gtk
.
CellRendererPixbuf
()
window
.
show_all
()
column_pixbuf
=
Gtk
.
TreeViewColumn
(
"
Image
"
,
renderer_pixbuf
,
pixbuf
=
0
)
treeview
.
append_column
(
column_pixbuf
)
for
idx
,
name
in
enumerate
([
'
Reason
'
,
'
Path
'
]):
renderer_text
=
Gtk
.
CellRendererText
()
column_text
=
Gtk
.
TreeViewColumn
(
name
,
renderer_text
,
text
=
idx
+
1
)
treeview
.
append_column
(
column_text
)
for
(
fname
,
mtype
,
reason
)
in
self
.
failed_items
:
# This part is all about adding mimetype icons to the liststore
icon
=
Gio
.
content_type_get_icon
(
'
text/plain
'
if
not
mtype
else
mtype
)
# in case we don't have the corresponding icon,
# we're adding `text/plain`, because we have this one for sure™
names
=
icon
.
get_names
()
+
[
'
text/plain
'
,
]
icon_theme
=
Gtk
.
IconTheme
.
get_default
()
for
name
in
names
:
try
:
img
=
icon_theme
.
load_icon
(
name
,
Gtk
.
IconSize
.
BUTTON
,
0
)
break
except
GLib
.
GError
:
pass
liststore
.
append
([
img
,
reason
,
fname
])
treeview
.
show_all
()
return
treeview
@staticmethod
def
__validate
(
fileinfo
):
"""
Validate if a given file FileInfo `fileinfo` can be processed.
"""
if
fileinfo
.
get_uri_scheme
()
!=
"
file
"
or
fileinfo
.
is_directory
():
return
False
elif
not
fileinfo
.
can_write
():
return
False
return
True
def
__create_progressbar
(
self
):
def
__create_progressbar
(
self
)
->
Gtk
.
ProgressBar
:
"""
Create the progressbar used to notify that files are currently
"""
Create the progressbar used to notify that files are currently
being processed.
being processed.
"""
"""
...
@@ -144,7 +166,7 @@ class ColumnExtension(GObject.GObject, Nautilus.MenuProvider, Nautilus.LocationW
...
@@ -144,7 +166,7 @@ class ColumnExtension(GObject.GObject, Nautilus.MenuProvider, Nautilus.LocationW
return
progressbar
return
progressbar
def
__update_progressbar
(
self
,
processing_queue
,
progressbar
):
def
__update_progressbar
(
self
,
processing_queue
,
progressbar
)
->
bool
:
"""
This method is run via `Glib.add_idle` to update the progressbar.
"""
"""
This method is run via `Glib.add_idle` to update the progressbar.
"""
try
:
try
:
fname
=
processing_queue
.
get
(
block
=
False
)
fname
=
processing_queue
.
get
(
block
=
False
)
...
@@ -169,7 +191,7 @@ class ColumnExtension(GObject.GObject, Nautilus.MenuProvider, Nautilus.LocationW
...
@@ -169,7 +191,7 @@ class ColumnExtension(GObject.GObject, Nautilus.MenuProvider, Nautilus.LocationW
self
.
infobar
.
show_all
()
self
.
infobar
.
show_all
()
return
True
return
True
def
__clean_files
(
self
,
files
,
processing_queue
)
:
def
__clean_files
(
self
,
files
:
list
,
processing_queue
:
queue
.
Queue
)
->
bool
:
"""
This method is threaded in order to avoid blocking the GUI
"""
This method is threaded in order to avoid blocking the GUI
while cleaning up the files.
while cleaning up the files.
"""
"""
...
@@ -177,14 +199,15 @@ class ColumnExtension(GObject.GObject, Nautilus.MenuProvider, Nautilus.LocationW
...
@@ -177,14 +199,15 @@ class ColumnExtension(GObject.GObject, Nautilus.MenuProvider, Nautilus.LocationW
fname
=
fileinfo
.
get_name
()
fname
=
fileinfo
.
get_name
()
processing_queue
.
put
(
fname
)
processing_queue
.
put
(
fname
)
if
not
self
.
__validate
(
fileinfo
):
valid
,
reason
=
self
.
__validate
(
fileinfo
)
self
.
failed_items
.
append
((
fname
,
None
))
if
not
valid
:
self
.
failed_items
.
append
((
fname
,
None
,
reason
))
continue
continue
fpath
=
unquote
(
fileinfo
.
get_uri
()[
7
:])
# `len('file://') = 7`
fpath
=
unquote
(
fileinfo
.
get_uri
()[
7
:])
# `len('file://') = 7`
success
,
mtype
=
_remove_metadata
(
fpath
)
success
,
mtype
=
_remove_metadata
(
fpath
)
if
not
success
:
if
not
success
:
self
.
failed_items
.
append
((
fname
,
mtype
))
self
.
failed_items
.
append
((
fname
,
mtype
,
'
Unsupported/invalid
'
))
processing_queue
.
put
(
None
)
# signal that we processed all the files
processing_queue
.
put
(
None
)
# signal that we processed all the files
return
True
return
True
...
@@ -215,7 +238,7 @@ class ColumnExtension(GObject.GObject, Nautilus.MenuProvider, Nautilus.LocationW
...
@@ -215,7 +238,7 @@ class ColumnExtension(GObject.GObject, Nautilus.MenuProvider, Nautilus.LocationW
"""
"""
# Do not show the menu item if not a single file has a chance to be
# Do not show the menu item if not a single file has a chance to be
# processed by mat2.
# processed by mat2.
if
not
any
(
map
(
self
.
__validate
,
files
)):
if
not
any
(
[
is_valid
for
(
is_valid
,
_
)
in
map
(
self
.
__validate
,
files
)
]
):
return
None
return
None
item
=
Nautilus
.
MenuItem
(
item
=
Nautilus
.
MenuItem
(
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment