295 Commits

Author SHA1 Message Date
Thomas Martitz
6cb443e863 plugins: enforce geany_plugin_register_proxy() can be called once
In the future we might want to enable calling it again to set new supported
plugin types/extensions. This is not implemented yet, but in order to
allow this in the future we have to prevent it now, otherwise we'd
need to break the API.
2015-10-06 15:40:57 +02:00
Thomas Martitz
6dfe5ce942 plugins: use GQueue to restore GLib compatibility
g_ptr_array_insert() is too recent (2.40), but prepending is required. GQueue
is a fine replacement with better old-glib support, at the expense of working
with a doubly-linked list instead of plain array.
2015-10-06 15:40:57 +02:00
Thomas Martitz
7ac89deebd plugins: improve PM dialog for proxy and sub-plugins
Geany now remembers how many plugins depend on a pluxy. It uses this
information to disable the "Active" checkbox in the PM dialog.

Additionally, the PM dialog displays plugins in a hierarchical manner, so that
sub-plugins are shown next to pluxy. This is espcially handy since it makes
the sub-plugin <-> pluxy relationship really obvious, and it's easier to spot
which plugins need to be disabled before the pluxy can be disabled. This allows
to remove code to re-select the plugin because the row (respective to the
hierarchy level) does not change anymore.
2015-10-06 15:40:57 +02:00
Thomas Martitz
8ac9d56fff plugins: reselect when toggling the current plugin
When enabling/disabling pluxys in the PM dialog the list of available
plugins might change. If plugins before the pluxy go/come then the wrong
plugin becomes selected (the selected row number stays the same). Re-apply
the selection to the current one in the toggle callback to overcome this issue.
2015-10-05 22:11:12 +02:00
Thomas Martitz
6e5ca69e2e plugins: add geany_plugin_register_proxy() to the plugin API
This function finally allows plugins to register themselves as a proxy
for one or more file extensions.

Lots of documentation is added to doc/plugins.dox, please refer to that for more
details.
2015-10-05 22:11:12 +02:00
Thomas Martitz
3ccf959013 plugins: introduce probe() for proxy plugins
When a file extension alone is ambigious as to whether a potential plugin is
really handled then the proxy should use the probe hook to find out. This can
be especially helpful when two pluxies work on the same file extension.

The proxy's probe() should return PROXY_IGNORED or PROXY_MATCHED accordingly.
A special flag value, PROXY_NOLOAD, can be or'ed into PROXY_MATCHED to say
that the file belongs to the proxy, but isn't directly loaded and should not
be handled by any other proxy or geany itself.

Example for PROXY_IGNORED:
geanypy only supports python2 at the moment. So, scripts written
for python3 aren't handled by it and should be skipped for the PM dialog.
Or perhaps they are handled by another proxy that supports python3.

Example for PROXY_NOLOAD:
A pluxy registers for the metadata file extension (.plugin) where author etc
is in. The actual implmentation is in a python script (.py). The .py file
is tied to the .plugin and should not be processed by other pluxies. Thus,
the pluxy also registers for the .py extension but returns
PROXY_MATCHED|PROXY_NOLOAD for it (if it would return only PROXY_MATCHED
the sub-plugin would show up twice in the PM dialog).
2015-10-05 22:11:12 +02:00
Thomas Martitz
e5bb6571c6 plugins: when loading active ones, loop until no more proxy plugins are added
During the loading of the active plugins they are also initialized (done at
startup). As a result, these plugins could be pluxys and make more plugins
available, some of which may be active as well.

Because of this the loop has to be restarted if pluxies become
available to also load active plugins that depend on the pluxy.

The loop is only restarted at the end so only nested pluxys could possibly
cause the loop to be run more than twice.
2015-10-05 22:11:12 +02:00
Thomas Martitz
203644a233 plugins: refactor GtkListStore population code into separate function 2015-10-05 22:11:12 +02:00
Thomas Martitz
bdaab9c837 plugins: generic load_data instead of module pointer in Plugin struct
Being a GModule is actually a detail of standard plugins. Future proxy plugins
might need different handles. Therefore replace the module field with a more
generic pointer and encapsulate the GModule detail further.

