Bringing to latest changes #3
|
@ -1,17 +1,17 @@
|
||||||
### Note
|
### Note
|
||||||
Copy the example and rename it to your desired name. Plugins define a ui target slot with the 'ui_target' permissions data but don't have to if not directly interacted with.
|
Copy the example and rename it to your desired name. Plugins define a ui target slot with the 'ui_target' requests data but don't have to if not directly interacted with.
|
||||||
Plugins must have a run method defined; though, you do not need to necessarily do anything within it. The run method implies that the passed in event system or other data is ready for the plugin to use.
|
Plugins must have a run method defined; though, you do not need to necessarily do anything within it. The run method implies that the passed in event system or other data is ready for the plugin to use.
|
||||||
|
|
||||||
|
|
||||||
### Manifest Example (All are required.)
|
### Manifest Example (All are required even if empty.)
|
||||||
```
|
```
|
||||||
class Manifest:
|
class Manifest:
|
||||||
path: str = os.path.dirname(os.path.realpath(__file__))
|
path: str = os.path.dirname(os.path.realpath(__file__))
|
||||||
name: str = "Example Plugin"
|
name: str = "Example Plugin"
|
||||||
author: str = "John Doe"
|
author: str = "John Doe"
|
||||||
version: str = "0.0.1"
|
version: str = "0.0.1"
|
||||||
support: str = ""
|
support: str = ""
|
||||||
permissions: {} = {
|
requests: {} = {
|
||||||
'ui_target': "plugin_control_list",
|
'ui_target': "plugin_control_list",
|
||||||
'pass_fm_events': "true"
|
'pass_fm_events': "true"
|
||||||
|
|
||||||
|
@ -19,9 +19,9 @@ class Manifest:
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
### Permissions
|
### Requests
|
||||||
```
|
```
|
||||||
permissions: {} = {
|
requests: {} = {
|
||||||
'ui_target': "plugin_control_list",
|
'ui_target': "plugin_control_list",
|
||||||
'ui_target_id': "<some other Gtk Glade ID>" # Only needed if using "other" in "ui_target". See below for predefined "ui_target" options...
|
'ui_target_id': "<some other Gtk Glade ID>" # Only needed if using "other" in "ui_target". See below for predefined "ui_target" options...
|
||||||
'pass_fm_events': "true" # If empty or not present will be ignored.
|
'pass_fm_events': "true" # If empty or not present will be ignored.
|
||||||
|
|
|
@ -0,0 +1,685 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!-- Generated with glade 3.38.2 -->
|
||||||
|
<interface>
|
||||||
|
<requires lib="gtk+" version="3.16"/>
|
||||||
|
<object class="GtkDialog" id="file_properties_dialog">
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="border-width">6</property>
|
||||||
|
<property name="title" translatable="yes">File Properties</property>
|
||||||
|
<property name="modal">True</property>
|
||||||
|
<property name="window-position">center-on-parent</property>
|
||||||
|
<property name="default-width">420</property>
|
||||||
|
<property name="destroy-with-parent">True</property>
|
||||||
|
<property name="type-hint">dialog</property>
|
||||||
|
<property name="skip-taskbar-hint">True</property>
|
||||||
|
<property name="skip-pager-hint">True</property>
|
||||||
|
<property name="gravity">center</property>
|
||||||
|
<signal name="response" handler="on_filePropertiesDlg_response" swapped="no"/>
|
||||||
|
<child internal-child="vbox">
|
||||||
|
<object class="GtkBox" id="dialog_vbox">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="spacing">12</property>
|
||||||
|
<child internal-child="action_area">
|
||||||
|
<object class="GtkButtonBox" id="dialog_action_area">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="layout-style">end</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="cancel_button">
|
||||||
|
<property name="label">gtk-cancel</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">True</property>
|
||||||
|
<property name="can-default">True</property>
|
||||||
|
<property name="receives-default">False</property>
|
||||||
|
<property name="use-stock">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">True</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkButton" id="ok_button">
|
||||||
|
<property name="label">gtk-ok</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">True</property>
|
||||||
|
<property name="can-default">True</property>
|
||||||
|
<property name="receives-default">False</property>
|
||||||
|
<property name="use-stock">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">True</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">False</property>
|
||||||
|
<property name="pack-type">end</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkNotebook" id="notebook">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">True</property>
|
||||||
|
<property name="border-width">6</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkAlignment" id="alignment2">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="top-padding">6</property>
|
||||||
|
<property name="bottom-padding">6</property>
|
||||||
|
<property name="left-padding">12</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkTable" id="general_table">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="border-width">4</property>
|
||||||
|
<property name="n-rows">7</property>
|
||||||
|
<property name="n-columns">2</property>
|
||||||
|
<property name="column-spacing">12</property>
|
||||||
|
<property name="row-spacing">6</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="label_filename">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="label" translatable="yes"><b>File _Name:</b></property>
|
||||||
|
<property name="use-markup">True</property>
|
||||||
|
<property name="use-underline">True</property>
|
||||||
|
<property name="mnemonic-widget">file_name</property>
|
||||||
|
<property name="xalign">0</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="x-options">GTK_FILL</property>
|
||||||
|
<property name="y-options"/>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkEntry" id="file_name">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left-attach">1</property>
|
||||||
|
<property name="right-attach">2</property>
|
||||||
|
<property name="y-options"/>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="label20">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="label" translatable="yes"><b>_Location:</b></property>
|
||||||
|
<property name="use-markup">True</property>
|
||||||
|
<property name="use-underline">True</property>
|
||||||
|
<property name="mnemonic-widget">file_location</property>
|
||||||
|
<property name="xalign">0</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="top-attach">1</property>
|
||||||
|
<property name="bottom-attach">2</property>
|
||||||
|
<property name="x-options">GTK_FILL</property>
|
||||||
|
<property name="y-options"/>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkEntry" id="file_location">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left-attach">1</property>
|
||||||
|
<property name="right-attach">2</property>
|
||||||
|
<property name="top-attach">1</property>
|
||||||
|
<property name="bottom-attach">2</property>
|
||||||
|
<property name="x-options">GTK_FILL</property>
|
||||||
|
<property name="y-options"/>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="label_target">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="label" translatable="yes"><b>Link _Target:</b></property>
|
||||||
|
<property name="use-markup">True</property>
|
||||||
|
<property name="use-underline">True</property>
|
||||||
|
<property name="mnemonic-widget">file_target</property>
|
||||||
|
<property name="xalign">0</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="top-attach">2</property>
|
||||||
|
<property name="bottom-attach">3</property>
|
||||||
|
<property name="x-options">GTK_FILL</property>
|
||||||
|
<property name="y-options"/>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkEntry" id="file_target">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left-attach">1</property>
|
||||||
|
<property name="right-attach">2</property>
|
||||||
|
<property name="top-attach">2</property>
|
||||||
|
<property name="bottom-attach">3</property>
|
||||||
|
<property name="x-options">GTK_FILL</property>
|
||||||
|
<property name="y-options"/>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="label4">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="label" translatable="yes"><b>Type:</b></property>
|
||||||
|
<property name="use-markup">True</property>
|
||||||
|
<property name="use-underline">True</property>
|
||||||
|
<property name="xalign">0</property>
|
||||||
|
<property name="yalign">0</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="top-attach">3</property>
|
||||||
|
<property name="bottom-attach">4</property>
|
||||||
|
<property name="x-options">GTK_FILL</property>
|
||||||
|
<property name="y-options">GTK_FILL</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="mime_type">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">True</property>
|
||||||
|
<property name="selectable">True</property>
|
||||||
|
<property name="ellipsize">end</property>
|
||||||
|
<property name="xalign">0</property>
|
||||||
|
<property name="yalign">0</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left-attach">1</property>
|
||||||
|
<property name="right-attach">2</property>
|
||||||
|
<property name="top-attach">3</property>
|
||||||
|
<property name="bottom-attach">4</property>
|
||||||
|
<property name="x-options">GTK_FILL</property>
|
||||||
|
<property name="y-options"/>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="label5">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="label" translatable="yes"><b>Size:</b></property>
|
||||||
|
<property name="use-markup">True</property>
|
||||||
|
<property name="use-underline">True</property>
|
||||||
|
<property name="xalign">0</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="top-attach">4</property>
|
||||||
|
<property name="bottom-attach">5</property>
|
||||||
|
<property name="x-options">GTK_FILL</property>
|
||||||
|
<property name="y-options"/>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="file_size">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">True</property>
|
||||||
|
<property name="selectable">True</property>
|
||||||
|
<property name="xalign">0</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left-attach">1</property>
|
||||||
|
<property name="right-attach">2</property>
|
||||||
|
<property name="top-attach">4</property>
|
||||||
|
<property name="bottom-attach">5</property>
|
||||||
|
<property name="x-options">GTK_FILL</property>
|
||||||
|
<property name="y-options"/>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="label7">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="label" translatable="yes"><b>_Modified:</b></property>
|
||||||
|
<property name="use-markup">True</property>
|
||||||
|
<property name="use-underline">True</property>
|
||||||
|
<property name="xalign">0</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="top-attach">5</property>
|
||||||
|
<property name="bottom-attach">6</property>
|
||||||
|
<property name="x-options">GTK_FILL</property>
|
||||||
|
<property name="y-options"/>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="label13">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="label" translatable="yes"><b>_Accessed:</b></property>
|
||||||
|
<property name="use-markup">True</property>
|
||||||
|
<property name="use-underline">True</property>
|
||||||
|
<property name="xalign">0</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="top-attach">6</property>
|
||||||
|
<property name="bottom-attach">7</property>
|
||||||
|
<property name="x-options">GTK_FILL</property>
|
||||||
|
<property name="y-options"/>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkEntry" id="mtime">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left-attach">1</property>
|
||||||
|
<property name="right-attach">2</property>
|
||||||
|
<property name="top-attach">5</property>
|
||||||
|
<property name="bottom-attach">6</property>
|
||||||
|
<property name="x-options">GTK_FILL</property>
|
||||||
|
<property name="y-options"/>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkEntry" id="atime">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left-attach">1</property>
|
||||||
|
<property name="right-attach">2</property>
|
||||||
|
<property name="top-attach">6</property>
|
||||||
|
<property name="bottom-attach">7</property>
|
||||||
|
<property name="x-options">GTK_FILL</property>
|
||||||
|
<property name="y-options"/>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child type="tab">
|
||||||
|
<object class="GtkLabel" id="label1">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="label" translatable="yes">_Info</property>
|
||||||
|
<property name="use-underline">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="tab-fill">False</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkAlignment" id="alignment1">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="top-padding">6</property>
|
||||||
|
<property name="bottom-padding">6</property>
|
||||||
|
<property name="left-padding">12</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkVBox" id="vbox1">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="spacing">6</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkTable" id="table3">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="border-width">2</property>
|
||||||
|
<property name="n-rows">2</property>
|
||||||
|
<property name="n-columns">2</property>
|
||||||
|
<property name="column-spacing">12</property>
|
||||||
|
<property name="row-spacing">6</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="owner_label">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="label" translatable="yes"><b>_Owner:</b></property>
|
||||||
|
<property name="use-markup">True</property>
|
||||||
|
<property name="use-underline">True</property>
|
||||||
|
<property name="mnemonic-widget">file_owner</property>
|
||||||
|
<property name="xalign">0</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="x-options">GTK_FILL</property>
|
||||||
|
<property name="y-options"/>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="group_label">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="label" translatable="yes"><b>_Group:</b></property>
|
||||||
|
<property name="use-markup">True</property>
|
||||||
|
<property name="use-underline">True</property>
|
||||||
|
<property name="mnemonic-widget">file_group</property>
|
||||||
|
<property name="xalign">0</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="top-attach">1</property>
|
||||||
|
<property name="bottom-attach">2</property>
|
||||||
|
<property name="x-options">GTK_FILL</property>
|
||||||
|
<property name="y-options"/>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkEntry" id="file_owner">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left-attach">1</property>
|
||||||
|
<property name="right-attach">2</property>
|
||||||
|
<property name="y-options"/>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkEntry" id="file_group">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left-attach">1</property>
|
||||||
|
<property name="right-attach">2</property>
|
||||||
|
<property name="top-attach">1</property>
|
||||||
|
<property name="bottom-attach">2</property>
|
||||||
|
<property name="y-options"/>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">False</property>
|
||||||
|
<property name="position">0</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkHSeparator" id="hseparator1">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">False</property>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkTable" id="table2">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="border-width">4</property>
|
||||||
|
<property name="n-rows">3</property>
|
||||||
|
<property name="n-columns">5</property>
|
||||||
|
<property name="column-spacing">12</property>
|
||||||
|
<property name="row-spacing">6</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="label17">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="label" translatable="yes"><b>Owner:</b></property>
|
||||||
|
<property name="use-markup">True</property>
|
||||||
|
<property name="use-underline">True</property>
|
||||||
|
<property name="xalign">0</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="x-options">GTK_FILL</property>
|
||||||
|
<property name="y-options"/>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="label18">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="label" translatable="yes"><b>Group:</b></property>
|
||||||
|
<property name="use-markup">True</property>
|
||||||
|
<property name="use-underline">True</property>
|
||||||
|
<property name="xalign">0</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="top-attach">1</property>
|
||||||
|
<property name="bottom-attach">2</property>
|
||||||
|
<property name="x-options">GTK_FILL</property>
|
||||||
|
<property name="y-options"/>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="label19">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="label" translatable="yes"><b>Other:</b></property>
|
||||||
|
<property name="use-markup">True</property>
|
||||||
|
<property name="use-underline">True</property>
|
||||||
|
<property name="xalign">0</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="top-attach">2</property>
|
||||||
|
<property name="bottom-attach">3</property>
|
||||||
|
<property name="x-options">GTK_FILL</property>
|
||||||
|
<property name="y-options"/>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkCheckButton" id="owner_r">
|
||||||
|
<property name="label" translatable="yes">Read</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">True</property>
|
||||||
|
<property name="receives-default">False</property>
|
||||||
|
<property name="border-width">2</property>
|
||||||
|
<property name="use-underline">True</property>
|
||||||
|
<property name="draw-indicator">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left-attach">1</property>
|
||||||
|
<property name="right-attach">2</property>
|
||||||
|
<property name="x-options">GTK_FILL</property>
|
||||||
|
<property name="y-options"/>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkCheckButton" id="group_r">
|
||||||
|
<property name="label" translatable="yes">Read</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">True</property>
|
||||||
|
<property name="receives-default">False</property>
|
||||||
|
<property name="border-width">2</property>
|
||||||
|
<property name="use-underline">True</property>
|
||||||
|
<property name="draw-indicator">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left-attach">1</property>
|
||||||
|
<property name="right-attach">2</property>
|
||||||
|
<property name="top-attach">1</property>
|
||||||
|
<property name="bottom-attach">2</property>
|
||||||
|
<property name="x-options">GTK_FILL</property>
|
||||||
|
<property name="y-options"/>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkCheckButton" id="others_r">
|
||||||
|
<property name="label" translatable="yes">Read</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">True</property>
|
||||||
|
<property name="receives-default">False</property>
|
||||||
|
<property name="border-width">2</property>
|
||||||
|
<property name="use-underline">True</property>
|
||||||
|
<property name="draw-indicator">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left-attach">1</property>
|
||||||
|
<property name="right-attach">2</property>
|
||||||
|
<property name="top-attach">2</property>
|
||||||
|
<property name="bottom-attach">3</property>
|
||||||
|
<property name="x-options">GTK_FILL</property>
|
||||||
|
<property name="y-options"/>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkCheckButton" id="owner_w">
|
||||||
|
<property name="label" translatable="yes">Write</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">True</property>
|
||||||
|
<property name="receives-default">False</property>
|
||||||
|
<property name="border-width">2</property>
|
||||||
|
<property name="use-underline">True</property>
|
||||||
|
<property name="draw-indicator">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left-attach">2</property>
|
||||||
|
<property name="right-attach">3</property>
|
||||||
|
<property name="x-options">GTK_FILL</property>
|
||||||
|
<property name="y-options"/>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkCheckButton" id="group_w">
|
||||||
|
<property name="label" translatable="yes">Write</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">True</property>
|
||||||
|
<property name="receives-default">False</property>
|
||||||
|
<property name="border-width">2</property>
|
||||||
|
<property name="use-underline">True</property>
|
||||||
|
<property name="draw-indicator">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left-attach">2</property>
|
||||||
|
<property name="right-attach">3</property>
|
||||||
|
<property name="top-attach">1</property>
|
||||||
|
<property name="bottom-attach">2</property>
|
||||||
|
<property name="x-options">GTK_FILL</property>
|
||||||
|
<property name="y-options"/>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkCheckButton" id="others_w">
|
||||||
|
<property name="label" translatable="yes">Write</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">True</property>
|
||||||
|
<property name="receives-default">False</property>
|
||||||
|
<property name="border-width">2</property>
|
||||||
|
<property name="use-underline">True</property>
|
||||||
|
<property name="draw-indicator">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left-attach">2</property>
|
||||||
|
<property name="right-attach">3</property>
|
||||||
|
<property name="top-attach">2</property>
|
||||||
|
<property name="bottom-attach">3</property>
|
||||||
|
<property name="x-options">GTK_FILL</property>
|
||||||
|
<property name="y-options"/>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkCheckButton" id="owner_x">
|
||||||
|
<property name="label" translatable="yes">Execute</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">True</property>
|
||||||
|
<property name="receives-default">False</property>
|
||||||
|
<property name="border-width">2</property>
|
||||||
|
<property name="use-underline">True</property>
|
||||||
|
<property name="draw-indicator">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left-attach">3</property>
|
||||||
|
<property name="right-attach">4</property>
|
||||||
|
<property name="x-options">GTK_FILL</property>
|
||||||
|
<property name="y-options"/>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkCheckButton" id="group_x">
|
||||||
|
<property name="label" translatable="yes">Execute</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">True</property>
|
||||||
|
<property name="receives-default">False</property>
|
||||||
|
<property name="border-width">2</property>
|
||||||
|
<property name="use-underline">True</property>
|
||||||
|
<property name="draw-indicator">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left-attach">3</property>
|
||||||
|
<property name="right-attach">4</property>
|
||||||
|
<property name="top-attach">1</property>
|
||||||
|
<property name="bottom-attach">2</property>
|
||||||
|
<property name="x-options">GTK_FILL</property>
|
||||||
|
<property name="y-options"/>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkCheckButton" id="others_x">
|
||||||
|
<property name="label" translatable="yes">Execute</property>
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">True</property>
|
||||||
|
<property name="receives-default">False</property>
|
||||||
|
<property name="border-width">2</property>
|
||||||
|
<property name="use-underline">True</property>
|
||||||
|
<property name="draw-indicator">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left-attach">3</property>
|
||||||
|
<property name="right-attach">4</property>
|
||||||
|
<property name="top-attach">2</property>
|
||||||
|
<property name="bottom-attach">3</property>
|
||||||
|
<property name="x-options">GTK_FILL</property>
|
||||||
|
<property name="y-options"/>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkVSeparator" id="vseparator1">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="left-attach">4</property>
|
||||||
|
<property name="right-attach">5</property>
|
||||||
|
<property name="bottom-attach">3</property>
|
||||||
|
<property name="x-options">GTK_FILL</property>
|
||||||
|
<property name="y-options">GTK_FILL</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">2</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="position">1</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
<child type="tab">
|
||||||
|
<object class="GtkLabel" id="label2">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
<property name="can-focus">False</property>
|
||||||
|
<property name="label" translatable="yes">_Permissions</property>
|
||||||
|
<property name="use-underline">True</property>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="position">1</property>
|
||||||
|
<property name="tab-fill">False</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
<packing>
|
||||||
|
<property name="expand">False</property>
|
||||||
|
<property name="fill">True</property>
|
||||||
|
<property name="position">2</property>
|
||||||
|
</packing>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<action-widgets>
|
||||||
|
<action-widget response="-6">cancel_button</action-widget>
|
||||||
|
<action-widget response="-5">ok_button</action-widget>
|
||||||
|
</action-widgets>
|
||||||
|
</object>
|
||||||
|
</interface>
|
|
@ -0,0 +1,263 @@
|
||||||
|
# Python imports
|
||||||
|
import os, threading, subprocess, time
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
# Gtk imports
|
||||||
|
import gi
|
||||||
|
gi.require_version('Gtk', '3.0')
|
||||||
|
from gi.repository import Gtk, GLib, Gio
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
|
||||||
|
|
||||||
|
# NOTE: Threads WILL NOT die with parent's destruction.
|
||||||
|
def threaded(fn):
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=False).start()
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
# NOTE: Threads WILL die with parent's destruction.
|
||||||
|
def daemon_threaded(fn):
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
threading.Thread(target=fn, args=args, kwargs=kwargs, daemon=True).start()
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Manifest:
|
||||||
|
path: str = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
name: str = "Properties"
|
||||||
|
author: str = "ITDominator"
|
||||||
|
version: str = "0.0.1"
|
||||||
|
support: str = ""
|
||||||
|
requests: {} = {
|
||||||
|
'ui_target': "context_menu",
|
||||||
|
'pass_fm_events': "true"
|
||||||
|
}
|
||||||
|
|
||||||
|
class Properties:
|
||||||
|
file_uri: str = None
|
||||||
|
file_name: str = None
|
||||||
|
file_location: str = None
|
||||||
|
file_target: str = None
|
||||||
|
mime_type: str = None
|
||||||
|
file_size: str = None
|
||||||
|
mtime: int = None
|
||||||
|
atime: int = None
|
||||||
|
file_owner: str = None
|
||||||
|
file_group: str = None
|
||||||
|
chmod_stat: str = None
|
||||||
|
|
||||||
|
|
||||||
|
class Plugin(Manifest):
|
||||||
|
def __init__(self):
|
||||||
|
self._GLADE_FILE = f"{self.path}/file_properties.glade"
|
||||||
|
self._builder = None
|
||||||
|
self._properties_dialog = None
|
||||||
|
|
||||||
|
self._event_system = None
|
||||||
|
self._event_sleep_time = .5
|
||||||
|
self._event_message = None
|
||||||
|
|
||||||
|
self._file_name = None
|
||||||
|
self._file_location = None
|
||||||
|
self._file_target = None
|
||||||
|
self._mime_type = None
|
||||||
|
self._file_size = None
|
||||||
|
self._mtime = None
|
||||||
|
self._atime = None
|
||||||
|
self._file_owner = None
|
||||||
|
self._file_group = None
|
||||||
|
|
||||||
|
self._chmod_map: {} = {
|
||||||
|
"7": "rwx",
|
||||||
|
"6": "rw",
|
||||||
|
"5": "rx",
|
||||||
|
"4": "r",
|
||||||
|
"3": "wx",
|
||||||
|
"2": "w",
|
||||||
|
"1": "x",
|
||||||
|
"0": ""
|
||||||
|
}
|
||||||
|
|
||||||
|
self._chmod_map_counter: {} = {
|
||||||
|
"rwx": "7",
|
||||||
|
"rw": "6",
|
||||||
|
"rx": "5",
|
||||||
|
"r": "4",
|
||||||
|
"wx": "3",
|
||||||
|
"w": "2",
|
||||||
|
"x": "1",
|
||||||
|
"": "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def get_ui_element(self):
|
||||||
|
self._builder = Gtk.Builder()
|
||||||
|
self._builder.add_from_file(self._GLADE_FILE)
|
||||||
|
|
||||||
|
self._properties_dialog = self._builder.get_object("file_properties_dialog")
|
||||||
|
self._file_name = self._builder.get_object("file_name")
|
||||||
|
self._file_location = self._builder.get_object("file_location")
|
||||||
|
self._file_target = self._builder.get_object("file_target")
|
||||||
|
self._mime_type = self._builder.get_object("mime_type")
|
||||||
|
self._file_size = self._builder.get_object("file_size")
|
||||||
|
self._mtime = self._builder.get_object("mtime")
|
||||||
|
self._atime = self._builder.get_object("atime")
|
||||||
|
self._file_owner = self._builder.get_object("file_owner")
|
||||||
|
self._file_group = self._builder.get_object("file_group")
|
||||||
|
|
||||||
|
button = Gtk.Button(label=self.name)
|
||||||
|
button.connect("button-release-event", self._show_properties_page)
|
||||||
|
return button
|
||||||
|
|
||||||
|
def set_fm_event_system(self, fm_event_system):
|
||||||
|
self._event_system = fm_event_system
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
self._module_event_observer()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@threaded
|
||||||
|
def _show_properties_page(self, widget=None, eve=None):
|
||||||
|
self._event_system.push_gui_event([self.name, "get_current_state", ()])
|
||||||
|
self.wait_for_fm_message()
|
||||||
|
|
||||||
|
state = self._event_message
|
||||||
|
self._event_message = None
|
||||||
|
|
||||||
|
GLib.idle_add(self._process_changes, (state))
|
||||||
|
|
||||||
|
def _process_changes(self, state):
|
||||||
|
if len(state.selected_files) == 1:
|
||||||
|
uri = state.selected_files[0]
|
||||||
|
path = state.tab.get_current_directory()
|
||||||
|
|
||||||
|
|
||||||
|
properties = self._set_ui_data(uri, path)
|
||||||
|
response = self._properties_dialog.run()
|
||||||
|
if response in [Gtk.ResponseType.CANCEL, Gtk.ResponseType.DELETE_EVENT]:
|
||||||
|
self._properties_dialog.hide()
|
||||||
|
|
||||||
|
self._update_file(properties)
|
||||||
|
self._properties_dialog.hide()
|
||||||
|
|
||||||
|
|
||||||
|
def _update_file(self, properties):
|
||||||
|
chmod_stat = self._get_check_boxes()
|
||||||
|
|
||||||
|
if chmod_stat is not properties.chmod_stat:
|
||||||
|
try:
|
||||||
|
print("\nNew chmod flags...")
|
||||||
|
print(f"Old: {''.join(properties.chmod_stat)}")
|
||||||
|
print(f"New: {chmod_stat}")
|
||||||
|
# self._guest_fs.chmod(int(chmod_stat), properties.file_uri)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Couldn't chmod\nFile: {properties.file_uri}")
|
||||||
|
print( repr(e) )
|
||||||
|
|
||||||
|
|
||||||
|
def _set_ui_data(self, uri, path):
|
||||||
|
properties = Properties()
|
||||||
|
file_info = Gio.File.new_for_path(uri).query_info(attributes="standard::*,owner::*,time::access,time::changed",
|
||||||
|
flags=Gio.FileQueryInfoFlags.NONE,
|
||||||
|
cancellable=None)
|
||||||
|
|
||||||
|
is_symlink = file_info.get_attribute_as_string("standard::is-symlink")
|
||||||
|
properties.file_uri = uri
|
||||||
|
properties.file_target = file_info.get_attribute_as_string("standard::symlink-target") if is_symlink else ""
|
||||||
|
properties.file_name = file_info.get_display_name()
|
||||||
|
properties.file_location = path
|
||||||
|
properties.mime_type = file_info.get_content_type()
|
||||||
|
properties.file_size = self._sizeof_fmt(file_info.get_size())
|
||||||
|
properties.mtime = datetime.fromtimestamp( int(file_info.get_attribute_as_string("time::changed")) ).strftime("%A, %B %d, %Y %I:%M:%S")
|
||||||
|
properties.atime = datetime.fromtimestamp( int(file_info.get_attribute_as_string("time::access")) ).strftime("%A, %B %d, %Y %I:%M:%S")
|
||||||
|
properties.file_owner = file_info.get_attribute_as_string("owner::user")
|
||||||
|
properties.file_group = file_info.get_attribute_as_string("owner::group")
|
||||||
|
|
||||||
|
# NOTE: Read = 4, Write = 2, Exec = 1
|
||||||
|
command = ["stat", "-c", "%a", uri]
|
||||||
|
with subprocess.Popen(command, stdout=subprocess.PIPE) as proc:
|
||||||
|
properties.chmod_stat = list(proc.stdout.read().decode("UTF-8").strip())
|
||||||
|
owner = self._chmod_map[f"{properties.chmod_stat[0]}"]
|
||||||
|
group = self._chmod_map[f"{properties.chmod_stat[1]}"]
|
||||||
|
others = self._chmod_map[f"{properties.chmod_stat[2]}"]
|
||||||
|
|
||||||
|
self._reset_check_boxes()
|
||||||
|
self._set_check_boxes([["owner", owner], ["group", group], ["others", others]])
|
||||||
|
|
||||||
|
self._file_name.set_text(properties.file_name)
|
||||||
|
self._file_location.set_text(properties.file_location)
|
||||||
|
self._file_target.set_text(properties.file_target)
|
||||||
|
self._mime_type.set_label(properties.mime_type)
|
||||||
|
self._file_size.set_label(properties.file_size)
|
||||||
|
self._mtime.set_text(properties.mtime)
|
||||||
|
self._atime.set_text(properties.atime)
|
||||||
|
self._file_owner.set_text(properties.file_owner)
|
||||||
|
self._file_group.set_text(properties.file_group)
|
||||||
|
|
||||||
|
return properties
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def _get_check_boxes(self):
|
||||||
|
perms = [[], [], []]
|
||||||
|
|
||||||
|
for i, target in enumerate(["owner", "group", "others"]):
|
||||||
|
for type in ["r", "w", "x"]:
|
||||||
|
is_active = self._builder.get_object(f"{target}_{type}").get_active()
|
||||||
|
if is_active:
|
||||||
|
perms[i].append(type)
|
||||||
|
|
||||||
|
digits = []
|
||||||
|
for perm in perms:
|
||||||
|
digits.append(self._chmod_map_counter[ ''.join(perm) ])
|
||||||
|
|
||||||
|
return ''.join(digits)
|
||||||
|
|
||||||
|
def _set_check_boxes(self, targets):
|
||||||
|
for name, target in targets:
|
||||||
|
for type in list(target):
|
||||||
|
obj = f"{name}_{type}"
|
||||||
|
self._builder.get_object(obj).set_active(True)
|
||||||
|
|
||||||
|
def _reset_check_boxes(self):
|
||||||
|
for target in ["owner", "group", "others"]:
|
||||||
|
for type in ["r", "w", "x"]:
|
||||||
|
self._builder.get_object(f"{target}_{type}").set_active(False)
|
||||||
|
|
||||||
|
def _sizeof_fmt(self, num, suffix="B"):
|
||||||
|
for unit in ["", "K", "M", "G", "T", "Pi", "Ei", "Zi"]:
|
||||||
|
if abs(num) < 1024.0:
|
||||||
|
return f"{num:3.1f} {unit}{suffix}"
|
||||||
|
num /= 1024.0
|
||||||
|
return f"{num:.1f} Yi{suffix}"
|
||||||
|
|
||||||
|
def wait_for_fm_message(self):
|
||||||
|
while not self._event_message:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@daemon_threaded
|
||||||
|
def _module_event_observer(self):
|
||||||
|
while True:
|
||||||
|
time.sleep(self._event_sleep_time)
|
||||||
|
event = self._event_system.read_module_event()
|
||||||
|
if event:
|
||||||
|
try:
|
||||||
|
if event[0] == self.name:
|
||||||
|
target_id, method_target, data = self._event_system.consume_module_event()
|
||||||
|
|
||||||
|
if not method_target:
|
||||||
|
self._event_message = data
|
||||||
|
else:
|
||||||
|
method = getattr(self.__class__, f"{method_target}")
|
||||||
|
if data:
|
||||||
|
data = method(*(self, *data))
|
||||||
|
else:
|
||||||
|
method(*(self,))
|
||||||
|
except Exception as e:
|
||||||
|
print(repr(e))
|
|
@ -25,12 +25,12 @@ def daemon_threaded(fn):
|
||||||
|
|
||||||
|
|
||||||
class Manifest:
|
class Manifest:
|
||||||
path: str = os.path.dirname(os.path.realpath(__file__))
|
path: str = os.path.dirname(os.path.realpath(__file__))
|
||||||
name: str = "Example Plugin"
|
name: str = "Example Plugin"
|
||||||
author: str = "John Doe"
|
author: str = "John Doe"
|
||||||
version: str = "0.0.1"
|
version: str = "0.0.1"
|
||||||
support: str = ""
|
support: str = ""
|
||||||
permissions: {} = {
|
requests: {} = {
|
||||||
'ui_target': "plugin_control_list",
|
'ui_target': "plugin_control_list",
|
||||||
'pass_fm_events': "true",
|
'pass_fm_events': "true",
|
||||||
'bind_keys': [f"{name}||send_message:<Control>f"]
|
'bind_keys': [f"{name}||send_message:<Control>f"]
|
||||||
|
@ -39,7 +39,7 @@ class Manifest:
|
||||||
|
|
||||||
class Plugin(Manifest):
|
class Plugin(Manifest):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._event_system = event_system
|
self._event_system = None
|
||||||
self._event_sleep_time = .5
|
self._event_sleep_time = .5
|
||||||
self._event_message = None
|
self._event_message = None
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ class Plugin(Manifest):
|
||||||
return button
|
return button
|
||||||
|
|
||||||
def set_fm_event_system(self, fm_event_system):
|
def set_fm_event_system(self, fm_event_system):
|
||||||
self.event_system = fm_event_system
|
self._event_system = fm_event_system
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
self._module_event_observer()
|
self._module_event_observer()
|
||||||
|
@ -62,6 +62,10 @@ class Plugin(Manifest):
|
||||||
self._event_system.push_gui_event([self.name, "display_message", ("warning", message, None)])
|
self._event_system.push_gui_event([self.name, "display_message", ("warning", message, None)])
|
||||||
|
|
||||||
|
|
||||||
|
def wait_for_fm_message(self):
|
||||||
|
while not self._event_message:
|
||||||
|
pass
|
||||||
|
|
||||||
@daemon_threaded
|
@daemon_threaded
|
||||||
def _module_event_observer(self):
|
def _module_event_observer(self):
|
||||||
while True:
|
while True:
|
||||||
|
@ -81,5 +85,4 @@ class Plugin(Manifest):
|
||||||
else:
|
else:
|
||||||
method(*(self,))
|
method(*(self,))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print("ewww here")
|
|
||||||
print(repr(e))
|
print(repr(e))
|
||||||
|
|
|
@ -25,12 +25,12 @@ def daemon_threaded(fn):
|
||||||
|
|
||||||
|
|
||||||
class Manifest:
|
class Manifest:
|
||||||
path: str = os.path.dirname(os.path.realpath(__file__))
|
path: str = os.path.dirname(os.path.realpath(__file__))
|
||||||
name: str = "Youtube Download"
|
name: str = "Youtube Download"
|
||||||
author: str = "ITDominator"
|
author: str = "ITDominator"
|
||||||
version: str = "0.0.1"
|
version: str = "0.0.1"
|
||||||
support: str = ""
|
support: str = ""
|
||||||
permissions: {} = {
|
requests: {} = {
|
||||||
'ui_target': "plugin_control_list",
|
'ui_target': "plugin_control_list",
|
||||||
'pass_fm_events': "true"
|
'pass_fm_events': "true"
|
||||||
|
|
||||||
|
@ -39,9 +39,9 @@ class Manifest:
|
||||||
|
|
||||||
class Plugin(Manifest):
|
class Plugin(Manifest):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._fm_event_system = None
|
self._event_system = None
|
||||||
self._event_sleep_time = .5
|
self._event_sleep_time = .5
|
||||||
self._fm_event_message = None
|
self._event_message = None
|
||||||
|
|
||||||
|
|
||||||
def get_ui_element(self):
|
def get_ui_element(self):
|
||||||
|
@ -50,24 +50,38 @@ class Plugin(Manifest):
|
||||||
return button
|
return button
|
||||||
|
|
||||||
def set_fm_event_system(self, fm_event_system):
|
def set_fm_event_system(self, fm_event_system):
|
||||||
self._fm_event_system = fm_event_system
|
self._event_system = fm_event_system
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
self._module_event_observer()
|
self._module_event_observer()
|
||||||
|
|
||||||
|
|
||||||
|
@threaded
|
||||||
|
def _do_download(self, widget=None, eve=None):
|
||||||
|
self._event_system.push_gui_event([self.name, "get_current_state", ()])
|
||||||
|
self.wait_for_fm_message()
|
||||||
|
|
||||||
|
state = self._event_message
|
||||||
|
subprocess.Popen([f'{self.path}/download.sh' , state.tab.get_current_directory()])
|
||||||
|
self._event_message = None
|
||||||
|
|
||||||
|
|
||||||
|
def wait_for_fm_message(self):
|
||||||
|
while not self._event_message:
|
||||||
|
pass
|
||||||
|
|
||||||
@daemon_threaded
|
@daemon_threaded
|
||||||
def _module_event_observer(self):
|
def _module_event_observer(self):
|
||||||
while True:
|
while True:
|
||||||
time.sleep(self._event_sleep_time)
|
time.sleep(self._event_sleep_time)
|
||||||
event = self._fm_event_system.read_module_event()
|
event = self._event_system.read_module_event()
|
||||||
if event:
|
if event:
|
||||||
try:
|
try:
|
||||||
if event[0] == self.name:
|
if event[0] == self.name:
|
||||||
target_id, method_target, data = self._fm_event_system.consume_module_event()
|
target_id, method_target, data = self._event_system.consume_module_event()
|
||||||
|
|
||||||
if not method_target:
|
if not method_target:
|
||||||
self._fm_event_message = data
|
self._event_message = data
|
||||||
else:
|
else:
|
||||||
method = getattr(self.__class__, f"{method_target}")
|
method = getattr(self.__class__, f"{method_target}")
|
||||||
if data:
|
if data:
|
||||||
|
@ -76,14 +90,3 @@ class Plugin(Manifest):
|
||||||
method(*(self,))
|
method(*(self,))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(repr(e))
|
print(repr(e))
|
||||||
|
|
||||||
|
|
||||||
@threaded
|
|
||||||
def _do_download(self, widget=None, eve=None):
|
|
||||||
self._fm_event_system.push_gui_event([self.name, "get_current_state", ()])
|
|
||||||
while not self._fm_event_message:
|
|
||||||
pass
|
|
||||||
|
|
||||||
state = self._fm_event_message
|
|
||||||
subprocess.Popen([f'{self.path}/download.sh' , state.tab.get_current_directory()])
|
|
||||||
self._fm_event_message = None
|
|
||||||
|
|
|
@ -19,6 +19,9 @@ class State:
|
||||||
tab: type = None
|
tab: type = None
|
||||||
icon_grid: gi.overrides.Gtk.IconView = None
|
icon_grid: gi.overrides.Gtk.IconView = None
|
||||||
store: gi.overrides.Gtk.ListStore = None
|
store: gi.overrides.Gtk.ListStore = None
|
||||||
|
selected_files: [] = None
|
||||||
|
to_copy_files: [] = None
|
||||||
|
to_cut_files: [] = None
|
||||||
|
|
||||||
|
|
||||||
class Controller_Data:
|
class Controller_Data:
|
||||||
|
@ -138,6 +141,18 @@ class Controller_Data:
|
||||||
state.icon_grid = self.builder.get_object(f"{state.wid}|{state.tid}|icon_grid")
|
state.icon_grid = self.builder.get_object(f"{state.wid}|{state.tid}|icon_grid")
|
||||||
state.store = state.icon_grid.get_model()
|
state.store = state.icon_grid.get_model()
|
||||||
|
|
||||||
|
|
||||||
|
selected_files = state.icon_grid.get_selected_items()
|
||||||
|
# if self.selected_files:
|
||||||
|
if selected_files:
|
||||||
|
state.selected_files = self.format_to_uris(state.store, state.wid, state.tid, selected_files, True)
|
||||||
|
|
||||||
|
# if self.to_copy_files:
|
||||||
|
# state.to_copy_files = self.format_to_uris(state.store, state.wid, state.tid, self.to_copy_files, True)
|
||||||
|
#
|
||||||
|
# if self.to_cut_files:
|
||||||
|
# state.to_cut_files = self.format_to_uris(state.store, state.wid, state.tid, self.to_cut_files, True)
|
||||||
|
|
||||||
return state
|
return state
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ class Plugin:
|
||||||
author: str = None
|
author: str = None
|
||||||
version: str = None
|
version: str = None
|
||||||
support: str = None
|
support: str = None
|
||||||
permissions:{} = None
|
requests:{} = None
|
||||||
reference: type = None
|
reference: type = None
|
||||||
|
|
||||||
|
|
||||||
|
@ -53,72 +53,76 @@ class Plugins:
|
||||||
print(f"Loading plugins...")
|
print(f"Loading plugins...")
|
||||||
parent_path = os.getcwd()
|
parent_path = os.getcwd()
|
||||||
|
|
||||||
for file in os.listdir(self._plugins_path):
|
for path, folder in [[join(self._plugins_path, item), item] if os.path.isdir(join(self._plugins_path, item)) else None for item in os.listdir(self._plugins_path)]:
|
||||||
try:
|
try:
|
||||||
path = join(self._plugins_path, file)
|
target = join(path, "plugin.py")
|
||||||
if isdir(path):
|
if not os.path.exists(target):
|
||||||
module = self.load_plugin_module(path, file)
|
raise Exception("Invalid Plugin Structure: Plugin doesn't have 'plugin.py'. Aboarting load...")
|
||||||
plugin = self.collect_info(module, path)
|
|
||||||
loading_data = self.parse_permissions(plugin)
|
|
||||||
|
|
||||||
self.execute_plugin(module, plugin, loading_data)
|
module = self.load_plugin_module(path, folder, target)
|
||||||
|
plugin = self.collect_info(module, path)
|
||||||
|
loading_data = self.parse_requests(plugin)
|
||||||
|
|
||||||
|
self.execute_plugin(module, plugin, loading_data)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print("Malformed plugin! Not loading!")
|
print(f"Malformed Plugin: Not loading -->: '{folder}' !")
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
# if debug:
|
||||||
|
# traceback.print_exc()
|
||||||
|
|
||||||
os.chdir(parent_path)
|
os.chdir(parent_path)
|
||||||
|
|
||||||
|
|
||||||
def load_plugin_module(self, path, file):
|
def load_plugin_module(self, path, folder, target):
|
||||||
os.chdir(path)
|
os.chdir(path)
|
||||||
sys.path.insert(0, path)
|
sys.path.insert(0, path)
|
||||||
spec = importlib.util.spec_from_file_location(file, join(path, "plugin.py"))
|
spec = importlib.util.spec_from_file_location(folder, target)
|
||||||
module = importlib.util.module_from_spec(spec)
|
module = importlib.util.module_from_spec(spec)
|
||||||
spec.loader.exec_module(module)
|
spec.loader.exec_module(module)
|
||||||
|
|
||||||
return module
|
return module
|
||||||
|
|
||||||
def collect_info(self, module, path) -> Plugin:
|
def collect_info(self, module, path) -> Plugin:
|
||||||
plugin = Plugin()
|
plugin = Plugin()
|
||||||
plugin.path = module.Manifest.path
|
plugin.path = module.Manifest.path
|
||||||
plugin.name = module.Manifest.name
|
plugin.name = module.Manifest.name
|
||||||
plugin.author = module.Manifest.author
|
plugin.author = module.Manifest.author
|
||||||
plugin.version = module.Manifest.version
|
plugin.version = module.Manifest.version
|
||||||
plugin.support = module.Manifest.support
|
plugin.support = module.Manifest.support
|
||||||
plugin.permissions = module.Manifest.permissions
|
plugin.requests = module.Manifest.requests
|
||||||
|
|
||||||
return plugin
|
return plugin
|
||||||
|
|
||||||
def parse_permissions(self, plugin):
|
def parse_requests(self, plugin):
|
||||||
loading_data = {}
|
loading_data = {}
|
||||||
permissions = plugin.permissions
|
requests = plugin.requests
|
||||||
keys = permissions.keys()
|
keys = requests.keys()
|
||||||
|
|
||||||
if "ui_target" in keys:
|
if "ui_target" in keys:
|
||||||
if permissions["ui_target"] in [
|
if requests["ui_target"] in [
|
||||||
"none", "other", "main_Window", "main_menu_bar", "path_menu_bar", "plugin_control_list",
|
"none", "other", "main_Window", "main_menu_bar", "path_menu_bar", "plugin_control_list",
|
||||||
"context_menu", "window_1", "window_2", "window_3", "window_4"
|
"context_menu", "window_1", "window_2", "window_3", "window_4"
|
||||||
]:
|
]:
|
||||||
if permissions["ui_target"] == "other":
|
if requests["ui_target"] == "other":
|
||||||
if "ui_target_id" in keys:
|
if "ui_target_id" in keys:
|
||||||
loading_data["ui_target"] = self._builder.get_object(permissions["ui_target_id"])
|
loading_data["ui_target"] = self._builder.get_object(requests["ui_target_id"])
|
||||||
if loading_data["ui_target"] == None:
|
if loading_data["ui_target"] == None:
|
||||||
raise Exception('Invalid "ui_target_id" given in permissions. Must have one if setting "ui_target" to "other"...')
|
raise Exception('Invalid "ui_target_id" given in requests. Must have one if setting "ui_target" to "other"...')
|
||||||
else:
|
else:
|
||||||
raise Exception('Invalid "ui_target_id" given in permissions. Must have one if setting "ui_target" to "other"...')
|
raise Exception('Invalid "ui_target_id" given in requests. Must have one if setting "ui_target" to "other"...')
|
||||||
else:
|
else:
|
||||||
loading_data["ui_target"] = self._builder.get_object(permissions["ui_target"])
|
loading_data["ui_target"] = self._builder.get_object(requests["ui_target"])
|
||||||
else:
|
else:
|
||||||
raise Exception('Unknown "ui_target" given in permissions.')
|
raise Exception('Unknown "ui_target" given in requests.')
|
||||||
|
|
||||||
|
|
||||||
if "pass_fm_events" in keys:
|
if "pass_fm_events" in keys:
|
||||||
if permissions["pass_fm_events"] in ["true"]:
|
if requests["pass_fm_events"] in ["true"]:
|
||||||
loading_data["pass_fm_events"] = True
|
loading_data["pass_fm_events"] = True
|
||||||
|
|
||||||
if "bind_keys" in keys:
|
if "bind_keys" in keys:
|
||||||
if isinstance(permissions["bind_keys"], list):
|
if isinstance(requests["bind_keys"], list):
|
||||||
loading_data["bind_keys"] = permissions["bind_keys"]
|
loading_data["bind_keys"] = requests["bind_keys"]
|
||||||
|
|
||||||
return loading_data
|
return loading_data
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue