[pdfmod] First pass at Bookmarks support
- From: Gabriel Burt <gburt src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pdfmod] First pass at Bookmarks support
- Date: Tue, 31 Aug 2010 20:27:49 +0000 (UTC)
commit 637b1cadba6e6ee9005ea519c2f1199a5f2ba778
Author: Gabriel Burt <gabriel burt gmail com>
Date: Tue Aug 31 15:23:35 2010 -0500
First pass at Bookmarks support
Adds a sidebar TreeView with that shows the existing bookmarks, letting
you edit and remove them and add new bookmarks. Needs more testing and
polish. A big step toward closing bgo#627747
src/Makefile.am | 3 +
src/PdfMod.mdp | 82 +++++-----
src/PdfMod/Core/Configuration.cs | 5 +
src/PdfMod/Gui/Actions.cs | 11 +-
src/PdfMod/Gui/BookmarkView.cs | 334 ++++++++++++++++++++++++++++++++++++++
src/PdfMod/Gui/Client.cs | 27 ++-
src/PdfMod/Pdf/Document.cs | 13 ++-
src/Resources/UIManager.xml | 1 +
8 files changed, 421 insertions(+), 55 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 3164485..dbb07e2 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -32,6 +32,7 @@ FILES = \
PdfMod/Core/Configuration.cs \
PdfMod/Core/Defines.cs \
PdfMod/Gui/Actions.cs \
+ PdfMod/Gui/BookmarkView.cs \
PdfMod/Gui/CairoCell.cs \
PdfMod/Gui/Client.cs \
PdfMod/Gui/DocumentIconView.cs \
@@ -68,6 +69,8 @@ REFERENCES = \
System \
System.Core
+PROJECT_REFERENCES = ../bin/PdfSharp.dll
+
if USE_BUNDLED_POPPLER
PROJECT_REFERENCES += ../bin/poppler-sharp.dll
PROGRAMFILES += $(POPPLER_SHARP_DLL_CONFIG)
diff --git a/src/PdfMod.mdp b/src/PdfMod.mdp
index aa37e31..5b0b84c 100644
--- a/src/PdfMod.mdp
+++ b/src/PdfMod.mdp
@@ -1,48 +1,57 @@
-<Project name="PdfMod" fileversion="2.0" language="C#" targetFramework="3.5" ctype="DotNetProject">
+<Project name="PdfMod" fileversion="2.0" DefaultNamespace="PdfMod" language="C#" targetFramework="3.5" ctype="DotNetProject">
<Policies>
<DotNetNamingPolicy DirectoryNamespaceAssociation="Flat" ResourceNamePolicy="FileFormatDefault" />
</Policies>
+ <GtkDesignInfo gettextClass="Mono.Posix.Catalog" />
+ <MonoDevelop.Autotools.MakefileInfo IntegrationEnabled="True" RelativeMakefileName="Makefile.am" BuildTargetName="" CleanTargetName="" SyncReferences="True" IsAutotoolsProject="True" RelativeConfigureInPath="..">
+ <BuildFilesVar Sync="True" Name="FILES" />
+ <DeployFilesVar />
+ <ResourcesVar Sync="True" Name="RESOURCES" />
+ <OthersVar />
+ <GacRefVar Sync="True" Name="REFERENCES" />
+ <AsmRefVar Sync="True" Name="DLL_REFERENCES" />
+ <ProjectRefVar Sync="True" Name="PROJECT_REFERENCES" />
+ </MonoDevelop.Autotools.MakefileInfo>
<Configurations active="Debug">
<Configuration name="Debug" ctype="DotNetProjectConfiguration">
<Output directory="../bin/" assembly="PdfMod" />
<Build debugmode="True" target="Exe" />
- <Execution runwithwarnings="True" consolepause="True" runtime="MsNet" />
- <EnvironmentVariables />
+ <Execution consolepause="True" runwithwarnings="True" runtime="MsNet" />
<CodeGeneration compiler="Mcs" warninglevel="4" optimize="True" unsafecodeallowed="False" generateoverflowchecks="False" definesymbols="DEBUG" generatexmldocumentation="False" ctype="CSharpCompilerParameters" />
</Configuration>
<Configuration name="Release" ctype="DotNetProjectConfiguration">
<Output directory="../bin/" assembly="PdfMod" />
<Build debugmode="True" target="Exe" />
- <Execution runwithwarnings="True" consolepause="True" runtime="MsNet" />
- <EnvironmentVariables />
+ <Execution consolepause="True" runwithwarnings="True" runtime="MsNet" />
<CodeGeneration compiler="Mcs" warninglevel="4" optimize="True" unsafecodeallowed="False" generateoverflowchecks="False" generatexmldocumentation="False" ctype="CSharpCompilerParameters" />
</Configuration>
</Configurations>
<Contents>
- <File name="PdfMod/Main.cs" subtype="Code" buildaction="Compile" />
- <File name="PdfMod/Core/AssemblyInfo.cs" subtype="Code" buildaction="Compile" />
- <File name="PdfMod/Gui/DocumentIconView.cs" subtype="Code" buildaction="Compile" />
- <File name="PdfMod/Gui/PageListStore.cs" subtype="Code" buildaction="Compile" />
- <File name="PdfMod/Gui/Actions.cs" subtype="Code" buildaction="Compile" />
- <File name="Resources/UIManager.xml" subtype="Code" buildaction="EmbedAsResource" />
- <File name="PdfMod/Pdf/Actions/RemoveAction.cs" subtype="Code" buildaction="Compile" />
- <File name="PdfMod/Pdf/Document.cs" subtype="Code" buildaction="Compile" />
- <File name="PdfMod/Pdf/Page.cs" subtype="Code" buildaction="Compile" />
- <File name="PdfMod/Pdf/Actions/RotateAction.cs" subtype="Code" buildaction="Compile" />
- <File name="PdfMod/Pdf/Actions/BasePageAction.cs" subtype="Code" buildaction="Compile" />
- <File name="PdfMod/Pdf/Actions/ExportImagesAction.cs" subtype="Code" buildaction="Compile" />
- <File name="PdfMod/Gui/SelectMatchingBox.cs" subtype="Code" buildaction="Compile" />
- <File name="PdfMod/Gui/CairoCell.cs" subtype="Code" buildaction="Compile" />
- <File name="PdfMod/Gui/PageCell.cs" subtype="Code" buildaction="Compile" />
- <File name="PdfMod/Gui/Client.cs" subtype="Code" buildaction="Compile" />
- <File name="PdfMod/Pdf/Actions/MoveAction.cs" subtype="Code" buildaction="Compile" />
- <File name="PdfMod/Gui/MetadataEditorBox.cs" subtype="Code" buildaction="Compile" />
- <File name="PdfMod/Pdf/PageThumbnail.cs" subtype="Code" buildaction="Compile" />
- <File name="PdfMod/Core/Defines.cs.in" subtype="Code" buildaction="Nothing" />
- <File name="PdfMod/Core/Defines.cs" subtype="Code" buildaction="Compile" />
- <File name="PdfMod/Core/Client.cs" subtype="Code" buildaction="Compile" />
- <File name="PdfMod/Core/Configuration.cs" subtype="Code" buildaction="Compile" />
- <File name="PdfMod/Pdf/PageLabels.cs" subtype="Code" buildaction="Compile" />
+ <File subtype="Code" buildaction="Compile" name="PdfMod/Main.cs" />
+ <File subtype="Code" buildaction="Compile" name="PdfMod/Core/AssemblyInfo.cs" />
+ <File subtype="Code" buildaction="Compile" name="PdfMod/Gui/DocumentIconView.cs" />
+ <File subtype="Code" buildaction="Compile" name="PdfMod/Gui/PageListStore.cs" />
+ <File subtype="Code" buildaction="Compile" name="PdfMod/Gui/Actions.cs" />
+ <File subtype="Code" buildaction="EmbedAsResource" name="Resources/UIManager.xml" />
+ <File subtype="Code" buildaction="Compile" name="PdfMod/Pdf/Actions/RemoveAction.cs" />
+ <File subtype="Code" buildaction="Compile" name="PdfMod/Pdf/Document.cs" />
+ <File subtype="Code" buildaction="Compile" name="PdfMod/Pdf/Page.cs" />
+ <File subtype="Code" buildaction="Compile" name="PdfMod/Pdf/Actions/RotateAction.cs" />
+ <File subtype="Code" buildaction="Compile" name="PdfMod/Pdf/Actions/BasePageAction.cs" />
+ <File subtype="Code" buildaction="Compile" name="PdfMod/Pdf/Actions/ExportImagesAction.cs" />
+ <File subtype="Code" buildaction="Compile" name="PdfMod/Gui/SelectMatchingBox.cs" />
+ <File subtype="Code" buildaction="Compile" name="PdfMod/Gui/CairoCell.cs" />
+ <File subtype="Code" buildaction="Compile" name="PdfMod/Gui/PageCell.cs" />
+ <File subtype="Code" buildaction="Compile" name="PdfMod/Gui/Client.cs" />
+ <File subtype="Code" buildaction="Compile" name="PdfMod/Pdf/Actions/MoveAction.cs" />
+ <File subtype="Code" buildaction="Compile" name="PdfMod/Gui/MetadataEditorBox.cs" />
+ <File subtype="Code" buildaction="Compile" name="PdfMod/Pdf/PageThumbnail.cs" />
+ <File subtype="Code" buildaction="Nothing" name="PdfMod/Core/Defines.cs.in" />
+ <File subtype="Code" buildaction="Compile" name="PdfMod/Core/Defines.cs" />
+ <File subtype="Code" buildaction="Compile" name="PdfMod/Core/Client.cs" />
+ <File subtype="Code" buildaction="Compile" name="PdfMod/Core/Configuration.cs" />
+ <File subtype="Code" buildaction="Compile" name="PdfMod/Pdf/PageLabels.cs" />
+ <File subtype="Code" buildaction="Compile" name="PdfMod/Gui/BookmarkView.cs" />
</Contents>
<References>
<ProjectReference type="Gac" localcopy="True" refto="System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
@@ -55,16 +64,9 @@
<ProjectReference type="Gac" localcopy="True" refto="gconf-sharp, Version=2.24.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
<ProjectReference type="Gac" localcopy="True" refto="Hyena, Version=0.0.0.0, Culture=neutral" />
<ProjectReference type="Gac" localcopy="True" refto="Hyena.Gui, Version=0.0.0.0, Culture=neutral" />
+ <ProjectReference type="Gac" localcopy="True" refto="pango-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
+ <ProjectReference type="Gac" localcopy="True" refto="atk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
+ <ProjectReference type="Gac" localcopy="True" refto="gdk-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
<ProjectReference type="Project" localcopy="True" refto="poppler-sharp" />
</References>
- <GtkDesignInfo gettextClass="Mono.Posix.Catalog" />
- <MonoDevelop.Autotools.MakefileInfo IntegrationEnabled="True" RelativeMakefileName="Makefile.am" BuildTargetName="" CleanTargetName="" SyncReferences="True" IsAutotoolsProject="True" RelativeConfigureInPath="..">
- <BuildFilesVar Sync="True" Name="FILES" />
- <DeployFilesVar />
- <ResourcesVar Sync="True" Name="RESOURCES" />
- <OthersVar />
- <GacRefVar Sync="True" Name="REFERENCES" />
- <AsmRefVar Sync="True" Name="DLL_REFERENCES" />
- <ProjectRefVar Sync="True" Name="PROJECT_REFERENCES" />
- </MonoDevelop.Autotools.MakefileInfo>
-</Project>
+</Project>
\ No newline at end of file
diff --git a/src/PdfMod/Core/Configuration.cs b/src/PdfMod/Core/Configuration.cs
index 677bbbd..817b9f4 100644
--- a/src/PdfMod/Core/Configuration.cs
+++ b/src/PdfMod/Core/Configuration.cs
@@ -46,6 +46,11 @@ namespace PdfMod.Core
set { Set<bool> ("show_toolbar", value); }
}
+ public bool ShowBookmarks {
+ get { return Get<bool> ("show_bookmarks", false); }
+ set { Set<bool> ("show_bookmarks", value); }
+ }
+
public string LastOpenFolder {
get { return Get<string> ("last_folder", System.Environment.GetFolderPath (System.Environment.SpecialFolder.Desktop)); }
set {
diff --git a/src/PdfMod/Gui/Actions.cs b/src/PdfMod/Gui/Actions.cs
index c934136..a110455 100644
--- a/src/PdfMod/Gui/Actions.cs
+++ b/src/PdfMod/Gui/Actions.cs
@@ -100,6 +100,7 @@ namespace PdfMod.Gui
new ToggleActionEntry ("Properties", Stock.Properties, null, "<alt>Return", Catalog.GetString ("View and edit the title, keywords, and more for this document"), OnProperties, false),
new ToggleActionEntry ("ZoomFit", Stock.ZoomFit, null, "<control>0", null, OnZoomFit, true),
new ToggleActionEntry ("ViewToolbar", null, Catalog.GetString ("Toolbar"), null, null, OnViewToolbar, Client.Configuration.ShowToolbar),
+ new ToggleActionEntry ("ViewBookmarks", null, Catalog.GetString ("Bookmarks"), "F9", null, OnViewBookmarks, Client.Configuration.ShowBookmarks),
new ToggleActionEntry ("FullScreenView", null, Catalog.GetString ("Fullscreen"), "F11", null, OnFullScreenView, false)
);
@@ -177,7 +178,7 @@ namespace PdfMod.Gui
? Catalog.GetString ("_Redo")
: String.Format (Catalog.GetString ("Redo {0}"), redo.Description);
- UpdateActions (true, have_doc && app.Document.HasUnsavedChanged, "Save", "SaveAs");
+ UpdateActions (true, have_doc && app.Document.HasUnsavedChanges, "Save", "SaveAs");
UpdateAction ("ZoomIn", true, have_doc && app.IconView.CanZoomIn);
UpdateAction ("ZoomOut", true, have_doc && app.IconView.CanZoomOut);
@@ -337,8 +338,6 @@ namespace PdfMod.Gui
var export_path_base = Path.Combine (
Path.GetDirectoryName (app.Document.SuggestedSavePath),
- // Translators: This is used for creating a folder name, be careful!
- //String.Format (Catalog.GetString ("{0} - Images for {1}"), app.Document.Title ?? app.Document.Filename, GetPageSummary (pages, 10))
Hyena.StringUtil.EscapeFilename (
app.Document.Title ?? System.IO.Path.GetFileNameWithoutExtension (app.Document.Filename))
);
@@ -535,6 +534,12 @@ namespace PdfMod.Gui
Client.Configuration.ShowToolbar = app.HeaderToolbar.Visible = show;
}
+ void OnViewBookmarks (object o, EventArgs args)
+ {
+ bool show = (this["ViewBookmarks"] as ToggleAction).Active;
+ Client.Configuration.ShowBookmarks = app.BookmarkView.Visible = show;
+ }
+
void OnRotateRight (object o, EventArgs args)
{
Rotate (90);
diff --git a/src/PdfMod/Gui/BookmarkView.cs b/src/PdfMod/Gui/BookmarkView.cs
new file mode 100644
index 0000000..f9d20e7
--- /dev/null
+++ b/src/PdfMod/Gui/BookmarkView.cs
@@ -0,0 +1,334 @@
+// Copyright (C) 2010 Novell, Inc.
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// as published by the Free Software Foundation; either version 2
+// of the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+using System;
+using System.Linq;
+
+using Gtk;
+
+using PdfSharp.Pdf;
+using PdfMod.Pdf;
+using System.Collections.Generic;
+using Mono.Unix;
+using PdfSharp.Pdf.Advanced;
+
+namespace PdfMod.Gui
+{
+ public class BookmarkView : VBox
+ {
+ TreeView tree_view;
+ TreeStore model;
+ Document document;
+
+ public bool IsModified { get; set; }
+
+ public BookmarkView ()
+ {
+ BuildTreeView ();
+ BuildButtonBar ();
+
+ WidthRequest = 200;
+ Spacing = 6;
+ ShowAll ();
+ }
+
+ public void SetDocument (Document new_doc)
+ {
+ if (document != null) {
+ document.PagesAdded -= OnPagesAdded;
+ document.PagesChanged -= OnPagesChanged;
+ document.PagesRemoved -= OnPagesRemoved;
+ document.PagesMoved -= OnPagesMoved;
+ }
+
+ document = new_doc;
+ document.PagesAdded += OnPagesAdded;
+ document.PagesChanged += OnPagesChanged;
+ document.PagesRemoved += OnPagesRemoved;
+ document.PagesMoved += OnPagesMoved;
+
+ model.Clear ();
+ AddOutlineCollection (document, document.Pdf.Outlines, TreeIter.Zero);
+ }
+
+ void OnPagesAdded (int index, Page [] pages)
+ {
+ UpdateModel ();
+ }
+
+ void OnPagesChanged (Page [] pages)
+ {
+ UpdateModel ();
+ }
+
+ void OnPagesRemoved (Page [] pages)
+ {
+ var pdf_pages = pages.Select (p => p.Pdf).ToList ();
+
+ var to_remove = new List<TreeIter> ();
+ // Remove bookmarks that point to removed pages
+ model.Foreach ((m, path, iter) => {
+ var outline = GetOutline (iter);
+ if (pdf_pages.Contains (outline.DestinationPage)) {
+ to_remove.Add (iter);
+ }
+ return false;
+ });
+
+ while (to_remove.Count > 0) {
+ var iter = to_remove[0];
+ to_remove.Remove (iter);
+
+ var outline = GetOutline (iter);
+ outline.Remove ();
+ model.Remove (ref iter);
+
+ Hyena.Log.DebugFormat ("Removing bookmark '{0}' since its page was removed", outline.Title);
+ }
+
+ UpdateModel ();
+ }
+
+ void OnPagesMoved ()
+ {
+ UpdateModel ();
+ }
+
+ public IEnumerable<PdfOutline> Outlines {
+ get {
+ TreeIter iter;
+ if (model.GetIterFirst (out iter)) {
+ do {
+ yield return GetOutline (iter);
+ } while (model.IterNext (ref iter));
+ }
+ }
+ }
+
+ private void BuildTreeView ()
+ {
+ // outline, expanded/opened, title, page # destination, tooltip
+ model = new TreeStore (typeof(PdfSharp.Pdf.PdfOutline), typeof(bool), typeof(string), typeof(int), typeof(string));
+
+ tree_view = new TreeView () {
+ Model = model,
+ SearchColumn = (int)ModelColumns.Title,
+ TooltipColumn = (int)ModelColumns.Tooltip,
+ EnableSearch = true,
+ EnableTreeLines = true,
+ HeadersVisible = false,
+ Reorderable = false,
+ ShowExpanders = true
+ };
+ tree_view.Selection.Mode = SelectionMode.Browse;
+
+ var title = new CellRendererText () {
+ Editable = true,
+ Ellipsize = Pango.EllipsizeMode.End
+ };
+ title.Edited += delegate(object o, EditedArgs args) {
+ TreeIter iter;
+ if (model.GetIterFromString (out iter, args.Path)) {
+ if (!String.IsNullOrEmpty (args.NewText)) {
+ var bookmark = GetOutline (iter);
+ bookmark.Title = args.NewText;
+ model.SetValue (iter, (int)ModelColumns.Title, bookmark.Title);
+ MarkModified ();
+ } else {
+ args.RetVal = false;
+ }
+ }
+ };
+ var title_col = tree_view.AppendColumn ("", title, "text", ModelColumns.Title);
+ title_col.Expand = true;
+
+ var page = new CellRendererText () {
+ Editable = true,
+ Style = Pango.Style.Italic
+ };
+ page.Edited += delegate(object o, EditedArgs args) {
+ TreeIter iter;
+ if (model.GetIterFromString (out iter, args.Path)) {
+ var bookmark = GetOutline (iter);
+ int i = -1;
+ if (Int32.TryParse (args.NewText, out i) && i >= 1 && i <= document.Count && i != (GetDestIndex (bookmark) + 1)) {
+ SetDestIndex (bookmark, i - 1);
+ model.SetValue (iter, (int)ModelColumns.PageNumber, i);
+ MarkModified ();
+ } else {
+ args.RetVal = false;
+ }
+ }
+ };
+ var num_col = tree_view.AppendColumn ("", page, "text", ModelColumns.PageNumber);
+ num_col.Alignment = 1.0f;
+ num_col.Expand = false;
+
+ var label = new Label (Catalog.GetString ("_Bookmarks")) { Xalign = 0f, MnemonicWidget = tree_view };
+ PackStart (label, false, false, 0);
+
+ var sw = new Gtk.ScrolledWindow () {
+ HscrollbarPolicy = PolicyType.Never,
+ VscrollbarPolicy = PolicyType.Automatic,
+ Child = tree_view
+ };
+ PackStart (sw, true, true, 0);
+ }
+
+ private void BuildButtonBar ()
+ {
+ var box = new HBox () { Spacing = 6 };
+ var add_button = new Button (Gtk.Stock.Add);
+ add_button.Clicked += (o, a) => {
+ TreeIter parent_iter;
+ if (!tree_view.Selection.GetSelected (out parent_iter) && !model.GetIterFirst (out parent_iter)) {
+ parent_iter = TreeIter.Zero;
+ }
+
+ // Add it to the PDF document
+ var outline = new PdfOutline (Catalog.GetString ("New bookmark"), document.Pages.First ().Pdf, true);
+ if (!TreeIter.Zero.Equals (parent_iter)) {
+ var parent = GetOutline (parent_iter);
+ SetDestIndex (outline, GetDestIndex (parent) + 1);
+ parent.Outlines.Add (outline);
+
+ tree_view.ExpandToPath (model.GetPath (parent_iter));
+ } else {
+ document.Pdf.Outlines.Add (outline);
+ }
+
+ // Add it to our TreeView
+ var iter = AddOutline (parent_iter, outline);
+ MarkModified ();
+
+ // Begin editing its name
+ tree_view.SetCursor (model.GetPath (iter), tree_view.Columns[0], true);
+ Hyena.Log.Debug ("Added bookmark");
+ };
+
+ var remove_button = new Button (Gtk.Stock.Remove);
+ remove_button.Clicked += (o, a) => {
+ TreeIter iter;
+ if (tree_view.Selection.GetSelected (out iter)) {
+ var outline = GetOutline (iter);
+ Hyena.Log.DebugFormat ("Removing bookmark '{0}'", outline.Title);
+ outline.Remove ();
+ model.Remove (ref iter);
+ MarkModified ();
+ }
+ };
+
+ box.PackStart (add_button, false, false, 0);
+ box.PackStart (remove_button, false, false, 0);
+
+ PackStart (box, false, false, 0);
+ }
+
+ private void UpdateModel ()
+ {
+ model.Foreach ((m, path, iter) => {
+ model.SetValues (iter, GetValuesFor (GetOutline (iter)));
+ return false;
+ });
+ }
+
+ private void MarkModified ()
+ {
+ IsModified = true;
+ document.HasUnsavedChanges = true;
+ }
+
+ private TreeIter AddOutline (TreeIter parent, PdfOutline outline)
+ {
+ return TreeIter.Zero.Equals (parent)
+ ? model.AppendValues (GetValuesFor (outline))
+ : model.AppendValues (parent, GetValuesFor (outline));
+ }
+
+ private object [] GetValuesFor (PdfOutline outline)
+ {
+ int dest_num = GetDestIndex (outline);
+
+ return new object [] { outline, outline.Opened, outline.Title, dest_num + 1,
+ String.Format (Catalog.GetString ("Bookmark links to page {0}"), dest_num + 1) };
+ }
+
+ private int GetDestIndex (PdfOutline outline)
+ {
+ if (outline.DestinationPage == null)
+ return -1;
+ else
+ return document.Pages.Select (p => p.Pdf).IndexOf (outline.DestinationPage);
+ }
+
+ private void SetDestIndex (PdfOutline outline, int i)
+ {
+ if (i >= 0 && i < document.Count) {
+ outline.DestinationPage = document.Pages.Skip (i).First ().Pdf;
+ }
+ }
+
+ private PdfOutline GetSelected ()
+ {
+ TreeIter iter;
+ if (tree_view.Selection.GetSelected (out iter))
+ return GetOutline (iter);
+ return null;
+ }
+
+ private void AddOutlineCollection (Document document, PdfOutline.PdfOutlineCollection outlines, TreeIter parent)
+ {
+ if (outlines != null) {
+ foreach (PdfOutline outline in outlines) {
+ var iter = AddOutline (parent, outline);
+
+ // Recursively add this item's children, if any
+ AddOutlineCollection (document, outline.Outlines, iter);
+ }
+ }
+ }
+
+ private PdfOutline GetOutline (TreeIter iter)
+ {
+ return (PdfOutline) model.GetValue (iter, (int)ModelColumns.Bookmark);
+ }
+
+ private enum ModelColumns : int {
+ Bookmark,
+ IsExpanded,
+ Title,
+ PageNumber,
+ Tooltip
+ };
+ }
+
+ internal static class Extensions
+ {
+ public static int IndexOf<T> (this IEnumerable<T> enumerable, T item)
+ {
+ int i = 0;
+ foreach (var a in enumerable) {
+ if (item.Equals (a)) {
+ return i;
+ } else {
+ i++;
+ }
+ }
+
+ return -1;
+ }
+ }
+}
diff --git a/src/PdfMod/Gui/Client.cs b/src/PdfMod/Gui/Client.cs
index c7f8af0..8eba73c 100644
--- a/src/PdfMod/Gui/Client.cs
+++ b/src/PdfMod/Gui/Client.cs
@@ -55,6 +55,7 @@ namespace PdfMod.Gui
public Gtk.Window Window { get; private set; }
public DocumentIconView IconView { get; private set; }
public MetadataEditorBox EditorBox { get; private set; }
+ public BookmarkView BookmarkView { get; private set; }
static Client ()
{
@@ -121,12 +122,22 @@ namespace PdfMod.Gui
HeaderToolbar.NoShowAll = true;
HeaderToolbar.Visible = Configuration.ShowToolbar;
+ // BookmarksView
+ BookmarkView = new BookmarkView ();
+ BookmarkView.NoShowAll = true;
+ BookmarkView.Visible = Configuration.ShowBookmarks;
+
var vbox = new VBox ();
vbox.PackStart (menu_bar, false, false, 0);
vbox.PackStart (HeaderToolbar, false, false, 0);
vbox.PackStart (EditorBox, false, false, 0);
vbox.PackStart (query_box, false, false, 0);
- vbox.PackStart (iconview_sw, true, true, 0);
+
+ var hbox = new HPaned ();
+ hbox.Add1 (BookmarkView);
+ hbox.Add2 (iconview_sw);
+ vbox.PackStart (hbox, true, true, 0);
+
vbox.PackStart (StatusBar, false, true, 0);
Window.Add (vbox);
@@ -184,7 +195,7 @@ namespace PdfMod.Gui
bool PromptIfUnsavedChanges ()
{
- if (Document != null && Document.HasUnsavedChanged) {
+ if (Document != null && Document.HasUnsavedChanges) {
var dialog = new Hyena.Widgets.HigMessageDialog (
Window, DialogFlags.Modal, MessageType.Warning, ButtonsType.None,
Catalog.GetString ("Save the changes made to this document?"),
@@ -268,7 +279,9 @@ namespace PdfMod.Gui
ThreadAssist.BlockingProxyToMain (delegate {
IconView.SetDocument (Document);
+ BookmarkView.SetDocument (Document);
RecentManager.Default.AddItem (Document.Uri);
+
Document.Changed += UpdateForDocument;
UpdateForDocument ();
OnDocumentLoaded ();
@@ -302,6 +315,7 @@ namespace PdfMod.Gui
void UpdateForDocument ()
{
+ ThreadAssist.AssertInMainThread ();
var current_size = Document.FileSize;
string size_str = null;
if (original_size_string == null) {
@@ -326,7 +340,7 @@ namespace PdfMod.Gui
var title = Document.Title;
var filename = Document.Filename;
- if (Document.HasUnsavedChanged) {
+ if (Document.HasUnsavedChanges) {
filename = "*" + filename;
}
Window.Title = title == null ? filename : String.Format ("{0} - {1}", filename, title);
@@ -337,9 +351,7 @@ namespace PdfMod.Gui
// This method is called from some random thread, but we need
// to do the dialog on the GUI thread; use the reset_event
// to block this thread until the user is done with the dialog.
- var reset_event = new System.Threading.ManualResetEvent (false);
-
- ThreadAssist.ProxyToMain (delegate {
+ ThreadAssist.BlockingProxyToMain (delegate {
Log.Debug ("Password requested to open document");
var dialog = new Hyena.Widgets.HigMessageDialog (
Window, DialogFlags.Modal, MessageType.Question, ButtonsType.None,
@@ -365,10 +377,7 @@ namespace PdfMod.Gui
Log.Information ("Password dialog cancelled");
args.Abort = true;
}
- reset_event.Set ();
});
-
- reset_event.WaitOne ();
}
public Gtk.FileChooserDialog CreateChooser (string title, FileChooserAction action)
diff --git a/src/PdfMod/Pdf/Document.cs b/src/PdfMod/Pdf/Document.cs
index be45113..9515c1c 100644
--- a/src/PdfMod/Pdf/Document.cs
+++ b/src/PdfMod/Pdf/Document.cs
@@ -144,7 +144,8 @@ namespace PdfMod.Pdf
Uri = uri_obj.AbsoluteUri;
SuggestedSavePath = Path = uri_obj.LocalPath;
- pdf_document = PdfSharp.Pdf.IO.PdfReader.Open (Path, PdfDocumentOpenMode.Modify | PdfDocumentOpenMode.Import, passwordProvider);
+ pdf_document = PdfSharp.Pdf.IO.PdfReader.Open (Path, PdfDocumentOpenMode.Modify, passwordProvider);
+
for (int i = 0; i < pdf_document.PageCount; i++) {
var page = new Page (pdf_document.Pages[i]) {
Document = this,
@@ -158,8 +159,13 @@ namespace PdfMod.Pdf
OnChanged ();
}
- public bool HasUnsavedChanged {
- get { return tmp_uri != null || save_timeout_id != 0; }
+ private bool has_unsaved_changes;
+ public bool HasUnsavedChanges {
+ get { return has_unsaved_changes || tmp_uri != null || save_timeout_id != 0; }
+ set {
+ has_unsaved_changes = value;
+ OnChanged ();
+ }
}
public long FileSize {
@@ -258,6 +264,7 @@ namespace PdfMod.Pdf
public void Save (string uri)
{
Pdf.Save (uri);
+ has_unsaved_changes = false;
Log.DebugFormat ("Saved to {0}", uri);
Uri = uri;
diff --git a/src/Resources/UIManager.xml b/src/Resources/UIManager.xml
index a8c68dd..b6cc7a0 100644
--- a/src/Resources/UIManager.xml
+++ b/src/Resources/UIManager.xml
@@ -40,6 +40,7 @@
<separator/>
<menuitem action="FullScreenView"/>
<menuitem action="ViewToolbar"/>
+ <menuitem action="ViewBookmarks"/>
</menu>
<menu action="HelpMenu">
<menuitem action="Help"/>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]