This pointer shall be returned from GeanyProxyFuncs::load and is passed back
to GeanyProxyFuncs::unload, and isn't interpreted by Geany.
2015-10-05 22:11:12 +02:00
Thomas Martitz
d008675b1b plugins: introduce load and unload functions for plugins
Currently they encapsulate loading and unloading of standard plugins. In
the future plugins can provide such functions to load their types of plugins.

Such a dummy proxy plugin is implemented now to load standard plugins so
that these aren't going to be specially handled.
2015-10-05 22:09:36 +02:00
Thomas Martitz
437837d3a5 plugins: separate geany_plugin_set_data() dual-use
It was found that because geany_plugin_set_data() could be used by both
plugin's init() and geany_load_module(), that it introduced some uncertainty
as to when to call the free_func. init() callers might expect the call
around the same time as cleanup() is called, while geany_load_module()
callers expected the call at module unload time.

It was indeed called at module unload time. But that means that init() callers
cannot call it again reliably after in a init()->cleanup()->init() flow (when
toggling the plugin) without fully unloading the plugin (which is what we do
currently but that's we would want to change).

With the separation we can actually destroy the data depending on where
it was set and do everything unambigiously.
2015-08-23 20:01:42 +02:00
Thomas Martitz
58c8144afc plugins: Pass pdata to PluginCallback function by default
If the plugin did not set its own user_data we set it to whatever it set
with geany_plugin_register_full() or geany_plugin_set_data().
This is particularly convinient because PluginCallback is usually statically
allocated, at which point dynamically allocated plugin data doesn't exists yet.
2015-08-23 20:01:41 +02:00
Thomas Martitz
43c58e0fdd plugins: change return codes of geany_load_module() and GeanyPluginFuncs::init
- The return value from geany_load_module is removed (void). It was ignored
  anyway and we have to check separately whether the plugin loaded OK or not
  anyway. If the plugin specific code fails it should simply not call
  geany_plugin_register() (which it should only call iff all other conditions
  are good).

- GeanyPluginFuncs::init() now returns a bool to allow failing initialization.
  Some plugins might want to defer work to their init() (i.e. only do
  it when the plugin was activated by the user), and some of that work can
  possibly fail (e.g. GtkBuilder fails to load .xml).

Note that the GUI integration of the latter is less than ideal but this kind
of GUI/policy work is out of scope for this patch set. Therefore a plugin
failing to init is simply removed from the PM dialog as if it became
incompatible. However, as the code that generates the list does not call init
they will show up again if the PM dialog is re-opened.
2015-08-23 20:01:41 +02:00
Thomas Martitz
75827c69c0 plugins: Refactor legacy plugin support
With geany_plugin_set_data() the legacy plugin support can be made
more transparent by using wrapper functions that call the actual plugin_*
functions. This allows to remove the differentiation in code that's not
directly concerned with actually loading plugins.

This commit doesn't change anything except for one thing: legacy plugins now
cannot call geany_plugin_set_data(). But it is meant for new-style plugins
anyway.
2015-08-23 20:01:38 +02:00
Thomas Martitz
f2579141bb plugins: Replace geany_plugin_register() pdata with a separate API function
The API function adds a free_func parameter, and can also be called
after geany_plugin_register(), i.e. in the plugin's init() callback. This
fixes a by-design memory leak and gives greater flexibility.
2015-08-23 15:23:24 +02:00
Thomas Martitz
babf008335 plugins: Let plugins fill GeanyPlugin::callbacks instead of passing their own pointer
This is easier to handle if we decide to add callbacks. Since we can
zero-initialize callbacks before passing it to the plugin we can be certain as
to which callbacks the plugin knew about when it was compiled. This is exactly
the same method used for GeanyPlugin::info already and easier than inspecting
the API version.
2015-08-23 15:23:22 +02:00
Thomas Martitz
721009e262 plugins: plugin loader redesign
The old plugin loader has a number of deficiencies:

- plugins need to export a couple of callback functions into the global namespace
- plugins need to export data pointers, that are written by Geany
- the exported functions have no user_data param, so there is no way to
  pass context/state back to the plugin (it needs global storage for that)
- plugin registration is implicit, plugins have no way to not register themselves
  (it may want that due to missing runtime dependencies)
- plugins perform the ABI/API verification, and even though we provide a
  convinience wrapper, it may get that wrong

As a result, I designed a new loader with the following design principles
- semantics of callbacks should not change, but they they shouldn't be mess
  with the global namespace
- each callback receives a self-identifying param (the GeanyPlugin instance) and
  a plugin-defined data pointer for their own use
- explicit registration through a new API function
- in-core API/ABI checks

The following principles shall be left unchanged:
- The scan is done on startup and when the PM dialog is opened
- Geany allocates GeanyPluginPrivate for each plugin, and GeanyPlugin is
  a member of it
- Geany initially probes for the validity of the plugin, including file type
  and API/ABI check, thus Geany has the last word in determining what a
  plugin is
- the PM dialog is updated with the proper, translated plugin information
- the PM dialog GUI and user interaction in general is unchanged

With the redesign, plugins export a single function: geany_load_module().
This is called when the GModule is loaded. The main purpose of this function
is to call geany_plugin_register() (new API function) to register the plugin.
This is the only function that is learned about through g_module_symbol().
Within this call the plugin should
a) set the localized info fields of GeanyPlugin::info
b) pass compiled-against and minimum API version as well as compiled-against
   ABI version, to allow Geany to verify compatibility
