[gnome-documents/wip/gepub: 1/6] Rewrite implementation of GActions
- From: Cosimo Cecchi <cosimoc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-documents/wip/gepub: 1/6] Rewrite implementation of GActions
- Date: Wed, 22 Jun 2016 13:49:01 +0000 (UTC)
commit b2c659822069feebeccfd2f312bde02705d626f6
Author: Cosimo Cecchi <cosimoc gnome org>
Date: Tue Jun 21 20:29:18 2016 -0700
Rewrite implementation of GActions
Instead of having global application actions everywhere, use an action
group for the preview.
This allows each view to have a much finer grained control over the
actions, their activation and lifecycle, and removes awkward roundtrips
to the application singleton to disconnect signals when a view is
destroyed, since now actions live as long as their views.
Finally, we can now use "hidden-when=action-missing" attributes in the
menu definition to automatically get menu sections removed when a view
does not support the actions.
Note that further cleanups could be done; in particular, the overview
implementation could benefit from the same treatment, and the "search"
action should be separated between in-view find and actual tracker
search.
data/ui/preview-context-menu.ui | 2 +-
data/ui/preview-menu.ui | 24 ++--
src/application.js | 130 ++----------------
src/edit.js | 23 +---
src/embed.js | 34 +++--
src/epubview.js | 20 ++-
src/evinceview.js | 277 +++++++++++++++++++++------------------
src/lokview.js | 129 +++++++-----------
src/mainWindow.js | 2 +-
src/preview.js | 68 +++++++---
src/utils.js | 35 +++++
11 files changed, 352 insertions(+), 392 deletions(-)
---
diff --git a/data/ui/preview-context-menu.ui b/data/ui/preview-context-menu.ui
index c4a7212..027f2c9 100644
--- a/data/ui/preview-context-menu.ui
+++ b/data/ui/preview-context-menu.ui
@@ -2,7 +2,7 @@
<menu id="preview-context-menu">
<section>
<item>
- <attribute name="action">app.copy</attribute>
+ <attribute name="action">view.copy</attribute>
<attribute name="label" translatable="yes">_Copy</attribute>
<attribute name="accel"><Primary>c</attribute>
</item>
diff --git a/data/ui/preview-menu.ui b/data/ui/preview-menu.ui
index 0550027..b2e7190 100644
--- a/data/ui/preview-menu.ui
+++ b/data/ui/preview-menu.ui
@@ -2,20 +2,22 @@
<menu id="preview-menu">
<section id="open-section">
<item>
- <attribute name="action">app.open-current</attribute>
+ <attribute name="action">view.open-current</attribute>
<attribute name="label" translatable="yes">Open</attribute>
</item>
<item>
- <attribute name="action">app.edit-current</attribute>
+ <attribute name="action">view.edit-current</attribute>
<attribute name="label" translatable="yes">Edit</attribute>
+ <attribute name='hidden-when'>action-missing</attribute>
</item>
<item>
- <attribute name="action">app.print-current</attribute>
+ <attribute name="action">view.print-current</attribute>
<attribute name="label" translatable="yes">Print…</attribute>
<attribute name="accel"><Primary>p</attribute>
+ <attribute name='hidden-when'>action-missing</attribute>
</item>
<item>
- <attribute name="action">app.present-current</attribute>
+ <attribute name="action">view.present-current</attribute>
<attribute name='hidden-when'>action-missing</attribute>
<attribute name="label" translatable="yes">Present</attribute>
<attribute name="accel">F5</attribute>
@@ -23,31 +25,35 @@
</section>
<section>
<item>
- <attribute name="action">app.zoom-in</attribute>
+ <attribute name="action">view.zoom-in</attribute>
+ <attribute name='hidden-when'>action-missing</attribute>
<attribute name="label" translatable="yes">Zoom In</attribute>
<attribute name="accel"><Primary>plus</attribute>
</item>
<item>
- <attribute name="action">app.zoom-out</attribute>
+ <attribute name="action">view.zoom-out</attribute>
+ <attribute name='hidden-when'>action-missing</attribute>
<attribute name="label" translatable="yes">Zoom Out</attribute>
<attribute name="accel"><Primary>minus</attribute>
</item>
</section>
<section id='rotate-section'>
<item>
- <attribute name="action">app.rotate-left</attribute>
+ <attribute name="action">view.rotate-left</attribute>
+ <attribute name='hidden-when'>action-missing</attribute>
<attribute name="label" translatable="yes">Rotate ↶</attribute>
<attribute name="accel"><Primary>Left</attribute>
</item>
<item>
- <attribute name="action">app.rotate-right</attribute>
+ <attribute name="action">view.rotate-right</attribute>
+ <attribute name='hidden-when'>action-missing</attribute>
<attribute name="label" translatable="yes">Rotate ↷</attribute>
<attribute name="accel"><Primary>Right</attribute>
</item>
</section>
<section>
<item>
- <attribute name="action">app.properties</attribute>
+ <attribute name="action">view.properties</attribute>
<attribute name="label" translatable="yes">Properties</attribute>
</item>
</section>
diff --git a/src/application.js b/src/application.js
index ba84ec3..58c2005 100644
--- a/src/application.js
+++ b/src/application.js
@@ -248,63 +248,6 @@ const Application = new Lang.Class({
settings.set_value('sort-by', parameter);
},
- _onActionOpenCurrent: function() {
- let doc = documentManager.getActiveItem();
- if (doc)
- doc.open(this._mainWindow.get_screen(), Gtk.get_current_event_time());
- },
-
- _onActionPrintCurrent: function() {
- let doc = documentManager.getActiveItem();
- if (doc)
- doc.print(this._mainWindow);
- },
-
- _onActionToggle: function(action) {
- let state = action.get_state();
- action.change_state(GLib.Variant.new('b', !state.get_boolean()));
- },
-
- _onActionProperties: function() {
- let doc = documentManager.getActiveItem();
- if (!doc)
- return;
-
- let dialog = new Properties.PropertiesDialog(doc.id);
- dialog.connect('response', Lang.bind(this,
- function(widget, response) {
- widget.destroy();
- }));
- },
-
- _initActions: function() {
- this._actionEntries.forEach(Lang.bind(this,
- function(actionEntry) {
- let state = actionEntry.state;
- let parameterType = actionEntry.parameter_type ?
- GLib.VariantType.new(actionEntry.parameter_type) : null;
- let action;
-
- if (state)
- action = Gio.SimpleAction.new_stateful(actionEntry.name,
- parameterType, actionEntry.state);
- else
- action = new Gio.SimpleAction({ name: actionEntry.name,
- parameter_type: parameterType });
-
- if (actionEntry.create_hook)
- actionEntry.create_hook.apply(this, [action]);
-
- if (actionEntry.callback)
- action.connect('activate', Lang.bind(this, actionEntry.callback));
-
- if (actionEntry.accels)
- this.set_accels_for_action('app.' + actionEntry.name, actionEntry.accels);
-
- this.add_action(action);
- }));
- },
-
_connectActionsToMode: function() {
this._actionEntries.forEach(Lang.bind(this,
function(actionEntry) {
@@ -519,70 +462,49 @@ const Application = new Lang.Class({
this._actionEntries = [
{ name: 'quit',
- callback: this._onActionQuit,
+ callback: Lang.bind(this, this._onActionQuit),
accels: ['<Primary>q'] },
{ name: 'about',
- callback: this._onActionAbout },
+ callback: Lang.bind(this, this._onActionAbout) },
{ name: 'help',
- callback: this._onActionHelp,
+ callback: Lang.bind(this, this._onActionHelp),
accels: ['F1'] },
{ name: 'fullscreen',
- callback: this._onActionFullscreen,
+ callback: Lang.bind(this, this._onActionFullscreen),
state: GLib.Variant.new('b', false),
- create_hook: this._fullscreenCreateHook,
+ create_hook: Lang.bind(this, this._fullscreenCreateHook),
accels: ['F11'],
window_mode: WindowMode.WindowMode.PREVIEW_EV },
{ name: 'night-mode',
- callback: this._onActionNightMode,
- create_hook: this._nightModeCreateHook,
+ callback: Lang.bind(this, this._onActionNightMode),
+ create_hook: Lang.bind(this, this._nightModeCreateHook),
state: settings.get_value('night-mode') },
{ name: 'gear-menu',
- callback: this._onActionToggle,
+ callback: Utils.actionToggleCallback,
state: GLib.Variant.new('b', false),
accels: ['F10'] },
{ name: 'view-as',
- callback: this._onActionViewAs,
- create_hook: this._viewAsCreateHook,
+ callback: Lang.bind(this, this._onActionViewAs),
+ create_hook: Lang.bind(this, this._viewAsCreateHook),
parameter_type: 's',
state: settings.get_value('view-as'),
window_modes: [WindowMode.WindowMode.COLLECTIONS,
WindowMode.WindowMode.DOCUMENTS,
WindowMode.WindowMode.SEARCH] },
{ name: 'sort-by',
- callback: this._onActionSortBy,
- create_hook: this._sortByCreateHook,
+ callback: Lang.bind(this, this._onActionSortBy),
+ create_hook: Lang.bind(this, this._sortByCreateHook),
parameter_type: 's',
state: settings.get_value('sort-by'),
window_modes: [WindowMode.WindowMode.COLLECTIONS,
WindowMode.WindowMode.DOCUMENTS,
WindowMode.WindowMode.SEARCH] },
- { name: 'open-current',
- callback: this._onActionOpenCurrent,
- window_modes: [WindowMode.WindowMode.PREVIEW_EV,
- WindowMode.WindowMode.PREVIEW_LOK] },
- { name: 'edit-current' },
{ name: 'view-current',
window_mode: WindowMode.WindowMode.EDIT },
- { name: 'print-current', accels: ['<Primary>p'],
- callback: this._onActionPrintCurrent },
{ name: 'search',
- callback: this._onActionToggle,
+ callback: Utils.actionToggleCallback,
state: GLib.Variant.new('b', false),
accels: ['<Primary>f'] },
- { name: 'find-next', accels: ['<Primary>g'],
- window_mode: WindowMode.WindowMode.PREVIEW_EV },
- { name: 'find-prev', accels: ['<Shift><Primary>g'],
- window_mode: WindowMode.WindowMode.PREVIEW_EV },
- { name: 'zoom-in', accels: ['<Primary>plus', '<Primary>equal'],
- window_modes: [WindowMode.WindowMode.PREVIEW_EV,
- WindowMode.WindowMode.PREVIEW_LOK] },
- { name: 'zoom-out', accels: ['<Primary>minus'],
- window_modes: [WindowMode.WindowMode.PREVIEW_EV,
- WindowMode.WindowMode.PREVIEW_LOK] },
- { name: 'rotate-left', accels: ['<Primary>Left'],
- window_mode: WindowMode.WindowMode.PREVIEW_EV },
- { name: 'rotate-right', accels: ['<Primary>Right'],
- window_mode: WindowMode.WindowMode.PREVIEW_EV },
{ name: 'select-all', accels: ['<Primary>a'],
window_modes: [WindowMode.WindowMode.COLLECTIONS,
WindowMode.WindowMode.DOCUMENTS,
@@ -591,21 +513,6 @@ const Application = new Lang.Class({
window_modes: [WindowMode.WindowMode.COLLECTIONS,
WindowMode.WindowMode.DOCUMENTS,
WindowMode.WindowMode.SEARCH] },
- { name: 'properties',
- callback: this._onActionProperties,
- window_modes: [WindowMode.WindowMode.PREVIEW_EV,
- WindowMode.WindowMode.PREVIEW_LOK] },
- { name: 'bookmark-page',
- callback: this._onActionToggle,
- state: GLib.Variant.new('b', false),
- accels: ['<Primary>d'],
- window_mode: WindowMode.WindowMode.PREVIEW_EV },
- { name: 'places',
- accels: ['<Primary>b'],
- window_mode: WindowMode.WindowMode.PREVIEW_EV },
- { name: 'copy',
- accels: ['<Primary>c'],
- window_mode: WindowMode.WindowMode.PREVIEW_EV },
{ name: 'search-source',
parameter_type: 's',
state: GLib.Variant.new('s', Search.SearchSourceStock.ALL),
@@ -626,17 +533,10 @@ const Application = new Lang.Class({
WindowMode.WindowMode.SEARCH] }
];
- if (!this.isBooks) {
- this._actionEntries.push (
- { name: 'present-current',
- window_mode: WindowMode.WindowMode.PREVIEW_EV,
- callback: this._onActionToggle,
- state: GLib.Variant.new('b', false),
- accels: ['F5'] });
+ if (!this.isBooks)
this._initGettingStarted();
- }
- this._initActions();
+ Utils.populateActionGroup(this, this._actionEntries, 'app');
},
_createWindow: function() {
diff --git a/src/edit.js b/src/edit.js
index 85d063e..187b1ea 100644
--- a/src/edit.js
+++ b/src/edit.js
@@ -59,17 +59,6 @@ const EditView = new Lang.Class({
this.show_all();
- this._editAction = Application.application.lookup_action('edit-current');
- this._editAction.enabled = false;
- this._editAction.connect('activate', Lang.bind(this,
- function() {
- let doc = Application.documentManager.getActiveItem();
- if (!doc)
- return;
- Application.modeController.setWindowMode(WindowMode.WindowMode.EDIT);
- this.setUri (doc.uri);
- }));
-
this._viewAction = Application.application.lookup_action('view-current');
this._viewAction.enabled = false;
this._viewAction.connect('activate', Lang.bind(this,
@@ -77,9 +66,6 @@ const EditView = new Lang.Class({
Application.modeController.goBack();
}));
- this._printAction = Application.application.lookup_action('print-current');
- this._printAction.set_enabled(false);
-
Application.documentManager.connect('load-started',
Lang.bind(this, this._onLoadStarted));
Application.documentManager.connect('load-finished',
@@ -88,19 +74,12 @@ const EditView = new Lang.Class({
},
_onLoadStarted: function() {
- this._editAction.enabled = false;
this._viewAction.enabled = false;
- this._printAction.set_enabled(false);
},
_onLoadFinished: function(manager, doc, docModel) {
- if (doc.uri) {
- if (doc.canEdit())
- this._editAction.enabled = true;
+ if (doc.uri)
this._viewAction.enabled = true;
- if (doc.canPrint(docModel))
- this._printAction.set_enabled(true);
- }
},
_createView: function() {
diff --git a/src/embed.js b/src/embed.js
index acf40e1..2ab34fd 100644
--- a/src/embed.js
+++ b/src/embed.js
@@ -47,9 +47,10 @@ const Embed = new Lang.Class({
Name: 'Embed',
Extends: Gtk.Box,
- _init: function() {
+ _init: function(mainWindow) {
this._loadShowId = 0;
this._searchState = null;
+ this._window = mainWindow;
this.parent({ orientation: Gtk.Orientation.VERTICAL,
visible: true });
@@ -316,6 +317,7 @@ const Embed = new Lang.Class({
let windowMode = Application.modeController.getWindowMode();
let showSearch = (windowMode == WindowMode.WindowMode.PREVIEW_EV && !doc
|| windowMode == WindowMode.WindowMode.SEARCH && !doc);
+
if (showSearch)
this._restoreSearch();
else
@@ -375,6 +377,15 @@ const Embed = new Lang.Class({
}));
},
+ _clearPreview: function() {
+ if (this._preview) {
+ this._preview.destroy();
+ this._preview = null;
+ }
+
+ this._window.insert_action_group('view', null);
+ },
+
_prepareForOverview: function(newMode, oldMode) {
let createToolbar = (oldMode != WindowMode.WindowMode.COLLECTIONS &&
oldMode != WindowMode.WindowMode.DOCUMENTS &&
@@ -397,11 +408,7 @@ const Embed = new Lang.Class({
break;
}
- if (this._preview) {
- this._preview.destroy();
- this._preview = null;
- }
-
+ this._clearPreview();
if (this._edit)
this._edit.setUri(null);
@@ -419,16 +426,14 @@ const Embed = new Lang.Class({
},
_prepareForPreview: function(constructor) {
- if (this._preview) {
- this._preview.destroy();
- this._preview = null;
- }
+ this._clearPreview();
if (this._edit)
this._edit.setUri(null);
if (this._toolbar)
this._toolbar.destroy();
- this._preview = new constructor(this._stackOverlay);
+ this._preview = new constructor(this._stackOverlay, this._window);
+ this._window.insert_action_group('view', this._preview.actionGroup);
this._stack.add_named(this._preview, 'preview');
// pack the toolbar
@@ -439,10 +444,7 @@ const Embed = new Lang.Class({
},
_prepareForEdit: function() {
- if (this._preview) {
- this._preview.destroy();
- this._preview = null;
- }
+ this._clearPreview();
if (this._toolbar)
this._toolbar.destroy();
@@ -450,6 +452,8 @@ const Embed = new Lang.Class({
this._toolbar = new Edit.EditToolbar(this._preview);
this._titlebar.add(this._toolbar);
+ let doc = Application.documentManager.getActiveItem();
+ this._edit.setUri(doc.uri);
this._stack.set_visible_child_name('edit');
},
diff --git a/src/epubview.js b/src/epubview.js
index 0417d41..4e19a39 100644
--- a/src/epubview.js
+++ b/src/epubview.js
@@ -44,6 +44,17 @@ const EPUBView = new Lang.Class({
Name: 'EPUBView',
Extends: Preview.Preview,
+ createActions: function() {
+ return [
+ { name: 'find-prev',
+ callback: Lang.bind(this, this.findPrev),
+ accels: ['<Shift><Primary>g'] },
+ { name: 'find-next',
+ callback: Lang.bind(this, this.findNext),
+ accels: ['<Primary>g'] },
+ ];
+ },
+
createToolbar: function() {
return new EPUBViewToolbar(this);
},
@@ -119,10 +130,8 @@ const EPUBSearchbar = new Lang.Class({
},
_onSearchChanged: function(view, hasResults) {
- let findPrev = Application.application.lookup_action('find-prev');
- let findNext = Application.application.lookup_action('find-next');
- findPrev.enabled = hasResults;
- findNext.enabled = hasResults;
+ this.preview.getAction('find-prev').enabled = hasResults;
+ this.preview.getAction('find-next').enabled = hasResults;
},
conceal: function() {
@@ -149,9 +158,6 @@ const EPUBViewToolbar = new Lang.Class({
this._searchAction = Application.application.lookup_action('search');
this._searchAction.enabled = true;
- this._gearMenu = Application.application.lookup_action('gear-menu');
- this._gearMenu.enabled = true;
-
// back button, on the left of the toolbar
let backButton = this.addBackButton();
backButton.connect('clicked', Lang.bind(this, function() {
diff --git a/src/evinceview.js b/src/evinceview.js
index c922e18..04c8ad6 100644
--- a/src/evinceview.js
+++ b/src/evinceview.js
@@ -46,7 +46,7 @@ const EvinceView = new Lang.Class({
Name: 'EvinceView',
Extends: Preview.Preview,
- _init: function(overlay) {
+ _init: function(overlay, mainWindow) {
this._model = null;
this._jobFind = null;
this._controlsFlipId = 0;
@@ -56,7 +56,7 @@ const EvinceView = new Lang.Class({
this._viewSelectionChanged = false;
this._fsToolbar = null;
- this.parent(overlay);
+ this.parent(overlay, mainWindow);
Application.modeController.connect('fullscreen-changed', Lang.bind(this,
this._onFullscreenChanged));
@@ -68,71 +68,136 @@ const EvinceView = new Lang.Class({
this._previewContextMenu = Gtk.Menu.new_from_model(model);
this._previewContextMenu.attach_to_widget(this.view, null);
- this._bookmarkPage = Application.application.lookup_action('bookmark-page');
- this._bookmarkPage.enabled = false;
- let bookmarkPageId = Application.application.connect('action-state-changed::bookmark-page',
- Lang.bind(this, this._onActionStateChanged));
+ this.getAction('bookmark-page').enabled = false;
- this._zoomIn = Application.application.lookup_action('zoom-in');
- let zoomInId = this._zoomIn.connect('activate', Lang.bind(this,
- function() {
- if (!this._model)
- return;
- this._model.set_sizing_mode(EvView.SizingMode.FREE);
- this._evView.zoom_in();
- }));
+ let nightModeId = Application.application.connect('action-state-changed::night-mode',
+ Lang.bind(this, this._updateNightMode));
- this._zoomOut = Application.application.lookup_action('zoom-out');
- let zoomOutId = this._zoomOut.connect('activate', Lang.bind(this,
+ this.connect('destroy', Lang.bind(this,
function() {
- if (!this._model)
- return;
- this._model.set_sizing_mode(EvView.SizingMode.FREE);
- this._evView.zoom_out();
+ Application.application.disconnect(nightModeId);
}));
+ },
- this._copy = Application.application.lookup_action('copy');
- let copyId = this._copy.connect('activate', Lang.bind(this,
- function() {
- this._evView.copy();
- }));
+ _copy: function() {
+ this._evView.copy();
+ },
- let rotLeft = Application.application.lookup_action('rotate-left');
- let rotLeftId = rotLeft.connect('activate', Lang.bind(this,
- function() {
- this._changeRotation(-90);
- }));
- let rotRight = Application.application.lookup_action('rotate-right');
- let rotRightId = rotRight.connect('activate', Lang.bind(this,
- function() {
- this._changeRotation(90);
- }));
- this._places = Application.application.lookup_action('places');
- let placesId = this._places.connect('activate', Lang.bind(this, this._showPlaces));
+ _zoomIn: function() {
+ if (!this._model)
+ return;
+ this._model.set_sizing_mode(EvView.SizingMode.FREE);
+ this._evView.zoom_in();
+ },
- let nightModeId = Application.application.connect('action-state-changed::night-mode',
- Lang.bind(this, this._updateNightMode));
+ _zoomOut: function() {
+ if (!this._model)
+ return;
+ this._model.set_sizing_mode(EvView.SizingMode.FREE);
+ this._evView.zoom_out();
+ },
- this._togglePresentation = Application.application.lookup_action('present-current');
- if (!Application.application.isBooks) {
- var presentCurrentId = Application.application.connect('action-state-changed::present-current',
- Lang.bind(this, this._onPresentStateChanged));
- }
+ _rotateLeft: function() {
+ let rotation = this._model.get_rotation();
+ this._model.set_rotation(rotation - 90);
+ },
- this.connect('destroy', Lang.bind(this,
- function() {
- this._zoomIn.disconnect(zoomInId);
- this._zoomOut.disconnect(zoomOutId);
- this._copy.disconnect(copyId);
- rotLeft.disconnect(rotLeftId);
- rotRight.disconnect(rotRightId);
- this._places.disconnect(placesId);
- if (!Application.application.isBooks)
- Application.application.disconnect(presentCurrentId);
-
- Application.application.disconnect(bookmarkPageId);
- Application.application.disconnect(nightModeId);
- }));
+ _rotateRight: function() {
+ let rotation = this._model.get_rotation();
+ this._model.set_rotation(rotation + 90);
+ },
+
+ findPrev: function() {
+ this._evView.find_previous();
+ },
+
+ findNext: function() {
+ this._evView.find_next();
+ },
+
+ _places: function() {
+ let dialog = new Places.PlacesDialog(this._model, this._bookmarks);
+ dialog.connect('response', Lang.bind(this, function(widget, response) {
+ widget.destroy();
+ }));
+ },
+
+ _bookmarkStateChanged: function(action) {
+ let pageNumber = this._model.page;
+ let bookmark = new GdPrivate.Bookmark({ page_number: pageNumber });
+
+ if (action.state.get_boolean())
+ this._bookmarks.add(bookmark);
+ else
+ this._bookmarks.remove(bookmark);
+ },
+
+ _presentStateChanged: function(action) {
+ if (!this._model)
+ return;
+
+ if (action.state.get_boolean())
+ this._promptPresentation();
+ else
+ this._hidePresentation();
+ },
+
+ _edit: function() {
+ Application.modeController.setWindowMode(WindowMode.WindowMode.EDIT);
+ },
+
+ _print: function() {
+ let doc = Application.documentManager.getActiveItem();
+ if (doc)
+ doc.print(this.mainWindow);
+ },
+
+ createActions: function() {
+ let actions = [
+ { name: 'zoom-in',
+ callback: Lang.bind(this, this._zoomIn),
+ accels: ['<Primary>plus', '<Primary>equal'] },
+ { name: 'zoom-out',
+ callback: Lang.bind(this, this._zoomOut),
+ accels: ['<Primary>minus'] },
+ { name: 'copy',
+ callback: Lang.bind(this, this._copy),
+ accels: ['<Primary>c'] },
+ { name: 'rotate-left',
+ callback: Lang.bind(this, this._rotateLeft),
+ accels: ['<Primary>Left'] },
+ { name: 'rotate-right',
+ callback: Lang.bind(this, this._rotateRight),
+ accels: ['<Primary>Right'] },
+ { name: 'find-prev',
+ callback: Lang.bind(this, this.findPrev),
+ accels: ['<Shift><Primary>g'] },
+ { name: 'find-next',
+ callback: Lang.bind(this, this.findNext),
+ accels: ['<Primary>g'] },
+ { name: 'places',
+ callback: Lang.bind(this, this._places),
+ accels: ['<Primary>b'] },
+ { name: 'bookmark-page',
+ callback: Utils.actionToggleCallback,
+ state: GLib.Variant.new('b', false),
+ stateChanged: Lang.bind(this, this._bookmarkStateChanged),
+ accels: ['<Primary>d'] },
+ { name: 'edit-current',
+ callback: Lang.bind(this, this._edit) },
+ { name: 'print-current',
+ callback: Lang.bind(this, this._print),
+ accels: ['<Primary>p'] }
+ ];
+
+ if (!Application.application.isBooks)
+ actions.push({ name: 'present-current',
+ callback: Utils.actionToggleCallback,
+ state: GLib.Variant.new('b', false),
+ stateChanged: Lang.bind(this, this._presentStateChanged),
+ accels: ['F5'] });
+
+ return actions;
},
createNavControls: function() {
@@ -176,9 +241,9 @@ const EvinceView = new Lang.Class({
onLoadStarted: function(manager, doc) {
if (doc.viewType != Documents.ViewType.EV)
return;
- this._bookmarkPage.enabled = false;
- this._places.enabled = false;
- this._copy.enabled = false;
+
+ this.getAction('bookmark-page').enabled = false;
+ this.getAction('places').enabled = false;
},
onLoadFinished: function(manager, doc, docModel) {
@@ -187,6 +252,10 @@ const EvinceView = new Lang.Class({
if (doc.viewType != Documents.ViewType.EV)
return;
+ this.getAction('copy').enabled = false;
+ this.getAction('edit-current').enabled = doc.canEdit();
+ this.getAction('print-current').enabled = doc.canPrint(docModel);
+
if (Application.application.isBooks)
docModel.set_sizing_mode(EvView.SizingMode.FIT_PAGE);
else
@@ -203,48 +272,17 @@ const EvinceView = new Lang.Class({
this.parent(manager, doc, message, exception);
},
- _onActionStateChanged: function(source, actionName, state) {
- if (!this._model)
- return;
-
- let page_number = this._model.page;
- let bookmark = new GdPrivate.Bookmark({ page_number: page_number });
-
- if (state.get_boolean())
- this._bookmarks.add(bookmark);
- else
- this._bookmarks.remove(bookmark);
- },
-
- _onPresentStateChanged: function(source, actionName, state) {
- if (!this._model)
- return;
-
- if (state.get_boolean())
- this._promptPresentation();
- else
- this._hidePresentation();
- },
-
_onPageChanged: function() {
this._pageChanged = true;
if (!this._bookmarks)
return;
- let page_number = this._model.page;
- let bookmark = new GdPrivate.Bookmark({ page_number: page_number });
+ let pageNumber = this._model.page;
+ let bookmark = new GdPrivate.Bookmark({ page_number: pageNumber });
let hasBookmark = (this._bookmarks.find_bookmark(bookmark) != null);
- this._bookmarkPage.change_state(GLib.Variant.new('b', hasBookmark));
- },
-
- _showPlaces: function() {
- let dialog = new Places.PlacesDialog(this._model, this._bookmarks);
- dialog.connect('response', Lang.bind(this,
- function(widget, response) {
- widget.destroy();
- }));
+ this.getAction('bookmark-page').change_state(GLib.Variant.new('b', hasBookmark));
},
_hidePresentation: function() {
@@ -253,7 +291,7 @@ const EvinceView = new Lang.Class({
this._presentation = null;
}
- Application.application.change_action_state('present-current', GLib.Variant.new('b', false));
+ this.getAction('present-current').change_state(GLib.Variant.new('b', false));
},
_showPresentation: function(output) {
@@ -283,7 +321,7 @@ const EvinceView = new Lang.Class({
_onViewSelectionChanged: function() {
let hasSelection = this._evView.get_has_selection();
- this._copy.enabled = hasSelection;
+ this.getAction('copy').enabled = hasSelection;
if (!hasSelection &&
hasSelection == this._hasSelection) {
@@ -354,11 +392,11 @@ const EvinceView = new Lang.Class({
},
_onCanZoomInChanged: function() {
- this._zoomIn.enabled = this._evView.can_zoom_in;
+ this.getAction('zoom-in').enabled = this._evView.can_zoom_in;
},
_onCanZoomOutChanged: function() {
- this._zoomOut.enabled = this._evView.can_zoom_out;
+ this.getAction('zoom-out').enabled = this._evView.can_zoom_out;
},
_getEvinceViewContextMenu: function() {
@@ -471,11 +509,6 @@ const EvinceView = new Lang.Class({
this._pageChanged = false;
},
- _changeRotation: function(offset) {
- let rotation = this._model.get_rotation();
- this._model.set_rotation(rotation + offset);
- },
-
get controlsVisible() {
return this._controlsVisible;
},
@@ -536,15 +569,16 @@ const EvinceView = new Lang.Class({
this._toolbar.setModel(this._model);
if (this._model) {
- if (this._togglePresentation)
- this._togglePresentation.enabled = true;
+ let presentCurrent = this.getAction('present-current');
+ if (presentCurrent)
+ presentCurrent.enabled = true;
if (Application.documentManager.metadata)
this._bookmarks = new GdPrivate.Bookmarks({ metadata: Application.documentManager.metadata
});
let hasMultiplePages = (this._model.document.get_n_pages() > 1);
- this._bookmarkPage.enabled = hasMultiplePages && this._bookmarks;
- this._places.enabled = hasMultiplePages;
+ this.getAction('bookmark-page').enabled = hasMultiplePages && this._bookmarks;
+ this.getAction('places').enabled = hasMultiplePages;
this._model.connect('page-changed', Lang.bind(this, this._onPageChanged));
this._onPageChanged();
@@ -596,14 +630,6 @@ const EvinceView = new Lang.Class({
return this._model ? this._model.document.get_n_pages() : 0;
},
- findPrev: function() {
- this._evView.find_previous();
- },
-
- findNext: function() {
- this._evView.find_next();
- },
-
scroll: function(direction) {
this._evView.scroll(direction, false);
},
@@ -635,7 +661,7 @@ const EvinceViewNavControls = new Lang.Class({
let buttonArea = barWidget.get_button_area();
- let button = new Gtk.Button({ action_name: 'app.places',
+ let button = new Gtk.Button({ action_name: 'view.places',
image: new Gtk.Image({ icon_name: 'view-list-symbolic',
pixel_size: 16 }),
valign: Gtk.Align.CENTER,
@@ -643,7 +669,7 @@ const EvinceViewNavControls = new Lang.Class({
});
buttonArea.pack_start(button, false, false, 0);
- button = new Gtk.ToggleButton({ action_name: 'app.bookmark-page',
+ button = new Gtk.ToggleButton({ action_name: 'view.bookmark-page',
image: new Gtk.Image({ icon_name: 'bookmark-new-symbolic',
pixel_size: 16 }),
valign: Gtk.Align.CENTER,
@@ -683,8 +709,7 @@ const EvinceViewToolbar = new Lang.Class({
this._searchAction = Application.application.lookup_action('search');
this._searchAction.enabled = false;
- this._gearMenu = Application.application.lookup_action('gear-menu');
- this._gearMenu.enabled = false;
+ this._previewView.getAction('gear-menu').enabled = false;
// back button, on the left of the toolbar
let backButton = this.addBackButton();
@@ -699,7 +724,7 @@ const EvinceViewToolbar = new Lang.Class({
let previewMenu = this._getEvinceViewMenu();
let menuButton = new Gtk.MenuButton({ image: new Gtk.Image ({ icon_name: 'open-menu-symbolic' }),
menu_model: previewMenu,
- action_name: 'app.gear-menu' });
+ action_name: 'view.gear-menu' });
this.toolbar.pack_end(menuButton);
// search button, on the right of the toolbar
@@ -746,7 +771,7 @@ const EvinceViewToolbar = new Lang.Class({
if (doc && doc.defaultAppName) {
let section = builder.get_object('open-section');
section.remove(0);
- section.prepend(_("Open with %s").format(doc.defaultAppName), 'app.open-current');
+ section.prepend(_("Open with %s").format(doc.defaultAppName), 'view.open-current');
}
return menu;
@@ -767,7 +792,7 @@ const EvinceViewToolbar = new Lang.Class({
},
setModel: function() {
- this._gearMenu.enabled = true;
+ this._previewView.getAction('gear-menu').enabled = true;
this._enableSearch();
this._setToolbarTitle();
}
@@ -785,10 +810,8 @@ const EvinceViewSearchbar = new Lang.Class({
},
_onSearchChanged: function(view, hasResults) {
- let findPrev = Application.application.lookup_action('find-prev');
- let findNext = Application.application.lookup_action('find-next');
- findPrev.enabled = hasResults;
- findNext.enabled = hasResults;
+ this.preview.getAction('find-prev').enabled = hasResults;
+ this.preview.getAction('find-next').enabled = hasResults;
},
entryChanged: function() {
diff --git a/src/lokview.js b/src/lokview.js
index 580baeb..892922c 100644
--- a/src/lokview.js
+++ b/src/lokview.js
@@ -27,6 +27,7 @@ try {
}
const Gdk = imports.gi.Gdk;
+const GLib = imports.gi.GLib;
const Gtk = imports.gi.Gtk;
const _ = imports.gettext.gettext;
@@ -37,6 +38,7 @@ const Application = imports.application;
const MainToolbar = imports.mainToolbar;
const Preview = imports.preview;
const Documents = imports.documents;
+const Utils = imports.utils;
const ZOOM_IN_FACTOR = 1.2;
const ZOOM_OUT_FACTOR = (1.0/ZOOM_IN_FACTOR);
@@ -96,8 +98,8 @@ const LOKView = new Lang.Class({
Name: 'LOKView',
Extends: Preview.Preview,
- _init: function(overlay) {
- this.parent(overlay);
+ _init: function(overlay, mainWindow) {
+ this.parent(overlay, mainWindow);
this._uri = null;
@@ -110,46 +112,20 @@ const LOKView = new Lang.Class({
let model = this._getPreviewContextMenu();
this._previewContextMenu = Gtk.Menu.new_from_model(model);
this._previewContextMenu.attach_to_widget(this.view, null);
-
- this._zoomIn = Application.application.lookup_action('zoom-in');
- this._zoomInId = this._zoomIn.connect('activate', Lang.bind(this,
- function() {
- // FIXME: https://bugs.documentfoundation.org/show_bug.cgi?id=97301
- if (!this._doc)
- return;
- let zoomLevel = this._lokview.get_zoom() * ZOOM_IN_FACTOR;
- this._lokview.set_zoom(zoomLevel);
- }));
-
- this._zoomOut = Application.application.lookup_action('zoom-out');
- this._zoomOutId = this._zoomOut.connect('activate', Lang.bind(this,
- function() {
- // FIXME: https://bugs.documentfoundation.org/show_bug.cgi?id=97301
- if (!this._doc)
- return;
- let zoomLevel = this._lokview.get_zoom() * ZOOM_OUT_FACTOR;
- this._lokview.set_zoom(zoomLevel);
- }));
-
- this._copy = Application.application.lookup_action('copy');
- this._copyId = this._copy.connect('activate', Lang.bind(this, this._onCopyActivated));
},
- vfunc_destroy: function() {
- if (this._zoomInId > 0) {
- this._zoomIn.disconnect(this._zoomInId);
- this._zoomInId = 0;
- }
- if (this._zoomOutId > 0) {
- this._zoomOut.disconnect(this._zoomOutId);
- this._zoomOutId = 0;
- }
- if (this._copyId > 0) {
- this._copy.disconnect(this._copyId);
- this._copyId = 0;
- }
-
- this.parent();
+ createActions: function() {
+ return [
+ { name: 'zoom-in',
+ callback: Lang.bind(this, this._zoomIn),
+ accels: ['<Primary>plus', '<Primary>equal'] },
+ { name: 'zoom-out',
+ callback: Lang.bind(this, this._zoomOut),
+ accels: ['<Primary>minus'] },
+ { name: 'copy',
+ callback: Lang.bind(this, this._copy),
+ accels: ['<Primary>c'] }
+ ];
},
createToolbar: function() {
@@ -176,22 +152,6 @@ const LOKView = new Lang.Class({
return sw;
},
- _onCanZoomInChanged: function() {
- this._zoomIn.enabled = this._lokview.can_zoom_in;
- },
-
- _onCanZoomOutChanged: function() {
- this._zoomOut.enabled = this._lokview.can_zoom_out;
- },
-
- _onCopyActivated: function() {
- let [selectedText, mimeType] = this._lokview.copy_selection('text/plain;charset=utf-8');
- let display = Gdk.Display.get_default();
- let clipboard = Gtk.Clipboard.get_default(display);
-
- clipboard.set_text(selectedText, selectedText.length);
- },
-
onLoadFinished: function(manager, doc) {
this.parent(manager, doc);
@@ -200,7 +160,6 @@ const LOKView = new Lang.Class({
if (!isAvailable())
return;
this._doc = doc;
- this._copy.enabled = false;
this._lokview.open_document(doc.uri, "{}", null, Lang.bind(this, this.open_document_cb));
this._progressBar.show();
},
@@ -212,6 +171,38 @@ const LOKView = new Lang.Class({
this._lokview.set_edit(false);
},
+ _copy: function() {
+ let [selectedText, mimeType] = this._lokview.copy_selection('text/plain;charset=utf-8');
+ let display = Gdk.Display.get_default();
+ let clipboard = Gtk.Clipboard.get_default(display);
+
+ clipboard.set_text(selectedText, selectedText.length);
+ },
+
+ _zoomIn: function() {
+ // FIXME: https://bugs.documentfoundation.org/show_bug.cgi?id=97301
+ if (!this._doc)
+ return;
+ let zoomLevel = this._lokview.get_zoom() * ZOOM_IN_FACTOR;
+ this._lokview.set_zoom(zoomLevel);
+ },
+
+ _zoomOut: function() {
+ // FIXME: https://bugs.documentfoundation.org/show_bug.cgi?id=97301
+ if (!this._doc)
+ return;
+ let zoomLevel = this._lokview.get_zoom() * ZOOM_OUT_FACTOR;
+ this._lokview.set_zoom(zoomLevel);
+ },
+
+ _onCanZoomInChanged: function() {
+ this.getAction('zoom-in').enabled = this._lokview.can_zoom_in;
+ },
+
+ _onCanZoomOutChanged: function() {
+ this.getAction('zoom-out').enabled = this._lokview.can_zoom_out;
+ },
+
_getPreviewContextMenu: function() {
let builder = new Gtk.Builder();
builder.add_from_resource('/org/gnome/Documents/ui/preview-context-menu.ui');
@@ -235,7 +226,7 @@ const LOKView = new Lang.Class({
},
_onTextSelection: function(hasSelection) {
- this._copy.enabled = hasSelection;
+ this.getAction('copy').enabled = hasSelection;
},
goPrev: function() {
@@ -283,12 +274,6 @@ const LOKViewToolbar = new Lang.Class({
this.parent();
this.toolbar.set_show_close_button(true);
- this._gearMenu = Application.application.lookup_action('gear-menu');
- this._gearMenu.enabled = true;
-
- this._lokView._zoomIn.enabled = true;
- this._lokView._zoomOut.enabled = true;
-
// back button, on the left of the toolbar
let backButton = this.addBackButton();
backButton.connect('clicked', Lang.bind(this,
@@ -301,7 +286,7 @@ const LOKViewToolbar = new Lang.Class({
let lokViewMenu = this._getLOKViewMenu();
let menuButton = new Gtk.MenuButton({ image: new Gtk.Image ({ icon_name: 'open-menu-symbolic' }),
menu_model: lokViewMenu,
- action_name: 'app.gear-menu' });
+ action_name: 'view.gear-menu' });
this.toolbar.pack_end(menuButton);
this._setToolbarTitle();
@@ -317,21 +302,9 @@ const LOKViewToolbar = new Lang.Class({
let doc = Application.documentManager.getActiveItem();
if (doc && doc.defaultAppName) {
section.remove(0);
- section.prepend(_("Open with %s").format(doc.defaultAppName), 'app.open-current');
+ section.prepend(_("Open with %s").format(doc.defaultAppName), 'view.open-current');
}
- // No edit support yet
- section.remove(1);
- // No print support yet
- section.remove(1);
- // No present support yet
- section.remove(1);
-
- // No rotate support
- section = builder.get_object('rotate-section');
- section.remove(0);
- section.remove(0);
-
return menu;
},
diff --git a/src/mainWindow.js b/src/mainWindow.js
index d1656ef..4974267 100644
--- a/src/mainWindow.js
+++ b/src/mainWindow.js
@@ -80,7 +80,7 @@ const MainWindow = new Lang.Class({
this._fsId = Application.modeController.connect('fullscreen-changed',
Lang.bind(this, this._onFullscreenChanged));
- this._embed = new Embed.Embed();
+ this._embed = new Embed.Embed(this);
this.add(this._embed);
},
diff --git a/src/preview.js b/src/preview.js
index 5f66844..a380d58 100644
--- a/src/preview.js
+++ b/src/preview.js
@@ -1,5 +1,7 @@
const GdPrivate = imports.gi.GdPrivate;
+const Gio = imports.gi.Gio;
const Gdk = imports.gi.Gdk;
+const GLib = imports.gi.GLib;
const Gtk = imports.gi.Gtk;
const Lang = imports.lang;
@@ -8,24 +10,25 @@ const Tweener = imports.tweener.tweener;
const Application = imports.application;
const ErrorBox = imports.errorBox;
+const Properties = imports.properties;
const Searchbar = imports.searchbar;
+const Utils = imports.utils;
const Preview = new Lang.Class({
Name: 'Preview',
Extends: Gtk.Stack,
- _init: function(overlay) {
+ _init: function(overlay, mainWindow) {
this._lastSearch = '';
this.overlay = overlay;
+ this.mainWindow = mainWindow;
this.parent({ homogeneous: true,
transition_type: Gtk.StackTransitionType.CROSSFADE });
- this._findPrev = Application.application.lookup_action('find-prev');
- this._findPrevId = this._findPrev.connect('activate', Lang.bind(this, this.findPrev));
-
- this._findNext = Application.application.lookup_action('find-next');
- this._findNextId = this._findNext.connect('activate', Lang.bind(this, this.findNext));
+ let actions = this.createActions().concat(this._getDefaultActions());
+ this.actionGroup = new Gio.SimpleActionGroup();
+ Utils.populateActionGroup(this.actionGroup, actions, 'view');
this._errorBox = new ErrorBox.ErrorBox();
this.add_named(this._errorBox, 'error');
@@ -47,15 +50,37 @@ const Preview = new Lang.Class({
Lang.bind(this, this.onLoadError));
},
+ _getDefaultActions: function() {
+ return [
+ { name: 'gear-menu',
+ callback: Utils.actionToggleCallback,
+ state: GLib.Variant.new('b', false),
+ accels: ['F10'] },
+ { name: 'properties',
+ callback: Lang.bind(this, this._properties) },
+ { name: 'open-current',
+ callback: Lang.bind(this, this._openCurrent) }
+ ];
+ },
+
+ _properties: function() {
+ let doc = Application.documentManager.getActiveItem();
+ if (!doc)
+ return;
+
+ let dialog = new Properties.PropertiesDialog(doc.id);
+ dialog.connect('response', Lang.bind(this, function(widget, response) {
+ widget.destroy();
+ }));
+ },
+
+ _openCurrent: function() {
+ let doc = Application.documentManager.getActiveItem();
+ if (doc)
+ doc.open(this.mainWindow.get_screen(), Gtk.get_current_event_time());
+ },
+
vfunc_destroy: function() {
- if (this._findPrevId > 0) {
- this._findPrev.disconnect(this._findPrevId);
- this._findPrevId = 0;
- }
- if (this._findNextId > 0) {
- this._findNext.disconnect(this._findNextId);
- this._findNextId = 0;
- }
if (this._loadStartedId > 0) {
Application.documentManager.disconnect(this._loadStartedId);
this._loadStartedId = 0;
@@ -76,6 +101,10 @@ const Preview = new Lang.Class({
this.parent();
},
+ createActions: function() {
+ return [];
+ },
+
createNavControls: function() {
return new PreviewNavControls(this, this.overlay);
},
@@ -92,6 +121,7 @@ const Preview = new Lang.Class({
},
onLoadFinished: function(manager, doc, docModel) {
+ this.getAction('open-current').enabled = (doc.defaultApp != null);
},
onLoadError: function(manager, doc, message, exception) {
@@ -99,6 +129,10 @@ const Preview = new Lang.Class({
this.set_visible_child_name('error');
},
+ getAction: function(name) {
+ return this.actionGroup.lookup_action(name);
+ },
+
goPrev: function() {
throw (new Error('Not implemented'));
},
@@ -360,17 +394,17 @@ const PreviewSearchbar = new Lang.Class({
this.searchEntry = new Gtk.SearchEntry({ width_request: 500 });
this.searchEntry.connect('activate', Lang.bind(this, function() {
- Application.application.activate_action('find-next', null);
+ this.preview.activateResult();
}));
box.add(this.searchEntry);
- this._prev = new Gtk.Button({ action_name: 'app.find-prev' });
+ this._prev = new Gtk.Button({ action_name: 'view.find-prev' });
this._prev.set_image(new Gtk.Image({ icon_name: 'go-up-symbolic',
icon_size: Gtk.IconSize.MENU }));
this._prev.set_tooltip_text(_("Find Previous"));
box.add(this._prev);
- this._next = new Gtk.Button({ action_name: 'app.find-next' });
+ this._next = new Gtk.Button({ action_name: 'view.find-next' });
this._next.set_image(new Gtk.Image({ icon_name: 'go-down-symbolic',
icon_size: Gtk.IconSize.MENU }));
this._next.set_tooltip_text(_("Find Next"));
diff --git a/src/utils.js b/src/utils.js
index 475137f..9de8618 100644
--- a/src/utils.js
+++ b/src/utils.js
@@ -120,3 +120,38 @@ function addJSSignalMethods(proto) {
proto.emitJS = Signals._emit;
proto.disconnectAllJS = Signals._disconnectAll;
}
+
+function actionToggleCallback(action) {
+ let state = action.get_state();
+ action.change_state(GLib.Variant.new('b', !state.get_boolean()));
+}
+
+function populateActionGroup(actionGroup, actionEntries, prefix) {
+ actionEntries.forEach(function(actionEntry) {
+ let state = actionEntry.state;
+ let parameterType = actionEntry.parameter_type ?
+ GLib.VariantType.new(actionEntry.parameter_type) : null;
+ let action;
+
+ if (state)
+ action = Gio.SimpleAction.new_stateful(actionEntry.name,
+ parameterType, actionEntry.state);
+ else
+ action = new Gio.SimpleAction({ name: actionEntry.name,
+ parameter_type: parameterType });
+
+ if (actionEntry.create_hook)
+ actionEntry.create_hook(action);
+
+ if (actionEntry.callback)
+ action.connect('activate', actionEntry.callback);
+
+ if (actionEntry.stateChanged)
+ action.connect('notify::state', actionEntry.stateChanged);
+
+ if (actionEntry.accels)
+ Application.application.set_accels_for_action(prefix + '.' + actionEntry.name,
actionEntry.accels);
+
+ actionGroup.add_action(action);
+ });
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]