c) pass a pointer to an instance of GeanyPluginFuncs
   which holds pointers to enhanced versions of the known callbacks (except
   configure_single which is dropped).
d) optionally pass a plugin-private data pointer for later callbacks

Enhanced means that all callbacks receive the GeanyPlugin pointer as the first
and a pdata pointer as the last. pdata is private to the plugin and is set
by geany_plugin_register().

The callbacks need (should) not be globally defined anymore, and the global
GeanyData, GeanyPlugin and GeanyFunctions pointers are ignored and not set
anymore. GeanyData is available through GeanyPlugin::geany_data.
2015-08-23 15:23:20 +02:00
Enrico Tröger
ccec1fe29a Merge pull request #414 from eht16/plugin_manager_usability
Plugin manager usability improvements
2015-06-05 18:45:56 +02:00
Jiří Techet
65c34bd37e Improved search for the plugin manager
Search in name, description, author fields and show all results
which contain all the words from the search query.
Search plugins also by filename
2015-06-05 18:44:04 +02:00
Enrico Tröger
b0f7f2859b Add a filter entry in the plugin manager dialog
Let the user filter plugins by searching the plugin names and descriptions.
While at it, group the plugin buttons into the dialog's action area to
save some space.
Rename OK button to Close in the plugin manager dialog
Set the input focus to the filter entry and set initial plugin button state
2015-04-14 22:18:28 +02:00
Enrico Tröger
0f179331ef Add a popup menu to the plugin list in the plugin manager dialog
This makes it easier to reach plugins' configure, keybindings and help
functions.
2015-03-23 15:16:44 +01:00
Matthew Brush
860df27696 Remove struct/macro/funcptr linkage control for plugin API
Add rest of headers needed for declarations of all public API
functions. Add HAVE_PLUGINS define to geanyplugins.h since some headers
need this and it should always be valid for this header.
geanyfunctions.h left for source-level backwards compatibility for
plugins which might `#include` this header directly. I don't know why
they do it, but some Geany-Plugins do this.
2015-03-10 22:06:47 +01:00
Jiří Techet
18d517bd95 Use gtk-mac-integration so app bundle can be created on OS X
This patch adds the gtk-mac-integration library and uses it to
adjust various paths in Geany to point it inside the app bundle
if Geany runs from inside the bundle.

It adds the utils_resource_dir() utility function to return
correct directories for various kinds of resources for all supported
operating systems. Using this function the patch adjusts all Geany
resource, plugin, icon, doc, and locale paths.
2015-03-04 12:40:27 +01:00
Colomban Wendling
1c1d76721d Fix several tooltips to properly use plain text instead of markup
Most of our tree view tooltips were set from plain text values but
parsed as markup by GTK, which sometimes lead to markup errors, when
the tooltip value contained markup control characters.

This also adds ui_tree_view_set_tooltip_text_column() to the plugin
API so plugins can easily set plain text tooltips from tree views
columns.

Fixes https://sourceforge.net/p/geany/bugs/1091/
2015-02-28 19:15:00 +01:00
Jiří Techet
daecf69c9c Make keybindings_get_modifiers() part of plugin API 2015-01-20 19:33:06 +01:00
Colomban Wendling
87331093a9 Merge pull request #361 from techee/prj_write
Add project_write_config() to force project file rewrite
2014-12-11 00:07:41 +01:00
Colomban Wendling
8c77accfd0 Merge PR#356 from 'b4n/techee/tm'
Huge TagManager improvements
2014-11-08 19:37:20 +01:00
Jiří Techet
a95fc1a994 Don't expose the source file update function to plugins 2014-11-05 21:50:07 +01:00
Jiří Techet
71cc1ecb20 Cleaner and safer TMWorkspace API
With the previous TMWorkspace API it was possible to make the workspace
inconsistent by e.g. removing source files and forgetting to update
workspace. This could lead to non-obvious and not immediately visible
crashes.

The new set of the public (but also Geany private) API calls always
updates the workspace accordingly and neither of the calls can lead
to an inconsistent state of the workspace.

In addition, perform some minor cleanups and simplifications - unify
parsing from buffer and from file, support "parsing" of 0-sized buffers
and improve documentation.
2014-11-02 11:39:57 +01:00
Jiří Techet
0285ec28a5 Move tm_source_file_update() to tm_workspace.c
The placement of this function in tm_source_file is not right - by moving
it to the workspace we can make the source file unaware of the existence
of the workspace (no inclusion of tm_workspace.h in tm_source_file any
more). Also change tm_source_file_new() so it doesn't offer the source file
update.

After this change
* TMWorkspace knows TMSourceFile and TMTag
* TMSourceFile knows TMTag
* TMTag knows TMSourceFile
2014-10-30 22:08:17 +01:00
Jiří Techet
233ca08e88 Add project_write_config() to force project file rewrite
Since plugins don't have direct access to the project file,
only through the project-save signal, they need some way to emit this
signal when saving their preferences outside the project dialog,
which is what this function does.
2014-10-25 22:30:54 +02:00
Colomban Wendling
c35dedf35f Rename internal plugin_init() to avoid confusion with plugins entry point 2014-10-20 16:18:05 +02:00
Jiří Techet
8c25ff871c Make tm_workspace_update() public 2014-10-18 21:40:10 +02:00
Jiří Techet
26587454b0 Remove TmWorkObject and all the OO related stuff
In addition, rename all functions, parameters, comments etc. mentioning
work_object and remove unnecessary parameters of various functions.
Delete dead code paths.

Also move common functions like tm_get_real_path() from tm_work_object to
tm_source_file.
2014-10-18 21:40:10 +02:00
Nick Treleaven
9d669a72f7 API: Rename document_reload_file -> document_reload_force
New name is clearer against document_reload_prompt.
Add deprecated alias.
2014-09-25 11:45:49 +01:00
Nick Treleaven
18181c2e90 Support pseudo-unique IDs for documents
Add GeanyDocument::id, document_find_by_id() to plugin API.

This also fixes clicking on a Messages item whose document has been
closed and reused. Now the click will be ignored instead of jumping to
an unexpected line in the new document.
2014-08-19 15:40:05 +01:00
Nick Treleaven
e1988964c1 Fix Windows build 2014-08-01 12:05:30 +01:00
Matthew Brush
4efcbab332 Include what you use
This is a mega-commit - because most of it had to be done in one go
otherwise some commits would fail to compile - that attempts to fix a
few problems with Geany's includes as well as various other related
cleanups. After this change it's easier to use includes and there's
little worry about which order things are included in or who includes
what.

Overview of changes:

* Include config.h at the start of each source file if HAVE_CONFIG_H
  is defined (and never in headers).
* Go through each source file and make the includes section generally
  like this:
  - Always config.h first as above
  - Then if the file has a header with the same name, include that
  - Then include in alphabetical order each other internal/geany header.
  - Then include standard headers
  - Then include non-standard system headers
  - Then include GLib/GTK+ related stuff
* Doing as above makes it easier to find implicit header include
  dependencies and it exposed quite a few weird problems with includes
  or forward declarations, fix those.
* Make geany.h contain not much besides some defines.
  - Add a little header file "app.h" for GeanyApp and move it there
  - Move "app" global to new "app.h" file
  - Move "ignore_callback" global to "callbacks.h"
  - Move "geany_object" global to "geanyobject.h"
* Add an include in "geany.h" for "app.h" since GeanyApp used to be
  defined there and some plugins included this header to access
  GeanyApp.
* Include "gtkcompat.h" everywhere instead of gtk/gtk.h so that
  everywhere sees the same definitions (not a problem in practice AFAIK
  so this could be changed back if better that way.
* Remove forward declarations from previous commits as some people
  apparently consider this bad style, despite that it reduces inter-
  header dependencies.

TODO:
* As always, to test on win32
* As always, to test with not Autotools
* Test plugins better, both builtin and geany-plugins, likely API/ABI bump
* Test with various defines/flags that may change what is included
* win32.[ch] not really touched since I couldn't test
2014-05-21 15:37:19 -07:00
Matthew Brush
23d9cad7dc Start to make it easier to compile the core in isolation
This is for work on making the files scannable by GObject-Introspection
but is still useful otherwise (even fixes a FIXME in the comments). I
made this by using a simple GNU Make file and trying to compile the
sources each on their own without all the build system infrastructure.

* Add keybindingsprivate.h file to hold private GeanyKeyGroup structure
and remove it from the GEANY_PRIVATE guard in keybindings.h.
* Move private members that were guarded by GEANY_PRIVATE from
GeanyFiletypes to GeanyFiletypesPrivate and remove guarded build.h
include.
* Move private members that were guarded by GEANY_PRIVATE from
GeanyProject to GeanyProjectPrivate.
2014-05-21 12:17:59 -07:00
Colomban Wendling
a13b033d42 Hide column headers in plugin manager dialog
They are not very useful and waste both vertical (the headers
themselves) and horizontal (first column wider because of title)
screen space.
2014-05-01 03:18:04 +02:00
Colomban Wendling
605ec0b02e Cleanup Plugin Manager dialog
Merge "Name" and "Description" columns, and move plugin details to
tooltips.
2014-04-25 18:46:14 +02:00
Colomban Wendling
27a073f1a6 Make plugin_signal_connect() safe on any object
Watch the lifetime of objects referenced in plugin->signal_ids and
remove our references to them if they get destroyed.  This avoids
possibly trying to disconnect signals on destroyed objects when the
plugin is unloaded.

Supporting this case is safer, and is useful for objects that may or
may not outlive the plugin (like ScintillaObjects), because in such
cases plugin_signal_connect() is handy to make sure the signals are
disconnected if the object is still alive, but used to crash if the
object was destroyed.
2014-04-13 19:59:37 +02:00
Matthew Brush
d44dfdb9ac Save configuration when plugin manager dialog is closed
Closes #62
2013-08-15 18:53:21 -07:00
Nick Treleaven
0998f1c19c Make code more readable by renaming poorly named macros NZV and NVL
Closes #159
2013-08-14 21:54:20 -07:00
Matthew Brush
13ec6ffbea Add new API function plugin_builder_connect_signals() 2013-06-09 15:22:25 -07:00
Matthew Brush
44fcdf1b7c Minor tweak to plugin manager button spacing 2013-05-25 17:02:49 -07:00
Pavel Roschin
169a2f4957 Keybindings for plugins 2013-05-25 16:49:06 -07:00
Colomban Wendling
c1a7b1b475 Fix various packing issue affecting GTK3 but compatible with GTK2 2012-09-28 18:06:58 +02:00
Colomban Wendling
d80bc7ce56 Update FSF address
Closes #3557875.
2012-08-24 19:25:57 +02:00
Matthew Brush
9a63e05f63 Change plugin manager's OK button response to GTK_RESPONSE_OK
Used to be GTK_RESPONSE_CANCEL for some reason.
2012-08-09 22:36:03 -07:00