29 Commits
1.6.3 ... 1.8.0

Author SHA1 Message Date
Clement Lefebvre
7951868e92 1.8.0 2018-05-06 16:43:43 +01:00
Clement Lefebvre
9788914d86 l10n: Update POT file 2018-05-06 16:42:09 +01:00
Clement Lefebvre
0409e91288 Wordcompletion: Fix a few mgsids 2018-03-16 11:10:22 +00:00
Mickael Albertus
8a32b92c33 Creation of plugin Word completion (#199)
* Creation of plugin

* Correction of shortcut

* Update translations+fix code

* Add Makefile.in and tab/space fix

* Add makefile.am remove makefile.in
2018-03-16 10:50:39 +00:00
JosephMcc
3999de8f59 xed-window: Fix a potential crash 2018-03-11 04:38:24 -07:00
Clement Lefebvre
37338603dc CI: Don't build for Mint 18
GTK 3.22 is now required.
2018-03-09 15:12:22 +00:00
Clement Lefebvre
87cd264acf Merge pull request #196 from JosephMcc/1.8-dev1
1.8 dev1
2018-03-09 15:11:24 +00:00
Nic
cc493b9b9b Add C tags to the taglist plugin (#188)
Added tags for:
 - Including stdio.h
 - `include` statements
 - The `main` function
 - Comments and multi-line comments
 - `printf` statements
2018-02-19 11:52:10 +00:00
JosephMcc
a86c482308 spell-plugin: Fix a link to the help file 2018-02-14 10:37:36 -08:00
JosephMcc
bd32e81f13 spell-plugin: Port to gspell 2018-02-10 12:22:37 -08:00
JosephMcc
19354f86c1 Clean up a few build warnings
Mostly just missing casts and removing a couple now unused functions and
variables.
2018-02-05 01:48:10 -08:00
JosephMcc
39dcfcab0b Fix a couple of issues turned up by Codacy 2018-02-05 01:03:13 -08:00
JosephMcc
6c7e40c3ba xed-notebook: Allow changing tabs with mouse back/forward buttons
While at it, fix the direction for switching tabs when scrolling with the
mouse wheel.

Closes https://github.com/linuxmint/xed/issues/115
2018-02-05 01:03:13 -08:00
JosephMcc
0a25600883 spell-plugin: Update for removal of some deprecated functionality
enchant_dict_add_to_pwl () was removed from libenchant. Use it's replacement,
enchant_dict_add () instead and bump our required version of libenchant.

Closes https://github.com/linuxmint/xed/issues/198
2018-02-05 01:03:13 -08:00
JosephMcc
a5af28a95d xed-spell-checker.c: Clean up the code formatting 2018-02-05 01:03:13 -08:00
JosephMcc
a13a573228 xed-searchbar: Fix the size of the searchbar close button
The theming for this changed in gtk3.20+. Get it back to the proper size and
theme it in xed-style.css instead of hard coding it.
2018-02-05 01:03:13 -08:00
JosephMcc
100428eaf9 css: Add support for Adwaita 2018-02-05 01:03:13 -08:00
JosephMcc
d86c906848 debian: Add --enable-silent-rules to debian/rules 2018-02-05 01:03:13 -08:00
JosephMcc
ddaf70747c xed-view: Add shortcuts for change case
Closes https://github.com/linuxmint/xed/issues/154
2018-02-05 01:03:13 -08:00
JosephMcc
6159ad5be2 Add a shortcuts window 2018-02-05 01:03:13 -08:00
JosephMcc
6383f71fa0 xed-notebook: Clean up some gtk3.20+ conditionals
Since we are moving to gtk3.22 we can clean these up.
2018-02-05 01:03:13 -08:00
JosephMcc
c269c57777 xed-view-frame: Fix the css for the minimap frame
This makes it work in gtk3.20+
2018-02-05 01:03:13 -08:00
JosephMcc
561c94e71a xed-status-combo-box: Remove some deprecated css functionality
This stuff is deprecated and just spams warnings so clean it up.
2018-02-05 01:03:12 -08:00
JosephMcc
78ca6d13e0 xed-window: Rework the fullscreen toolbar
The animation used for hiding/showing the fullscreen toolbar is totally broken
under HiDPI. Port to GtkRevealer and GtkEventBox to get the proper behaviour.
2018-02-05 01:03:12 -08:00
JosephMcc
bc18f166a3 preferences-dialog: Complete revamp
Use the new XApps preferences window as the base for a total redesign of the
new dialog. While at it port to GtkSourceStyleSchemeChooserWidget.
2018-02-05 01:03:12 -08:00
JosephMcc
ef9294aae2 Pull upstream fixes for gtk and gtksourceview changes
* fix errors in xed-metadata-manager
* upstream changes for file loading and saving
* modernize some code in xed-document

Closes https://github.com/linuxmint/xed/issues/146
2018-02-05 01:03:12 -08:00
Leigh Scott
4c813f2c7f Fix Py*DeprecationWarning (#202) 2018-02-03 10:26:28 +00:00
Leigh Scott
50b01551ac Fix clang compile issue (#209) 2018-01-30 10:09:43 +00:00
Clement Lefebvre
d5ccae34be Add CI configuration 2018-01-23 10:37:51 +00:00
64 changed files with 4721 additions and 8448 deletions

64
.circleci/config.yml Normal file
View File

@@ -0,0 +1,64 @@
version: 2.0
shared: &shared
steps:
- checkout
- run:
name: Prepare environment
command: apt-get update
- run:
name: Install dependencies
command: |
wget https://github.com/linuxmint/xapps/releases/download/master.${CIRCLE_JOB}/packages.tar.gz -O xapps.tar.gz
ls *.tar.gz | xargs -i tar zxvf {}
apt install --yes --allow-downgrades ./packages/*.deb
rm -rf packages
- run:
name: Build project
command: mint-build -i
- run:
name: Prepare packages
command: |
if [ -z $CI_PULL_REQUEST ]; then
mkdir /packages
mv /root/*.deb /packages/
git log > /packages/git.log
cd /
tar zcvf packages.tar.gz packages
fi
- run:
name: Deploy packages to Github
command: |
if [ -z $CI_PULL_REQUEST ]; then
wget https://github.com/tcnksm/ghr/releases/download/v0.5.4/ghr_v0.5.4_linux_amd64.zip
apt-get install --yes unzip
unzip ghr_v0.5.4_linux_amd64.zip
TAG="master".$CIRCLE_JOB
./ghr -t $GITHUB_TOKEN -u $CIRCLE_PROJECT_USERNAME -r $CIRCLE_PROJECT_REPONAME -replace $TAG /packages.tar.gz
./ghr -t $GITHUB_TOKEN -u $CIRCLE_PROJECT_USERNAME -r $CIRCLE_PROJECT_REPONAME -recreate -b "Latest unstable packages" $TAG /packages.tar.gz
fi
jobs:
"mint19":
<<: *shared
docker:
- image: linuxmintd/mint19-amd64
"lmde3":
<<: *shared
docker:
- image: linuxmintd/lmde3-amd64
workflows:
version: 2
build:
jobs:
- "mint19"
- "lmde3"

View File

@@ -3,8 +3,8 @@ dnl Process this file with autoconf to produce a configure script.
AC_PREREQ(2.63.2) AC_PREREQ(2.63.2)
m4_define(xed_major_version, 1) m4_define(xed_major_version, 1)
m4_define(xed_minor_version, 6) m4_define(xed_minor_version, 8)
m4_define(xed_micro_version, 3) m4_define(xed_micro_version, 0)
m4_define(xed_version, xed_major_version.xed_minor_version.xed_micro_version) m4_define(xed_version, xed_major_version.xed_minor_version.xed_micro_version)
AC_INIT([xed], [xed_version], AC_INIT([xed], [xed_version],
@@ -94,49 +94,25 @@ dnl ================================================================
dnl spell plugins checks: enchant and iso-codes dnl spell plugins checks: enchant and iso-codes
dnl ================================================================ dnl ================================================================
ENCHANT_REQUIRED=1.2.0 GSPELL_REQUIRED=0.2.5
ISO_CODES_REQUIRED=0.35
AC_ARG_ENABLE([spell], AC_ARG_ENABLE([spell],
AS_HELP_STRING([--disable-spell],[Disable spell plugin (default: enabled)]), AS_HELP_STRING([--disable-spell],[Disable spell plugin (default: enabled)]),
[enable_enchant=$enableval], [enable_spell=$enableval],
[enable_enchant=yes]) [enable_spell=yes])
if test "x$enable_enchant" = "xyes" ; then if test "x$enable_spell" = "xyes" ; then
PKG_CHECK_MODULES(ENCHANT, enchant >= $ENCHANT_REQUIRED, \ PKG_CHECK_MODULES(GSPELL, gspell-1 >= $GSPELL_REQUIRED, \
have_enchant=yes, have_enchant=no) have_gspell=yes, have_gspell=no)
if test "x$have_enchant" = "xyes"; then if test "x$have_gspell" = "xno"; then
enable_spell=no
PKG_CHECK_EXISTS([iso-codes >= $ISO_CODES_REQUIRED], AC_MSG_ERROR([gspell library not found or too old. Use --disable-spell to build without spell plugin.])
[have_iso_codes=yes],[have_iso_codes=no])
if test "x$have_iso_codes" = "xyes"; then
AC_MSG_CHECKING([whether iso-codes has iso-639 and iso-3166 domains])
if $PKG_CONFIG --variable=domains iso-codes | grep 639 > /dev/null && \
$PKG_CONFIG --variable=domains iso-codes | grep 3166 > /dev/null ; then
result=yes
else
result=no
have_iso_codes=no
fi
AC_MSG_RESULT([$result])
fi
if test "x$have_iso_codes" = "xyes"; then
AC_DEFINE_UNQUOTED([ISO_CODES_PREFIX],["`$PKG_CONFIG --variable=prefix iso-codes`"],[ISO codes prefix])
AC_DEFINE([HAVE_ISO_CODES],[1],[Define if you have the iso-codes package])
else
AC_MSG_ERROR([iso-codes is required to build the spell plugin. Use --disable-spell to build without spell plugin.])
fi
else
enable_enchant=no
AC_MSG_ERROR([Enchant library not found or too old. Use --disable-spell to build without spell plugin.])
fi fi
fi fi
AM_CONDITIONAL(ENABLE_ENCHANT, test x"$enable_enchant" = "xyes") AM_CONDITIONAL(ENABLE_SPELL, test x"$enable_spell" = "xyes")
dnl ================================================================ dnl ================================================================
dnl Start of pkg-config checks dnl Start of pkg-config checks
@@ -149,10 +125,11 @@ PKG_CHECK_MODULES(XED, [
$GMODULE_ADD $GMODULE_ADD
gthread-2.0 >= 2.13.0 gthread-2.0 >= 2.13.0
gio-2.0 >= 2.40.0 gio-2.0 >= 2.40.0
gtk+-3.0 >= 3.18.0 gtk+-3.0 >= 3.19.3
gtksourceview-3.0 >= 3.18.0 gtksourceview-3.0 >= 3.19.0
libpeas-1.0 >= 1.12.0 libpeas-1.0 >= 1.12.0
libpeas-gtk-1.0 >= 1.12.0 libpeas-gtk-1.0 >= 1.12.0
xapp
]) ])
PKG_CHECK_MODULES(X11, [x11]) PKG_CHECK_MODULES(X11, [x11])
@@ -243,6 +220,8 @@ plugins/textsize/textsize/Makefile
plugins/time/Makefile plugins/time/Makefile
plugins/time/org.x.editor.plugins.time.gschema.xml plugins/time/org.x.editor.plugins.time.gschema.xml
plugins/trailsave/Makefile plugins/trailsave/Makefile
plugins/wordcompletion/Makefile
plugins/wordcompletion/org.x.editor.plugins.wordcompletion.gschema.xml
po/Makefile.in po/Makefile.in
]) ])
@@ -254,7 +233,7 @@ Configuration:
Source code location: ${srcdir} Source code location: ${srcdir}
Compiler: ${CC} Compiler: ${CC}
Spell Plugin enabled: $enable_enchant Spell Plugin enabled: $enable_spell
Gvfs metadata enabled: $enable_gvfs_metadata Gvfs metadata enabled: $enable_gvfs_metadata
GObject Introspection: ${enable_introspection} GObject Introspection: ${enable_introspection}
" "

47
debian/changelog vendored
View File

@@ -1,3 +1,50 @@
xed (1.8.0) tara; urgency=medium
[ Clement Lefebvre ]
* Add CI configuration
[ Leigh Scott ]
* Fix clang compile issue (#209)
* Fix Py*DeprecationWarning (#202)
[ JosephMcc ]
* Pull upstream fixes for gtk and gtksourceview changes
* preferences-dialog: Complete revamp
* xed-window: Rework the fullscreen toolbar
* xed-status-combo-box: Remove some deprecated css functionality
* xed-view-frame: Fix the css for the minimap frame
* xed-notebook: Clean up some gtk3.20+ conditionals
* Add a shortcuts window
* xed-view: Add shortcuts for change case
* debian: Add --enable-silent-rules to debian/rules
* css: Add support for Adwaita
* xed-searchbar: Fix the size of the searchbar close button
* xed-spell-checker.c: Clean up the code formatting
* spell-plugin: Update for removal of some deprecated functionality
* xed-notebook: Allow changing tabs with mouse back/forward buttons
* Fix a couple of issues turned up by Codacy
* Clean up a few build warnings
* spell-plugin: Port to gspell
* spell-plugin: Fix a link to the help file
[ Nic ]
* Add C tags to the taglist plugin (#188)
[ Clement Lefebvre ]
* CI: Don't build for Mint 18
[ JosephMcc ]
* xed-window: Fix a potential crash
[ Mickael Albertus ]
* Creation of plugin Word completion (#199)
[ Clement Lefebvre ]
* Wordcompletion: Fix a few mgsids
* l10n: Update POT file
-- Clement Lefebvre <root@linuxmint.com> Sun, 06 May 2018 16:43:18 +0100
xed (1.6.3) sylvia; urgency=medium xed (1.6.3) sylvia; urgency=medium
* l10n: Update translations * l10n: Update translations

6
debian/control vendored
View File

@@ -7,13 +7,13 @@ Build-Depends: autotools-dev,
gobject-introspection, gobject-introspection,
gtk-doc-tools, gtk-doc-tools,
intltool, intltool,
iso-codes,
libenchant-dev,
libgirepository1.0-dev, libgirepository1.0-dev,
libglib2.0-dev, libglib2.0-dev,
libgspell-1-dev,
libgtk-3-dev, libgtk-3-dev,
libgtksourceview-3.0-dev, libgtksourceview-3.0-dev,
libpeas-dev, libpeas-dev,
libxapp-dev,
libsm-dev, libsm-dev,
libx11-dev, libx11-dev,
libxml2-dev, libxml2-dev,
@@ -145,4 +145,4 @@ Description: Text editor (documentation files)
includes support for spell checking, comparing files, viewing CVS includes support for spell checking, comparing files, viewing CVS
ChangeLogs, and adjusting indentation levels. ChangeLogs, and adjusting indentation levels.
. .
This package contains the documentation files. This package contains the documentation files.

2
debian/rules vendored
View File

@@ -14,7 +14,7 @@ override_dh_auto_configure:
# upstream tarball is without configure. autogen.sh will create it # upstream tarball is without configure. autogen.sh will create it
NOCONFIGURE=1 ./autogen.sh NOCONFIGURE=1 ./autogen.sh
dh_auto_configure $(DHFLAGS) -- \ dh_auto_configure $(DHFLAGS) -- \
--disable-silent-rules \ --enable-silent-rules \
--libexecdir=/usr/lib/ \ --libexecdir=/usr/lib/ \
--enable-gtk-doc --enable-gtk-doc

View File

@@ -7,7 +7,8 @@ DIST_SUBDIRS = \
taglist \ taglist \
textsize \ textsize \
time \ time \
trailsave trailsave \
wordcompletion
SUBDIRS = \ SUBDIRS = \
docinfo \ docinfo \
@@ -17,9 +18,10 @@ SUBDIRS = \
taglist \ taglist \
textsize \ textsize \
time \ time \
trailsave trailsave \
wordcompletion
if ENABLE_ENCHANT if ENABLE_SPELL
SUBDIRS += spell SUBDIRS += spell
endif endif

View File

@@ -4,7 +4,7 @@ plugindir = $(XED_PLUGINS_LIBS_DIR)
AM_CPPFLAGS = \ AM_CPPFLAGS = \
-I$(top_srcdir) \ -I$(top_srcdir) \
$(XED_CFLAGS) \ $(XED_CFLAGS) \
$(ENCHANT_CFLAGS) \ $(GSPELL_CFLAGS) \
$(WARN_CFLAGS) \ $(WARN_CFLAGS) \
$(DISABLE_DEPRECATED_CFLAGS) $(DISABLE_DEPRECATED_CFLAGS)
@@ -17,25 +17,13 @@ plugin_LTLIBRARIES = libspell.la
libspell_la_SOURCES = \ libspell_la_SOURCES = \
xed-spell-plugin.c \ xed-spell-plugin.c \
xed-spell-plugin.h \ xed-spell-plugin.h \
xed-spell-checker.c \
xed-spell-checker.h \
xed-spell-checker-dialog.c \
xed-spell-checker-dialog.h \
xed-spell-checker-language.c \
xed-spell-checker-language.h \
xed-spell-language-dialog.c \
xed-spell-language-dialog.h \
xed-automatic-spell-checker.c \
xed-automatic-spell-checker.h \
xed-spell-utils.c \
xed-spell-utils.h \
$(BUILT_SOURCES) $(BUILT_SOURCES)
libspell_la_LDFLAGS = $(PLUGIN_LIBTOOL_FLAGS) libspell_la_LDFLAGS = $(PLUGIN_LIBTOOL_FLAGS)
libspell_la_LIBADD = $(XED_LIBS) $(ENCHANT_LIBS) libspell_la_LIBADD = $(XED_LIBS) $(GSPELL_LIBS)
uidir = $(XED_PLUGINS_DATA_DIR)/spell uidir = $(XED_PLUGINS_DATA_DIR)/spell
ui_DATA = spell-checker.ui languages-dialog.ui xed-spell-setup-dialog.ui ui_DATA = xed-spell-setup-dialog.ui
xed-spell-marshal.h: xed-spell-marshal.list $(GLIB_GENMARSHAL) xed-spell-marshal.h: xed-spell-marshal.list $(GLIB_GENMARSHAL)
$(AM_V_GEN) $(GLIB_GENMARSHAL) $< --header --prefix=xed_marshal > $@ $(AM_V_GEN) $(GLIB_GENMARSHAL) $< --header --prefix=xed_marshal > $@

View File

@@ -1,140 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.18.3 -->
<!--*- mode: xml -*-->
<interface>
<requires lib="gtk+" version="3.10"/>
<object class="GtkDialog" id="dialog">
<property name="can_focus">False</property>
<property name="border_width">5</property>
<property name="title" translatable="yes">Set language</property>
<property name="modal">True</property>
<property name="destroy_with_parent">True</property>
<property name="type_hint">dialog</property>
<child internal-child="vbox">
<object class="GtkBox" id="dialog-vbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">2</property>
<child internal-child="action_area">
<object class="GtkButtonBox" id="dialog-action_area1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="helpbutton1">
<property name="label">gtk-help</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="closebutton1">
<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">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="button1">
<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">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox" id="content">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="border_width">5</property>
<property name="orientation">vertical</property>
<property name="spacing">11</property>
<child>
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Select the _language of the current document.</property>
<property name="use_underline">True</property>
<property name="wrap">True</property>
<property name="mnemonic_widget">languages_treeview</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="scrolledwindow1">
<property name="height_request">180</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="shadow_type">etched-in</property>
<child>
<object class="GtkTreeView" id="languages_treeview">
<property name="height_request">180</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="headers_visible">False</property>
<child internal-child="selection">
<object class="GtkTreeSelection" id="treeview-selection1"/>
</child>
</object>
</child>
</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">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
</child>
<action-widgets>
<action-widget response="-11">helpbutton1</action-widget>
<action-widget response="-6">closebutton1</action-widget>
<action-widget response="-5">button1</action-widget>
</action-widgets>
</object>
</interface>

View File

@@ -1,369 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.18.3 -->
<interface>
<requires lib="gtk+" version="3.10"/>
<object class="GtkWindow" id="check_spelling_window">
<property name="can_focus">False</property>
<property name="resizable">False</property>
<property name="destroy_with_parent">True</property>
<property name="type_hint">dialog</property>
<property name="skip_taskbar_hint">True</property>
<property name="startup_id">Check spelling</property>
<child>
<object class="GtkBox" id="content">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="border_width">12</property>
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkGrid" id="grid1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="row_spacing">6</property>
<property name="column_spacing">12</property>
<child>
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Misspelled word:</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="misspelled_word_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">word</property>
<property name="use_markup">True</property>
<property name="justify">center</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Change _to:</property>
<property name="use_underline">True</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkBox" id="box1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="spacing">12</property>
<child>
<object class="GtkEntry" id="word_entry">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hexpand">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="check_word_button">
<property name="label" translatable="yes">Check _Word</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_underline">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkGrid" id="grid2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="row_spacing">6</property>
<property name="column_spacing">12</property>
<child>
<object class="GtkLabel" id="label3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">_Suggestions:</property>
<property name="use_underline">True</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="scrolledwindow1">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="shadow_type">in</property>
<child>
<object class="GtkTreeView" id="suggestions_list">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="headers_visible">False</property>
<child internal-child="selection">
<object class="GtkTreeSelection" id="treeview-selection1"/>
</child>
</object>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkBox" id="box2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_bottom">6</property>
<property name="orientation">vertical</property>
<property name="spacing">12</property>
<child>
<object class="GtkGrid" id="grid3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="row_spacing">12</property>
<property name="column_spacing">12</property>
<child>
<object class="GtkButton" id="ignore_button">
<property name="label" translatable="yes">_Ignore</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_underline">True</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="ignore_all_button">
<property name="label" translatable="yes">Ignore _All</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_underline">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="change_button">
<property name="label" translatable="yes">Cha_nge</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_underline">True</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="change_all_button">
<property name="label" translatable="yes">Change A_ll</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_underline">True</property>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox" id="box3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="orientation">vertical</property>
<property name="spacing">11</property>
<child>
<object class="GtkLabel" id="label4">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">User dictionary:</property>
<property name="use_markup">True</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox" id="box7">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">6</property>
<property name="homogeneous">True</property>
<child>
<object class="GtkButton" id="add_word_button">
<property name="label" translatable="yes">Add w_ord</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_underline">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkBox" id="box4">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">12</property>
<child>
<object class="GtkLabel" id="label5">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Language:</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="language_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Language</property>
<property name="use_markup">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">2</property>
</packing>
</child>
<child>
<object class="GtkButtonBox" id="buttonbox1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="homogeneous">True</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="close_button">
<property name="label" translatable="yes">_Close</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="halign">end</property>
<property name="use_underline">True</property>
<style>
<class name="text-button"/>
</style>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">3</property>
</packing>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
</object>
</interface>

View File

@@ -1,967 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* xed-automatic-spell-checker.c
* This file is part of xed
*
* Copyright (C) 2002 Paolo Maggi
*
* 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 St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xed Team, 2002. See the AUTHORS file for a
* list of people on the xed Team.
* See the ChangeLog files for a list of changes.
*/
/* This is a modified version of gtkspell 2.0.5 (gtkspell.sf.net) */
/* gtkspell - a spell-checking addon for GTK's TextView widget
* Copyright (c) 2002 Evan Martin.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
#include <glib/gi18n.h>
#include "xed-automatic-spell-checker.h"
#include "xed-spell-utils.h"
struct _XedAutomaticSpellChecker
{
XedDocument *doc;
GSList *views;
GtkTextMark *mark_insert_start;
GtkTextMark *mark_insert_end;
gboolean deferred_check;
GtkTextTag *tag_highlight;
GtkTextMark *mark_click;
XedSpellChecker *spell_checker;
};
static GQuark automatic_spell_checker_id = 0;
static GQuark suggestion_id = 0;
static void xed_automatic_spell_checker_free_internal (XedAutomaticSpellChecker *spell);
static void
view_destroy (XedView *view,
XedAutomaticSpellChecker *spell)
{
xed_automatic_spell_checker_detach_view (spell, view);
}
static void
check_word (XedAutomaticSpellChecker *spell,
GtkTextIter *start,
GtkTextIter *end)
{
gchar *word;
word = gtk_text_buffer_get_text (GTK_TEXT_BUFFER (spell->doc), start, end, FALSE);
/*
g_print ("Check word: %s [%d - %d]\n", word, gtk_text_iter_get_offset (start),
gtk_text_iter_get_offset (end));
*/
if (!xed_spell_checker_check_word (spell->spell_checker, word, -1))
{
/*
g_print ("Apply tag: [%d - %d]\n", gtk_text_iter_get_offset (start),
gtk_text_iter_get_offset (end));
*/
gtk_text_buffer_apply_tag (GTK_TEXT_BUFFER (spell->doc), spell->tag_highlight, start, end);
}
g_free (word);
}
static void
check_range (XedAutomaticSpellChecker *spell,
GtkTextIter start,
GtkTextIter end,
gboolean force_all)
{
/* we need to "split" on word boundaries.
* luckily, Pango knows what "words" are
* so we don't have to figure it out. */
GtkTextIter wstart;
GtkTextIter wend;
GtkTextIter cursor;
GtkTextIter precursor;
gboolean highlight;
/*
g_print ("Check range: [%d - %d]\n", gtk_text_iter_get_offset (&start),
gtk_text_iter_get_offset (&end));
*/
if (gtk_text_iter_inside_word (&end))
{
gtk_text_iter_forward_word_end (&end);
}
if (!gtk_text_iter_starts_word (&start))
{
if (gtk_text_iter_inside_word (&start) || gtk_text_iter_ends_word (&start))
{
gtk_text_iter_backward_word_start (&start);
}
else
{
/* if we're neither at the beginning nor inside a word,
* me must be in some spaces.
* skip forward to the beginning of the next word. */
if (gtk_text_iter_forward_word_end (&start))
{
gtk_text_iter_backward_word_start (&start);
}
}
}
gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (spell->doc),
&cursor,
gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (spell->doc)));
precursor = cursor;
gtk_text_iter_backward_char (&precursor);
highlight = gtk_text_iter_has_tag (&cursor, spell->tag_highlight) ||
gtk_text_iter_has_tag (&precursor, spell->tag_highlight);
gtk_text_buffer_remove_tag (GTK_TEXT_BUFFER (spell->doc), spell->tag_highlight, &start, &end);
/* Fix a corner case when replacement occurs at beginning of buffer:
* An iter at offset 0 seems to always be inside a word,
* even if it's not. Possibly a pango bug.
*/
if (gtk_text_iter_get_offset (&start) == 0)
{
gtk_text_iter_forward_word_end(&start);
gtk_text_iter_backward_word_start(&start);
}
wstart = start;
while (xed_spell_utils_skip_no_spell_check (&wstart, &end) && gtk_text_iter_compare (&wstart, &end) < 0)
{
gboolean inword;
/* move wend to the end of the current word. */
wend = wstart;
gtk_text_iter_forward_word_end (&wend);
inword = (gtk_text_iter_compare (&wstart, &cursor) < 0) && (gtk_text_iter_compare (&cursor, &wend) <= 0);
if (inword && !force_all)
{
/* this word is being actively edited,
* only check if it's already highligted,
* otherwise defer this check until later. */
if (highlight)
{
check_word (spell, &wstart, &wend);
}
else
{
spell->deferred_check = TRUE;
}
}
else
{
check_word (spell, &wstart, &wend);
spell->deferred_check = FALSE;
}
/* now move wend to the beginning of the next word, */
gtk_text_iter_forward_word_end (&wend);
gtk_text_iter_backward_word_start (&wend);
/* make sure we've actually advanced
* (we don't advance in some corner cases), */
if (gtk_text_iter_equal (&wstart, &wend))
{
break; /* we're done in these cases.. */
}
/* and then pick this as the new next word beginning. */
wstart = wend;
}
}
static void
check_deferred_range (XedAutomaticSpellChecker *spell,
gboolean force_all)
{
GtkTextIter start, end;
gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (spell->doc), &start, spell->mark_insert_start);
gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (spell->doc), &end, spell->mark_insert_end);
check_range (spell, start, end, force_all);
}
/* insertion works like this:
* - before the text is inserted, we mark the position in the buffer.
* - after the text is inserted, we see where our mark is and use that and
* the current position to check the entire range of inserted text.
*
* this may be overkill for the common case (inserting one character). */
static void
insert_text_before (GtkTextBuffer *buffer,
GtkTextIter *iter,
gchar *text,
gint len,
XedAutomaticSpellChecker *spell)
{
gtk_text_buffer_move_mark (buffer, spell->mark_insert_start, iter);
}
static void
insert_text_after (GtkTextBuffer *buffer,
GtkTextIter *iter,
gchar *text,
gint len,
XedAutomaticSpellChecker *spell)
{
GtkTextIter start;
/* we need to check a range of text. */
gtk_text_buffer_get_iter_at_mark (buffer, &start, spell->mark_insert_start);
check_range (spell, start, *iter, FALSE);
gtk_text_buffer_move_mark (buffer, spell->mark_insert_end, iter);
}
/* deleting is more simple: we're given the range of deleted text.
* after deletion, the start and end iters should be at the same position
* (because all of the text between them was deleted!).
* this means we only really check the words immediately bounding the
* deletion.
*/
static void
delete_range_after (GtkTextBuffer *buffer,
GtkTextIter *start,
GtkTextIter *end,
XedAutomaticSpellChecker *spell)
{
check_range (spell, *start, *end, FALSE);
}
static void
mark_set (GtkTextBuffer *buffer,
GtkTextIter *iter,
GtkTextMark *mark,
XedAutomaticSpellChecker *spell)
{
/* if the cursor has moved and there is a deferred check so handle it now */
if ((mark == gtk_text_buffer_get_insert (buffer)) && spell->deferred_check)
{
check_deferred_range (spell, FALSE);
}
}
static void
get_word_extents_from_mark (GtkTextBuffer *buffer,
GtkTextIter *start,
GtkTextIter *end,
GtkTextMark *mark)
{
gtk_text_buffer_get_iter_at_mark(buffer, start, mark);
if (!gtk_text_iter_starts_word (start))
{
gtk_text_iter_backward_word_start (start);
}
*end = *start;
if (gtk_text_iter_inside_word (end))
{
gtk_text_iter_forward_word_end (end);
}
}
static void
remove_tag_to_word (XedAutomaticSpellChecker *spell,
const gchar *word)
{
GtkTextIter iter;
GtkTextIter match_start, match_end;
gboolean found;
gtk_text_buffer_get_iter_at_offset (GTK_TEXT_BUFFER (spell->doc), &iter, 0);
found = TRUE;
while (found)
{
found = gtk_text_iter_forward_search (&iter,
word,
GTK_TEXT_SEARCH_VISIBLE_ONLY | GTK_TEXT_SEARCH_TEXT_ONLY,
&match_start,
&match_end,
NULL);
if (found)
{
if (gtk_text_iter_starts_word (&match_start) && gtk_text_iter_ends_word (&match_end))
{
gtk_text_buffer_remove_tag (GTK_TEXT_BUFFER (spell->doc),
spell->tag_highlight,
&match_start,
&match_end);
}
iter = match_end;
}
}
}
static void
add_to_dictionary (GtkWidget *menuitem,
XedAutomaticSpellChecker *spell)
{
gchar *word;
GtkTextIter start, end;
get_word_extents_from_mark (GTK_TEXT_BUFFER (spell->doc), &start, &end, spell->mark_click);
word = gtk_text_buffer_get_text (GTK_TEXT_BUFFER (spell->doc), &start, &end, FALSE);
xed_spell_checker_add_word_to_personal (spell->spell_checker, word, -1);
g_free (word);
}
static void
ignore_all (GtkWidget *menuitem,
XedAutomaticSpellChecker *spell)
{
gchar *word;
GtkTextIter start, end;
get_word_extents_from_mark (GTK_TEXT_BUFFER (spell->doc), &start, &end, spell->mark_click);
word = gtk_text_buffer_get_text (GTK_TEXT_BUFFER (spell->doc), &start, &end, FALSE);
xed_spell_checker_add_word_to_session (spell->spell_checker, word, -1);
g_free (word);
}
static void
replace_word (GtkWidget *menuitem,
XedAutomaticSpellChecker *spell)
{
gchar *oldword;
const gchar *newword;
GtkTextIter start, end;
get_word_extents_from_mark (GTK_TEXT_BUFFER (spell->doc), &start, &end, spell->mark_click);
oldword = gtk_text_buffer_get_text (GTK_TEXT_BUFFER (spell->doc), &start, &end, FALSE);
newword = g_object_get_qdata (G_OBJECT (menuitem), suggestion_id);
g_return_if_fail (newword != NULL);
gtk_text_buffer_begin_user_action (GTK_TEXT_BUFFER (spell->doc));
gtk_text_buffer_delete (GTK_TEXT_BUFFER (spell->doc), &start, &end);
gtk_text_buffer_insert (GTK_TEXT_BUFFER (spell->doc), &start, newword, -1);
gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER (spell->doc));
xed_spell_checker_set_correction (spell->spell_checker,
oldword, strlen (oldword),
newword, strlen (newword));
g_free (oldword);
}
static GtkWidget *
build_suggestion_menu (XedAutomaticSpellChecker *spell,
const gchar *word)
{
GtkWidget *topmenu, *menu;
GtkWidget *mi;
GSList *suggestions;
GSList *list;
gchar *label_text;
topmenu = menu = gtk_menu_new();
suggestions = xed_spell_checker_get_suggestions (spell->spell_checker, word, -1);
list = suggestions;
if (suggestions == NULL)
{
/* no suggestions. put something in the menu anyway... */
GtkWidget *label;
/* Translators: Displayed in the "Check Spelling" dialog if there are no suggestions for the current misspelled word */
label = gtk_label_new (_("(no suggested words)"));
mi = gtk_menu_item_new ();
gtk_widget_set_sensitive (mi, FALSE);
gtk_container_add (GTK_CONTAINER(mi), label);
gtk_widget_show_all (mi);
gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), mi);
}
else
{
gint count = 0;
/* build a set of menus with suggestions. */
while (suggestions != NULL)
{
GtkWidget *label;
if (count == 10)
{
/* Separator */
mi = gtk_menu_item_new ();
gtk_widget_show (mi);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
mi = gtk_menu_item_new_with_mnemonic (_("_More..."));
gtk_widget_show (mi);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
menu = gtk_menu_new ();
gtk_menu_item_set_submenu (GTK_MENU_ITEM (mi), menu);
count = 0;
}
label_text = g_strdup_printf ("<b>%s</b>", (gchar*) suggestions->data);
label = gtk_label_new (label_text);
gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
gtk_widget_set_halign (label, GTK_ALIGN_START);
mi = gtk_menu_item_new ();
gtk_container_add (GTK_CONTAINER (mi), label);
gtk_widget_show_all (mi);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), mi);
g_object_set_qdata_full (G_OBJECT (mi),
suggestion_id,
g_strdup (suggestions->data),
(GDestroyNotify)g_free);
g_free (label_text);
g_signal_connect (mi, "activate",
G_CALLBACK (replace_word), spell);
count++;
suggestions = g_slist_next (suggestions);
}
}
/* free the suggestion list */
suggestions = list;
while (list)
{
g_free (list->data);
list = g_slist_next (list);
}
g_slist_free (suggestions);
/* Separator */
mi = gtk_menu_item_new ();
gtk_widget_show (mi);
gtk_menu_shell_append (GTK_MENU_SHELL (topmenu), mi);
/* Ignore all */
mi = gtk_menu_item_new_with_mnemonic (_("_Ignore All"));
g_signal_connect (mi, "activate",
G_CALLBACK(ignore_all), spell);
gtk_widget_show_all (mi);
gtk_menu_shell_append (GTK_MENU_SHELL (topmenu), mi);
/* + Add to Dictionary */
mi = gtk_menu_item_new_with_mnemonic (_("_Add"));
g_signal_connect (mi, "activate",
G_CALLBACK (add_to_dictionary), spell);
gtk_widget_show_all (mi);
gtk_menu_shell_append (GTK_MENU_SHELL (topmenu), mi);
return topmenu;
}
static void
populate_popup (GtkTextView *textview,
GtkMenu *menu,
XedAutomaticSpellChecker *spell)
{
GtkWidget *mi;
GtkTextIter start, end;
char *word;
/* we need to figure out if they picked a misspelled word. */
get_word_extents_from_mark (GTK_TEXT_BUFFER (spell->doc), &start, &end, spell->mark_click);
/* if our highlight algorithm ever messes up,
* this isn't correct, either. */
if (!gtk_text_iter_has_tag (&start, spell->tag_highlight))
{
return; /* word wasn't misspelled. */
}
/* menu separator comes first. */
mi = gtk_menu_item_new ();
gtk_widget_show (mi);
gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), mi);
/* then, on top of it, the suggestions menu. */
mi = gtk_menu_item_new_with_mnemonic (_("_Spelling Suggestions..."));
word = gtk_text_buffer_get_text (GTK_TEXT_BUFFER (spell->doc), &start, &end, FALSE);
gtk_menu_item_set_submenu (GTK_MENU_ITEM (mi), build_suggestion_menu (spell, word));
g_free(word);
gtk_widget_show_all (mi);
gtk_menu_shell_prepend (GTK_MENU_SHELL (menu), mi);
}
void
xed_automatic_spell_checker_recheck_all (XedAutomaticSpellChecker *spell)
{
GtkTextIter start, end;
g_return_if_fail (spell != NULL);
gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER (spell->doc), &start, &end);
check_range (spell, start, end, TRUE);
}
static void
add_word_signal_cb (XedSpellChecker *checker,
const gchar *word,
gint len,
XedAutomaticSpellChecker *spell)
{
gchar *w;
if (len < 0)
{
w = g_strdup (word);
}
else
{
w = g_strndup (word, len);
}
remove_tag_to_word (spell, w);
g_free (w);
}
static void
set_language_cb (XedSpellChecker *checker,
const XedSpellCheckerLanguage *lang,
XedAutomaticSpellChecker *spell)
{
xed_automatic_spell_checker_recheck_all (spell);
}
static void
clear_session_cb (XedSpellChecker *checker,
XedAutomaticSpellChecker *spell)
{
xed_automatic_spell_checker_recheck_all (spell);
}
/* When the user right-clicks on a word, they want to check that word.
* Here, we do NOT move the cursor to the location of the clicked-upon word
* since that prevents the use of edit functions on the context menu.
*/
static gboolean
button_press_event (GtkTextView *view,
GdkEventButton *event,
XedAutomaticSpellChecker *spell)
{
if (event->button == 3)
{
gint x, y;
GtkTextIter iter;
GtkTextBuffer *buffer = gtk_text_view_get_buffer (view);
/* handle deferred check if it exists */
if (spell->deferred_check)
{
check_deferred_range (spell, TRUE);
}
gtk_text_view_window_to_buffer_coords (view, GTK_TEXT_WINDOW_TEXT, event->x, event->y, &x, &y);
gtk_text_view_get_iter_at_location (view, &iter, x, y);
gtk_text_buffer_move_mark (buffer, spell->mark_click, &iter);
}
return FALSE; /* false: let gtk process this event, too.
we don't want to eat any events. */
}
/* Move the insert mark before popping up the menu, otherwise it
* will contain the wrong set of suggestions.
*/
static gboolean
popup_menu_event (GtkTextView *view,
XedAutomaticSpellChecker *spell)
{
GtkTextIter iter;
GtkTextBuffer *buffer;
buffer = gtk_text_view_get_buffer (view);
/* handle deferred check if it exists */
if (spell->deferred_check)
{
check_deferred_range (spell, TRUE);
}
gtk_text_buffer_get_iter_at_mark (buffer, &iter, gtk_text_buffer_get_insert (buffer));
gtk_text_buffer_move_mark (buffer, spell->mark_click, &iter);
return FALSE;
}
static void
tag_table_changed (GtkTextTagTable *table,
XedAutomaticSpellChecker *spell)
{
g_return_if_fail (spell->tag_highlight != NULL);
gtk_text_tag_set_priority (spell->tag_highlight, gtk_text_tag_table_get_size (table) - 1);
}
static void
tag_added_or_removed (GtkTextTagTable *table,
GtkTextTag *tag,
XedAutomaticSpellChecker *spell)
{
tag_table_changed (table, spell);
}
static void
tag_changed (GtkTextTagTable *table,
GtkTextTag *tag,
gboolean size_changed,
XedAutomaticSpellChecker *spell)
{
tag_table_changed (table, spell);
}
static void
highlight_updated (GtkSourceBuffer *buffer,
GtkTextIter *start,
GtkTextIter *end,
XedAutomaticSpellChecker *spell)
{
check_range (spell, *start, *end, FALSE);
}
static void
spell_tag_destroyed (XedAutomaticSpellChecker *spell,
GObject *where_the_object_was)
{
spell->tag_highlight = NULL;
}
XedAutomaticSpellChecker *
xed_automatic_spell_checker_new (XedDocument *doc,
XedSpellChecker *checker)
{
XedAutomaticSpellChecker *spell;
GtkTextTagTable *tag_table;
GtkTextIter start, end;
g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL);
g_return_val_if_fail (XED_IS_SPELL_CHECKER (checker), NULL);
g_return_val_if_fail ((spell = xed_automatic_spell_checker_get_from_document (doc)) == NULL, spell);
/* attach to the widget */
spell = g_new0 (XedAutomaticSpellChecker, 1);
spell->doc = doc;
spell->spell_checker = g_object_ref (checker);
if (automatic_spell_checker_id == 0)
{
automatic_spell_checker_id = g_quark_from_string ("XedAutomaticSpellCheckerID");
}
if (suggestion_id == 0)
{
suggestion_id = g_quark_from_string ("XedAutoSuggestionID");
}
g_object_set_qdata_full (G_OBJECT (doc), automatic_spell_checker_id,
spell, (GDestroyNotify)xed_automatic_spell_checker_free_internal);
g_signal_connect (doc, "insert-text",
G_CALLBACK (insert_text_before), spell);
g_signal_connect_after (doc, "insert-text",
G_CALLBACK (insert_text_after), spell);
g_signal_connect_after (doc, "delete-range",
G_CALLBACK (delete_range_after), spell);
g_signal_connect (doc, "mark-set",
G_CALLBACK (mark_set), spell);
g_signal_connect (doc, "highlight-updated",
G_CALLBACK (highlight_updated), spell);
g_signal_connect (spell->spell_checker, "add_word_to_session",
G_CALLBACK (add_word_signal_cb), spell);
g_signal_connect (spell->spell_checker, "add_word_to_personal",
G_CALLBACK (add_word_signal_cb), spell);
g_signal_connect (spell->spell_checker, "clear_session",
G_CALLBACK (clear_session_cb), spell);
g_signal_connect (spell->spell_checker, "set_language",
G_CALLBACK (set_language_cb), spell);
spell->tag_highlight = gtk_text_buffer_create_tag (GTK_TEXT_BUFFER (doc),
"gtkspell-misspelled",
"underline", PANGO_UNDERLINE_ERROR,
NULL);
g_object_weak_ref (G_OBJECT (spell->tag_highlight), (GWeakNotify)spell_tag_destroyed, spell);
tag_table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (doc));
gtk_text_tag_set_priority (spell->tag_highlight, gtk_text_tag_table_get_size (tag_table) - 1);
g_signal_connect (tag_table, "tag-added",
G_CALLBACK (tag_added_or_removed), spell);
g_signal_connect (tag_table, "tag-removed",
G_CALLBACK (tag_added_or_removed), spell);
g_signal_connect (tag_table, "tag-changed",
G_CALLBACK (tag_changed), spell);
/* we create the mark here, but we don't use it until text is
* inserted, so we don't really care where iter points. */
gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER (doc), &start, &end);
spell->mark_insert_start = gtk_text_buffer_get_mark (GTK_TEXT_BUFFER (doc),
"xed-automatic-spell-checker-insert-start");
if (spell->mark_insert_start == NULL)
{
spell->mark_insert_start = gtk_text_buffer_create_mark (GTK_TEXT_BUFFER (doc),
"xed-automatic-spell-checker-insert-start",
&start,
TRUE);
}
else
{
gtk_text_buffer_move_mark (GTK_TEXT_BUFFER (doc), spell->mark_insert_start, &start);
}
spell->mark_insert_end = gtk_text_buffer_get_mark (GTK_TEXT_BUFFER (doc),
"xed-automatic-spell-checker-insert-end");
if (spell->mark_insert_end == NULL)
{
spell->mark_insert_end = gtk_text_buffer_create_mark (GTK_TEXT_BUFFER (doc),
"xed-automatic-spell-checker-insert-end",
&start,
TRUE);
}
else
{
gtk_text_buffer_move_mark (GTK_TEXT_BUFFER (doc), spell->mark_insert_end, &start);
}
spell->mark_click = gtk_text_buffer_get_mark (GTK_TEXT_BUFFER (doc),
"xed-automatic-spell-checker-click");
if (spell->mark_click == NULL)
{
spell->mark_click = gtk_text_buffer_create_mark (GTK_TEXT_BUFFER (doc),
"xed-automatic-spell-checker-click",
&start,
TRUE);
}
else
{
gtk_text_buffer_move_mark (GTK_TEXT_BUFFER (doc), spell->mark_click, &start);
}
spell->deferred_check = FALSE;
return spell;
}
XedAutomaticSpellChecker *
xed_automatic_spell_checker_get_from_document (const XedDocument *doc)
{
g_return_val_if_fail (XED_IS_DOCUMENT (doc), NULL);
if (automatic_spell_checker_id == 0)
{
return NULL;
}
return g_object_get_qdata (G_OBJECT (doc), automatic_spell_checker_id);
}
void
xed_automatic_spell_checker_free (XedAutomaticSpellChecker *spell)
{
g_return_if_fail (spell != NULL);
g_return_if_fail (xed_automatic_spell_checker_get_from_document (spell->doc) == spell);
if (automatic_spell_checker_id == 0)
{
return;
}
g_object_set_qdata (G_OBJECT (spell->doc), automatic_spell_checker_id, NULL);
}
static void
xed_automatic_spell_checker_free_internal (XedAutomaticSpellChecker *spell)
{
GtkTextTagTable *table;
GtkTextIter start, end;
GSList *list;
g_return_if_fail (spell != NULL);
table = gtk_text_buffer_get_tag_table (GTK_TEXT_BUFFER (spell->doc));
if (table != NULL && spell->tag_highlight != NULL)
{
gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER (spell->doc), &start, &end);
gtk_text_buffer_remove_tag (GTK_TEXT_BUFFER (spell->doc), spell->tag_highlight, &start, &end);
g_signal_handlers_disconnect_matched (G_OBJECT (table),
G_SIGNAL_MATCH_DATA,
0, 0, NULL, NULL,
spell);
gtk_text_tag_table_remove (table, spell->tag_highlight);
}
g_signal_handlers_disconnect_matched (G_OBJECT (spell->doc),
G_SIGNAL_MATCH_DATA,
0, 0, NULL, NULL,
spell);
g_signal_handlers_disconnect_matched (G_OBJECT (spell->spell_checker),
G_SIGNAL_MATCH_DATA,
0, 0, NULL, NULL,
spell);
g_object_unref (spell->spell_checker);
list = spell->views;
while (list != NULL)
{
XedView *view = XED_VIEW (list->data);
g_signal_handlers_disconnect_matched (G_OBJECT (view),
G_SIGNAL_MATCH_DATA,
0, 0, NULL, NULL,
spell);
g_signal_handlers_disconnect_matched (G_OBJECT (view),
G_SIGNAL_MATCH_DATA,
0, 0, NULL, NULL,
spell);
list = g_slist_next (list);
}
g_slist_free (spell->views);
g_free (spell);
}
void
xed_automatic_spell_checker_attach_view (XedAutomaticSpellChecker *spell,
XedView *view)
{
g_return_if_fail (spell != NULL);
g_return_if_fail (XED_IS_VIEW (view));
g_return_if_fail (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)) == GTK_TEXT_BUFFER (spell->doc));
g_signal_connect (view, "button-press-event",
G_CALLBACK (button_press_event), spell);
g_signal_connect (view, "popup-menu",
G_CALLBACK (popup_menu_event), spell);
g_signal_connect (view, "populate-popup",
G_CALLBACK (populate_popup), spell);
g_signal_connect (view, "destroy",
G_CALLBACK (view_destroy), spell);
spell->views = g_slist_prepend (spell->views, view);
}
void
xed_automatic_spell_checker_detach_view (XedAutomaticSpellChecker *spell,
XedView *view)
{
g_return_if_fail (spell != NULL);
g_return_if_fail (XED_IS_VIEW (view));
g_return_if_fail (gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)) == GTK_TEXT_BUFFER (spell->doc));
g_return_if_fail (spell->views != NULL);
g_signal_handlers_disconnect_matched (G_OBJECT (view),
G_SIGNAL_MATCH_DATA,
0, 0, NULL, NULL,
spell);
g_signal_handlers_disconnect_matched (G_OBJECT (view),
G_SIGNAL_MATCH_DATA,
0, 0, NULL, NULL,
spell);
spell->views = g_slist_remove (spell->views, view);
}

View File

@@ -1,67 +0,0 @@
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* xed-automatic-spell-checker.h
* This file is part of xed
*
* Copyright (C) 2002 Paolo Maggi
*
* 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 St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xed Team, 2002. See the AUTHORS file for a
* list of people on the xed Team.
* See the ChangeLog files for a list of changes.
*/
/* This is a modified version of gtkspell 2.0.2 (gtkspell.sf.net) */
/* gtkspell - a spell-checking addon for GTK's TextView widget
* Copyright (c) 2002 Evan Martin.
*/
#ifndef __XED_AUTOMATIC_SPELL_CHECKER_H__
#define __XED_AUTOMATIC_SPELL_CHECKER_H__
#include <xed/xed-document.h>
#include <xed/xed-view.h>
#include "xed-spell-checker.h"
typedef struct _XedAutomaticSpellChecker XedAutomaticSpellChecker;
XedAutomaticSpellChecker *xed_automatic_spell_checker_new (
XedDocument *doc,
XedSpellChecker *checker);
XedAutomaticSpellChecker *xed_automatic_spell_checker_get_from_document (
const XedDocument *doc);
void xed_automatic_spell_checker_free (
XedAutomaticSpellChecker *spell);
void xed_automatic_spell_checker_attach_view (
XedAutomaticSpellChecker *spell,
XedView *view);
void xed_automatic_spell_checker_detach_view (
XedAutomaticSpellChecker *spell,
XedView *view);
void xed_automatic_spell_checker_recheck_all (
XedAutomaticSpellChecker *spell);
#endif /* __XED_AUTOMATIC_SPELL_CHECKER_H__ */

View File

@@ -1,726 +0,0 @@
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* xed-spell-checker-dialog.c
* This file is part of xed
*
* Copyright (C) 2002 Paolo Maggi
*
* 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 St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xed Team, 2002. See the AUTHORS file for a
* list of people on the xed Team.
* See the ChangeLog files for a list of changes.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include <xed/xed-utils.h>
#include "xed-spell-checker-dialog.h"
#include "xed-spell-marshal.h"
struct _XedSpellCheckerDialog
{
GtkWindow parent_instance;
XedSpellChecker *spell_checker;
gchar *misspelled_word;
GtkWidget *misspelled_word_label;
GtkWidget *word_entry;
GtkWidget *check_word_button;
GtkWidget *ignore_button;
GtkWidget *ignore_all_button;
GtkWidget *change_button;
GtkWidget *change_all_button;
GtkWidget *add_word_button;
GtkWidget *close_button;
GtkWidget *suggestions_list;
GtkWidget *language_label;
GtkTreeModel *suggestions_list_model;
};
enum
{
IGNORE,
IGNORE_ALL,
CHANGE,
CHANGE_ALL,
ADD_WORD_TO_PERSONAL,
LAST_SIGNAL
};
enum
{
COLUMN_SUGGESTIONS,
NUM_COLUMNS
};
static void update_suggestions_list_model (XedSpellCheckerDialog *dlg,
GSList *suggestions);
static void word_entry_changed_handler (GtkEditable *editable,
XedSpellCheckerDialog *dlg);
static void close_button_clicked_handler (GtkButton *button,
XedSpellCheckerDialog *dlg);
static void suggestions_list_selection_changed_handler (GtkTreeSelection *selection,
XedSpellCheckerDialog *dlg);
static void check_word_button_clicked_handler (GtkButton *button,
XedSpellCheckerDialog *dlg);
static void add_word_button_clicked_handler (GtkButton *button,
XedSpellCheckerDialog *dlg);
static void ignore_button_clicked_handler (GtkButton *button,
XedSpellCheckerDialog *dlg);
static void ignore_all_button_clicked_handler (GtkButton *button,
XedSpellCheckerDialog *dlg);
static void change_button_clicked_handler (GtkButton *button,
XedSpellCheckerDialog *dlg);
static void change_all_button_clicked_handler (GtkButton *button,
XedSpellCheckerDialog *dlg);
static void suggestions_list_row_activated_handler (GtkTreeView *view,
GtkTreePath *path,
GtkTreeViewColumn *column,
XedSpellCheckerDialog *dlg);
static guint signals [LAST_SIGNAL] = { 0 };
G_DEFINE_TYPE(XedSpellCheckerDialog, xed_spell_checker_dialog, GTK_TYPE_WINDOW)
static void
xed_spell_checker_dialog_dispose (GObject *object)
{
XedSpellCheckerDialog *dlg = XED_SPELL_CHECKER_DIALOG (object);
if (dlg->spell_checker != NULL)
{
g_object_unref (dlg->spell_checker);
dlg->spell_checker = NULL;
}
if (dlg->misspelled_word != NULL)
{
g_free (dlg->misspelled_word);
dlg->misspelled_word = NULL;
}
G_OBJECT_CLASS (xed_spell_checker_dialog_parent_class)->dispose (object);
}
static void
xed_spell_checker_dialog_class_init (XedSpellCheckerDialogClass * klass)
{
GObjectClass *object_class;
object_class = G_OBJECT_CLASS (klass);
object_class->dispose = xed_spell_checker_dialog_dispose;
signals[IGNORE] =
g_signal_new ("ignore",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (XedSpellCheckerDialogClass, ignore),
NULL, NULL,
xed_marshal_VOID__STRING,
G_TYPE_NONE,
1,
G_TYPE_STRING);
signals[IGNORE_ALL] =
g_signal_new ("ignore_all",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (XedSpellCheckerDialogClass, ignore_all),
NULL, NULL,
xed_marshal_VOID__STRING,
G_TYPE_NONE,
1,
G_TYPE_STRING);
signals[CHANGE] =
g_signal_new ("change",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (XedSpellCheckerDialogClass, change),
NULL, NULL,
xed_marshal_VOID__STRING_STRING,
G_TYPE_NONE,
2,
G_TYPE_STRING,
G_TYPE_STRING);
signals[CHANGE_ALL] =
g_signal_new ("change_all",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (XedSpellCheckerDialogClass, change_all),
NULL, NULL,
xed_marshal_VOID__STRING_STRING,
G_TYPE_NONE,
2,
G_TYPE_STRING,
G_TYPE_STRING);
signals[ADD_WORD_TO_PERSONAL] =
g_signal_new ("add_word_to_personal",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (XedSpellCheckerDialogClass, add_word_to_personal),
NULL, NULL,
xed_marshal_VOID__STRING,
G_TYPE_NONE,
1,
G_TYPE_STRING);
}
static void
create_dialog (XedSpellCheckerDialog *dlg,
const gchar *data_dir)
{
GtkWidget *error_widget;
GtkWidget *content;
GtkTreeViewColumn *column;
GtkCellRenderer *cell;
GtkTreeSelection *selection;
gchar *root_objects[] = {
"content",
"check_word_image",
"add_word_image",
"ignore_image",
"change_image",
"ignore_all_image",
"change_all_image",
NULL
};
gboolean ret;
gchar *ui_file;
g_return_if_fail (dlg != NULL);
dlg->spell_checker = NULL;
dlg->misspelled_word = NULL;
ui_file = g_build_filename (data_dir, "spell-checker.ui", NULL);
ret = xed_utils_get_ui_objects (ui_file,
root_objects,
&error_widget,
"content", &content,
"misspelled_word_label", &dlg->misspelled_word_label,
"word_entry", &dlg->word_entry,
"check_word_button", &dlg->check_word_button,
"ignore_button", &dlg->ignore_button,
"ignore_all_button", &dlg->ignore_all_button,
"change_button", &dlg->change_button,
"change_all_button", &dlg->change_all_button,
"add_word_button", &dlg->add_word_button,
"close_button", &dlg->close_button,
"suggestions_list", &dlg->suggestions_list,
"language_label", &dlg->language_label,
NULL);
g_free (ui_file);
if (!ret)
{
gtk_widget_show (error_widget);
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))),
error_widget, TRUE, TRUE, 0);
return;
}
gtk_label_set_label (GTK_LABEL (dlg->misspelled_word_label), "");
gtk_widget_set_sensitive (dlg->word_entry, FALSE);
gtk_widget_set_sensitive (dlg->check_word_button, FALSE);
gtk_widget_set_sensitive (dlg->ignore_button, FALSE);
gtk_widget_set_sensitive (dlg->ignore_all_button, FALSE);
gtk_widget_set_sensitive (dlg->change_button, FALSE);
gtk_widget_set_sensitive (dlg->change_all_button, FALSE);
gtk_widget_set_sensitive (dlg->add_word_button, FALSE);
gtk_label_set_label (GTK_LABEL (dlg->language_label), "");
gtk_container_add (GTK_CONTAINER (dlg), content);
g_object_unref (content);
gtk_window_set_resizable (GTK_WINDOW (dlg), FALSE);
gtk_window_set_title (GTK_WINDOW (dlg), _("Check Spelling"));
/* Suggestion list */
dlg->suggestions_list_model = GTK_TREE_MODEL (
gtk_list_store_new (NUM_COLUMNS, G_TYPE_STRING));
gtk_tree_view_set_model (GTK_TREE_VIEW (dlg->suggestions_list),
dlg->suggestions_list_model);
/* Add the suggestions column */
cell = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes (_("Suggestions"), cell,
"text", COLUMN_SUGGESTIONS, NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (dlg->suggestions_list), column);
gtk_tree_view_set_search_column (GTK_TREE_VIEW (dlg->suggestions_list),
COLUMN_SUGGESTIONS);
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dlg->suggestions_list));
gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
/* Set default button */
gtk_widget_set_can_default (dlg->change_button, TRUE);
gtk_widget_grab_default (dlg->change_button);
gtk_entry_set_activates_default (GTK_ENTRY (dlg->word_entry), TRUE);
/* Connect signals */
g_signal_connect (dlg->word_entry, "changed",
G_CALLBACK (word_entry_changed_handler), dlg);
g_signal_connect (dlg->close_button, "clicked",
G_CALLBACK (close_button_clicked_handler), dlg);
g_signal_connect (selection, "changed",
G_CALLBACK (suggestions_list_selection_changed_handler),
dlg);
g_signal_connect (dlg->check_word_button, "clicked",
G_CALLBACK (check_word_button_clicked_handler), dlg);
g_signal_connect (dlg->add_word_button, "clicked",
G_CALLBACK (add_word_button_clicked_handler), dlg);
g_signal_connect (dlg->ignore_button, "clicked",
G_CALLBACK (ignore_button_clicked_handler), dlg);
g_signal_connect (dlg->ignore_all_button, "clicked",
G_CALLBACK (ignore_all_button_clicked_handler), dlg);
g_signal_connect (dlg->change_button, "clicked",
G_CALLBACK (change_button_clicked_handler), dlg);
g_signal_connect (dlg->change_all_button, "clicked",
G_CALLBACK (change_all_button_clicked_handler), dlg);
g_signal_connect (dlg->suggestions_list, "row-activated",
G_CALLBACK (suggestions_list_row_activated_handler), dlg);
}
static void
xed_spell_checker_dialog_init (XedSpellCheckerDialog *dlg)
{
}
GtkWidget *
xed_spell_checker_dialog_new (const gchar *data_dir)
{
XedSpellCheckerDialog *dlg;
dlg = XED_SPELL_CHECKER_DIALOG (
g_object_new (XED_TYPE_SPELL_CHECKER_DIALOG, NULL));
g_return_val_if_fail (dlg != NULL, NULL);
create_dialog (dlg, data_dir);
return GTK_WIDGET (dlg);
}
GtkWidget *
xed_spell_checker_dialog_new_from_spell_checker (XedSpellChecker *spell,
const gchar *data_dir)
{
XedSpellCheckerDialog *dlg;
g_return_val_if_fail (spell != NULL, NULL);
dlg = XED_SPELL_CHECKER_DIALOG (
g_object_new (XED_TYPE_SPELL_CHECKER_DIALOG, NULL));
g_return_val_if_fail (dlg != NULL, NULL);
create_dialog (dlg, data_dir);
xed_spell_checker_dialog_set_spell_checker (dlg, spell);
return GTK_WIDGET (dlg);
}
void
xed_spell_checker_dialog_set_spell_checker (XedSpellCheckerDialog *dlg, XedSpellChecker *spell)
{
const XedSpellCheckerLanguage* language;
const gchar *lang;
gchar *tmp;
g_return_if_fail (XED_IS_SPELL_CHECKER_DIALOG (dlg));
g_return_if_fail (spell != NULL);
if (dlg->spell_checker != NULL)
g_object_unref (dlg->spell_checker);
dlg->spell_checker = spell;
g_object_ref (dlg->spell_checker);
language = xed_spell_checker_get_language (dlg->spell_checker);
lang = xed_spell_checker_language_to_string (language);
tmp = g_strdup_printf("<b>%s</b>", lang);
gtk_label_set_label (GTK_LABEL (dlg->language_label), tmp);
g_free (tmp);
if (dlg->misspelled_word != NULL)
xed_spell_checker_dialog_set_misspelled_word (dlg, dlg->misspelled_word, -1);
else
gtk_list_store_clear (GTK_LIST_STORE (dlg->suggestions_list_model));
/* TODO: reset all widgets */
}
void
xed_spell_checker_dialog_set_misspelled_word (XedSpellCheckerDialog *dlg,
const gchar *word,
gint len)
{
gchar *tmp;
GSList *sug;
g_return_if_fail (XED_IS_SPELL_CHECKER_DIALOG (dlg));
g_return_if_fail (word != NULL);
g_return_if_fail (dlg->spell_checker != NULL);
g_return_if_fail (!xed_spell_checker_check_word (dlg->spell_checker, word, -1));
/* build_suggestions_list */
if (dlg->misspelled_word != NULL)
g_free (dlg->misspelled_word);
dlg->misspelled_word = g_strdup (word);
tmp = g_strdup_printf("<b>%s</b>", word);
gtk_label_set_label (GTK_LABEL (dlg->misspelled_word_label), tmp);
g_free (tmp);
sug = xed_spell_checker_get_suggestions (dlg->spell_checker,
dlg->misspelled_word,
-1);
update_suggestions_list_model (dlg, sug);
/* free the suggestion list */
g_slist_foreach (sug, (GFunc)g_free, NULL);
g_slist_free (sug);
gtk_widget_set_sensitive (dlg->ignore_button, TRUE);
gtk_widget_set_sensitive (dlg->ignore_all_button, TRUE);
gtk_widget_set_sensitive (dlg->add_word_button, TRUE);
}
static void
update_suggestions_list_model (XedSpellCheckerDialog *dlg, GSList *suggestions)
{
GtkListStore *store;
GtkTreeIter iter;
GtkTreeSelection *sel;
g_return_if_fail (XED_IS_SPELL_CHECKER_DIALOG (dlg));
g_return_if_fail (GTK_IS_LIST_STORE (dlg->suggestions_list_model));
store = GTK_LIST_STORE (dlg->suggestions_list_model);
gtk_list_store_clear (store);
gtk_widget_set_sensitive (dlg->word_entry, TRUE);
if (suggestions == NULL)
{
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter,
/* Translators: Displayed in the "Check Spelling" dialog if there are no suggestions
* for the current misspelled word */
COLUMN_SUGGESTIONS, _("(no suggested words)"),
-1);
gtk_entry_set_text (GTK_ENTRY (dlg->word_entry), "");
gtk_widget_set_sensitive (dlg->suggestions_list, FALSE);
return;
}
gtk_widget_set_sensitive (dlg->suggestions_list, TRUE);
gtk_entry_set_text (GTK_ENTRY (dlg->word_entry), (gchar*)suggestions->data);
while (suggestions != NULL)
{
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter,
COLUMN_SUGGESTIONS, (gchar*)suggestions->data,
-1);
suggestions = g_slist_next (suggestions);
}
sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (dlg->suggestions_list));
gtk_tree_model_get_iter_first (dlg->suggestions_list_model, &iter);
gtk_tree_selection_select_iter (sel, &iter);
}
static void
word_entry_changed_handler (GtkEditable *editable, XedSpellCheckerDialog *dlg)
{
const gchar *text;
g_return_if_fail (XED_IS_SPELL_CHECKER_DIALOG (dlg));
text = gtk_entry_get_text (GTK_ENTRY (dlg->word_entry));
if (g_utf8_strlen (text, -1) > 0)
{
gtk_widget_set_sensitive (dlg->check_word_button, TRUE);
gtk_widget_set_sensitive (dlg->change_button, TRUE);
gtk_widget_set_sensitive (dlg->change_all_button, TRUE);
}
else
{
gtk_widget_set_sensitive (dlg->check_word_button, FALSE);
gtk_widget_set_sensitive (dlg->change_button, FALSE);
gtk_widget_set_sensitive (dlg->change_all_button, FALSE);
}
}
static void
close_button_clicked_handler (GtkButton *button, XedSpellCheckerDialog *dlg)
{
g_return_if_fail (XED_IS_SPELL_CHECKER_DIALOG (dlg));
gtk_widget_destroy (GTK_WIDGET (dlg));
}
static void
suggestions_list_selection_changed_handler (GtkTreeSelection *selection,
XedSpellCheckerDialog *dlg)
{
GtkTreeIter iter;
GValue value = {0, };
const gchar *text;
g_return_if_fail (XED_IS_SPELL_CHECKER_DIALOG (dlg));
if (! gtk_tree_selection_get_selected (selection, NULL, &iter))
return;
gtk_tree_model_get_value (dlg->suggestions_list_model, &iter,
COLUMN_SUGGESTIONS,
&value);
text = g_value_get_string (&value);
gtk_entry_set_text (GTK_ENTRY (dlg->word_entry), text);
g_value_unset (&value);
}
static void
check_word_button_clicked_handler (GtkButton *button, XedSpellCheckerDialog *dlg)
{
const gchar *word;
gssize len;
g_return_if_fail (XED_IS_SPELL_CHECKER_DIALOG (dlg));
word = gtk_entry_get_text (GTK_ENTRY (dlg->word_entry));
len = strlen (word);
g_return_if_fail (len > 0);
if (xed_spell_checker_check_word (dlg->spell_checker, word, len))
{
GtkListStore *store;
GtkTreeIter iter;
store = GTK_LIST_STORE (dlg->suggestions_list_model);
gtk_list_store_clear (store);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter,
/* Translators: Displayed in the "Check Spelling" dialog if the current word isn't misspelled */
COLUMN_SUGGESTIONS, _("(correct spelling)"),
-1);
gtk_widget_set_sensitive (dlg->suggestions_list, FALSE);
}
else
{
GSList *sug;
sug = xed_spell_checker_get_suggestions (dlg->spell_checker,
word,
len);
update_suggestions_list_model (dlg, sug);
/* free the suggestion list */
g_slist_foreach (sug, (GFunc)g_free, NULL);
g_slist_free (sug);
}
}
static void
add_word_button_clicked_handler (GtkButton *button, XedSpellCheckerDialog *dlg)
{
gchar *word;
g_return_if_fail (XED_IS_SPELL_CHECKER_DIALOG (dlg));
g_return_if_fail (dlg->misspelled_word != NULL);
xed_spell_checker_add_word_to_personal (dlg->spell_checker,
dlg->misspelled_word,
-1);
word = g_strdup (dlg->misspelled_word);
g_signal_emit (G_OBJECT (dlg), signals [ADD_WORD_TO_PERSONAL], 0, word);
g_free (word);
}
static void
ignore_button_clicked_handler (GtkButton *button, XedSpellCheckerDialog *dlg)
{
gchar *word;
g_return_if_fail (XED_IS_SPELL_CHECKER_DIALOG (dlg));
g_return_if_fail (dlg->misspelled_word != NULL);
word = g_strdup (dlg->misspelled_word);
g_signal_emit (G_OBJECT (dlg), signals [IGNORE], 0, word);
g_free (word);
}
static void
ignore_all_button_clicked_handler (GtkButton *button, XedSpellCheckerDialog *dlg)
{
gchar *word;
g_return_if_fail (XED_IS_SPELL_CHECKER_DIALOG (dlg));
g_return_if_fail (dlg->misspelled_word != NULL);
xed_spell_checker_add_word_to_session (dlg->spell_checker,
dlg->misspelled_word,
-1);
word = g_strdup (dlg->misspelled_word);
g_signal_emit (G_OBJECT (dlg), signals [IGNORE_ALL], 0, word);
g_free (word);
}
static void
change_button_clicked_handler (GtkButton *button, XedSpellCheckerDialog *dlg)
{
const gchar *entry_text;
gchar *change;
gchar *word;
g_return_if_fail (XED_IS_SPELL_CHECKER_DIALOG (dlg));
g_return_if_fail (dlg->misspelled_word != NULL);
entry_text = gtk_entry_get_text (GTK_ENTRY (dlg->word_entry));
g_return_if_fail (entry_text != NULL);
g_return_if_fail (*entry_text != '\0');
change = g_strdup (entry_text);
xed_spell_checker_set_correction (dlg->spell_checker,
dlg->misspelled_word, -1,
change, -1);
word = g_strdup (dlg->misspelled_word);
g_signal_emit (G_OBJECT (dlg), signals [CHANGE], 0, word, change);
g_free (word);
g_free (change);
}
/* double click on one of the suggestions is like clicking on "change" */
static void
suggestions_list_row_activated_handler (GtkTreeView *view,
GtkTreePath *path,
GtkTreeViewColumn *column,
XedSpellCheckerDialog *dlg)
{
g_return_if_fail (XED_IS_SPELL_CHECKER_DIALOG (dlg));
change_button_clicked_handler (GTK_BUTTON (dlg->change_button), dlg);
}
static void
change_all_button_clicked_handler (GtkButton *button, XedSpellCheckerDialog *dlg)
{
const gchar *entry_text;
gchar *change;
gchar *word;
g_return_if_fail (XED_IS_SPELL_CHECKER_DIALOG (dlg));
g_return_if_fail (dlg->misspelled_word != NULL);
entry_text = gtk_entry_get_text (GTK_ENTRY (dlg->word_entry));
g_return_if_fail (entry_text != NULL);
g_return_if_fail (*entry_text != '\0');
change = g_strdup (entry_text);
xed_spell_checker_set_correction (dlg->spell_checker,
dlg->misspelled_word, -1,
change, -1);
word = g_strdup (dlg->misspelled_word);
g_signal_emit (G_OBJECT (dlg), signals [CHANGE_ALL], 0, word, change);
g_free (word);
g_free (change);
}
void
xed_spell_checker_dialog_set_completed (XedSpellCheckerDialog *dlg)
{
gchar *tmp;
g_return_if_fail (XED_IS_SPELL_CHECKER_DIALOG (dlg));
tmp = g_strdup_printf("<b>%s</b>", _("Completed spell checking"));
gtk_label_set_label (GTK_LABEL (dlg->misspelled_word_label),
tmp);
g_free (tmp);
gtk_list_store_clear (GTK_LIST_STORE (dlg->suggestions_list_model));
gtk_entry_set_text (GTK_ENTRY (dlg->word_entry), "");
gtk_widget_set_sensitive (dlg->word_entry, FALSE);
gtk_widget_set_sensitive (dlg->check_word_button, FALSE);
gtk_widget_set_sensitive (dlg->ignore_button, FALSE);
gtk_widget_set_sensitive (dlg->ignore_all_button, FALSE);
gtk_widget_set_sensitive (dlg->change_button, FALSE);
gtk_widget_set_sensitive (dlg->change_all_button, FALSE);
gtk_widget_set_sensitive (dlg->add_word_button, FALSE);
gtk_widget_set_sensitive (dlg->suggestions_list, FALSE);
}

View File

@@ -1,92 +0,0 @@
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* xed-spell-checker-dialog.h
* This file is part of xed
*
* Copyright (C) 2002 Paolo Maggi
*
* 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 St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xed Team, 2002. See the AUTHORS file for a
* list of people on the xed Team.
* See the ChangeLog files for a list of changes.
*/
#ifndef __XED_SPELL_CHECKER_DIALOG_H__
#define __XED_SPELL_CHECKER_DIALOG_H__
#include <gtk/gtk.h>
#include "xed-spell-checker.h"
G_BEGIN_DECLS
#define XED_TYPE_SPELL_CHECKER_DIALOG (xed_spell_checker_dialog_get_type ())
#define XED_SPELL_CHECKER_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), XED_TYPE_SPELL_CHECKER_DIALOG, XedSpellCheckerDialog))
#define XED_SPELL_CHECKER_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), XED_TYPE_SPELL_CHECKER_DIALOG, XedSpellCheckerDialog))
#define XED_IS_SPELL_CHECKER_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XED_TYPE_SPELL_CHECKER_DIALOG))
#define XED_IS_SPELL_CHECKER_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XED_TYPE_SPELL_CHECKER_DIALOG))
#define XED_SPELL_CHECKER_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), XED_TYPE_SPELL_CHECKER_DIALOG, XedSpellCheckerDialog))
typedef struct _XedSpellCheckerDialog XedSpellCheckerDialog;
typedef struct _XedSpellCheckerDialogClass XedSpellCheckerDialogClass;
struct _XedSpellCheckerDialogClass
{
GtkWindowClass parent_class;
/* Signals */
void (*ignore) (XedSpellCheckerDialog *dlg,
const gchar *word);
void (*ignore_all) (XedSpellCheckerDialog *dlg,
const gchar *word);
void (*change) (XedSpellCheckerDialog *dlg,
const gchar *word,
const gchar *change_to);
void (*change_all) (XedSpellCheckerDialog *dlg,
const gchar *word,
const gchar *change_to);
void (*add_word_to_personal) (XedSpellCheckerDialog *dlg,
const gchar *word);
};
GType xed_spell_checker_dialog_get_type (void) G_GNUC_CONST;
/* Constructors */
GtkWidget *xed_spell_checker_dialog_new (const gchar *data_dir);
GtkWidget *xed_spell_checker_dialog_new_from_spell_checker
(XedSpellChecker *spell,
const gchar *data_dir);
void xed_spell_checker_dialog_set_spell_checker
(XedSpellCheckerDialog *dlg,
XedSpellChecker *spell);
void xed_spell_checker_dialog_set_misspelled_word
(XedSpellCheckerDialog *dlg,
const gchar* word,
gint len);
void xed_spell_checker_dialog_set_completed
(XedSpellCheckerDialog *dlg);
G_END_DECLS
#endif /* __XED_SPELL_CHECKER_DIALOG_H__ */

View File

@@ -1,439 +0,0 @@
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* xed-spell-checker-language.c
* This file is part of xed
*
* Copyright (C) 2006 Paolo Maggi
*
* 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 St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xed Team, 2006. See the AUTHORS file for a
* list of people on the xed Team.
* See the ChangeLog files for a list of changes.
*/
/* Part of the code taked from Epiphany.
*
* Copyright (C) 2003, 2004 Christian Persch
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
#include <enchant.h>
#include <glib/gi18n.h>
#include <libxml/xmlreader.h>
#include "xed-spell-checker-language.h"
#include <xed/xed-debug.h>
#define ISO_639_DOMAIN "iso_639"
#define ISO_3166_DOMAIN "iso_3166"
#define ISOCODESLOCALEDIR ISO_CODES_PREFIX "/share/locale"
struct _XedSpellCheckerLanguage
{
gchar *abrev;
gchar *name;
};
static gboolean available_languages_initialized = FALSE;
static GSList *available_languages = NULL;
static GHashTable *iso_639_table = NULL;
static GHashTable *iso_3166_table = NULL;
static void
bind_iso_domains (void)
{
static gboolean bound = FALSE;
if (bound == FALSE)
{
bindtextdomain (ISO_639_DOMAIN, ISOCODESLOCALEDIR);
bind_textdomain_codeset (ISO_639_DOMAIN, "UTF-8");
bindtextdomain(ISO_3166_DOMAIN, ISOCODESLOCALEDIR);
bind_textdomain_codeset (ISO_3166_DOMAIN, "UTF-8");
bound = TRUE;
}
}
static void
read_iso_639_entry (xmlTextReaderPtr reader,
GHashTable *table)
{
xmlChar *code, *name;
code = xmlTextReaderGetAttribute (reader, (const xmlChar *) "iso_639_1_code");
name = xmlTextReaderGetAttribute (reader, (const xmlChar *) "name");
/* Get iso-639-2 code */
if (code == NULL || code[0] == '\0')
{
xmlFree (code);
/* FIXME: use the 2T or 2B code? */
code = xmlTextReaderGetAttribute (reader, (const xmlChar *) "iso_639_2T_code");
}
if (code != NULL && code[0] != '\0' && name != NULL && name[0] != '\0')
{
g_hash_table_insert (table, code, name);
}
else
{
xmlFree (code);
xmlFree (name);
}
}
static void
read_iso_3166_entry (xmlTextReaderPtr reader,
GHashTable *table)
{
xmlChar *code, *name;
code = xmlTextReaderGetAttribute (reader, (const xmlChar *) "alpha_2_code");
name = xmlTextReaderGetAttribute (reader, (const xmlChar *) "name");
if (code != NULL && code[0] != '\0' && name != NULL && name[0] != '\0')
{
char *lcode;
lcode = g_ascii_strdown ((char *) code, -1);
xmlFree (code);
/* g_print ("%s -> %s\n", lcode, name); */
g_hash_table_insert (table, lcode, name);
}
else
{
xmlFree (code);
xmlFree (name);
}
}
typedef enum
{
STATE_START,
STATE_STOP,
STATE_ENTRIES,
} ParserState;
static void
load_iso_entries (int iso,
GFunc read_entry_func,
gpointer user_data)
{
xmlTextReaderPtr reader;
ParserState state = STATE_START;
xmlChar iso_entries[32], iso_entry[32];
char *filename;
int ret = -1;
xed_debug_message (DEBUG_PLUGINS, "Loading ISO-%d codes", iso);
filename = g_strdup_printf (ISO_CODES_PREFIX "/share/xml/iso-codes/iso_%d.xml", iso);
reader = xmlNewTextReaderFilename (filename);
if (reader == NULL) goto out;
xmlStrPrintf (iso_entries, sizeof (iso_entries), (const xmlChar *)"iso_%d_entries", iso);
xmlStrPrintf (iso_entry, sizeof (iso_entry), (const xmlChar *)"iso_%d_entry", iso);
ret = xmlTextReaderRead (reader);
while (ret == 1)
{
const xmlChar *tag;
xmlReaderTypes type;
tag = xmlTextReaderConstName (reader);
type = xmlTextReaderNodeType (reader);
if (state == STATE_ENTRIES &&
type == XML_READER_TYPE_ELEMENT &&
xmlStrEqual (tag, iso_entry))
{
read_entry_func (reader, user_data);
}
else if (state == STATE_START &&
type == XML_READER_TYPE_ELEMENT &&
xmlStrEqual (tag, iso_entries))
{
state = STATE_ENTRIES;
}
else if (state == STATE_ENTRIES &&
type == XML_READER_TYPE_END_ELEMENT &&
xmlStrEqual (tag, iso_entries))
{
state = STATE_STOP;
}
else if (type == XML_READER_TYPE_SIGNIFICANT_WHITESPACE ||
type == XML_READER_TYPE_WHITESPACE ||
type == XML_READER_TYPE_TEXT ||
type == XML_READER_TYPE_COMMENT)
{
/* eat it */
}
else
{
/* ignore it */
}
ret = xmlTextReaderRead (reader);
}
xmlFreeTextReader (reader);
out:
if (ret < 0 || state != STATE_STOP)
{
g_warning ("Failed to load ISO-%d codes from %s!\n",
iso, filename);
}
g_free (filename);
}
static GHashTable *
create_iso_639_table (void)
{
GHashTable *table;
bind_iso_domains ();
table = g_hash_table_new_full (g_str_hash, g_str_equal,
(GDestroyNotify) xmlFree,
(GDestroyNotify) xmlFree);
load_iso_entries (639, (GFunc) read_iso_639_entry, table);
return table;
}
static GHashTable *
create_iso_3166_table (void)
{
GHashTable *table;
bind_iso_domains ();
table = g_hash_table_new_full (g_str_hash, g_str_equal,
(GDestroyNotify) g_free,
(GDestroyNotify) xmlFree);
load_iso_entries (3166, (GFunc) read_iso_3166_entry, table);
return table;
}
static char *
create_name_for_language (const char *code)
{
char **str;
char *name = NULL;
const char *langname, *localename;
int len;
g_return_val_if_fail (iso_639_table != NULL, NULL);
g_return_val_if_fail (iso_3166_table != NULL, NULL);
str = g_strsplit (code, "_", -1);
len = g_strv_length (str);
g_return_val_if_fail (len != 0, NULL);
langname = (const char *) g_hash_table_lookup (iso_639_table, str[0]);
if (len == 1 && langname != NULL)
{
name = g_strdup (dgettext (ISO_639_DOMAIN, langname));
}
else if (len == 2 && langname != NULL)
{
gchar *locale_code = g_ascii_strdown (str[1], -1);
localename = (const char *) g_hash_table_lookup (iso_3166_table, locale_code);
g_free (locale_code);
if (localename != NULL)
{
/* Translators: the first %s is the language name, and
* the second %s is the locale name. Example:
* "French (France)"
*/
name = g_strdup_printf (C_("language", "%s (%s)"),
dgettext (ISO_639_DOMAIN, langname),
dgettext (ISO_3166_DOMAIN, localename));
}
else
{
name = g_strdup_printf (C_("language", "%s (%s)"),
dgettext (ISO_639_DOMAIN, langname), str[1]);
}
}
else
{
/* Translators: this refers to an unknown language code
* (one which isn't in our built-in list).
*/
name = g_strdup_printf (C_("language", "Unknown (%s)"), code);
}
g_strfreev (str);
return name;
}
static void
enumerate_dicts (const char * const lang_tag,
const char * const provider_name,
const char * const provider_desc,
const char * const provider_file,
void * user_data)
{
gchar *lang_name;
GTree *dicts = (GTree *)user_data;
lang_name = create_name_for_language (lang_tag);
g_return_if_fail (lang_name != NULL);
/* g_print ("%s - %s\n", lang_tag, lang_name); */
g_tree_replace (dicts, g_strdup (lang_tag), lang_name);
}
static gint
key_cmp (gconstpointer a, gconstpointer b, gpointer user_data)
{
return strcmp (a, b);
}
static gint
lang_cmp (const XedSpellCheckerLanguage *a,
const XedSpellCheckerLanguage *b)
{
return g_utf8_collate (a->name, b->name);
}
static gboolean
build_langs_list (const gchar *key,
const gchar *value,
gpointer data)
{
XedSpellCheckerLanguage *lang = g_new (XedSpellCheckerLanguage, 1);
lang->abrev = g_strdup (key);
lang->name = g_strdup (value);
available_languages = g_slist_insert_sorted (available_languages,
lang,
(GCompareFunc)lang_cmp);
return FALSE;
}
const GSList *
xed_spell_checker_get_available_languages (void)
{
EnchantBroker *broker;
GTree *dicts;
if (available_languages_initialized)
return available_languages;
g_return_val_if_fail (available_languages == NULL, NULL);
available_languages_initialized = TRUE;
broker = enchant_broker_init ();
g_return_val_if_fail (broker != NULL, NULL);
/* Use a GTree to efficiently remove duplicates while building the list */
dicts = g_tree_new_full (key_cmp,
NULL,
(GDestroyNotify)g_free,
(GDestroyNotify)g_free);
iso_639_table = create_iso_639_table ();
iso_3166_table = create_iso_3166_table ();
enchant_broker_list_dicts (broker, enumerate_dicts, dicts);
enchant_broker_free (broker);
g_hash_table_destroy (iso_639_table);
g_hash_table_destroy (iso_3166_table);
iso_639_table = NULL;
iso_3166_table = NULL;
g_tree_foreach (dicts, (GTraverseFunc)build_langs_list, NULL);
g_tree_destroy (dicts);
return available_languages;
}
const gchar *
xed_spell_checker_language_to_string (const XedSpellCheckerLanguage *lang)
{
if (lang == NULL)
/* Translators: this refers the Default language used by the
* spell checker
*/
return C_("language", "Default");
return lang->name;
}
const gchar *
xed_spell_checker_language_to_key (const XedSpellCheckerLanguage *lang)
{
g_return_val_if_fail (lang != NULL, NULL);
return lang->abrev;
}
const XedSpellCheckerLanguage *
xed_spell_checker_language_from_key (const gchar *key)
{
const GSList *langs;
g_return_val_if_fail (key != NULL, NULL);
langs = xed_spell_checker_get_available_languages ();
while (langs != NULL)
{
const XedSpellCheckerLanguage *l = (const XedSpellCheckerLanguage *)langs->data;
if (g_ascii_strcasecmp (key, l->abrev) == 0)
return l;
langs = g_slist_next (langs);
}
return NULL;
}

View File

@@ -1,51 +0,0 @@
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* xed-spell-checker-language.h
* This file is part of xed
*
* Copyright (C) 2006 Paolo Maggi
*
* 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 St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xed Team, 2006. See the AUTHORS file for a
* list of people on the xed Team.
* See the ChangeLog files for a list of changes.
*/
#ifndef __XED_SPELL_CHECKER_LANGUAGE_H__
#define __XED_SPELL_CHECKER_LANGUAGE_H__
#include <glib.h>
G_BEGIN_DECLS
typedef struct _XedSpellCheckerLanguage XedSpellCheckerLanguage;
const gchar *xed_spell_checker_language_to_string (const XedSpellCheckerLanguage *lang);
const gchar *xed_spell_checker_language_to_key (const XedSpellCheckerLanguage *lang);
const XedSpellCheckerLanguage *xed_spell_checker_language_from_key (const gchar *key);
/* GSList contains "XedSpellCheckerLanguage*" items */
const GSList *xed_spell_checker_get_available_languages
(void);
G_END_DECLS
#endif /* __XED_SPELL_CHECKER_LANGUAGE_H__ */

View File

@@ -1,520 +0,0 @@
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* xed-spell-checker.c
* This file is part of xed
*
* Copyright (C) 2002-2006 Paolo Maggi
*
* 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 St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xed Team, 2002-2006. See the AUTHORS file for a
* list of people on the xed Team.
* See the ChangeLog files for a list of changes.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <string.h>
#include <enchant.h>
#include <glib/gi18n.h>
#include <glib.h>
#include "xed-spell-checker.h"
#include "xed-spell-utils.h"
#include "xed-spell-marshal.h"
struct _XedSpellChecker
{
GObject parent_instance;
EnchantDict *dict;
EnchantBroker *broker;
const XedSpellCheckerLanguage *active_lang;
};
/* GObject properties */
enum {
PROP_0 = 0,
PROP_LANGUAGE,
LAST_PROP
};
/* Signals */
enum {
ADD_WORD_TO_PERSONAL = 0,
ADD_WORD_TO_SESSION,
SET_LANGUAGE,
CLEAR_SESSION,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
G_DEFINE_TYPE(XedSpellChecker, xed_spell_checker, G_TYPE_OBJECT)
static void
xed_spell_checker_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
/*
XedSpellChecker *spell = XED_SPELL_CHECKER (object);
*/
switch (prop_id)
{
case PROP_LANGUAGE:
/* TODO */
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
xed_spell_checker_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
/*
XedSpellChecker *spell = XED_SPELL_CHECKER (object);
*/
switch (prop_id)
{
case PROP_LANGUAGE:
/* TODO */
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
xed_spell_checker_finalize (GObject *object)
{
XedSpellChecker *spell_checker;
g_return_if_fail (XED_IS_SPELL_CHECKER (object));
spell_checker = XED_SPELL_CHECKER (object);
if (spell_checker->dict != NULL)
enchant_broker_free_dict (spell_checker->broker, spell_checker->dict);
if (spell_checker->broker != NULL)
enchant_broker_free (spell_checker->broker);
G_OBJECT_CLASS (xed_spell_checker_parent_class)->finalize (object);
}
static void
xed_spell_checker_class_init (XedSpellCheckerClass * klass)
{
GObjectClass *object_class;
object_class = G_OBJECT_CLASS (klass);
object_class->set_property = xed_spell_checker_set_property;
object_class->get_property = xed_spell_checker_get_property;
object_class->finalize = xed_spell_checker_finalize;
g_object_class_install_property (object_class,
PROP_LANGUAGE,
g_param_spec_pointer ("language",
"Language",
"The language used by the spell checker",
G_PARAM_READWRITE));
signals[ADD_WORD_TO_PERSONAL] =
g_signal_new ("add_word_to_personal",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (XedSpellCheckerClass, add_word_to_personal),
NULL, NULL,
xed_marshal_VOID__STRING_INT,
G_TYPE_NONE,
2,
G_TYPE_STRING,
G_TYPE_INT);
signals[ADD_WORD_TO_SESSION] =
g_signal_new ("add_word_to_session",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (XedSpellCheckerClass, add_word_to_session),
NULL, NULL,
xed_marshal_VOID__STRING_INT,
G_TYPE_NONE,
2,
G_TYPE_STRING,
G_TYPE_INT);
signals[SET_LANGUAGE] =
g_signal_new ("set_language",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (XedSpellCheckerClass, set_language),
NULL, NULL,
xed_marshal_VOID__POINTER,
G_TYPE_NONE,
1,
G_TYPE_POINTER);
signals[CLEAR_SESSION] =
g_signal_new ("clear_session",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (XedSpellCheckerClass, clear_session),
NULL, NULL,
xed_marshal_VOID__VOID,
G_TYPE_NONE,
0);
}
static void
xed_spell_checker_init (XedSpellChecker *spell_checker)
{
spell_checker->broker = enchant_broker_init ();
spell_checker->dict = NULL;
spell_checker->active_lang = NULL;
}
XedSpellChecker *
xed_spell_checker_new (void)
{
XedSpellChecker *spell;
spell = XED_SPELL_CHECKER (
g_object_new (XED_TYPE_SPELL_CHECKER, NULL));
g_return_val_if_fail (spell != NULL, NULL);
return spell;
}
static gboolean
lazy_init (XedSpellChecker *spell,
const XedSpellCheckerLanguage *language)
{
if (spell->dict != NULL)
return TRUE;
g_return_val_if_fail (spell->broker != NULL, FALSE);
spell->active_lang = NULL;
if (language != NULL)
{
spell->active_lang = language;
}
else
{
/* First try to get a default language */
const XedSpellCheckerLanguage *l;
gint i = 0;
const gchar * const *lang_tags = g_get_language_names ();
while (lang_tags [i])
{
l = xed_spell_checker_language_from_key (lang_tags [i]);
if (l != NULL)
{
spell->active_lang = l;
break;
}
i++;
}
}
/* Second try to get a default language */
if (spell->active_lang == NULL)
spell->active_lang = xed_spell_checker_language_from_key ("en_US");
/* Last try to get a default language */
if (spell->active_lang == NULL)
{
const GSList *langs;
langs = xed_spell_checker_get_available_languages ();
if (langs != NULL)
spell->active_lang = (const XedSpellCheckerLanguage *)langs->data;
}
if (spell->active_lang != NULL)
{
const gchar *key;
key = xed_spell_checker_language_to_key (spell->active_lang);
spell->dict = enchant_broker_request_dict (spell->broker,
key);
}
if (spell->dict == NULL)
{
spell->active_lang = NULL;
if (language != NULL)
g_warning ("Spell checker plugin: cannot select a default language.");
return FALSE;
}
return TRUE;
}
gboolean
xed_spell_checker_set_language (XedSpellChecker *spell,
const XedSpellCheckerLanguage *language)
{
gboolean ret;
g_return_val_if_fail (XED_IS_SPELL_CHECKER (spell), FALSE);
if (spell->dict != NULL)
{
enchant_broker_free_dict (spell->broker, spell->dict);
spell->dict = NULL;
}
ret = lazy_init (spell, language);
if (ret)
g_signal_emit (G_OBJECT (spell), signals[SET_LANGUAGE], 0, language);
else
g_warning ("Spell checker plugin: cannot use language %s.",
xed_spell_checker_language_to_string (language));
return ret;
}
const XedSpellCheckerLanguage *
xed_spell_checker_get_language (XedSpellChecker *spell)
{
g_return_val_if_fail (XED_IS_SPELL_CHECKER (spell), NULL);
if (!lazy_init (spell, spell->active_lang))
return NULL;
return spell->active_lang;
}
gboolean
xed_spell_checker_check_word (XedSpellChecker *spell,
const gchar *word,
gssize len)
{
gint enchant_result;
gboolean res = FALSE;
g_return_val_if_fail (XED_IS_SPELL_CHECKER (spell), FALSE);
g_return_val_if_fail (word != NULL, FALSE);
if (!lazy_init (spell, spell->active_lang))
return FALSE;
if (len < 0)
len = strlen (word);
if (strcmp (word, "xed") == 0)
return TRUE;
if (xed_spell_utils_is_digit (word, len))
return TRUE;
g_return_val_if_fail (spell->dict != NULL, FALSE);
enchant_result = enchant_dict_check (spell->dict, word, len);
switch (enchant_result)
{
case -1:
/* error */
res = FALSE;
g_warning ("Spell checker plugin: error checking word '%s' (%s).",
word, enchant_dict_get_error (spell->dict));
break;
case 1:
/* it is not in the directory */
res = FALSE;
break;
case 0:
/* is is in the directory */
res = TRUE;
break;
default:
g_return_val_if_reached (FALSE);
}
return res;
}
/* return NULL on error or if no suggestions are found */
GSList *
xed_spell_checker_get_suggestions (XedSpellChecker *spell,
const gchar *word,
gssize len)
{
gchar **suggestions;
size_t n_suggestions = 0;
GSList *suggestions_list = NULL;
gint i;
g_return_val_if_fail (XED_IS_SPELL_CHECKER (spell), NULL);
g_return_val_if_fail (word != NULL, NULL);
if (!lazy_init (spell, spell->active_lang))
return NULL;
g_return_val_if_fail (spell->dict != NULL, NULL);
if (len < 0)
len = strlen (word);
suggestions = enchant_dict_suggest (spell->dict, word, len, &n_suggestions);
if (n_suggestions == 0)
return NULL;
g_return_val_if_fail (suggestions != NULL, NULL);
for (i = 0; i < (gint)n_suggestions; i++)
{
suggestions_list = g_slist_prepend (suggestions_list,
suggestions[i]);
}
/* The single suggestions will be freed by the caller */
g_free (suggestions);
suggestions_list = g_slist_reverse (suggestions_list);
return suggestions_list;
}
gboolean
xed_spell_checker_add_word_to_personal (XedSpellChecker *spell,
const gchar *word,
gssize len)
{
g_return_val_if_fail (XED_IS_SPELL_CHECKER (spell), FALSE);
g_return_val_if_fail (word != NULL, FALSE);
if (!lazy_init (spell, spell->active_lang))
return FALSE;
g_return_val_if_fail (spell->dict != NULL, FALSE);
if (len < 0)
len = strlen (word);
enchant_dict_add_to_pwl (spell->dict, word, len);
g_signal_emit (G_OBJECT (spell), signals[ADD_WORD_TO_PERSONAL], 0, word, len);
return TRUE;
}
gboolean
xed_spell_checker_add_word_to_session (XedSpellChecker *spell,
const gchar *word,
gssize len)
{
g_return_val_if_fail (XED_IS_SPELL_CHECKER (spell), FALSE);
g_return_val_if_fail (word != NULL, FALSE);
if (!lazy_init (spell, spell->active_lang))
return FALSE;
g_return_val_if_fail (spell->dict != NULL, FALSE);
if (len < 0)
len = strlen (word);
enchant_dict_add_to_session (spell->dict, word, len);
g_signal_emit (G_OBJECT (spell), signals[ADD_WORD_TO_SESSION], 0, word, len);
return TRUE;
}
gboolean
xed_spell_checker_clear_session (XedSpellChecker *spell)
{
g_return_val_if_fail (XED_IS_SPELL_CHECKER (spell), FALSE);
/* free and re-request dictionary */
if (spell->dict != NULL)
{
enchant_broker_free_dict (spell->broker, spell->dict);
spell->dict = NULL;
}
if (!lazy_init (spell, spell->active_lang))
return FALSE;
g_signal_emit (G_OBJECT (spell), signals[CLEAR_SESSION], 0);
return TRUE;
}
/*
* Informs dictionary, that word 'word' will be replaced/corrected by word
* 'replacement'
*/
gboolean
xed_spell_checker_set_correction (XedSpellChecker *spell,
const gchar *word,
gssize w_len,
const gchar *replacement,
gssize r_len)
{
g_return_val_if_fail (XED_IS_SPELL_CHECKER (spell), FALSE);
g_return_val_if_fail (word != NULL, FALSE);
g_return_val_if_fail (replacement != NULL, FALSE);
if (!lazy_init (spell, spell->active_lang))
return FALSE;
g_return_val_if_fail (spell->dict != NULL, FALSE);
if (w_len < 0)
w_len = strlen (word);
if (r_len < 0)
r_len = strlen (replacement);
enchant_dict_store_replacement (spell->dict,
word,
w_len,
replacement,
r_len);
return TRUE;
}

View File

@@ -1,109 +0,0 @@
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* xed-spell-checker.h
* This file is part of xed
*
* Copyright (C) 2002-2006 Paolo Maggi
*
* 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 St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xed Team, 2002. See the AUTHORS file for a
* list of people on the xed Team.
* See the ChangeLog files for a list of changes.
*/
#ifndef __XED_SPELL_CHECKER_H__
#define __XED_SPELL_CHECKER_H__
#include <glib.h>
#include <glib-object.h>
#include "xed-spell-checker-language.h"
G_BEGIN_DECLS
#define XED_TYPE_SPELL_CHECKER (xed_spell_checker_get_type ())
#define XED_SPELL_CHECKER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), XED_TYPE_SPELL_CHECKER, XedSpellChecker))
#define XED_SPELL_CHECKER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), XED_TYPE_SPELL_CHECKER, XedSpellChecker))
#define XED_IS_SPELL_CHECKER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), XED_TYPE_SPELL_CHECKER))
#define XED_IS_SPELL_CHECKER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XED_TYPE_SPELL_CHECKER))
#define XED_SPELL_CHECKER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), XED_TYPE_SPELL_CHECKER, XedSpellChecker))
typedef struct _XedSpellChecker XedSpellChecker;
typedef struct _XedSpellCheckerClass XedSpellCheckerClass;
struct _XedSpellCheckerClass
{
GObjectClass parent_class;
/* Signals */
void (*add_word_to_personal) (XedSpellChecker *spell,
const gchar *word,
gint len);
void (*add_word_to_session) (XedSpellChecker *spell,
const gchar *word,
gint len);
void (*set_language) (XedSpellChecker *spell,
const XedSpellCheckerLanguage *lang);
void (*clear_session) (XedSpellChecker *spell);
};
GType xed_spell_checker_get_type (void) G_GNUC_CONST;
/* Constructors */
XedSpellChecker *xed_spell_checker_new (void);
gboolean xed_spell_checker_set_language (XedSpellChecker *spell,
const XedSpellCheckerLanguage *lang);
const XedSpellCheckerLanguage
*xed_spell_checker_get_language (XedSpellChecker *spell);
gboolean xed_spell_checker_check_word (XedSpellChecker *spell,
const gchar *word,
gssize len);
GSList *xed_spell_checker_get_suggestions (XedSpellChecker *spell,
const gchar *word,
gssize len);
gboolean xed_spell_checker_add_word_to_personal
(XedSpellChecker *spell,
const gchar *word,
gssize len);
gboolean xed_spell_checker_add_word_to_session
(XedSpellChecker *spell,
const gchar *word,
gssize len);
gboolean xed_spell_checker_clear_session (XedSpellChecker *spell);
gboolean xed_spell_checker_set_correction (XedSpellChecker *spell,
const gchar *word,
gssize w_len,
const gchar *replacement,
gssize r_len);
G_END_DECLS
#endif /* __XED_SPELL_CHECKER_H__ */

View File

@@ -1,284 +0,0 @@
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* xed-spell-language-dialog.c
* This file is part of xed
*
* Copyright (C) 2002 Paolo Maggi
*
* 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 St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xed Team, 2002. See the AUTHORS file for a
* list of people on the xed Team.
* See the ChangeLog files for a list of changes.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include <xed/xed-utils.h>
#include <xed/xed-app.h>
#include "xed-spell-language-dialog.h"
#include "xed-spell-checker-language.h"
enum
{
COLUMN_LANGUAGE_NAME = 0,
COLUMN_LANGUAGE_POINTER,
ENCODING_NUM_COLS
};
struct _XedSpellLanguageDialog
{
GtkDialog dialog;
GtkWidget *languages_treeview;
GtkTreeModel *model;
};
G_DEFINE_TYPE (XedSpellLanguageDialog, xed_spell_language_dialog, GTK_TYPE_DIALOG)
static void
xed_spell_language_dialog_class_init (XedSpellLanguageDialogClass *klass)
{
/* GObjectClass *object_class = G_OBJECT_CLASS (klass); */
}
static void
dialog_response_handler (GtkDialog *dlg,
gint res_id)
{
if (res_id == GTK_RESPONSE_HELP)
{
xed_app_show_help (XED_APP (g_application_get_default ()), GTK_WINDOW (dlg), NULL, "xed-spell-checker-plugin");
g_signal_stop_emission_by_name (dlg, "response");
}
}
static void
scroll_to_selected (GtkTreeView *tree_view)
{
GtkTreeModel *model;
GtkTreeSelection *selection;
GtkTreeIter iter;
model = gtk_tree_view_get_model (tree_view);
g_return_if_fail (model != NULL);
/* Scroll to selected */
selection = gtk_tree_view_get_selection (tree_view);
g_return_if_fail (selection != NULL);
if (gtk_tree_selection_get_selected (selection, NULL, &iter))
{
GtkTreePath* path;
path = gtk_tree_model_get_path (model, &iter);
g_return_if_fail (path != NULL);
gtk_tree_view_scroll_to_cell (tree_view, path, NULL, TRUE, 1.0, 0.0);
gtk_tree_path_free (path);
}
}
static void
language_row_activated (GtkTreeView *tree_view,
GtkTreePath *path,
GtkTreeViewColumn *column,
XedSpellLanguageDialog *dialog)
{
gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
}
static void
create_dialog (XedSpellLanguageDialog *dlg,
const gchar *data_dir)
{
GtkWidget *error_widget;
GtkWidget *content;
gboolean ret;
GtkCellRenderer *cell;
GtkTreeViewColumn *column;
gchar *ui_file;
gchar *root_objects[] = {
"content",
NULL
};
gtk_dialog_add_buttons (GTK_DIALOG (dlg),
_("_Cancel"), GTK_RESPONSE_CANCEL,
_("_OK"), GTK_RESPONSE_OK,
_("_Help"), GTK_RESPONSE_HELP,
NULL);
gtk_window_set_title (GTK_WINDOW (dlg), _("Set language"));
gtk_window_set_modal (GTK_WINDOW (dlg), TRUE);
gtk_window_set_destroy_with_parent (GTK_WINDOW (dlg), TRUE);
/* HIG defaults */
gtk_container_set_border_width (GTK_CONTAINER (dlg), 5);
gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))), 2);
gtk_container_set_border_width (GTK_CONTAINER (gtk_dialog_get_action_area (GTK_DIALOG (dlg))), 5);
gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_action_area (GTK_DIALOG (dlg))), 6);
g_signal_connect (dlg, "response",
G_CALLBACK (dialog_response_handler), NULL);
ui_file = g_build_filename (data_dir, "languages-dialog.ui", NULL);
ret = xed_utils_get_ui_objects (ui_file,
root_objects,
&error_widget,
"content", &content,
"languages_treeview", &dlg->languages_treeview,
NULL);
g_free (ui_file);
if (!ret)
{
gtk_widget_show (error_widget);
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))), error_widget, TRUE, TRUE, 0);
return;
}
gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))), content, TRUE, TRUE, 0);
g_object_unref (content);
gtk_container_set_border_width (GTK_CONTAINER (content), 5);
dlg->model = GTK_TREE_MODEL (gtk_list_store_new (ENCODING_NUM_COLS, G_TYPE_STRING, G_TYPE_POINTER));
gtk_tree_view_set_model (GTK_TREE_VIEW (dlg->languages_treeview), dlg->model);
g_object_unref (dlg->model);
/* Add the encoding column */
cell = gtk_cell_renderer_text_new ();
column = gtk_tree_view_column_new_with_attributes (_("Languages"),
cell,
"text",
COLUMN_LANGUAGE_NAME,
NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (dlg->languages_treeview), column);
gtk_tree_view_set_search_column (GTK_TREE_VIEW (dlg->languages_treeview), COLUMN_LANGUAGE_NAME);
g_signal_connect (dlg->languages_treeview, "realize",
G_CALLBACK (scroll_to_selected), dlg);
g_signal_connect (dlg->languages_treeview, "row-activated",
G_CALLBACK (language_row_activated), dlg);
}
static void
xed_spell_language_dialog_init (XedSpellLanguageDialog *dlg)
{
}
static void
populate_language_list (XedSpellLanguageDialog *dlg,
const XedSpellCheckerLanguage *cur_lang)
{
GtkListStore *store;
GtkTreeIter iter;
const GSList* langs;
/* create list store */
store = GTK_LIST_STORE (dlg->model);
langs = xed_spell_checker_get_available_languages ();
while (langs)
{
const gchar *name;
name = xed_spell_checker_language_to_string ((const XedSpellCheckerLanguage*)langs->data);
gtk_list_store_append (store, &iter);
gtk_list_store_set (store, &iter,
COLUMN_LANGUAGE_NAME, name,
COLUMN_LANGUAGE_POINTER, langs->data,
-1);
if (langs->data == cur_lang)
{
GtkTreeSelection *selection;
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dlg->languages_treeview));
g_return_if_fail (selection != NULL);
gtk_tree_selection_select_iter (selection, &iter);
}
langs = g_slist_next (langs);
}
}
GtkWidget *
xed_spell_language_dialog_new (GtkWindow *parent,
const XedSpellCheckerLanguage *cur_lang,
const gchar *data_dir)
{
XedSpellLanguageDialog *dlg;
g_return_val_if_fail (GTK_IS_WINDOW (parent), NULL);
dlg = g_object_new (XED_TYPE_SPELL_LANGUAGE_DIALOG, NULL);
create_dialog (dlg, data_dir);
populate_language_list (dlg, cur_lang);
gtk_window_set_transient_for (GTK_WINDOW (dlg), parent);
gtk_widget_grab_focus (dlg->languages_treeview);
return GTK_WIDGET (dlg);
}
const XedSpellCheckerLanguage *
xed_spell_language_get_selected_language (XedSpellLanguageDialog *dlg)
{
GValue value = {0, };
const XedSpellCheckerLanguage* lang;
GtkTreeIter iter;
GtkTreeSelection *selection;
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (dlg->languages_treeview));
g_return_val_if_fail (selection != NULL, NULL);
if (!gtk_tree_selection_get_selected (selection, NULL, &iter))
{
return NULL;
}
gtk_tree_model_get_value (dlg->model, &iter, COLUMN_LANGUAGE_POINTER, &value);
lang = (const XedSpellCheckerLanguage* ) g_value_get_pointer (&value);
return lang;
}

View File

@@ -1,65 +0,0 @@
/* vim: set sw=8: -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* xed-spell-language-dialog.h
* This file is part of xed
*
* Copyright (C) 2002 Paolo Maggi
*
* 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 St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
/*
* Modified by the xed Team, 2002. See the AUTHORS file for a
* list of people on the xed Team.
* See the ChangeLog files for a list of changes.
*/
#ifndef __XED_SPELL_LANGUAGE_DIALOG_H__
#define __XED_SPELL_LANGUAGE_DIALOG_H__
#include <gtk/gtk.h>
#include "xed-spell-checker-language.h"
G_BEGIN_DECLS
#define XED_TYPE_SPELL_LANGUAGE_DIALOG (xed_spell_language_dialog_get_type())
#define XED_SPELL_LANGUAGE_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XED_TYPE_SPELL_LANGUAGE_DIALOG, XedSpellLanguageDialog))
#define XED_SPELL_LANGUAGE_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), XED_TYPE_SPELL_LANGUAGE_DIALOG, XedSpellLanguageDialogClass))
#define XED_IS_SPELL_LANGUAGE_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), XED_TYPE_SPELL_LANGUAGE_DIALOG))
#define XED_IS_SPELL_LANGUAGE_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XED_TYPE_SPELL_LANGUAGE_DIALOG))
#define XED_SPELL_LANGUAGE_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), XED_TYPE_SPELL_LANGUAGE_DIALOG, XedSpellLanguageDialogClass))
typedef struct _XedSpellLanguageDialog XedSpellLanguageDialog;
typedef struct _XedSpellLanguageDialogClass XedSpellLanguageDialogClass;
struct _XedSpellLanguageDialogClass
{
GtkDialogClass parent_class;
};
GType xed_spell_language_dialog_get_type (void) G_GNUC_CONST;
GtkWidget *xed_spell_language_dialog_new (GtkWindow *parent,
const XedSpellCheckerLanguage *cur_lang,
const gchar *data_dir);
const XedSpellCheckerLanguage *xed_spell_language_get_selected_language (XedSpellLanguageDialog *dlg);
G_END_DECLS
#endif /* __XED_SPELL_LANGUAGE_DIALOG_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -1,94 +0,0 @@
/*
* xed-spell-utils.c
* This file is part of xed
*
* Copyright (C) 2010 - Jesse van den Kieboom
*
* 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 St, Fifth Floor,
* Boston, MA 02110-1301 USA
*/
#include <string.h>
#include "xed-spell-utils.h"
#include <gtksourceview/gtksource.h>
gboolean
xed_spell_utils_is_digit (const char *text, gssize length)
{
gunichar c;
const gchar *p;
const gchar *end;
g_return_val_if_fail (text != NULL, FALSE);
if (length < 0)
length = strlen (text);
p = text;
end = text + length;
while (p != end) {
const gchar *next;
next = g_utf8_next_char (p);
c = g_utf8_get_char (p);
if (!g_unichar_isdigit (c) && c != '.' && c != ',')
return FALSE;
p = next;
}
return TRUE;
}
gboolean
xed_spell_utils_skip_no_spell_check (GtkTextIter *start,
GtkTextIter *end)
{
GtkSourceBuffer *buffer = GTK_SOURCE_BUFFER (gtk_text_iter_get_buffer (start));
while (gtk_source_buffer_iter_has_context_class (buffer, start, "no-spell-check"))
{
GtkTextIter last = *start;
if (!gtk_source_buffer_iter_forward_to_context_class_toggle (buffer, start, "no-spell-check"))
{
return FALSE;
}
if (gtk_text_iter_compare (start, &last) <= 0)
{
return FALSE;
}
gtk_text_iter_forward_word_end (start);
gtk_text_iter_backward_word_start (start);
if (gtk_text_iter_compare (start, &last) <= 0)
{
return FALSE;
}
if (gtk_text_iter_compare (start, end) >= 0)
{
return FALSE;
}
}
return TRUE;
}

View File

@@ -1,37 +0,0 @@
/*
* xed-spell-utils.h
* This file is part of xed
*
* Copyright (C) 2010 - Jesse van den Kieboom
*
* 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 St, Fifth Floor,
* Boston, MA 02110-1301 USA
*/
#ifndef __XED_SPELL_UTILS_H__
#define __XED_SPELL_UTILS_H__
#include <gtk/gtk.h>
G_BEGIN_DECLS
gboolean xed_spell_utils_is_digit (const char *text, gssize length);
gboolean xed_spell_utils_skip_no_spell_check (GtkTextIter *start, GtkTextIter *end);
G_END_DECLS
#endif /* __XED_SPELL_UTILS_H__ */

View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<TagList xmlns="http://xed.sourceforge.net/some-location">
<TagGroup _name="C - Tags" sort="true">
<Tag name="STDIO">
<Begin>#include &lt;stdio.h&gt;</Begin>
</Tag>
<Tag name="include">
<Begin>#include </Begin>
</Tag>
<Tag name="main">
<Begin>int main() {
</Begin>
<End>
}</End>
</Tag>
<Tag name="Comment">
<Begin>/* </Begin>
<End> */</End>
</Tag>
<Tag name="Multi-Line Comment">
<Begin>/*
* </Begin>
<End>
*/</End>
</Tag>
<Tag name="printf">
<Begin>printf("</Begin>
<End>");</End>
</Tag>
</TagGroup>
</TagList>

View File

@@ -34,7 +34,7 @@ MENU_PATH = "/MenuBar/ViewMenu/ViewOps_1"
class TextSizePlugin(GObject.Object, Xed.WindowActivatable): class TextSizePlugin(GObject.Object, Xed.WindowActivatable):
__gtype_name__ = "TextSizePlugin" __gtype_name__ = "TextSizePlugin"
window = GObject.property(type=Xed.Window) window = GObject.Property(type=Xed.Window)
def __init__(self): def __init__(self):
GObject.Object.__init__(self) GObject.Object.__init__(self)
@@ -119,7 +119,7 @@ class TextSizePlugin(GObject.Object, Xed.WindowActivatable):
manager = self.window.get_ui_manager() manager = self.window.get_ui_manager()
# Create a new action group # Create a new action group
self._action_group = Gtk.ActionGroup("XedTextSizePluginActions") self._action_group = Gtk.ActionGroup(name="XedTextSizePluginActions")
self._action_group.add_actions([("LargerTextAction", None, _("_Larger Text"), self._action_group.add_actions([("LargerTextAction", None, _("_Larger Text"),
"<Ctrl>equal", None, "<Ctrl>equal", None,
self.on_larger_text_activate), self.on_larger_text_activate),

View File

@@ -0,0 +1,49 @@
# Word completion plugin
plugindir = $(XED_PLUGINS_LIBS_DIR)
AM_CPPFLAGS = \
-I$(top_srcdir) \
$(XED_CFLAGS) \
$(ENCHANT_CFLAGS) \
$(WARN_CFLAGS) \
$(DISABLE_DEPRECATED_CFLAGS)
plugin_LTLIBRARIES = libwordcompletion.la
libwordcompletion_la_SOURCES = \
xed-wordcompletion-plugin.h \
xed-wordcompletion-plugin.c
libwordcompletion_la_LDFLAGS = $(PLUGIN_LIBTOOL_FLAGS)
libwordcompletion_la_LIBADD = $(XED_LIBS) $(ENCHANT_LIBS)
plugin_in_files = wordcompletion.plugin.desktop.in
%.plugin: %.plugin.desktop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< $@ -d -u -c $(top_builddir)/po/.intltool-merge-cache
plugin_DATA = $(plugin_in_files:.plugin.desktop.in=.plugin)
uidir = $(XED_PLUGINS_DATA_DIR)/wordcompletion
ui_DATA = xed-wordcompletion-configure.ui
@INTLTOOL_XML_NOMERGE_RULE@
wordcompletion_gschema_in = org.x.editor.plugins.wordcompletion.gschema.xml.in
gsettings_SCHEMAS = $(wordcompletion_gschema_in:.xml.in=.xml)
@GSETTINGS_RULES@
EXTRA_DIST = \
$(plugin_in_files) \
$(wordcompletion_gschema_in)
CLEANFILES = \
$(plugin_DATA) \
$(gsettings_SCHEMAS)
DISTCLEANFILES = \
$(plugin_DATA)
dist-hook:
cd $(distdir); rm -f $(BUILT_SOURCES)
-include $(top_srcdir)/git.mk

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<schemalist gettext-domain="xed">
<schema id="org.x.editor.plugins.wordcompletion" path="/org/x/editor/plugins/wordcompletion/">
<key name="interactive-completion" type="b">
<default>true</default>
<summary>Interactive Completion</summary>
<description>Whether to enable interactive completion.</description>
</key>
<key name="minimum-word-size" type="u">
<range min="2" max="100" />
<default>2</default>
<summary>Minimum Word Size</summary>
<description>The minimum word size to complete.</description>
</key>
</schema>
</schemalist>

View File

@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<schemalist gettext-domain="@GETTEXT_PACKAGE@">
<schema id="org.x.editor.plugins.wordcompletion" path="/org/x/editor/plugins/wordcompletion/">
<key name="interactive-completion" type="b">
<default>true</default>
<summary>Interactive Completion</summary>
<description>Whether to enable interactive completion.</description>
</key>
<key name="minimum-word-size" type="u">
<range min="2" max="100" />
<default>2</default>
<summary>Minimum Word Size</summary>
<description>The minimum word size to complete.</description>
</key>
</schema>
</schemalist>

View File

@@ -0,0 +1,9 @@
[Plugin]
Module=wordcompletion
IAge=3
Name=Word Completion
Description=Predicts the rest of the word after a few characters have been typed.
Authors=Jesse van den Kieboom <jesse@gnome.org>\nIgnacio Casal Quinteiro <icq@gnome.org>\nMickael Albertus <mickael.albertus@gmail.com>
Copyright=Copyright © 2017 Mickael Albertus\n2009 Jesse van den Kieboom
Website=https://github.com/linuxmint/xed
Version=@VERSION@

View File

@@ -0,0 +1,9 @@
[Plugin]
Module=wordcompletion
IAge=3
_Name=Word Completion
_Description=Predicts the rest of the word after a few characters have been typed.
Authors=Jesse van den Kieboom <jesse@gnome.org>\nIgnacio Casal Quinteiro <icq@gnome.org>\nMickael Albertus <mickael.albertus@gmail.com>
Copyright=Copyright © 2017 Mickael Albertus\n2009 Jesse van den Kieboom
Website=https://github.com/linuxmint/xed
Version=@VERSION@

View File

@@ -0,0 +1,140 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.18.3 -->
<interface>
<requires lib="gtk+" version="3.0"/>
<object class="GtkAdjustment" id="adjustment1">
<property name="lower">2</property>
<property name="upper">100</property>
<property name="value">2</property>
<property name="step_increment">1</property>
<property name="page_increment">10</property>
</object>
<object class="GtkDialog" id="configure_dialog">
<property name="can_focus">False</property>
<property name="title" translatable="yes">Word Completion</property>
<property name="resizable">False</property>
<property name="type_hint">normal</property>
<child internal-child="vbox">
<object class="GtkBox" id="dialog-vbox1">
<property name="can_focus">False</property>
<property name="margin_left">5</property>
<property name="margin_right">5</property>
<property name="margin_top">2</property>
<property name="margin_bottom">5</property>
<property name="orientation">vertical</property>
<child internal-child="action_area">
<object class="GtkButtonBox" id="dialog-action_area1">
<property name="can_focus">False</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="button1">
<property name="label">gtk-ok</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
<property name="yalign">0.52999997138977051</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkBox" id="box1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_top">5</property>
<property name="margin_bottom">10</property>
<property name="orientation">vertical</property>
<property name="spacing">9</property>
<child>
<object class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="ypad">6</property>
<property name="label" translatable="yes">Use Ctrl+Space to manually trigger word completion.</property>
<attributes>
<attribute name="style" value="italic"/>
</attributes>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="check_button_interactive_completion">
<property name="label" translatable="yes">Automatic completion</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="xalign">0.10000000149011612</property>
<property name="yalign">0.44999998807907104</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkBox" id="box2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="spacing">5</property>
<child>
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Minimum word size for auto-completion</property>
</object>
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkSpinButton" id="spin_button_min_word_size">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="adjustment">adjustment1</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
</child>
<action-widgets>
<action-widget response="0">button1</action-widget>
</action-widgets>
</object>
</interface>

View File

@@ -0,0 +1,470 @@
/*
* Copyright (C) 2009 Ignacio Casal Quinteiro <icq@gnome.org>
* 2009 Jesse van den Kieboom <jesse@gnome.org>
* 2013 Sébastien Wilmet <swilmet@gnome.org>
* 2017 Mickael Albertus <mickael.albertus@gmail.com>
*
* 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, 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.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "xed-wordcompletion-plugin.h"
#include <glib/gi18n-lib.h>
#include <glib.h>
#include <gio/gio.h>
#include <xed/xed-debug.h>
#include <xed/xed-window.h>
#include <xed/xed-window-activatable.h>
#include <xed/xed-utils.h>
#include <xed/xed-view.h>
#include <xed/xed-view-activatable.h>
#include <libpeas-gtk/peas-gtk-configurable.h>
#include <gtksourceview/gtksource.h>
#include <gtksourceview/completion-providers/words/gtksourcecompletionwords.h>
#define WINDOW_PROVIDER "XedWordCompletionPluginProvider"
#define WORDCOMPLETION_SETTINGS_BASE "org.x.editor.plugins.wordcompletion"
#define SETTINGS_KEY_INTERACTIVE_COMPLETION "interactive-completion"
#define SETTINGS_KEY_MINIMUM_WORD_SIZE "minimum-word-size"
static void xed_window_activatable_iface_init (XedWindowActivatableInterface *iface);
static void xed_view_activatable_iface_init (XedViewActivatableInterface *iface);
static void peas_gtk_configurable_iface_init (PeasGtkConfigurableInterface *iface);
G_DEFINE_DYNAMIC_TYPE_EXTENDED (XedWordCompletionPlugin,
xed_wordcompletion_plugin,
PEAS_TYPE_EXTENSION_BASE,
0,
G_IMPLEMENT_INTERFACE_DYNAMIC (XED_TYPE_WINDOW_ACTIVATABLE,
xed_window_activatable_iface_init)
G_IMPLEMENT_INTERFACE_DYNAMIC (XED_TYPE_VIEW_ACTIVATABLE,
xed_view_activatable_iface_init)
G_IMPLEMENT_INTERFACE_DYNAMIC (PEAS_GTK_TYPE_CONFIGURABLE,
peas_gtk_configurable_iface_init))
struct _XedWordCompletionPluginPrivate
{
GtkWidget *window;
XedView *view;
GtkSourceCompletionProvider *provider;
GSettings *settings;
};
enum
{
PROP_0,
PROP_WINDOW,
PROP_VIEW
};
typedef struct _WordCompletionConfigureWidget WordCompletionConfigureWidget;
struct _WordCompletionConfigureWidget
{
GtkWidget *dialog;
GtkWidget *min_word_size;
GtkWidget *interactive_completion;
GSettings *settings;
};
static void
xed_wordcompletion_plugin_init (XedWordCompletionPlugin *plugin)
{
xed_debug_message (DEBUG_PLUGINS, "XedWordCompletionPlugin initializing");
plugin->priv = G_TYPE_INSTANCE_GET_PRIVATE (plugin,
XED_TYPE_WORDCOMPLETION_PLUGIN,
XedWordCompletionPluginPrivate);
plugin->priv->settings = g_settings_new (WORDCOMPLETION_SETTINGS_BASE);
}
static void
xed_wordcompletion_plugin_finalize (GObject *object)
{
XedWordCompletionPlugin *plugin = XED_WORDCOMPLETION_PLUGIN (object);
xed_debug_message (DEBUG_PLUGINS, "XedWordCompletionPlugin finalizing");
g_object_unref (G_OBJECT (plugin->priv->settings));
G_OBJECT_CLASS (xed_wordcompletion_plugin_parent_class)->finalize (object);
}
static void
xed_wordcompletion_plugin_dispose (GObject *object)
{
XedWordCompletionPlugin *plugin = XED_WORDCOMPLETION_PLUGIN (object);
if (plugin->priv->window != NULL)
{
g_object_unref (plugin->priv->window);
plugin->priv->window = NULL;
}
if (plugin->priv->view != NULL)
{
g_object_unref (plugin->priv->view);
plugin->priv->view = NULL;
}
if (plugin->priv->provider != NULL)
{
g_object_unref (plugin->priv->provider);
plugin->priv->provider = NULL;
}
G_OBJECT_CLASS (xed_wordcompletion_plugin_parent_class)->dispose (object);
}
static void
xed_wordcompletion_plugin_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
XedWordCompletionPlugin *plugin = XED_WORDCOMPLETION_PLUGIN (object);
switch (prop_id)
{
case PROP_WINDOW:
plugin->priv->window = g_value_dup_object (value);
break;
case PROP_VIEW:
plugin->priv->view = XED_VIEW (g_value_dup_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
xed_wordcompletion_plugin_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
XedWordCompletionPlugin *plugin = XED_WORDCOMPLETION_PLUGIN (object);
switch (prop_id)
{
case PROP_WINDOW:
g_value_set_object (value, plugin->priv->window);
break;
case PROP_VIEW:
g_value_set_object (value, plugin->priv->view);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
update_activation (GtkSourceCompletionWords *provider,
GSettings *settings)
{
GtkSourceCompletionActivation activation;
g_object_get (provider, "activation", &activation, NULL);
if (g_settings_get_boolean (settings, SETTINGS_KEY_INTERACTIVE_COMPLETION))
{
activation |= GTK_SOURCE_COMPLETION_ACTIVATION_INTERACTIVE;
}
else
{
activation &= ~GTK_SOURCE_COMPLETION_ACTIVATION_INTERACTIVE;
}
g_object_set (provider, "activation", activation, NULL);
}
static void
on_interactive_completion_changed_cb (GSettings *settings,
gchar *key,
GtkSourceCompletionWords *provider)
{
update_activation (provider, settings);
}
static GtkSourceCompletionWords *
create_provider (void)
{
GtkSourceCompletionWords *provider;
GSettings *settings;
provider = gtk_source_completion_words_new (_("Word completion"), NULL);
settings = g_settings_new (WORDCOMPLETION_SETTINGS_BASE);
g_settings_bind (settings, SETTINGS_KEY_MINIMUM_WORD_SIZE,
provider, "minimum-word-size",
G_SETTINGS_BIND_GET);
update_activation (provider, settings);
g_signal_connect_object (settings,
"changed::" SETTINGS_KEY_INTERACTIVE_COMPLETION,
G_CALLBACK (on_interactive_completion_changed_cb),
provider,
0);
g_object_unref (settings);
return provider;
}
static void
xed_wordcompletion_window_activate (XedWindowActivatable *activatable)
{
XedWordCompletionPluginPrivate *priv;
GtkSourceCompletionWords *provider;
xed_debug (DEBUG_PLUGINS);
priv = XED_WORDCOMPLETION_PLUGIN (activatable)->priv;
provider = create_provider ();
g_object_set_data_full (G_OBJECT (priv->window),
WINDOW_PROVIDER,
provider,
(GDestroyNotify)g_object_unref);
}
static void
xed_wordcompletion_window_deactivate (XedWindowActivatable *activatable)
{
XedWordCompletionPluginPrivate *priv;
xed_debug (DEBUG_PLUGINS);
priv = XED_WORDCOMPLETION_PLUGIN (activatable)->priv;
g_object_set_data (G_OBJECT (priv->window), WINDOW_PROVIDER, NULL);
}
static void
xed_wordcompletion_view_activate (XedViewActivatable *activatable)
{
XedWordCompletionPluginPrivate *priv;
GtkSourceCompletion *completion;
GtkSourceCompletionProvider *provider;
GtkTextBuffer *buf;
xed_debug (DEBUG_PLUGINS);
priv = XED_WORDCOMPLETION_PLUGIN (activatable)->priv;
priv->window = gtk_widget_get_toplevel (GTK_WIDGET (priv->view));
/* We are disposing the window */
g_object_ref (priv->window);
completion = gtk_source_view_get_completion (GTK_SOURCE_VIEW (priv->view));
buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->view));
provider = g_object_get_data (G_OBJECT (priv->window), WINDOW_PROVIDER);
if (provider == NULL)
{
/* Standalone provider */
provider = GTK_SOURCE_COMPLETION_PROVIDER (create_provider ());
}
priv->provider = g_object_ref (provider);
gtk_source_completion_add_provider (completion, provider, NULL);
gtk_source_completion_words_register (GTK_SOURCE_COMPLETION_WORDS (provider),
buf);
}
static void
xed_wordcompletion_view_deactivate (XedViewActivatable *activatable)
{
XedWordCompletionPluginPrivate *priv;
GtkSourceCompletion *completion;
GtkSourceCompletionProvider *provider;
GtkTextBuffer *buf;
xed_debug (DEBUG_PLUGINS);
priv = XED_WORDCOMPLETION_PLUGIN (activatable)->priv;
completion = gtk_source_view_get_completion (GTK_SOURCE_VIEW (priv->view));
buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (priv->view));
gtk_source_completion_remove_provider (completion,
priv->provider,
NULL);
gtk_source_completion_words_unregister (GTK_SOURCE_COMPLETION_WORDS (priv->provider),
buf);
}
static void
dialog_response_cb (GtkWidget *widget,
gint response,
gpointer data)
{
gtk_widget_destroy (widget);
}
static void
configure_widget_destroyed (GtkWidget *widget,
gpointer data)
{
WordCompletionConfigureWidget *conf_widget = (WordCompletionConfigureWidget *) data;
xed_debug (DEBUG_PLUGINS);
g_object_unref (conf_widget->settings);
g_slice_free (WordCompletionConfigureWidget, data);
xed_debug_message (DEBUG_PLUGINS, "END");
}
static WordCompletionConfigureWidget *
get_configure_widget (XedWordCompletionPlugin *plugin)
{
WordCompletionConfigureWidget *widget;
gchar *data_dir;
gchar *ui_file;
GtkWidget *error_widget;
gboolean ret;
xed_debug (DEBUG_PLUGINS);
widget = g_slice_new (WordCompletionConfigureWidget);
widget->settings = g_object_ref (plugin->priv->settings);
data_dir = peas_extension_base_get_data_dir (PEAS_EXTENSION_BASE (plugin));
ui_file = g_build_filename (data_dir, "xed-wordcompletion-configure.ui", NULL);
ret = xed_utils_get_ui_objects (ui_file,
NULL,
&error_widget,
"configure_dialog", &widget->dialog,
"spin_button_min_word_size", &widget->min_word_size,
"check_button_interactive_completion", &widget->interactive_completion,
NULL);
g_free (data_dir);
g_free (ui_file);
if (!ret)
{
return NULL;
}
gtk_window_set_modal (GTK_WINDOW (widget->dialog), TRUE);
g_settings_bind (widget->settings, SETTINGS_KEY_INTERACTIVE_COMPLETION,
widget->interactive_completion, "active",
G_SETTINGS_BIND_DEFAULT | G_SETTINGS_BIND_GET_NO_CHANGES);
g_settings_bind (widget->settings, SETTINGS_KEY_MINIMUM_WORD_SIZE,
widget->min_word_size, "value",
G_SETTINGS_BIND_DEFAULT | G_SETTINGS_BIND_GET_NO_CHANGES);
g_signal_connect (widget->dialog, "destroy",
G_CALLBACK (configure_widget_destroyed), widget);
gtk_widget_show (GTK_WIDGET (widget->dialog));
g_signal_connect (widget->dialog, "response",
G_CALLBACK (dialog_response_cb), widget);
return widget;
}
static GtkWidget *
xed_wordcompletion_create_configure_widget (PeasGtkConfigurable *configurable)
{
WordCompletionConfigureWidget *widget;
widget = get_configure_widget (XED_WORDCOMPLETION_PLUGIN (configurable));
return widget->dialog;
}
static void
xed_wordcompletion_plugin_class_init (XedWordCompletionPluginClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = xed_wordcompletion_plugin_finalize;
object_class->dispose = xed_wordcompletion_plugin_dispose;
object_class->set_property = xed_wordcompletion_plugin_set_property;
object_class->get_property = xed_wordcompletion_plugin_get_property;
g_object_class_override_property (object_class, PROP_WINDOW, "window");
g_object_class_override_property (object_class, PROP_VIEW, "view");
g_type_class_add_private (klass, sizeof (XedWordCompletionPluginPrivate));
}
static void
xed_wordcompletion_plugin_class_finalize (XedWordCompletionPluginClass *klass)
{
}
static void
xed_window_activatable_iface_init (XedWindowActivatableInterface *iface)
{
iface->activate = xed_wordcompletion_window_activate;
iface->deactivate = xed_wordcompletion_window_deactivate;
}
static void
xed_view_activatable_iface_init (XedViewActivatableInterface *iface)
{
iface->activate = xed_wordcompletion_view_activate;
iface->deactivate = xed_wordcompletion_view_deactivate;
}
static void
peas_gtk_configurable_iface_init (PeasGtkConfigurableInterface *iface)
{
iface->create_configure_widget = xed_wordcompletion_create_configure_widget;
}
G_MODULE_EXPORT void
peas_register_types (PeasObjectModule *module)
{
xed_wordcompletion_plugin_register_type (G_TYPE_MODULE (module));
peas_object_module_register_extension_type (module,
XED_TYPE_WINDOW_ACTIVATABLE,
XED_TYPE_WORDCOMPLETION_PLUGIN);
peas_object_module_register_extension_type (module,
XED_TYPE_VIEW_ACTIVATABLE,
XED_TYPE_WORDCOMPLETION_PLUGIN);
peas_object_module_register_extension_type (module,
PEAS_GTK_TYPE_CONFIGURABLE,
XED_TYPE_WORDCOMPLETION_PLUGIN);
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright (C) 2009 Ignacio Casal Quinteiro <icq@gnome.org>
* 2017 Mickael Albertus <mickael.albertus@gmail.com>
*
* 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, 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.
*
*/
#ifndef __XED_WORDCOMPLETION_PLUGIN_H__
#define __XED_WORDCOMPLETION_PLUGIN_H__
#include <glib.h>
#include <glib-object.h>
#include <libpeas/peas-extension-base.h>
#include <libpeas/peas-object-module.h>
G_BEGIN_DECLS
#define XED_TYPE_WORDCOMPLETION_PLUGIN (xed_wordcompletion_plugin_get_type ())
#define XED_WORDCOMPLETION_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), XED_TYPE_WORDCOMPLETION_PLUGIN, XedWordCompletionPlugin))
#define XED_WORDCOMPLETION_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), XED_TYPE_WORDCOMPLETION_PLUGIN, XedWordCompletionPluginClass))
#define XED_IS_WORDCOMPLETION_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), XED_TYPE_WORDCOMPLETION_PLUGIN))
#define XED_IS_WORDCOMPLETION_PLUGIN_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), XED_TYPE_WORDCOMPLETION_PLUGIN))
#define XED_WORDCOMPLETION_PLUGIN_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), XED_TYPE_WORDCOMPLETION_PLUGIN, XedWordCompletionPluginClass))
typedef struct _XedWordCompletionPlugin XedWordCompletionPlugin;
typedef struct _XedWordCompletionPluginPrivate XedWordCompletionPluginPrivate;
typedef struct _XedWordCompletionPluginClass XedWordCompletionPluginClass;
struct _XedWordCompletionPlugin
{
PeasExtensionBase parent_instance;
XedWordCompletionPluginPrivate *priv;
};
struct _XedWordCompletionPluginClass
{
PeasExtensionBaseClass parent_class;
};
GType xed_wordcompletion_plugin_get_type (void) G_GNUC_CONST;
G_MODULE_EXPORT void peas_register_types (PeasObjectModule *module);
G_END_DECLS
#endif /* __XED_WORDCOMPLETION_PLUGIN_H__ */

View File

@@ -77,18 +77,10 @@ plugins/modelines/modelines.plugin.desktop.in
plugins/modelines/xed-modeline-plugin.c plugins/modelines/xed-modeline-plugin.c
plugins/sort/sort.plugin.desktop.in plugins/sort/sort.plugin.desktop.in
plugins/sort/xed-sort-plugin.c plugins/sort/xed-sort-plugin.c
[type: gettext/glade]plugins/spell/languages-dialog.ui
[type: gettext/gsettings]plugins/spell/org.x.editor.plugins.spell.gschema.xml.in [type: gettext/gsettings]plugins/spell/org.x.editor.plugins.spell.gschema.xml.in
[type: gettext/glade]plugins/spell/spell-checker.ui
plugins/spell/spell.plugin.desktop.in plugins/spell/spell.plugin.desktop.in
plugins/spell/xed-automatic-spell-checker.c
plugins/spell/xed-spell-checker-dialog.c
plugins/spell/xed-spell-checker-language.c
plugins/spell/xed-spell-checker.c
plugins/spell/xed-spell-language-dialog.c
plugins/spell/xed-spell-plugin.c plugins/spell/xed-spell-plugin.c
[type: gettext/glade]plugins/spell/xed-spell-setup-dialog.ui [type: gettext/glade]plugins/spell/xed-spell-setup-dialog.ui
plugins/spell/xed-spell-utils.c
plugins/taglist/HTML.tags.xml.in plugins/taglist/HTML.tags.xml.in
plugins/taglist/Latex.tags.xml.in plugins/taglist/Latex.tags.xml.in
plugins/taglist/taglist.plugin.desktop.in plugins/taglist/taglist.plugin.desktop.in
@@ -106,3 +98,5 @@ plugins/time/xed-time-plugin.c
[type: gettext/glade]plugins/time/xed-time-setup-dialog.ui [type: gettext/glade]plugins/time/xed-time-setup-dialog.ui
plugins/trailsave/trailsave.plugin.desktop.in plugins/trailsave/trailsave.plugin.desktop.in
plugins/trailsave/xed-trail-save-plugin.c plugins/trailsave/xed-trail-save-plugin.c
[type: gettext/glade]plugins/wordcompletion/xed-wordcompletion-configure.ui
plugins/wordcompletion/xed-wordcompletion-plugin.c

File diff suppressed because it is too large Load Diff

View File

@@ -40,10 +40,12 @@ NOINST_H_FILES = \
xed-close-button.h \ xed-close-button.h \
xed-close-confirmation-dialog.h \ xed-close-confirmation-dialog.h \
xed-dirs.h \ xed-dirs.h \
xed-document-private.h \
xed-documents-panel.h \ xed-documents-panel.h \
xed-encodings-dialog.h \ xed-encodings-dialog.h \
xed-history-entry.h \ xed-history-entry.h \
xed-io-error-info-bar.h \ xed-io-error-info-bar.h \
xed-metadata-manager.h \
xed-paned.h \ xed-paned.h \
xed-plugins-engine.h \ xed-plugins-engine.h \
xed-preferences-dialog.h \ xed-preferences-dialog.h \
@@ -80,10 +82,6 @@ INST_H_FILES = \
xed-window.h \ xed-window.h \
xed-window-activatable.h xed-window-activatable.h
if !ENABLE_GVFS_METADATA
NOINST_H_FILES += xed-metadata-manager.h
endif
headerdir = $(prefix)/include/xed headerdir = $(prefix)/include/xed
header_DATA = \ header_DATA = \
@@ -119,6 +117,7 @@ libxed_c_files = \
xed-message-bus.c \ xed-message-bus.c \
xed-message-type.c \ xed-message-type.c \
xed-message.c \ xed-message.c \
xed-metadata-manager.c \
xed-notebook.c \ xed-notebook.c \
xed-paned.c \ xed-paned.c \
xed-panel.c \ xed-panel.c \
@@ -146,10 +145,6 @@ libxed_la_SOURCES = \
$(NOINST_H_FILES) \ $(NOINST_H_FILES) \
$(INST_H_FILES) $(INST_H_FILES)
if !ENABLE_GVFS_METADATA
libxed_la_SOURCES += xed-metadata-manager.c
endif
xed-enum-types.h: xed-enum-types.h.template $(INST_H_FILES) $(GLIB_MKENUMS) xed-enum-types.h: xed-enum-types.h.template $(INST_H_FILES) $(GLIB_MKENUMS)
$(AM_V_GEN) (cd $(srcdir) && $(GLIB_MKENUMS) --template xed-enum-types.h.template $(INST_H_FILES)) > $@ $(AM_V_GEN) (cd $(srcdir) && $(GLIB_MKENUMS) --template xed-enum-types.h.template $(INST_H_FILES)) > $@

View File

@@ -1,7 +1,13 @@
.xed-map-frame:dir(ltr) { .xed-map-frame:dir(ltr) border {
border-width: 0 0 0 1px; border-width: 0 0 0 1px;
} }
.xed-map-frame:dir(rtl) { .xed-map-frame:dir(rtl) border {
border-width: 0 1px 0 0; border-width: 0 1px 0 0;
} }
.xed-searchbar .close-button {
padding: 0;
min-height: 0;
min-width: 0;
}

View File

@@ -0,0 +1,17 @@
.xed-window .primary-toolbar {
border: 0px solid @borders;
border-bottom-width: 1px;
}
.xed-statusbar {
border: 0px solid @borders;
border-top-width: 1px;
}
.xed-searchbar {
box-shadow: inset 0 1px @borders;
}
.xed-statusbar button {
padding: 0 4px;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,335 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<!-- interface-requires gtk+ 3.17 -->
<object class="GtkShortcutsWindow" id="shortcuts-xed">
<property name="modal">1</property>
<child>
<object class="GtkShortcutsSection">
<property name="visible">1</property>
<property name="section-name">shortcuts</property>
<property name="max-height">12</property>
<child>
<object class="GtkShortcutsGroup">
<property name="visible">1</property>
<property name="title" translatable="yes">Documents</property>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">1</property>
<property name="accelerator">&lt;ctrl&gt;N</property>
<property name="title" translatable="yes">Create a new document</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">1</property>
<property name="accelerator">&lt;ctrl&gt;O</property>
<property name="title" translatable="yes">Open a document</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">1</property>
<property name="accelerator">&lt;ctrl&gt;S</property>
<property name="title" translatable="yes">Save the document</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">1</property>
<property name="accelerator">&lt;ctrl&gt;&lt;shift&gt;S</property>
<property name="title" translatable="yes">Save the document with a new filename</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">1</property>
<property name="accelerator">&lt;ctrl&gt;&lt;shift&gt;L</property>
<property name="title" translatable="yes">Save all the documents</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">1</property>
<property name="accelerator">&lt;ctrl&gt;W</property>
<property name="title" translatable="yes">Close the document</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">1</property>
<property name="accelerator">&lt;ctrl&gt;&lt;shift&gt;W</property>
<property name="title" translatable="yes">Close all the documents</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">1</property>
<property name="accelerator">&lt;ctrl&gt;&lt;Alt&gt;Page_Down</property>
<property name="title" translatable="yes">Switch to the next document</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">1</property>
<property name="accelerator">&lt;ctrl&gt;&lt;Alt&gt;Page_Up</property>
<property name="title" translatable="yes">Switch to the previous document</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">1</property>
<property name="accelerator">&lt;Alt&gt;1...9</property>
<property name="title" translatable="yes">Switch to the first - ninth document</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkShortcutsGroup">
<property name="visible">1</property>
<property name="title" translatable="yes">Windows and Panes</property>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">1</property>
<property name="accelerator">F9</property>
<property name="title" translatable="yes">Show side pane</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">1</property>
<property name="accelerator">&lt;ctrl&gt;F9</property>
<property name="title" translatable="yes">Show bottom pane</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">1</property>
<property name="accelerator">F11</property>
<property name="title" translatable="yes">Fullscreen on / off</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">1</property>
<property name="accelerator">&lt;ctrl&gt;Q</property>
<property name="title" translatable="yes">Quit the application</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkShortcutsGroup">
<property name="visible">1</property>
<property name="title" translatable="yes">Find and Replace</property>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">1</property>
<property name="accelerator">&lt;ctrl&gt;F</property>
<property name="title" translatable="yes">Find</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">1</property>
<property name="accelerator">&lt;ctrl&gt;G</property>
<property name="title" translatable="yes">Find the next match</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">1</property>
<property name="accelerator">&lt;ctrl&gt;&lt;Shift&gt;G</property>
<property name="title" translatable="yes">Find the previous match</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">1</property>
<property name="accelerator">&lt;ctrl&gt;H</property>
<property name="title" translatable="yes">Find and Replace</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">1</property>
<property name="accelerator">&lt;ctrl&gt;I</property>
<property name="title" translatable="yes">Go to line</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkShortcutsGroup">
<property name="visible">1</property>
<property name="title" translatable="yes">Copy and Paste</property>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">1</property>
<property name="accelerator">&lt;ctrl&gt;C</property>
<property name="title" translatable="yes">Copy selected text to clipboard</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">1</property>
<property name="accelerator">&lt;ctrl&gt;X</property>
<property name="title" translatable="yes">Cut selected text to clipboard</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">1</property>
<property name="accelerator">&lt;ctrl&gt;V</property>
<property name="title" translatable="yes">Paste text from clipboard</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkShortcutsGroup">
<property name="visible">1</property>
<property name="title" translatable="yes">Undo and Redo</property>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">1</property>
<property name="accelerator">&lt;ctrl&gt;Z</property>
<property name="title" translatable="yes">Undo previous command</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">1</property>
<property name="accelerator">&lt;ctrl&gt;Y</property>
<property name="title" translatable="yes">Redo previous command</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkShortcutsGroup">
<property name="visible">1</property>
<property name="title" translatable="yes">Selection</property>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">1</property>
<property name="accelerator">&lt;ctrl&gt;A</property>
<property name="title" translatable="yes">Select all text</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkShortcutsGroup">
<property name="visible">1</property>
<property name="title" translatable="yes">Tools</property>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">1</property>
<property name="accelerator">&lt;shift&gt;F7</property>
<property name="title" translatable="yes">Check spelling</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">1</property>
<property name="accelerator">&lt;ctrl&gt;P</property>
<property name="title" translatable="yes">Print the document</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkShortcutsGroup">
<property name="visible">1</property>
<property name="title" translatable="yes">Editing</property>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">1</property>
<property name="accelerator">Insert</property>
<property name="title" translatable="yes">Toggle insert / overwrite</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">1</property>
<property name="accelerator">&lt;ctrl&gt;D</property>
<property name="title" translatable="yes">Delete current line</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">1</property>
<property name="accelerator">&lt;alt&gt;Up</property>
<property name="title" translatable="yes">Move current line up</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">1</property>
<property name="accelerator">&lt;alt&gt;Down</property>
<property name="title" translatable="yes">Move current line down</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">1</property>
<property name="accelerator">&lt;alt&gt;Left</property>
<property name="title" translatable="yes">Move current word left</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">1</property>
<property name="accelerator">&lt;alt&gt;Right</property>
<property name="title" translatable="yes">Move current word right</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">1</property>
<property name="accelerator">&lt;ctrl&gt;U</property>
<property name="title" translatable="yes">Convert to uppercase</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">1</property>
<property name="accelerator">&lt;ctrl&gt;L</property>
<property name="title" translatable="yes">Convert to lowercase</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">1</property>
<property name="accelerator">&lt;ctrl&gt;T</property>
<property name="title" translatable="yes">Convert to title case</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">1</property>
<property name="accelerator">&lt;ctrl&gt;asciitilde</property>
<property name="title" translatable="yes">Invert case</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">1</property>
<property name="accelerator">&lt;ctrl&gt;&lt;shift&gt;a</property>
<property name="title" translatable="yes">Increment number at cursor</property>
</object>
</child>
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">1</property>
<property name="accelerator">&lt;ctrl&gt;&lt;shift&gt;x</property>
<property name="title" translatable="yes">Decrement number at cursor</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
</interface>

View File

@@ -123,6 +123,8 @@
<menu name="HelpMenu" action="Help"> <menu name="HelpMenu" action="Help">
<menuitem name="HelpContentsMenu" action="HelpContents"/> <menuitem name="HelpContentsMenu" action="HelpContents"/>
<menuitem name="HelpAboutMenu" action="HelpAbout"/> <menuitem name="HelpAboutMenu" action="HelpAbout"/>
<menuitem name="HelpAboutMenu" action="HelpAbout"/>
<menuitem name="HelpShortcutsMenu" action="HelpShortcuts"/>
</menu> </menu>
</menubar> </menubar>

View File

@@ -6,7 +6,9 @@
<file preprocess="xml-stripblanks">ui/xed-preferences-dialog.ui</file> <file preprocess="xml-stripblanks">ui/xed-preferences-dialog.ui</file>
<file preprocess="xml-stripblanks">ui/xed-print-preferences.ui</file> <file preprocess="xml-stripblanks">ui/xed-print-preferences.ui</file>
<file preprocess="xml-stripblanks">ui/xed-searchbar.ui</file> <file preprocess="xml-stripblanks">ui/xed-searchbar.ui</file>
<file preprocess="xml-stripblanks">ui/xed-shortcuts.ui</file>
<file preprocess="xml-stripblanks">ui/xed-view-frame.ui</file> <file preprocess="xml-stripblanks">ui/xed-view-frame.ui</file>
<file>css/xed-style.css</file> <file>css/xed-style.css</file>
<file>css/xed.adwaita.css</file>
</gresource> </gresource>
</gresources> </gresources>

View File

@@ -223,6 +223,54 @@ set_initial_theme_style (XedApp *app)
} }
} }
static void
theme_changed (GtkSettings *settings,
GParamSpec *pspec,
gpointer data)
{
static GtkCssProvider *provider;
gchar *theme;
GdkScreen *screen;
g_object_get (settings, "gtk-theme-name", &theme, NULL);
screen = gdk_screen_get_default ();
if (g_str_equal (theme, "Adwaita"))
{
if (provider == NULL)
{
GFile *file;
provider = gtk_css_provider_new ();
file = g_file_new_for_uri ("resource:///org/x/editor/css/xed.adwaita.css");
gtk_css_provider_load_from_file (provider, file, NULL);
g_object_unref (file);
}
gtk_style_context_add_provider_for_screen (screen,
GTK_STYLE_PROVIDER (provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
}
else if (provider != NULL)
{
gtk_style_context_remove_provider_for_screen (screen, GTK_STYLE_PROVIDER (provider));
g_clear_object (&provider);
}
g_free (theme);
}
static void
setup_theme_extensions (void)
{
GtkSettings *settings;
settings = gtk_settings_get_default ();
g_signal_connect (settings, "notify::gtk-theme-name",
G_CALLBACK (theme_changed), NULL);
theme_changed (settings, NULL, NULL);
}
static void static void
xed_app_startup (GApplication *application) xed_app_startup (GApplication *application)
{ {
@@ -251,6 +299,8 @@ xed_app_startup (GApplication *application)
gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (), icon_dir); gtk_icon_theme_append_search_path (gtk_icon_theme_get_default (), icon_dir);
g_free (icon_dir); g_free (icon_dir);
setup_theme_extensions ();
#ifndef ENABLE_GVFS_METADATA #ifndef ENABLE_GVFS_METADATA
/* Setup metadata-manager */ /* Setup metadata-manager */
cache_dir = xed_dirs_get_user_cache_dir (); cache_dir = xed_dirs_get_user_cache_dir ();

View File

@@ -32,10 +32,13 @@
#include <config.h> #include <config.h>
#endif #endif
#include "xed-close-confirmation-dialog.h"
#include <glib/gi18n.h> #include <glib/gi18n.h>
#include "xed-close-confirmation-dialog.h"
#include <xed/xed-app.h> #include <xed/xed-app.h>
#include <xed/xed-document.h>
#include <xed/xed-document-private.h>
#include <xed/xed-utils.h> #include <xed/xed-utils.h>
#include <xed/xed-window.h> #include <xed/xed-window.h>

View File

@@ -38,31 +38,27 @@
#include <gio/gio.h> #include <gio/gio.h>
#include <gtk/gtk.h> #include <gtk/gtk.h>
#include "xed-debug.h"
#include "xed-document.h"
#include "xed-document-private.h"
#include "xed-commands.h" #include "xed-commands.h"
#include "xed-window.h" #include "xed-window.h"
#include "xed-window-private.h" #include "xed-window-private.h"
#include "xed-statusbar.h" #include "xed-statusbar.h"
#include "xed-debug.h"
#include "xed-utils.h" #include "xed-utils.h"
#include "xed-file-chooser-dialog.h" #include "xed-file-chooser-dialog.h"
#include "xed-close-confirmation-dialog.h" #include "xed-close-confirmation-dialog.h"
/* Defined constants */ /* Defined constants */
#define XED_OPEN_DIALOG_KEY "xed-open-dialog-key" #define XED_OPEN_DIALOG_KEY "xed-open-dialog-key"
#define XED_TAB_TO_SAVE_AS "xed-tab-to-save-as"
#define XED_LIST_OF_TABS_TO_SAVE_AS "xed-list-of-tabs-to-save-as"
#define XED_IS_CLOSING_ALL "xed-is-closing-all" #define XED_IS_CLOSING_ALL "xed-is-closing-all"
#define XED_IS_QUITTING "xed-is-quitting" #define XED_IS_QUITTING "xed-is-quitting"
#define XED_IS_CLOSING_TAB "xed-is-closing-tab"
#define XED_IS_QUITTING_ALL "xed-is-quitting-all" #define XED_IS_QUITTING_ALL "xed-is-quitting-all"
static void tab_state_changed_while_saving (XedTab *tab, static void tab_state_changed_while_saving (XedTab *tab,
GParamSpec *pspec, GParamSpec *pspec,
XedWindow *window); XedWindow *window);
static void save_as_tab (XedTab *tab,
XedWindow *window);
void void
_xed_cmd_file_new (GtkAction *action, _xed_cmd_file_new (GtkAction *action,
XedWindow *window) XedWindow *window)
@@ -521,110 +517,70 @@ replace_read_only_file (GtkWindow *parent,
} }
static void static void
save_finish_cb (XedTab *tab, tab_save_as_ready_cb (XedTab *tab,
GAsyncResult *result, GAsyncResult *result,
gpointer user_data) GTask *task)
{ {
_xed_tab_save_finish (tab, result); gboolean success = _xed_tab_save_finish (tab, result);
g_task_return_boolean (task, success);
g_object_unref (task);
} }
static void static void
save_dialog_response_cb (XedFileChooserDialog *dialog, save_dialog_response_cb (XedFileChooserDialog *dialog,
gint response_id, gint response_id,
XedWindow *window) GTask *task)
{ {
XedTab *tab; XedTab *tab;
gpointer data; XedWindow *window;
GSList *tabs_to_save_as; GFile *location;
gchar *parse_name;
GtkSourceNewlineType newline_type;
const GtkSourceEncoding *encoding;
xed_debug (DEBUG_COMMANDS); xed_debug (DEBUG_COMMANDS);
tab = XED_TAB (g_object_get_data (G_OBJECT (dialog), XED_TAB_TO_SAVE_AS)); tab = g_task_get_source_object (task);
window = g_task_get_task_data (task);
if (response_id != GTK_RESPONSE_OK) if (response_id != GTK_RESPONSE_OK)
{ {
gtk_widget_destroy (GTK_WIDGET (dialog)); gtk_widget_destroy (GTK_WIDGET (dialog));
goto save_next_tab; g_task_return_boolean (task, FALSE);
} g_object_unref (task);
if (tab != NULL)
{
GFile *location;
XedDocument *doc;
gchar *parse_name;
GtkSourceNewlineType newline_type;
const GtkSourceEncoding *encoding;
doc = xed_tab_get_document (tab);
location = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
g_return_if_fail (location != NULL);
encoding = xed_file_chooser_dialog_get_encoding (dialog);
newline_type = xed_file_chooser_dialog_get_newline_type (dialog);
gtk_widget_destroy (GTK_WIDGET (dialog));
doc = xed_tab_get_document (tab);
g_return_if_fail (XED_IS_DOCUMENT (doc));
parse_name = g_file_get_parse_name (location);
xed_statusbar_flash_message (XED_STATUSBAR (window->priv->statusbar),
window->priv->generic_message_cid,
_("Saving file '%s'\342\200\246"),
parse_name);
g_free (parse_name);
/* let's remember the dir we navigated too,
* even if the saving fails... */
_xed_window_set_default_location (window, location);
_xed_tab_save_as_async (tab,
location,
encoding,
newline_type,
NULL,
(GAsyncReadyCallback) save_finish_cb,
NULL);
g_object_unref (location);
}
save_next_tab:
data = g_object_get_data (G_OBJECT (window), XED_LIST_OF_TABS_TO_SAVE_AS);
if (data == NULL)
{
return; return;
} }
/* Save As the next tab of the list (we are Saving All files) */ location = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
tabs_to_save_as = (GSList *)data; g_return_if_fail (location != NULL);
g_return_if_fail (tab == XED_TAB (tabs_to_save_as->data));
/* Remove the first item of the list */ encoding = xed_file_chooser_dialog_get_encoding (dialog);
tabs_to_save_as = g_slist_delete_link (tabs_to_save_as, tabs_to_save_as); newline_type = xed_file_chooser_dialog_get_newline_type (dialog);
g_object_set_data (G_OBJECT (window), XED_LIST_OF_TABS_TO_SAVE_AS, tabs_to_save_as); gtk_widget_destroy (GTK_WIDGET (dialog));
if (tabs_to_save_as != NULL) parse_name = g_file_get_parse_name (location);
{
tab = XED_TAB (tabs_to_save_as->data);
if (GPOINTER_TO_BOOLEAN (g_object_get_data (G_OBJECT (tab), XED_IS_CLOSING_TAB)) == TRUE) xed_statusbar_flash_message (XED_STATUSBAR (window->priv->statusbar),
{ window->priv->generic_message_cid,
g_object_set_data (G_OBJECT (tab), XED_IS_CLOSING_TAB, NULL); _("Saving file '%s'\342\200\246"),
parse_name);
/* Trace tab state changes */ g_free (parse_name);
g_signal_connect (tab, "notify::state", G_CALLBACK (tab_state_changed_while_saving), window);
}
xed_window_set_active_tab (window, tab); /* let's remember the dir we navigated too, even if the saving fails... */
save_as_tab (tab, window); _xed_window_set_default_location (window, location);
}
_xed_tab_save_as_async (tab,
location,
encoding,
newline_type,
g_task_get_cancellable (task),
(GAsyncReadyCallback) tab_save_as_ready_cb,
task);
g_object_unref (location);
} }
static GtkFileChooserConfirmation static GtkFileChooserConfirmation
@@ -663,16 +619,20 @@ confirm_overwrite_callback (GtkFileChooser *dialog,
return res; return res;
} }
/* Call save_as_tab_finish() in @callback. */
static void static void
save_as_tab (XedTab *tab, save_as_tab_async (XedTab *tab,
XedWindow *window) XedWindow *window,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{ {
GTask *task;
GtkWidget *save_dialog; GtkWidget *save_dialog;
GtkWindowGroup *wg; GtkWindowGroup *wg;
XedDocument *doc; XedDocument *doc;
GtkSourceFile *file; GtkSourceFile *file;
GFile *location; GFile *location;
gboolean uri_set = FALSE;
const GtkSourceEncoding *encoding; const GtkSourceEncoding *encoding;
GtkSourceNewlineType newline_type; GtkSourceNewlineType newline_type;
@@ -681,6 +641,9 @@ save_as_tab (XedTab *tab,
xed_debug (DEBUG_COMMANDS); xed_debug (DEBUG_COMMANDS);
task = g_task_new (tab, cancellable, callback, user_data);
g_task_set_task_data (task, g_object_ref (window), g_object_unref);
save_dialog = xed_file_chooser_dialog_new (_("Save As\342\200\246"), save_dialog = xed_file_chooser_dialog_new (_("Save As\342\200\246"),
GTK_WINDOW (window), GTK_WINDOW (window),
GTK_FILE_CHOOSER_ACTION_SAVE, GTK_FILE_CHOOSER_ACTION_SAVE,
@@ -706,11 +669,11 @@ save_as_tab (XedTab *tab,
if (location != NULL) if (location != NULL)
{ {
uri_set = gtk_file_chooser_set_file (GTK_FILE_CHOOSER (save_dialog), location, NULL); gtk_file_chooser_set_file (GTK_FILE_CHOOSER (save_dialog), location, NULL);
} }
if (!uri_set) else
{ {
GFile *default_path; GFile *default_path;
gchar *docname; gchar *docname;
@@ -734,7 +697,7 @@ save_as_tab (XedTab *tab,
g_free (docname); g_free (docname);
} }
/* Set suggested encoding */ /* Set suggested encoding and newline type */
encoding = gtk_source_file_get_encoding (file); encoding = gtk_source_file_get_encoding (file);
if (encoding == NULL) if (encoding == NULL)
@@ -748,39 +711,94 @@ save_as_tab (XedTab *tab,
xed_file_chooser_dialog_set_newline_type (XED_FILE_CHOOSER_DIALOG (save_dialog), newline_type); xed_file_chooser_dialog_set_newline_type (XED_FILE_CHOOSER_DIALOG (save_dialog), newline_type);
g_object_set_data (G_OBJECT (save_dialog), XED_TAB_TO_SAVE_AS, tab); g_signal_connect (save_dialog, "response", G_CALLBACK (save_dialog_response_cb), task);
g_signal_connect (save_dialog, "response", G_CALLBACK (save_dialog_response_cb), window);
gtk_widget_show (save_dialog); gtk_widget_show (save_dialog);
} }
static void static gboolean
save_tab (XedTab *tab, save_as_tab_finish (XedTab *tab,
XedWindow *window) GAsyncResult *result)
{ {
XedDocument *doc; g_return_val_if_fail (g_task_is_valid (result, tab), FALSE);
return g_task_propagate_boolean (G_TASK (result), NULL);
}
static void
save_as_tab_ready_cb (XedTab *tab,
GAsyncResult *result,
GTask *task)
{
gboolean success = save_as_tab_finish (tab, result);
g_task_return_boolean (task, success);
g_object_unref (task);
}
static void
tab_save_ready_cb (XedTab *tab,
GAsyncResult *result,
GTask *task)
{
gboolean success = _xed_tab_save_finish (tab, result);
g_task_return_boolean (task, success);
g_object_unref (task);
}
/**
* xed_commands_save_document_async:
* @document: the #XedDocument to save.
* @window: a #XedWindow.
* @cancellable: (nullable): optional #GCancellable object, %NULL to ignore.
* @callback: (scope async): a #GAsyncReadyCallback to call when the operation
* is finished.
* @user_data: (closure): the data to pass to the @callback function.
*
* Asynchronously save the @document. @document must belong to @window. The
* source object of the async task is @document (which will be the first
* parameter of the #GAsyncReadyCallback).
*
* When the operation is finished, @callback will be called. You can then call
* xed_commands_save_document_finish() to get the result of the operation.
*/
void
xed_commands_save_document_async (XedDocument *document,
XedWindow *window,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
GTask *task;
XedTab *tab;
gchar *uri_for_display; gchar *uri_for_display;
xed_debug (DEBUG_COMMANDS); xed_debug (DEBUG_COMMANDS);
g_return_if_fail (XED_IS_TAB (tab)); g_return_if_fail (XED_IS_DOCUMENT (document));
g_return_if_fail (XED_IS_WINDOW (window)); g_return_if_fail (XED_IS_WINDOW (window));
g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
doc = xed_tab_get_document (tab); task = g_task_new (document, cancellable, callback, user_data);
g_return_if_fail (XED_IS_DOCUMENT (doc));
if (xed_document_is_untitled (doc) || tab = xed_tab_get_from_document (document);
xed_document_get_readonly (doc))
if (xed_document_is_untitled (document) ||
xed_document_get_readonly (document))
{ {
xed_debug_message (DEBUG_COMMANDS, "Untitled or Readonly"); xed_debug_message (DEBUG_COMMANDS, "Untitled or Readonly");
save_as_tab (tab, window); save_as_tab_async (tab,
window,
cancellable,
(GAsyncReadyCallback) save_as_tab_ready_cb,
task);
return; return;
} }
uri_for_display = xed_document_get_uri_for_display (doc); uri_for_display = xed_document_get_uri_for_display (document);
xed_statusbar_flash_message (XED_STATUSBAR (window->priv->statusbar), xed_statusbar_flash_message (XED_STATUSBAR (window->priv->statusbar),
window->priv->generic_message_cid, window->priv->generic_message_cid,
_("Saving file '%s'\342\200\246"), _("Saving file '%s'\342\200\246"),
@@ -789,9 +807,53 @@ save_tab (XedTab *tab,
g_free (uri_for_display); g_free (uri_for_display);
_xed_tab_save_async (tab, _xed_tab_save_async (tab,
NULL, cancellable,
(GAsyncReadyCallback) save_finish_cb, (GAsyncReadyCallback) tab_save_ready_cb,
NULL); task);
}
/**
* xed_commands_save_document_finish:
* @document: a #XedDocument.
* @result: a #GAsyncResult.
*
* Finishes an asynchronous document saving operation started with
* xed_commands_save_document_async().
*
* Note that there is no error parameter because the errors are already handled
* by xed.
*
* Returns: %TRUE if the document has been correctly saved, %FALSE otherwise.
*/
gboolean
xed_commands_save_document_finish (XedDocument *document,
GAsyncResult *result)
{
g_return_val_if_fail (g_task_is_valid (result, document), FALSE);
return g_task_propagate_boolean (G_TASK (result), NULL);
}
static void
save_tab_ready_cb (XedDocument *doc,
GAsyncResult *result,
gpointer user_data)
{
xed_commands_save_document_finish (doc, result);
}
/* Save tab asynchronously, but without results. */
static void
save_tab (XedTab *tab,
XedWindow *window)
{
XedDocument *doc = xed_tab_get_document (tab);
xed_commands_save_document_async (doc,
window,
NULL,
(GAsyncReadyCallback) save_tab_ready_cb,
NULL);
} }
void void
@@ -803,12 +865,18 @@ _xed_cmd_file_save (GtkAction *action,
xed_debug (DEBUG_COMMANDS); xed_debug (DEBUG_COMMANDS);
tab = xed_window_get_active_tab (window); tab = xed_window_get_active_tab (window);
if (tab == NULL) if (tab != NULL)
{ {
return; save_tab (tab, window);
} }
}
save_tab (tab, window); static void
_xed_cmd_file_save_as_cb (XedTab *tab,
GAsyncResult *result,
gpointer user_data)
{
save_as_tab_finish (tab, result);
} }
void void
@@ -820,12 +888,149 @@ _xed_cmd_file_save_as (GtkAction *action,
xed_debug (DEBUG_COMMANDS); xed_debug (DEBUG_COMMANDS);
tab = xed_window_get_active_tab (window); tab = xed_window_get_active_tab (window);
if (tab == NULL) if (tab != NULL)
{
save_as_tab_async (tab,
window,
NULL,
(GAsyncReadyCallback) _xed_cmd_file_save_as_cb,
NULL);
}
}
static void
quit_if_needed (XedWindow *window)
{
gboolean is_quitting;
gboolean is_quitting_all;
is_quitting = GPOINTER_TO_BOOLEAN (g_object_get_data (G_OBJECT (window), XED_IS_QUITTING));
is_quitting_all = GPOINTER_TO_BOOLEAN (g_object_get_data (G_OBJECT (window), XED_IS_QUITTING_ALL));
if (is_quitting)
{
gtk_widget_destroy (GTK_WIDGET (window));
}
if (is_quitting_all)
{
GtkApplication *app;
app = GTK_APPLICATION (g_application_get_default ());
if (gtk_application_get_windows (app) == NULL)
{
g_application_quit (G_APPLICATION (app));
}
}
}
static gboolean
really_close_tab (XedTab *tab)
{
GtkWidget *toplevel;
XedWindow *window;
xed_debug (DEBUG_COMMANDS);
g_return_val_if_fail (xed_tab_get_state (tab) == XED_TAB_STATE_CLOSING, FALSE);
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (tab));
g_return_val_if_fail (XED_IS_WINDOW (toplevel), FALSE);
window = XED_WINDOW (toplevel);
xed_window_close_tab (window, tab);
if (xed_window_get_active_tab (window) == NULL)
{
quit_if_needed (window);
}
return FALSE;
}
static void
close_tab (XedTab *tab)
{
XedDocument *doc;
doc = xed_tab_get_document (tab);
g_return_if_fail (doc != NULL);
/* If the user has modified again the document, do not close the tab. */
if (_xed_document_needs_saving (doc))
{ {
return; return;
} }
save_as_tab (tab, window); /* Close the document only if it has been succesfully saved.
* Tab state is set to CLOSING (it is a state without exiting
* transitions) and the tab is closed in an idle handler.
*/
_xed_tab_mark_for_closing (tab);
g_idle_add_full (G_PRIORITY_HIGH_IDLE,
(GSourceFunc) really_close_tab,
tab,
NULL);
}
typedef struct _SaveAsData SaveAsData;
struct _SaveAsData
{
/* Reffed */
XedWindow *window;
/* List of reffed GeditTab's */
GSList *tabs_to_save_as;
guint close_tabs : 1;
};
static void save_as_documents_list (SaveAsData *data);
static void
save_as_documents_list_cb (XedTab *tab,
GAsyncResult *result,
SaveAsData *data)
{
gboolean saved = save_as_tab_finish (tab, result);
if (saved && data->close_tabs)
{
close_tab (tab);
}
g_return_if_fail (tab == XED_TAB (data->tabs_to_save_as->data));
g_object_unref (data->tabs_to_save_as->data);
data->tabs_to_save_as = g_slist_delete_link (data->tabs_to_save_as, data->tabs_to_save_as);
if (data->tabs_to_save_as != NULL)
{
save_as_documents_list (data);
}
else
{
g_object_unref (data->window);
g_slice_free (SaveAsData, data);
}
}
static void
save_as_documents_list (SaveAsData *data)
{
XedTab *next_tab = XED_TAB (data->tabs_to_save_as->data);
xed_window_set_active_tab (data->window, next_tab);
save_as_tab_async (next_tab,
data->window,
NULL,
(GAsyncReadyCallback) save_as_documents_list_cb,
data);
} }
/* /*
@@ -835,8 +1040,8 @@ static void
save_documents_list (XedWindow *window, save_documents_list (XedWindow *window,
GList *docs) GList *docs)
{ {
SaveAsData *data = NULL;
GList *l; GList *l;
GSList *tabs_to_save_as = NULL;
xed_debug (DEBUG_COMMANDS); xed_debug (DEBUG_COMMANDS);
@@ -868,9 +1073,17 @@ save_documents_list (XedWindow *window,
if (xed_document_is_untitled (doc) || xed_document_get_readonly (doc)) if (xed_document_is_untitled (doc) || xed_document_get_readonly (doc))
{ {
if (_xed_document_needs_saving (doc)) if (_xed_document_needs_saving (doc))
{
if (data == NULL)
{ {
tabs_to_save_as = g_slist_prepend (tabs_to_save_as, t); data = g_slice_new (SaveAsData);
data->window = g_object_ref (window);
data->tabs_to_save_as = NULL;
data->close_tabs = FALSE;
} }
data->tabs_to_save_as = g_slist_prepend (data->tabs_to_save_as, g_object_ref (t));
}
} }
else else
{ {
@@ -913,23 +1126,21 @@ save_documents_list (XedWindow *window,
l = g_list_next (l); l = g_list_next (l);
} }
if (tabs_to_save_as != NULL) if (data != NULL)
{ {
XedTab *tab; data->tabs_to_save_as = g_slist_reverse (data->tabs_to_save_as);
save_as_documents_list (data);
tabs_to_save_as = g_slist_reverse (tabs_to_save_as );
g_return_if_fail (g_object_get_data (G_OBJECT (window), XED_LIST_OF_TABS_TO_SAVE_AS) == NULL);
g_object_set_data (G_OBJECT (window), XED_LIST_OF_TABS_TO_SAVE_AS, tabs_to_save_as);
tab = XED_TAB (tabs_to_save_as->data);
xed_window_set_active_tab (window, tab);
save_as_tab (tab, window);
} }
} }
/**
* xed_commands_save_all_documents:
* @window: a #XedWindow.
*
* Asynchronously save all documents belonging to @window. The result of the
* operation is not available, so it's difficult to know whether all the
* documents are correctly saved.
*/
void void
xed_commands_save_all_documents (XedWindow *window) xed_commands_save_all_documents (XedWindow *window)
{ {
@@ -953,6 +1164,14 @@ _xed_cmd_file_save_all (GtkAction *action,
xed_commands_save_all_documents (window); xed_commands_save_all_documents (window);
} }
/**
* xed_commands_save_document:
* @window: a #XedWindow.
* @document: the #XedDocument to save.
*
* Asynchronously save @document. @document must belong to @window. If you need
* the result of the operation, use xed_commands_save_document_async().
*/
void void
xed_commands_save_document (XedWindow *window, xed_commands_save_document (XedWindow *window,
XedDocument *document) XedDocument *document)
@@ -1161,39 +1380,6 @@ _xed_cmd_file_revert (GtkAction *action,
gtk_widget_show (dialog); gtk_widget_show (dialog);
} }
/* Close tab */
static gboolean
really_close_tab (XedTab *tab)
{
GtkWidget *toplevel;
XedWindow *window;
xed_debug (DEBUG_COMMANDS);
g_return_val_if_fail (xed_tab_get_state (tab) == XED_TAB_STATE_CLOSING, FALSE);
toplevel = gtk_widget_get_toplevel (GTK_WIDGET (tab));
g_return_val_if_fail (XED_IS_WINDOW (toplevel), FALSE);
window = XED_WINDOW (toplevel);
xed_window_close_tab (window, tab);
if (xed_window_get_active_tab (window) == NULL)
{
gboolean is_quitting;
is_quitting = GPOINTER_TO_BOOLEAN (g_object_get_data (G_OBJECT (window), XED_IS_QUITTING));
if (is_quitting)
{
gtk_widget_destroy (GTK_WIDGET (window));
}
}
return FALSE;
}
static void static void
tab_state_changed_while_saving (XedTab *tab, tab_state_changed_while_saving (XedTab *tab,
GParamSpec *pspec, GParamSpec *pspec,
@@ -1209,26 +1395,9 @@ tab_state_changed_while_saving (XedTab *tab,
finished */ finished */
if (ts == XED_TAB_STATE_NORMAL) if (ts == XED_TAB_STATE_NORMAL)
{ {
XedDocument *doc;
g_signal_handlers_disconnect_by_func (tab, G_CALLBACK (tab_state_changed_while_saving), window); g_signal_handlers_disconnect_by_func (tab, G_CALLBACK (tab_state_changed_while_saving), window);
doc = xed_tab_get_document (tab); close_tab (tab);
g_return_if_fail (doc != NULL);
/* If the saving operation failed or was interrupted, then the
document is still "modified" -> do not close the tab */
if (_xed_document_needs_saving (doc))
{
return;
}
/* Close the document only if it has been succesfully saved.
Tab state is set to CLOSING (it is a state without exiting
transitions) and the tab is closed in a idle handler */
_xed_tab_mark_for_closing (tab);
g_idle_add_full (G_PRIORITY_HIGH_IDLE, (GSourceFunc)really_close_tab, tab, NULL);
} }
} }
@@ -1244,21 +1413,6 @@ save_and_close (XedTab *tab,
save_tab (tab, window); save_tab (tab, window);
} }
static void
save_as_and_close (XedTab *tab,
XedWindow *window)
{
xed_debug (DEBUG_COMMANDS);
g_object_set_data (G_OBJECT (tab), XED_IS_CLOSING_TAB, NULL);
/* Trace tab state changes */
g_signal_connect (tab, "notify::state", G_CALLBACK (tab_state_changed_while_saving), window);
xed_window_set_active_tab (window, tab);
save_as_tab (tab, window);
}
static void static void
save_and_close_all_documents (const GList *docs, save_and_close_all_documents (const GList *docs,
XedWindow *window) XedWindow *window)
@@ -1266,9 +1420,9 @@ save_and_close_all_documents (const GList *docs,
GList *tabs; GList *tabs;
GList *l; GList *l;
GSList *sl; GSList *sl;
GSList *tabs_to_save_as; SaveAsData *data = NULL;
GSList *tabs_to_save_and_close; GSList *tabs_to_save_and_close = NULL;
GList *tabs_to_close; GList *tabs_to_close = NULL;
xed_debug (DEBUG_COMMANDS); xed_debug (DEBUG_COMMANDS);
@@ -1276,19 +1430,13 @@ save_and_close_all_documents (const GList *docs,
tabs = gtk_container_get_children (GTK_CONTAINER (_xed_window_get_notebook (window))); tabs = gtk_container_get_children (GTK_CONTAINER (_xed_window_get_notebook (window)));
tabs_to_save_as = NULL;
tabs_to_save_and_close = NULL;
tabs_to_close = NULL;
l = tabs; l = tabs;
while (l != NULL) while (l != NULL)
{ {
XedTab *t; XedTab *t = XED_TAB (l->data);;
XedTabState state; XedTabState state;
XedDocument *doc; XedDocument *doc;
t = XED_TAB (l->data);
state = xed_tab_get_state (t); state = xed_tab_get_state (t);
doc = xed_tab_get_document (t); doc = xed_tab_get_document (t);
@@ -1337,9 +1485,15 @@ save_and_close_all_documents (const GList *docs,
user is running xed - Paolo (Dec. 8, 2005) */ user is running xed - Paolo (Dec. 8, 2005) */
if (xed_document_is_untitled (doc) || xed_document_get_readonly (doc)) if (xed_document_is_untitled (doc) || xed_document_get_readonly (doc))
{ {
g_object_set_data (G_OBJECT (t), XED_IS_CLOSING_TAB, GBOOLEAN_TO_POINTER (TRUE)); if (data == NULL)
{
data = g_slice_new (SaveAsData);
data->window = g_object_ref (window);
data->tabs_to_save_as = NULL;
data->close_tabs = TRUE;
}
tabs_to_save_as = g_slist_prepend (tabs_to_save_as, t); data->tabs_to_save_as = g_slist_prepend (data->tabs_to_save_as, g_object_ref (t));
} }
else else
{ {
@@ -1371,20 +1525,11 @@ save_and_close_all_documents (const GList *docs,
} }
g_slist_free (tabs_to_save_and_close); g_slist_free (tabs_to_save_and_close);
/* Save As and close all the files in tabs_to_save_as */ /* Save As and close all the files in data->tabs_to_save_as. */
if (tabs_to_save_as != NULL) if (data != NULL)
{ {
XedTab *tab; data->tabs_to_save_as = g_slist_reverse (data->tabs_to_save_as);
save_as_documents_list (data);
tabs_to_save_as = g_slist_reverse (tabs_to_save_as );
g_return_if_fail (g_object_get_data (G_OBJECT (window), XED_LIST_OF_TABS_TO_SAVE_AS) == NULL);
g_object_set_data (G_OBJECT (window), XED_LIST_OF_TABS_TO_SAVE_AS, tabs_to_save_as);
tab = XED_TAB (tabs_to_save_as->data);
save_as_and_close (tab, window);
} }
} }

View File

@@ -46,7 +46,7 @@
void _xed_cmd_help_contents (GtkAction *action, void _xed_cmd_help_contents (GtkAction *action,
XedWindow *window) XedWindow *window)
{ {
xed_debug(DEBUG_COMMANDS); xed_debug (DEBUG_COMMANDS);
xed_app_show_help (XED_APP (g_application_get_default ()), GTK_WINDOW (window), NULL, NULL); xed_app_show_help (XED_APP (g_application_get_default ()), GTK_WINDOW (window), NULL, NULL);
} }
@@ -67,3 +67,33 @@ void _xed_cmd_help_about (GtkAction *action,
"website", "http://github.com/linuxmint/xed", "website", "http://github.com/linuxmint/xed",
NULL); NULL);
} }
void
_xed_cmd_help_keyboard_shortcuts (GtkAction *action,
XedWindow *window)
{
static GtkWidget *shortcuts_window;
xed_debug (DEBUG_COMMANDS);
if (shortcuts_window == NULL)
{
GtkBuilder *builder;
builder = gtk_builder_new_from_resource ("/org/x/editor/ui/xed-shortcuts.ui");
shortcuts_window = GTK_WIDGET (gtk_builder_get_object (builder, "shortcuts-xed"));
g_signal_connect (shortcuts_window, "destroy",
G_CALLBACK (gtk_widget_destroyed), &shortcuts_window);
g_object_unref (builder);
}
if (GTK_WINDOW (window) != gtk_window_get_transient_for (GTK_WINDOW (shortcuts_window)))
{
gtk_window_set_transient_for (GTK_WINDOW (shortcuts_window), GTK_WINDOW (window));
}
gtk_widget_show_all (shortcuts_window);
gtk_window_present (GTK_WINDOW (shortcuts_window));
}

View File

@@ -12,6 +12,8 @@ void xed_commands_load_location (XedWindow *window, GFile *location, const GtkSo
/* Ignore non-existing URIs */ /* Ignore non-existing URIs */
GSList *xed_commands_load_locations (XedWindow *window, const GSList *locations, const GtkSourceEncoding *encoding, gint line_pos); GSList *xed_commands_load_locations (XedWindow *window, const GSList *locations, const GtkSourceEncoding *encoding, gint line_pos);
void xed_commands_save_document (XedWindow *window, XedDocument *document); void xed_commands_save_document (XedWindow *window, XedDocument *document);
void xed_commands_save_document_async (XedDocument *document, XedWindow *window, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data);
gboolean xed_commands_save_document_finish (XedDocument *document, GAsyncResult *result);
void xed_commands_save_all_documents (XedWindow *window); void xed_commands_save_all_documents (XedWindow *window);
/* /*
@@ -64,6 +66,7 @@ void _xed_cmd_documents_move_to_new_window (GtkAction *action, XedWindow *window
void _xed_cmd_help_contents (GtkAction *action, XedWindow *window); void _xed_cmd_help_contents (GtkAction *action, XedWindow *window);
void _xed_cmd_help_about (GtkAction *action, XedWindow *window); void _xed_cmd_help_about (GtkAction *action, XedWindow *window);
void _xed_cmd_help_keyboard_shortcuts (GtkAction *action, XedWindow *window);
void _xed_cmd_file_close_tab (XedTab *tab, XedWindow *window); void _xed_cmd_file_close_tab (XedTab *tab, XedWindow *window);

View File

@@ -0,0 +1,21 @@
#ifndef __XED_DOCUMENT_PRIVATE_H__
#define __XED_DOCUMENT_PRIVATE_H__
#include "xed-document.h"
G_BEGIN_DECLS
glong _xed_document_get_seconds_since_last_save_or_load (XedDocument *doc);
gboolean _xed_document_needs_saving (XedDocument *doc);
gboolean _xed_document_get_empty_search (XedDocument *doc);
void _xed_document_set_create (XedDocument *doc,
gboolean create);
gboolean _xed_document_get_create (XedDocument *doc);
G_END_DECLS
#endif /* __XED_DOCUMENT_PRIVATE_H__ */

File diff suppressed because it is too large Load Diff

View File

@@ -37,29 +37,14 @@
G_BEGIN_DECLS G_BEGIN_DECLS
#define XED_TYPE_DOCUMENT (xed_document_get_type()) #define XED_TYPE_DOCUMENT (xed_document_get_type())
#define XED_DOCUMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XED_TYPE_DOCUMENT, XedDocument))
#define XED_DOCUMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), XED_TYPE_DOCUMENT, XedDocumentClass)) G_DECLARE_DERIVABLE_TYPE (XedDocument, xed_document, XED, DOCUMENT, GtkSourceBuffer)
#define XED_IS_DOCUMENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), XED_TYPE_DOCUMENT))
#define XED_IS_DOCUMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XED_TYPE_DOCUMENT))
#define XED_DOCUMENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), XED_TYPE_DOCUMENT, XedDocumentClass))
#define XED_METADATA_ATTRIBUTE_POSITION "metadata::xed-position" #define XED_METADATA_ATTRIBUTE_POSITION "metadata::xed-position"
#define XED_METADATA_ATTRIBUTE_ENCODING "metadata::xed-encoding" #define XED_METADATA_ATTRIBUTE_ENCODING "metadata::xed-encoding"
#define XED_METADATA_ATTRIBUTE_LANGUAGE "metadata::xed-language" #define XED_METADATA_ATTRIBUTE_LANGUAGE "metadata::xed-language"
typedef struct _XedDocument XedDocument;
typedef struct _XedDocumentPrivate XedDocumentPrivate;
typedef struct _XedDocumentClass XedDocumentClass;
struct _XedDocument
{
GtkSourceBuffer buffer;
/*< private > */
XedDocumentPrivate *priv;
};
struct _XedDocumentClass struct _XedDocumentClass
{ {
GtkSourceBufferClass parent_class; GtkSourceBufferClass parent_class;
@@ -77,8 +62,6 @@ struct _XedDocumentClass
void (* saved) (XedDocument *document); void (* saved) (XedDocument *document);
}; };
GType xed_document_get_type (void) G_GNUC_CONST;
XedDocument *xed_document_new (void); XedDocument *xed_document_new (void);
GtkSourceFile *xed_document_get_file (XedDocument *doc); GtkSourceFile *xed_document_get_file (XedDocument *doc);
@@ -138,24 +121,6 @@ void xed_document_set_search_context (XedDocument *doc,
GtkSourceSearchContext *xed_document_get_search_context (XedDocument *doc); GtkSourceSearchContext *xed_document_get_search_context (XedDocument *doc);
/* Non exported functions */
glong _xed_document_get_seconds_since_last_save_or_load (XedDocument *doc);
void _xed_document_apply_error_style (XedDocument *doc,
GtkTextIter *start,
GtkTextIter *end);
/* Note: this is a sync stat: use only on local files */
gboolean _xed_document_check_externally_modified (XedDocument *doc);
gboolean _xed_document_needs_saving (XedDocument *doc);
void _xed_document_set_create (XedDocument *doc,
gboolean create);
gboolean _xed_document_get_create (XedDocument *doc);
G_END_DECLS G_END_DECLS
#endif /* __XED_DOCUMENT_H__ */ #endif /* __XED_DOCUMENT_H__ */

View File

@@ -21,23 +21,15 @@
* Boston, MA 02110-1301, USA. * Boston, MA 02110-1301, USA.
*/ */
/*
* Modified by the xed Team, 2003-2007. See the AUTHORS file for a
* list of people on the xed Team.
* See the ChangeLog files for a list of changes.
*/
#include <time.h>
#include <stdlib.h>
#include <libxml/xmlreader.h> #include <libxml/xmlreader.h>
#include "xed-metadata-manager.h" #include "xed-metadata-manager.h"
#include "xed-debug.h" #include "xed-debug.h"
/* /*
#define XED_METADATA_VERBOSE_DEBUG 1 #define XED_METADATA_VERBOSE_DEBUG 1
*/ */
#define MAX_ITEMS 50 #define MAX_ITEMS 50
typedef struct _XedMetadataManager XedMetadataManager; typedef struct _XedMetadataManager XedMetadataManager;
@@ -45,21 +37,21 @@ typedef struct _Item Item;
struct _Item struct _Item
{ {
time_t atime; /* time of last access */ gint64 atime; /* time of last access in seconds since January 1, 1970 UTC */
GHashTable *values; GHashTable *values;
}; };
struct _XedMetadataManager struct _XedMetadataManager
{ {
gboolean values_loaded; /* It is true if the file gboolean values_loaded; /* It is true if the file
has been read */ has been read */
guint timeout_id; guint timeout_id;
GHashTable *items; GHashTable *items;
gchar *metadata_filename; gchar *metadata_filename;
}; };
static gboolean xed_metadata_manager_save (gpointer data); static gboolean xed_metadata_manager_save (gpointer data);
@@ -70,34 +62,34 @@ static XedMetadataManager *xed_metadata_manager = NULL;
static void static void
item_free (gpointer data) item_free (gpointer data)
{ {
Item *item; Item *item;
g_return_if_fail (data != NULL); g_return_if_fail (data != NULL);
#ifdef XED_METADATA_VERBOSE_DEBUG #ifdef XED_METADATA_VERBOSE_DEBUG
xed_debug (DEBUG_METADATA); xed_debug (DEBUG_METADATA);
#endif #endif
item = (Item *)data; item = (Item *)data;
if (item->values != NULL) if (item->values != NULL)
g_hash_table_destroy (item->values); g_hash_table_destroy (item->values);
g_free (item); g_free (item);
} }
static void static void
xed_metadata_manager_arm_timeout (void) xed_metadata_manager_arm_timeout (void)
{ {
if (xed_metadata_manager->timeout_id == 0) if (xed_metadata_manager->timeout_id == 0)
{ {
xed_metadata_manager->timeout_id = xed_metadata_manager->timeout_id =
g_timeout_add_seconds_full (G_PRIORITY_DEFAULT_IDLE, g_timeout_add_seconds_full (G_PRIORITY_DEFAULT_IDLE,
2, 2,
(GSourceFunc)xed_metadata_manager_save, (GSourceFunc)xed_metadata_manager_save,
NULL, NULL,
NULL); NULL);
} }
} }
/** /**
@@ -110,22 +102,22 @@ xed_metadata_manager_arm_timeout (void)
void void
xed_metadata_manager_init (const gchar *metadata_filename) xed_metadata_manager_init (const gchar *metadata_filename)
{ {
xed_debug (DEBUG_METADATA); xed_debug (DEBUG_METADATA);
if (xed_metadata_manager != NULL) if (xed_metadata_manager != NULL)
return; return;
xed_metadata_manager = g_new0 (XedMetadataManager, 1); xed_metadata_manager = g_new0 (XedMetadataManager, 1);
xed_metadata_manager->values_loaded = FALSE; xed_metadata_manager->values_loaded = FALSE;
xed_metadata_manager->items = xed_metadata_manager->items =
g_hash_table_new_full (g_str_hash, g_hash_table_new_full (g_str_hash,
g_str_equal, g_str_equal,
g_free, g_free,
item_free); item_free);
xed_metadata_manager->metadata_filename = g_strdup (metadata_filename); xed_metadata_manager->metadata_filename = g_strdup (metadata_filename);
return; return;
} }
@@ -139,154 +131,159 @@ xed_metadata_manager_init (const gchar *metadata_filename)
void void
xed_metadata_manager_shutdown (void) xed_metadata_manager_shutdown (void)
{ {
xed_debug (DEBUG_METADATA); xed_debug (DEBUG_METADATA);
if (xed_metadata_manager == NULL) if (xed_metadata_manager == NULL)
return; return;
if (xed_metadata_manager->timeout_id) if (xed_metadata_manager->timeout_id)
{ {
g_source_remove (xed_metadata_manager->timeout_id); g_source_remove (xed_metadata_manager->timeout_id);
xed_metadata_manager->timeout_id = 0; xed_metadata_manager->timeout_id = 0;
xed_metadata_manager_save (NULL); xed_metadata_manager_save (NULL);
} }
if (xed_metadata_manager->items != NULL) if (xed_metadata_manager->items != NULL)
g_hash_table_destroy (xed_metadata_manager->items); g_hash_table_destroy (xed_metadata_manager->items);
g_free (gedit_metadata_manager->metadata_filename); g_free (xed_metadata_manager->metadata_filename);
g_free (xed_metadata_manager); g_free (xed_metadata_manager);
xed_metadata_manager = NULL; xed_metadata_manager = NULL;
} }
static void static void
parseItem (xmlDocPtr doc, xmlNodePtr cur) parseItem (xmlDocPtr doc, xmlNodePtr cur)
{ {
Item *item; Item *item;
xmlChar *uri; xmlChar *uri;
xmlChar *atime; xmlChar *atime;
#ifdef XED_METADATA_VERBOSE_DEBUG #ifdef XED_METADATA_VERBOSE_DEBUG
xed_debug (DEBUG_METADATA); xed_debug (DEBUG_METADATA);
#endif #endif
if (xmlStrcmp (cur->name, (const xmlChar *)"document") != 0) if (xmlStrcmp (cur->name, (const xmlChar *)"document") != 0)
return; return;
uri = xmlGetProp (cur, (const xmlChar *)"uri"); uri = xmlGetProp (cur, (const xmlChar *)"uri");
if (uri == NULL) if (uri == NULL)
return; return;
atime = xmlGetProp (cur, (const xmlChar *)"atime"); atime = xmlGetProp (cur, (const xmlChar *)"atime");
if (atime == NULL) if (atime == NULL)
{ {
xmlFree (uri); xmlFree (uri);
return; return;
} }
item = g_new0 (Item, 1); item = g_new0 (Item, 1);
item->atime = g_ascii_strtoull ((char *)atime, NULL, 0); item->atime = g_ascii_strtoll ((char *)atime, NULL, 0);
item->values = g_hash_table_new_full (g_str_hash, item->values = g_hash_table_new_full (g_str_hash,
g_str_equal, g_str_equal,
g_free, g_free,
g_free); g_free);
cur = cur->xmlChildrenNode; cur = cur->xmlChildrenNode;
while (cur != NULL) while (cur != NULL)
{ {
if (xmlStrcmp (cur->name, (const xmlChar *)"entry") == 0) if (xmlStrcmp (cur->name, (const xmlChar *)"entry") == 0)
{ {
xmlChar *key; xmlChar *key;
xmlChar *value; xmlChar *value;
key = xmlGetProp (cur, (const xmlChar *)"key"); key = xmlGetProp (cur, (const xmlChar *)"key");
value = xmlGetProp (cur, (const xmlChar *)"value"); value = xmlGetProp (cur, (const xmlChar *)"value");
if ((key != NULL) && (value != NULL)) if ((key != NULL) && (value != NULL))
g_hash_table_insert (item->values, g_hash_table_insert (item->values,
g_strdup ((gchar *)key), g_strdup ((gchar *)key),
g_strdup ((gchar *)value)); g_strdup ((gchar *)value));
if (key != NULL) if (key != NULL)
xmlFree (key); xmlFree (key);
if (value != NULL) if (value != NULL)
xmlFree (value); xmlFree (value);
} }
cur = cur->next; cur = cur->next;
} }
g_hash_table_insert (xed_metadata_manager->items, g_hash_table_insert (xed_metadata_manager->items,
g_strdup ((gchar *)uri), g_strdup ((gchar *)uri),
item); item);
xmlFree (uri); xmlFree (uri);
xmlFree (atime); xmlFree (atime);
} }
static gboolean static gboolean
load_values (void) load_values (void)
{ {
xmlDocPtr doc; xmlDocPtr doc;
xmlNodePtr cur; xmlNodePtr cur;
xed_debug (DEBUG_METADATA); xed_debug (DEBUG_METADATA);
g_return_val_if_fail (xed_metadata_manager != NULL, FALSE); g_return_val_if_fail (xed_metadata_manager != NULL, FALSE);
g_return_val_if_fail (xed_metadata_manager->values_loaded == FALSE, FALSE); g_return_val_if_fail (xed_metadata_manager->values_loaded == FALSE, FALSE);
xed_metadata_manager->values_loaded = TRUE; xed_metadata_manager->values_loaded = TRUE;
xmlKeepBlanksDefault (0); xmlKeepBlanksDefault (0);
/* FIXME: file locking - Paolo */ /* FIXME: file locking - Paolo */
if ((xed_metadata_manager->metadata_filename == NULL) || if (xed_metadata_manager->metadata_filename == NULL)
(!g_file_test (xed_metadata_manager->metadata_filename, G_FILE_TEST_EXISTS))) {
{ return FALSE;
return FALSE; }
}
doc = xmlParseFile (xed_metadata_manager->metadata_filename); /* TODO: avoid races */
if (!g_file_test (xed_metadata_manager->metadata_filename, G_FILE_TEST_EXISTS))
{
return TRUE;
}
if (doc == NULL) doc = xmlParseFile (xed_metadata_manager->metadata_filename);
{
return FALSE;
}
cur = xmlDocGetRootElement (doc); if (doc == NULL)
if (cur == NULL) {
{ return FALSE;
g_message ("The metadata file '%s' is empty", g_path_get_basename (xed_metadata_manager->metadata_filename)); }
xmlFreeDoc (doc);
return FALSE; cur = xmlDocGetRootElement (doc);
} if (cur == NULL)
{
g_message ("The metadata file '%s' is empty", g_path_get_basename (xed_metadata_manager->metadata_filename));
xmlFreeDoc (doc);
if (xmlStrcmp (cur->name, (const xmlChar *) "metadata")) return TRUE;
{ }
g_message ("File '%s' is of the wrong type", g_path_get_basename (xed_metadata_manager->metadata_filename));
xmlFreeDoc (doc);
return FALSE; if (xmlStrcmp (cur->name, (const xmlChar *) "metadata"))
} {
g_message ("File '%s' is of the wrong type", g_path_get_basename (xed_metadata_manager->metadata_filename));
xmlFreeDoc (doc);
cur = xmlDocGetRootElement (doc); return FALSE;
cur = cur->xmlChildrenNode; }
while (cur != NULL) cur = xmlDocGetRootElement (doc);
{ cur = cur->xmlChildrenNode;
parseItem (doc, cur);
cur = cur->next; while (cur != NULL)
} {
parseItem (doc, cur);
xmlFreeDoc (doc); cur = cur->next;
}
return TRUE; xmlFreeDoc (doc);
return TRUE;
} }
/** /**
@@ -298,48 +295,51 @@ load_values (void)
*/ */
gchar * gchar *
xed_metadata_manager_get (GFile *location, xed_metadata_manager_get (GFile *location,
const gchar *key) const gchar *key)
{ {
Item *item; Item *item;
gchar *value; gchar *value;
gchar *uri; gchar *uri;
g_return_val_if_fail (G_IS_FILE (location), NULL); g_return_val_if_fail (G_IS_FILE (location), NULL);
g_return_val_if_fail (key != NULL, NULL); g_return_val_if_fail (key != NULL, NULL);
uri = g_file_get_uri (location); uri = g_file_get_uri (location);
xed_debug_message (DEBUG_METADATA, "URI: %s --- key: %s", uri, key ); xed_debug_message (DEBUG_METADATA, "URI: %s --- key: %s", uri, key );
if (!xed_metadata_manager->values_loaded) if (!xed_metadata_manager->values_loaded)
{ {
gboolean res; gboolean res;
res = load_values (); res = load_values ();
if (!res) if (!res)
return NULL; {
} g_free (uri);
return NULL;
}
}
item = (Item *)g_hash_table_lookup (xed_metadata_manager->items, item = (Item *)g_hash_table_lookup (xed_metadata_manager->items,
uri); uri);
g_free (uri); g_free (uri);
if (item == NULL) if (item == NULL)
return NULL; return NULL;
item->atime = time (NULL); item->atime = g_get_real_time () / 1000;
if (item->values == NULL) if (item->values == NULL)
return NULL; return NULL;
value = g_hash_table_lookup (item->values, key); value = g_hash_table_lookup (item->values, key);
if (value == NULL) if (value == NULL)
return NULL; return NULL;
else else
return g_strdup (value); return g_strdup (value);
} }
/** /**
@@ -352,219 +352,221 @@ xed_metadata_manager_get (GFile *location,
*/ */
void void
xed_metadata_manager_set (GFile *location, xed_metadata_manager_set (GFile *location,
const gchar *key, const gchar *key,
const gchar *value) const gchar *value)
{ {
Item *item; Item *item;
gchar *uri; gchar *uri;
g_return_if_fail (G_IS_FILE (location)); g_return_if_fail (G_IS_FILE (location));
g_return_if_fail (key != NULL); g_return_if_fail (key != NULL);
uri = g_file_get_uri (location); uri = g_file_get_uri (location);
xed_debug_message (DEBUG_METADATA, "URI: %s --- key: %s --- value: %s", uri, key, value); xed_debug_message (DEBUG_METADATA, "URI: %s --- key: %s --- value: %s", uri, key, value);
if (!xed_metadata_manager->values_loaded) if (!xed_metadata_manager->values_loaded)
{ {
gboolean res; gboolean ok;
res = load_values (); ok = load_values ();
if (!res) if (!ok)
return; {
} g_free (uri);
return;
}
}
item = (Item *)g_hash_table_lookup (xed_metadata_manager->items, item = (Item *)g_hash_table_lookup (xed_metadata_manager->items,
uri); uri);
if (item == NULL) if (item == NULL)
{ {
item = g_new0 (Item, 1); item = g_new0 (Item, 1);
g_hash_table_insert (xed_metadata_manager->items, g_hash_table_insert (xed_metadata_manager->items,
g_strdup (uri), g_strdup (uri),
item); item);
} }
if (item->values == NULL) if (item->values == NULL)
item->values = g_hash_table_new_full (g_str_hash, item->values = g_hash_table_new_full (g_str_hash,
g_str_equal, g_str_equal,
g_free, g_free,
g_free); g_free);
if (value != NULL) if (value != NULL)
g_hash_table_insert (item->values, g_hash_table_insert (item->values,
g_strdup (key), g_strdup (key),
g_strdup (value)); g_strdup (value));
else else
g_hash_table_remove (item->values, g_hash_table_remove (item->values,
key); key);
item->atime = time (NULL); item->atime = g_get_real_time () / 1000;
g_free (uri); g_free (uri);
xed_metadata_manager_arm_timeout (); xed_metadata_manager_arm_timeout ();
} }
static void static void
save_values (const gchar *key, const gchar *value, xmlNodePtr parent) save_values (const gchar *key, const gchar *value, xmlNodePtr parent)
{ {
xmlNodePtr xml_node; xmlNodePtr xml_node;
#ifdef XED_METADATA_VERBOSE_DEBUG #ifdef XED_METADATA_VERBOSE_DEBUG
xed_debug (DEBUG_METADATA); xed_debug (DEBUG_METADATA);
#endif #endif
g_return_if_fail (key != NULL); g_return_if_fail (key != NULL);
if (value == NULL) if (value == NULL)
return; return;
xml_node = xmlNewChild (parent, xml_node = xmlNewChild (parent,
NULL, NULL,
(const xmlChar *)"entry", (const xmlChar *)"entry",
NULL); NULL);
xmlSetProp (xml_node, xmlSetProp (xml_node,
(const xmlChar *)"key", (const xmlChar *)"key",
(const xmlChar *)key); (const xmlChar *)key);
xmlSetProp (xml_node, xmlSetProp (xml_node,
(const xmlChar *)"value", (const xmlChar *)"value",
(const xmlChar *)value); (const xmlChar *)value);
#ifdef XED_METADATA_VERBOSE_DEBUG #ifdef XED_METADATA_VERBOSE_DEBUG
xed_debug_message (DEBUG_METADATA, "entry: %s = %s", key, value); xed_debug_message (DEBUG_METADATA, "entry: %s = %s", key, value);
#endif #endif
} }
static void static void
save_item (const gchar *key, const gpointer *data, xmlNodePtr parent) save_item (const gchar *key, const gpointer *data, xmlNodePtr parent)
{ {
xmlNodePtr xml_node; xmlNodePtr xml_node;
const Item *item = (const Item *)data; const Item *item = (const Item *)data;
gchar *atime; gchar *atime;
#ifdef XED_METADATA_VERBOSE_DEBUG #ifdef XED_METADATA_VERBOSE_DEBUG
xed_debug (DEBUG_METADATA); xed_debug (DEBUG_METADATA);
#endif #endif
g_return_if_fail (key != NULL); g_return_if_fail (key != NULL);
if (item == NULL) if (item == NULL)
return; return;
xml_node = xmlNewChild (parent, NULL, (const xmlChar *)"document", NULL); xml_node = xmlNewChild (parent, NULL, (const xmlChar *)"document", NULL);
xmlSetProp (xml_node, (const xmlChar *)"uri", (const xmlChar *)key); xmlSetProp (xml_node, (const xmlChar *)"uri", (const xmlChar *)key);
#ifdef XED_METADATA_VERBOSE_DEBUG #ifdef XED_METADATA_VERBOSE_DEBUG
xed_debug_message (DEBUG_METADATA, "uri: %s", key); xed_debug_message (DEBUG_METADATA, "uri: %s", key);
#endif #endif
atime = g_strdup_printf ("%ld", item->atime); atime = g_strdup_printf ("%" G_GINT64_FORMAT, item->atime);
xmlSetProp (xml_node, (const xmlChar *)"atime", (const xmlChar *)atime); xmlSetProp (xml_node, (const xmlChar *)"atime", (const xmlChar *)atime);
#ifdef XED_METADATA_VERBOSE_DEBUG #ifdef XED_METADATA_VERBOSE_DEBUG
xed_debug_message (DEBUG_METADATA, "atime: %s", atime); xed_debug_message (DEBUG_METADATA, "atime: %s", atime);
#endif #endif
g_free (atime); g_free (atime);
g_hash_table_foreach (item->values, g_hash_table_foreach (item->values,
(GHFunc)save_values, (GHFunc)save_values,
xml_node); xml_node);
} }
static void static void
get_oldest (const gchar *key, const gpointer value, const gchar ** key_to_remove) get_oldest (const gchar *key, const gpointer value, const gchar ** key_to_remove)
{ {
const Item *item = (const Item *)value; const Item *item = (const Item *)value;
if (*key_to_remove == NULL) if (*key_to_remove == NULL)
{ {
*key_to_remove = key; *key_to_remove = key;
} }
else else
{ {
const Item *item_to_remove = const Item *item_to_remove =
g_hash_table_lookup (xed_metadata_manager->items, g_hash_table_lookup (xed_metadata_manager->items,
*key_to_remove); *key_to_remove);
g_return_if_fail (item_to_remove != NULL); g_return_if_fail (item_to_remove != NULL);
if (item->atime < item_to_remove->atime) if (item->atime < item_to_remove->atime)
{ {
*key_to_remove = key; *key_to_remove = key;
} }
} }
} }
static void static void
resize_items (void) resize_items (void)
{ {
while (g_hash_table_size (xed_metadata_manager->items) > MAX_ITEMS) while (g_hash_table_size (xed_metadata_manager->items) > MAX_ITEMS)
{ {
gpointer key_to_remove = NULL; gpointer key_to_remove = NULL;
g_hash_table_foreach (xed_metadata_manager->items, g_hash_table_foreach (xed_metadata_manager->items,
(GHFunc)get_oldest, (GHFunc)get_oldest,
&key_to_remove); &key_to_remove);
g_return_if_fail (key_to_remove != NULL); g_return_if_fail (key_to_remove != NULL);
g_hash_table_remove (xed_metadata_manager->items, g_hash_table_remove (xed_metadata_manager->items,
key_to_remove); key_to_remove);
} }
} }
static gboolean static gboolean
xed_metadata_manager_save (gpointer data) xed_metadata_manager_save (gpointer data)
{ {
xmlDocPtr doc; xmlDocPtr doc;
xmlNodePtr root; xmlNodePtr root;
xed_debug (DEBUG_METADATA); xed_debug (DEBUG_METADATA);
xed_metadata_manager->timeout_id = 0; xed_metadata_manager->timeout_id = 0;
resize_items (); resize_items ();
xmlIndentTreeOutput = TRUE; xmlIndentTreeOutput = TRUE;
doc = xmlNewDoc ((const xmlChar *)"1.0"); doc = xmlNewDoc ((const xmlChar *)"1.0");
if (doc == NULL) if (doc == NULL)
return TRUE; return TRUE;
/* Create metadata root */ /* Create metadata root */
root = xmlNewDocNode (doc, NULL, (const xmlChar *)"metadata", NULL); root = xmlNewDocNode (doc, NULL, (const xmlChar *)"metadata", NULL);
xmlDocSetRootElement (doc, root); xmlDocSetRootElement (doc, root);
g_hash_table_foreach (xed_metadata_manager->items, g_hash_table_foreach (xed_metadata_manager->items,
(GHFunc)save_item, (GHFunc)save_item,
root); root);
/* FIXME: lock file - Paolo */ /* FIXME: lock file - Paolo */
if (xed_metadata_manager->metadata_filename != NULL) if (xed_metadata_manager->metadata_filename != NULL)
{ {
gchar *cache_dir; gchar *cache_dir;
int res; int res;
/* make sure the cache dir exists */ /* make sure the cache dir exists */
cache_dir = g_path_get_dirname (xed_metadata_manager->metadata_filename); cache_dir = g_path_get_dirname (xed_metadata_manager->metadata_filename);
res = g_mkdir_with_parents (cache_dir, 0755); res = g_mkdir_with_parents (cache_dir, 0755);
if (res != -1) if (res != -1)
{ {
xmlSaveFormatFile (xed_metadata_manager->metadata_filename, doc, 1); xmlSaveFormatFile (xed_metadata_manager->metadata_filename, doc, 1);
} }
g_free (cache_dir); g_free (cache_dir);
} }
xmlFreeDoc (doc); xmlFreeDoc (doc);
xed_debug_message (DEBUG_METADATA, "DONE"); xed_debug_message (DEBUG_METADATA, "DONE");
return FALSE; return FALSE;
} }

View File

@@ -30,7 +30,7 @@
#ifndef __XED_METADATA_MANAGER_H__ #ifndef __XED_METADATA_MANAGER_H__
#define __XED_METADATA_MANAGER_H__ #define __XED_METADATA_MANAGER_H__
#include <glib.h> #include <gio/gio.h>
G_BEGIN_DECLS G_BEGIN_DECLS

View File

@@ -543,6 +543,8 @@ button_release_cb (XedNotebook *notebook,
GdkEventButton *event, GdkEventButton *event,
gpointer data) gpointer data)
{ {
gboolean ret_val = FALSE;
if (notebook->priv->drag_in_progress) if (notebook->priv->drag_in_progress)
{ {
gint cur_page_num; gint cur_page_num;
@@ -566,11 +568,23 @@ button_release_cb (XedNotebook *notebook,
} }
gtk_grab_remove (GTK_WIDGET (notebook)); gtk_grab_remove (GTK_WIDGET (notebook));
} }
else if ((event->type == GDK_BUTTON_RELEASE) && (event->button == 8))
{
gtk_notebook_prev_page (GTK_NOTEBOOK (notebook));
ret_val = TRUE;
}
else if ((event->type == GDK_BUTTON_RELEASE) && (event->button == 9))
{
gtk_notebook_next_page (GTK_NOTEBOOK (notebook));
ret_val = TRUE;
}
/* This must be called even if a drag isn't happening */ /* This must be called even if a drag isn't happening */
drag_stop (notebook); drag_stop (notebook);
return FALSE; return ret_val;
} }
static gboolean static gboolean
@@ -638,13 +652,13 @@ notebook_scroll_event_cb (XedNotebook *notebook,
switch (event->direction) switch (event->direction)
{ {
case GDK_SCROLL_DOWN: case GDK_SCROLL_DOWN:
case GDK_SCROLL_RIGHT:
gtk_notebook_next_page (GTK_NOTEBOOK (notebook));
break;
case GDK_SCROLL_UP:
case GDK_SCROLL_LEFT: case GDK_SCROLL_LEFT:
gtk_notebook_prev_page (GTK_NOTEBOOK (notebook)); gtk_notebook_prev_page (GTK_NOTEBOOK (notebook));
break; break;
case GDK_SCROLL_UP:
case GDK_SCROLL_RIGHT:
gtk_notebook_next_page (GTK_NOTEBOOK (notebook));
break;
default: default:
break; break;
} }
@@ -714,11 +728,9 @@ xed_notebook_init (XedNotebook *notebook)
notebook->priv->tab_scrolling_enabled = g_settings_get_boolean (notebook->priv->ui_settings, "enable-tab-scrolling"); notebook->priv->tab_scrolling_enabled = g_settings_get_boolean (notebook->priv->ui_settings, "enable-tab-scrolling");
gtk_notebook_set_scrollable (GTK_NOTEBOOK (notebook), TRUE); gtk_notebook_set_scrollable (GTK_NOTEBOOK (notebook), TRUE);
gtk_notebook_set_show_border (GTK_NOTEBOOK (notebook), FALSE);
#if GTK_CHECK_VERSION (3, 20, 0)
gtk_notebook_set_show_border (GTK_NOTEBOOK (notebook), FALSE);
#endif
gtk_notebook_set_show_tabs (GTK_NOTEBOOK (notebook), FALSE); gtk_notebook_set_show_tabs (GTK_NOTEBOOK (notebook), FALSE);
gtk_container_set_border_width (GTK_CONTAINER (notebook), 0);
g_signal_connect (notebook, "button-press-event", g_signal_connect (notebook, "button-press-event",
(GCallback)button_press_cb, NULL); (GCallback)button_press_cb, NULL);

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,7 @@
* xed-preferences-dialog.c * xed-preferences-dialog.c
* This file is part of xed * This file is part of xed
* *
* Copyright (C) 2001-2005 Paolo Maggi * Copyright (C) 2001-2005 Paolo Maggi
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -17,14 +17,14 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, * Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA. * Boston, MA 02110-1301, USA.
*/ */
/* /*
* Modified by the xed Team, 2003. See the AUTHORS file for a * Modified by the xed Team, 2003. See the AUTHORS file for a
* list of people on the xed Team. * list of people on the xed Team.
* See the ChangeLog files for a list of changes. * See the ChangeLog files for a list of changes.
* *
* $Id$ * $Id$
*/ */
@@ -32,54 +32,13 @@
#ifndef __XED_PREFERENCES_DIALOG_H__ #ifndef __XED_PREFERENCES_DIALOG_H__
#define __XED_PREFERENCES_DIALOG_H__ #define __XED_PREFERENCES_DIALOG_H__
#include <libxapp/xapp-preferences-window.h>
#include "xed-window.h" #include "xed-window.h"
G_BEGIN_DECLS G_BEGIN_DECLS
/* void xed_show_preferences_dialog (XedWindow *parent);
* Type checking and casting macros
*/
#define XED_TYPE_PREFERENCES_DIALOG (xed_preferences_dialog_get_type())
#define XED_PREFERENCES_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XED_TYPE_PREFERENCES_DIALOG, XedPreferencesDialog))
#define XED_PREFERENCES_DIALOG_CONST(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), XED_TYPE_PREFERENCES_DIALOG, XedPreferencesDialog const))
#define XED_PREFERENCES_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), XED_TYPE_PREFERENCES_DIALOG, XedPreferencesDialogClass))
#define XED_IS_PREFERENCES_DIALOG(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), XED_TYPE_PREFERENCES_DIALOG))
#define XED_IS_PREFERENCES_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), XED_TYPE_PREFERENCES_DIALOG))
#define XED_PREFERENCES_DIALOG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), XED_TYPE_PREFERENCES_DIALOG, XedPreferencesDialogClass))
/* Private structure type */
typedef struct _XedPreferencesDialogPrivate XedPreferencesDialogPrivate;
/*
* Main object structure
*/
typedef struct _XedPreferencesDialog XedPreferencesDialog;
struct _XedPreferencesDialog
{
GtkDialog dialog;
/*< private > */
XedPreferencesDialogPrivate *priv;
};
/*
* Class definition
*/
typedef struct _XedPreferencesDialogClass XedPreferencesDialogClass;
struct _XedPreferencesDialogClass
{
GtkDialogClass parent_class;
};
/*
* Public methods
*/
GType xed_preferences_dialog_get_type (void) G_GNUC_CONST;
void xed_show_preferences_dialog (XedWindow *parent);
G_END_DECLS G_END_DECLS

View File

@@ -659,11 +659,8 @@ xed_searchbar_init (XedSearchbar *searchbar)
{ {
GtkWidget *content; GtkWidget *content;
GtkSizeGroup *size_group; GtkSizeGroup *size_group;
GtkStyleContext *context;
GtkCssProvider *provider;
GtkBuilder *builder; GtkBuilder *builder;
gchar *root_objects[] = { "searchbar_content", NULL }; gchar *root_objects[] = { "searchbar_content", NULL };
const gchar *data = ".button {padding: 0;}";
searchbar->priv = XED_SEARCHBAR_GET_PRIVATE (searchbar); searchbar->priv = XED_SEARCHBAR_GET_PRIVATE (searchbar);
@@ -709,10 +706,7 @@ xed_searchbar_init (XedSearchbar *searchbar)
gtk_label_set_mnemonic_widget (GTK_LABEL (searchbar->priv->search_label), searchbar->priv->search_entry); gtk_label_set_mnemonic_widget (GTK_LABEL (searchbar->priv->search_label), searchbar->priv->search_entry);
gtk_label_set_mnemonic_widget (GTK_LABEL (searchbar->priv->replace_label), searchbar->priv->replace_entry); gtk_label_set_mnemonic_widget (GTK_LABEL (searchbar->priv->replace_label), searchbar->priv->replace_entry);
provider = gtk_css_provider_new (); gtk_style_context_add_class (gtk_widget_get_style_context (searchbar->priv->close_button), "close-button");
context = gtk_widget_get_style_context (searchbar->priv->close_button);
gtk_css_provider_load_from_data (provider, data, -1, NULL);
gtk_style_context_add_provider (context, GTK_STYLE_PROVIDER (provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); size_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
gtk_size_group_add_widget (size_group, GTK_WIDGET (searchbar->priv->find_button)); gtk_size_group_add_widget (size_group, GTK_WIDGET (searchbar->priv->find_button));

View File

@@ -282,26 +282,6 @@ on_auto_save_interval_changed (GSettings *settings,
g_list_free (docs); g_list_free (docs);
} }
static void
on_wrap_mode_changed (GSettings *settings,
const gchar *key,
XedSettings *xs)
{
GtkWrapMode wrap_mode;
GList *views, *l;
wrap_mode = g_settings_get_enum (settings, key);
views = xed_app_get_views (XED_APP (g_application_get_default ()));
for (l = views; l != NULL; l = g_list_next (l))
{
gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (l->data), wrap_mode);
}
g_list_free (views);
}
static void static void
on_syntax_highlighting_changed (GSettings *settings, on_syntax_highlighting_changed (GSettings *settings,
const gchar *key, const gchar *key,

View File

@@ -141,18 +141,14 @@ xed_status_combo_box_changed (XedStatusComboBox *combo,
static void static void
xed_status_combo_box_class_init (XedStatusComboBoxClass *klass) xed_status_combo_box_class_init (XedStatusComboBoxClass *klass)
{ {
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
static const gchar style[] = static const gchar style[] =
"* {\n" "* {\n"
"-GtkButton-default-border : 0;\n"
"-GtkButton-default-outside-border : 0;\n"
"-GtkButton-inner-border: 0;\n"
"-GtkWidget-focus-line-width : 0;\n"
"-GtkWidget-focus-padding : 0;\n"
"padding: 2px;\n" "padding: 2px;\n"
"}"; "}";
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
object_class->finalize = xed_status_combo_box_finalize; object_class->finalize = xed_status_combo_box_finalize;
object_class->get_property = xed_status_combo_box_get_property; object_class->get_property = xed_status_combo_box_get_property;
object_class->set_property = xed_status_combo_box_set_property; object_class->set_property = xed_status_combo_box_set_property;

View File

@@ -43,6 +43,8 @@
#include "xed-print-preview.h" #include "xed-print-preview.h"
#include "xed-progress-info-bar.h" #include "xed-progress-info-bar.h"
#include "xed-debug.h" #include "xed-debug.h"
#include "xed-document.h"
#include "xed-document-private.h"
#include "xed-enum-types.h" #include "xed-enum-types.h"
#include "xed-settings.h" #include "xed-settings.h"
#include "xed-view-frame.h" #include "xed-view-frame.h"
@@ -1112,39 +1114,39 @@ view_focused_in (GtkWidget *widget,
XedTab *tab) XedTab *tab)
{ {
XedDocument *doc; XedDocument *doc;
GtkSourceFile *file;
g_return_val_if_fail (XED_IS_TAB (tab), FALSE); g_return_val_if_fail (XED_IS_TAB (tab), FALSE);
/* we try to detect file changes only in the normal state */ /* we try to detect file changes only in the normal state */
if (tab->priv->state != XED_TAB_STATE_NORMAL) if (tab->priv->state != XED_TAB_STATE_NORMAL)
{ {
return FALSE; return GDK_EVENT_PROPAGATE;
} }
/* we already asked, don't bug the user again */ /* we already asked, don't bug the user again */
if (!tab->priv->ask_if_externally_modified) if (!tab->priv->ask_if_externally_modified)
{ {
return FALSE; return GDK_EVENT_PROPAGATE;
} }
doc = xed_tab_get_document (tab); doc = xed_tab_get_document (tab);
file = xed_document_get_file (doc);
/* If file was never saved or is remote we do not check */ /* If file was never saved or is remote we do not check */
if (!xed_document_is_local (doc)) if (gtk_source_file_is_local (file))
{ {
return FALSE; gtk_source_file_check_file_on_disk (file);
if (gtk_source_file_is_externally_modified (file))
{
xed_tab_set_state (tab, XED_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION);
display_externally_modified_notification (tab);
}
} }
if (_xed_document_check_externally_modified (doc)) return GDK_EVENT_PROPAGATE;
{
xed_tab_set_state (tab, XED_TAB_STATE_EXTERNALLY_MODIFIED_NOTIFICATION);
display_externally_modified_notification (tab);
return FALSE;
}
return FALSE;
} }
static void static void

View File

@@ -67,6 +67,8 @@ static const GtkActionEntry xed_always_sensitive_menu_entries[] =
N_("Open the xed manual"), G_CALLBACK (_xed_cmd_help_contents) }, N_("Open the xed manual"), G_CALLBACK (_xed_cmd_help_contents) },
{ "HelpAbout", "help-about-symbolic", N_("_About"), NULL, { "HelpAbout", "help-about-symbolic", N_("_About"), NULL,
N_("About this application"), G_CALLBACK (_xed_cmd_help_about) }, N_("About this application"), G_CALLBACK (_xed_cmd_help_about) },
{ "HelpShortcuts", NULL, N_("_Keyboard Shortcuts"), NULL,
N_("Show the keyboard shortcuts dialog"), G_CALLBACK (_xed_cmd_help_keyboard_shortcuts) },
/* Fullscreen toolbar */ /* Fullscreen toolbar */
{ "LeaveFullscreen", "view-restore-symbolic", NULL, { "LeaveFullscreen", "view-restore-symbolic", NULL,

View File

@@ -904,6 +904,8 @@ xed_utils_is_valid_location (GFile *location)
return is_valid; return is_valid;
} }
static GtkWidget *handle_builder_error (const gchar *message, ...) G_GNUC_PRINTF (1, 2);
static GtkWidget * static GtkWidget *
handle_builder_error (const gchar *message, handle_builder_error (const gchar *message,
...) ...)

View File

@@ -7,7 +7,6 @@ G_DEFINE_TYPE (XedViewGutterRenderer, xed_view_gutter_renderer, GTK_SOURCE_TYPE_
static void static void
xed_view_gutter_renderer_class_init (XedViewGutterRendererClass *klass) xed_view_gutter_renderer_class_init (XedViewGutterRendererClass *klass)
{ {
GtkSourceGutterRendererClass *renderer_class = GTK_SOURCE_GUTTER_RENDERER_CLASS (klass);
} }
static void static void

View File

@@ -607,8 +607,36 @@ xed_view_class_init (XedViewClass *klass)
binding_set = gtk_binding_set_by_class (klass); binding_set = gtk_binding_set_by_class (klass);
gtk_binding_entry_add_signal (binding_set, GDK_KEY_d, GDK_CONTROL_MASK, "delete_from_cursor", 2, G_TYPE_ENUM, gtk_binding_entry_add_signal (binding_set,
GTK_DELETE_PARAGRAPHS, G_TYPE_INT, 1); GDK_KEY_d,
GDK_CONTROL_MASK,
"delete_from_cursor", 2,
G_TYPE_ENUM, GTK_DELETE_PARAGRAPHS,
G_TYPE_INT, 1);
gtk_binding_entry_add_signal (binding_set,
GDK_KEY_u,
GDK_CONTROL_MASK,
"change_case", 1,
G_TYPE_ENUM, GTK_SOURCE_CHANGE_CASE_UPPER);
gtk_binding_entry_add_signal (binding_set,
GDK_KEY_l,
GDK_CONTROL_MASK,
"change_case", 1,
G_TYPE_ENUM, GTK_SOURCE_CHANGE_CASE_LOWER);
gtk_binding_entry_add_signal (binding_set,
GDK_KEY_asciitilde,
GDK_CONTROL_MASK,
"change_case", 1,
G_TYPE_ENUM, GTK_SOURCE_CHANGE_CASE_TOGGLE);
gtk_binding_entry_add_signal (binding_set,
GDK_KEY_t,
GDK_CONTROL_MASK,
"change_case", 1,
G_TYPE_ENUM, GTK_SOURCE_CHANGE_CASE_TITLE);
} }
/** /**

View File

@@ -66,9 +66,9 @@ struct _XedWindowPrivate
/* Widgets for fullscreen mode */ /* Widgets for fullscreen mode */
GtkWidget *fullscreen_controls; GtkWidget *fullscreen_controls;
GtkWidget *fullscreen_controls_container; GtkWidget *fullscreen_overlay;
guint fullscreen_animation_timeout_id; GtkWidget *fullscreen_eventbox;
gboolean fullscreen_animation_enter; GtkWidget *fullscreen_revealer;
/* statusbar and context ids for statusbar messages */ /* statusbar and context ids for statusbar messages */
GtkWidget *statusbar; GtkWidget *statusbar;

View File

@@ -20,6 +20,8 @@
#include "xed-utils.h" #include "xed-utils.h"
#include "xed-commands.h" #include "xed-commands.h"
#include "xed-debug.h" #include "xed-debug.h"
#include "xed-document.h"
#include "xed-document-private.h"
#include "xed-panel.h" #include "xed-panel.h"
#include "xed-documents-panel.h" #include "xed-documents-panel.h"
#include "xed-plugins-engine.h" #include "xed-plugins-engine.h"
@@ -33,8 +35,6 @@
#define TAB_WIDTH_DATA "XedWindowTabWidthData" #define TAB_WIDTH_DATA "XedWindowTabWidthData"
#define LANGUAGE_DATA "XedWindowLanguageData" #define LANGUAGE_DATA "XedWindowLanguageData"
#define FULLSCREEN_ANIMATION_SPEED 4
#define XED_WINDOW_DEFAULT_WIDTH 650 #define XED_WINDOW_DEFAULT_WIDTH 650
#define XED_WINDOW_DEFAULT_HEIGHT 500 #define XED_WINDOW_DEFAULT_HEIGHT 500
@@ -205,18 +205,6 @@ xed_window_dispose (GObject *object)
window->priv->dispose_has_run = TRUE; window->priv->dispose_has_run = TRUE;
} }
if (window->priv->fullscreen_animation_timeout_id != 0)
{
g_source_remove (window->priv->fullscreen_animation_timeout_id);
window->priv->fullscreen_animation_timeout_id = 0;
}
if (window->priv->fullscreen_controls != NULL)
{
gtk_widget_destroy (window->priv->fullscreen_controls);
window->priv->fullscreen_controls = NULL;
}
if (window->priv->recents_handler_id != 0) if (window->priv->recents_handler_id != 0)
{ {
GtkRecentManager *recent_manager; GtkRecentManager *recent_manager;
@@ -509,7 +497,7 @@ received_clipboard_contents (GtkClipboard *clipboard,
GtkSelectionData *selection_data, GtkSelectionData *selection_data,
XedWindow *window) XedWindow *window)
{ {
gboolean sens; gboolean sensitive;
GtkAction *action; GtkAction *action;
/* getting clipboard contents is async, so we need to /* getting clipboard contents is async, so we need to
@@ -519,17 +507,23 @@ received_clipboard_contents (GtkClipboard *clipboard,
{ {
XedTabState state; XedTabState state;
gboolean state_normal; gboolean state_normal;
state = xed_tab_get_state (window->priv->active_tab); state = xed_tab_get_state (window->priv->active_tab);
state_normal = (state == XED_TAB_STATE_NORMAL); state_normal = (state == XED_TAB_STATE_NORMAL);
sens = state_normal && gtk_selection_data_targets_include_text (selection_data); sensitive = state_normal && gtk_selection_data_targets_include_text (selection_data);
} }
else else
{ {
sens = FALSE; sensitive = FALSE;
} }
action = gtk_action_group_get_action (window->priv->action_group, "EditPaste"); action = gtk_action_group_get_action (window->priv->action_group, "EditPaste");
gtk_action_set_sensitive (action, sens);
if (action != NULL)
{
gtk_action_set_sensitive (action, sensitive);
}
g_object_unref (window); g_object_unref (window);
} }
@@ -1209,7 +1203,6 @@ create_menu_bar_and_toolbar (XedWindow *window,
GtkUIManager *manager; GtkUIManager *manager;
GtkRecentManager *recent_manager; GtkRecentManager *recent_manager;
GError *error = NULL; GError *error = NULL;
gchar *ui_file;
GtkWidget *tool_item; GtkWidget *tool_item;
GtkWidget *tool_box; GtkWidget *tool_box;
GtkWidget *box; GtkWidget *box;
@@ -2182,7 +2175,7 @@ show_overview_map_changed (GObject *object,
map_frame = GTK_FRAME (object); map_frame = GTK_FRAME (object);
action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, "ViewOverviewMap"); action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, "ViewOverviewMap");
if (gtk_widget_get_visible (map_frame)) if (gtk_widget_get_visible (GTK_WIDGET (map_frame)))
{ {
overveiw_map_visible = TRUE; overveiw_map_visible = TRUE;
} }
@@ -2235,7 +2228,7 @@ notebook_switch_page (GtkNotebook *book,
if (window->priv->show_overview_map_id) if (window->priv->show_overview_map_id)
{ {
g_signal_handler_disconnect (xed_view_frame_get_map_frame (_xed_tab_get_view_frame (window->priv->active_tab)), window->priv->show_overview_map_id); g_signal_handler_disconnect (xed_view_frame_get_map_frame (XED_VIEW_FRAME (_xed_tab_get_view_frame (window->priv->active_tab))), window->priv->show_overview_map_id);
window->priv->show_overview_map_id = 0; window->priv->show_overview_map_id = 0;
} }
} }
@@ -2265,7 +2258,7 @@ notebook_switch_page (GtkNotebook *book,
update_languages_menu (window); update_languages_menu (window);
view = xed_tab_get_view (tab); view = xed_tab_get_view (tab);
map_frame = xed_view_frame_get_map_frame (_xed_tab_get_view_frame (tab)); map_frame = xed_view_frame_get_map_frame (XED_VIEW_FRAME (_xed_tab_get_view_frame (tab)));
/* sync the statusbar */ /* sync the statusbar */
update_cursor_position_statusbar (GTK_TEXT_BUFFER (xed_tab_get_document (tab)), window); update_cursor_position_statusbar (GTK_TEXT_BUFFER (xed_tab_get_document (tab)), window);
@@ -2372,15 +2365,6 @@ set_sensitivity_according_to_window_state (XedWindow *window)
} }
} }
static void
update_tab_autosave (GtkWidget *widget,
gpointer data)
{
XedTab *tab = XED_TAB(widget);
gboolean *enabled = (gboolean *) data;
xed_tab_set_auto_save_enabled (tab, *enabled);
}
static void static void
analyze_tab_state (XedTab *tab, analyze_tab_state (XedTab *tab,
XedWindow *window) XedWindow *window)
@@ -2456,7 +2440,7 @@ update_can_close (XedWindow *window)
GList *l; GList *l;
gboolean can_close = TRUE; gboolean can_close = TRUE;
tabs = xed_notebook_get_all_tabs (priv->notebook); tabs = xed_notebook_get_all_tabs (XED_NOTEBOOK (priv->notebook));
for (l = tabs; l != NULL; l = g_list_next (l)) for (l = tabs; l != NULL; l = g_list_next (l))
{ {
@@ -2634,143 +2618,22 @@ drop_uris_cb (GtkWidget *widget,
load_uris_from_drop (window, uri_list); load_uris_from_drop (window, uri_list);
} }
static void
fullscreen_controls_show (XedWindow *window)
{
GdkScreen *screen;
GdkRectangle fs_rect;
gint min_h, nat_h;
screen = gtk_window_get_screen (GTK_WINDOW (window));
gdk_screen_get_monitor_geometry (
screen, gdk_screen_get_monitor_at_window (screen, gtk_widget_get_window (GTK_WIDGET(window))),
&fs_rect);
gtk_widget_get_preferred_height (window->priv->fullscreen_controls_container, &min_h, &nat_h);
gtk_window_resize (GTK_WINDOW (window->priv->fullscreen_controls), fs_rect.width, nat_h);
gtk_window_move (GTK_WINDOW (window->priv->fullscreen_controls), fs_rect.x, fs_rect.y - nat_h + 1);
gtk_widget_show_all (window->priv->fullscreen_controls);
}
static gboolean static gboolean
run_fullscreen_animation (gpointer data) on_fullscreen_controls_enter_notify_event (GtkWidget *widget,
{
XedWindow *window = XED_WINDOW(data);
GdkScreen *screen;
GdkRectangle fs_rect;
gint x, y;
screen = gtk_window_get_screen (GTK_WINDOW(window));
gdk_screen_get_monitor_geometry (screen,
gdk_screen_get_monitor_at_window (screen, gtk_widget_get_window (GTK_WIDGET(window))),
&fs_rect);
gtk_window_get_position (GTK_WINDOW(window->priv->fullscreen_controls), &x, &y);
if (window->priv->fullscreen_animation_enter)
{
if (y == fs_rect.y)
{
window->priv->fullscreen_animation_timeout_id = 0;
return FALSE;
}
else
{
gtk_window_move (GTK_WINDOW(window->priv->fullscreen_controls), x, y + 1);
return TRUE;
}
}
else
{
gint w, h;
gtk_window_get_size (GTK_WINDOW(window->priv->fullscreen_controls), &w, &h);
if (y == fs_rect.y - h + 1)
{
window->priv->fullscreen_animation_timeout_id = 0;
return FALSE;
}
else
{
gtk_window_move (GTK_WINDOW(window->priv->fullscreen_controls), x, y - 1);
return TRUE;
}
}
}
static void
show_hide_fullscreen_toolbar (XedWindow *window,
gboolean show,
gint height)
{
GtkSettings *settings;
gboolean enable_animations;
settings = gtk_widget_get_settings (GTK_WIDGET(window));
g_object_get (G_OBJECT(settings), "gtk-enable-animations", &enable_animations, NULL);
if (enable_animations)
{
window->priv->fullscreen_animation_enter = show;
if (window->priv->fullscreen_animation_timeout_id == 0)
{
window->priv->fullscreen_animation_timeout_id = g_timeout_add (FULLSCREEN_ANIMATION_SPEED,
(GSourceFunc) run_fullscreen_animation, window);
}
}
else
{
GdkRectangle fs_rect;
GdkScreen *screen;
screen = gtk_window_get_screen (GTK_WINDOW(window));
gdk_screen_get_monitor_geometry (screen,
gdk_screen_get_monitor_at_window (screen, gtk_widget_get_window (GTK_WIDGET(window))),
&fs_rect);
if (show)
{
gtk_window_move (GTK_WINDOW(window->priv->fullscreen_controls), fs_rect.x, fs_rect.y);
}
else
{
gtk_window_move (GTK_WINDOW(window->priv->fullscreen_controls), fs_rect.x, fs_rect.y - height + 1);
}
}
}
static gboolean
on_fullscreen_controls_enter_notify_event (GtkWidget *widget,
GdkEventCrossing *event, GdkEventCrossing *event,
XedWindow *window) XedWindow *window)
{ {
show_hide_fullscreen_toolbar (window, TRUE, 0); gtk_revealer_set_reveal_child (GTK_REVEALER (window->priv->fullscreen_controls), TRUE);
return FALSE; return FALSE;
} }
static gboolean static gboolean
on_fullscreen_controls_leave_notify_event (GtkWidget *widget, on_fullscreen_controls_leave_notify_event (GtkWidget *widget,
GdkEventCrossing *event, GdkEventCrossing *event,
XedWindow *window) XedWindow *window)
{ {
GdkDisplay *display; gtk_revealer_set_reveal_child (GTK_REVEALER (window->priv->fullscreen_controls), FALSE);
GdkScreen *screen;
gint w, h;
gint x, y;
display = gdk_display_get_default ();
screen = gtk_window_get_screen (GTK_WINDOW(window));
gtk_window_get_size (GTK_WINDOW(window->priv->fullscreen_controls), &w, &h);
gdk_display_get_pointer (display, &screen, &x, &y, NULL);
/* gtk seems to emit leave notify when clicking on tool items,
* work around it by checking the coordinates
*/
if (y >= h)
{
show_hide_fullscreen_toolbar (window, FALSE, h);
}
return FALSE; return FALSE;
} }
@@ -2781,6 +2644,9 @@ fullscreen_controls_build (XedWindow *window)
XedWindowPrivate *priv = window->priv; XedWindowPrivate *priv = window->priv;
GtkAction *action; GtkAction *action;
GtkWidget *box; GtkWidget *box;
GtkWidget *toolbar;
GtkWidget *toolitem;
GtkWidget *toolbox;
GtkWidget *fullscreen_btn; GtkWidget *fullscreen_btn;
GtkWidget *separator; GtkWidget *separator;
GtkWidget *button; GtkWidget *button;
@@ -2790,17 +2656,23 @@ fullscreen_controls_build (XedWindow *window)
return; return;
} }
priv->fullscreen_controls = gtk_window_new (GTK_WINDOW_POPUP); priv->fullscreen_controls = gtk_revealer_new ();
gtk_widget_set_valign (priv->fullscreen_controls, GTK_ALIGN_START);
gtk_container_add (GTK_CONTAINER (priv->fullscreen_eventbox), priv->fullscreen_controls);
gtk_window_set_transient_for (GTK_WINDOW (priv->fullscreen_controls), GTK_WINDOW (&window->window)); toolbar = gtk_toolbar_new ();
toolitem = gtk_tool_item_new ();
gtk_tool_item_set_expand (GTK_TOOL_ITEM (toolitem), TRUE);
gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (toolitem), 0);
window->priv->fullscreen_controls_container = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); toolbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_container_set_border_width (GTK_CONTAINER (window->priv->fullscreen_controls_container), 6); gtk_style_context_add_class (gtk_widget_get_style_context (toolbar), "primary-toolbar");
gtk_container_add (GTK_CONTAINER (priv->fullscreen_controls), window->priv->fullscreen_controls_container); gtk_container_add (GTK_CONTAINER (toolitem), toolbox);
gtk_container_add (GTK_CONTAINER (priv->fullscreen_controls), toolbar);
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
gtk_widget_set_vexpand (box, FALSE); gtk_widget_set_vexpand (box, FALSE);
gtk_box_pack_start (GTK_BOX (window->priv->fullscreen_controls_container), box, FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (toolbox), box, FALSE, FALSE, 0);
action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, "FileNew"); action = gtk_action_group_get_action (window->priv->always_sensitive_action_group, "FileNew");
button = create_toolbar_button (action); button = create_toolbar_button (action);
@@ -2856,13 +2728,15 @@ fullscreen_controls_build (XedWindow *window)
fullscreen_btn = create_toolbar_button (action); fullscreen_btn = create_toolbar_button (action);
gtk_box_pack_end (GTK_BOX (box), fullscreen_btn, FALSE, FALSE, 0); gtk_box_pack_end (GTK_BOX (box), fullscreen_btn, FALSE, FALSE, 0);
gtk_widget_show_all (window->priv->fullscreen_controls_container); gtk_widget_show_all (toolbox);
g_signal_connect(priv->fullscreen_controls, "enter-notify-event", g_signal_connect (priv->fullscreen_eventbox, "enter-notify-event",
G_CALLBACK (on_fullscreen_controls_enter_notify_event), window); G_CALLBACK (on_fullscreen_controls_enter_notify_event), window);
g_signal_connect(priv->fullscreen_controls, "leave-notify-event", g_signal_connect (priv->fullscreen_eventbox, "leave-notify-event",
G_CALLBACK (on_fullscreen_controls_leave_notify_event), window); G_CALLBACK (on_fullscreen_controls_leave_notify_event), window);
gtk_widget_set_size_request (priv->fullscreen_eventbox, -1, 1);
} }
static void static void
@@ -3069,7 +2943,7 @@ notebook_tab_removed (XedNotebook *notebook,
--window->priv->num_tabs; --window->priv->num_tabs;
view = xed_tab_get_view (tab); view = xed_tab_get_view (tab);
frame = _xed_tab_get_view_frame (tab); frame = XED_VIEW_FRAME (_xed_tab_get_view_frame (tab));
doc = xed_tab_get_document (tab); doc = xed_tab_get_document (tab);
g_signal_handlers_disconnect_by_func (tab, G_CALLBACK (sync_name), window); g_signal_handlers_disconnect_by_func (tab, G_CALLBACK (sync_name), window);
@@ -3272,7 +3146,7 @@ side_panel_size_allocate (GtkWidget *widget,
GtkAllocation *allocation, GtkAllocation *allocation,
XedWindow *window) XedWindow *window)
{ {
if (!xed_paned_get_is_animating (window->priv->hpaned)) if (!xed_paned_get_is_animating (XED_PANED (window->priv->hpaned)))
{ {
window->priv->side_panel_size = allocation->width; window->priv->side_panel_size = allocation->width;
} }
@@ -3283,7 +3157,7 @@ bottom_panel_size_allocate (GtkWidget *widget,
GtkAllocation *allocation, GtkAllocation *allocation,
XedWindow *window) XedWindow *window)
{ {
if (!xed_paned_get_is_animating (window->priv->vpaned)) if (!xed_paned_get_is_animating (XED_PANED (window->priv->vpaned)))
{ {
window->priv->bottom_panel_size = allocation->height; window->priv->bottom_panel_size = allocation->height;
} }
@@ -3404,7 +3278,7 @@ bottom_panel_item_removed (XedPanel *panel,
{ {
GtkAction *action; GtkAction *action;
xed_paned_close (window->priv->vpaned, 2); xed_paned_close (XED_PANED (window->priv->vpaned), 2);
gtk_revealer_set_reveal_child (GTK_REVEALER (window->priv->bottom_pane_button_revealer), FALSE); gtk_revealer_set_reveal_child (GTK_REVEALER (window->priv->bottom_pane_button_revealer), FALSE);
action = gtk_action_group_get_action (window->priv->panes_action_group, "ViewBottomPane"); action = gtk_action_group_get_action (window->priv->panes_action_group, "ViewBottomPane");
gtk_action_set_sensitive (action, FALSE); gtk_action_set_sensitive (action, FALSE);
@@ -3529,14 +3403,7 @@ check_window_is_active (XedWindow *window,
{ {
if (window->priv->window_state & GDK_WINDOW_STATE_FULLSCREEN) if (window->priv->window_state & GDK_WINDOW_STATE_FULLSCREEN)
{ {
if (gtk_window_is_active (GTK_WINDOW(window))) gtk_widget_set_visible (window->priv->fullscreen_eventbox, gtk_window_is_active (GTK_WINDOW (window)));
{
gtk_widget_show (window->priv->fullscreen_controls);
}
else
{
gtk_widget_hide (window->priv->fullscreen_controls);
}
} }
} }
@@ -3604,7 +3471,6 @@ xed_window_init (XedWindow *window)
window->priv->inhibition_cookie = 0; window->priv->inhibition_cookie = 0;
window->priv->dispose_has_run = FALSE; window->priv->dispose_has_run = FALSE;
window->priv->fullscreen_controls = NULL; window->priv->fullscreen_controls = NULL;
window->priv->fullscreen_animation_timeout_id = 0;
window->priv->editor_settings = g_settings_new ("org.x.editor.preferences.editor"); window->priv->editor_settings = g_settings_new ("org.x.editor.preferences.editor");
window->priv->ui_settings = g_settings_new ("org.x.editor.preferences.ui"); window->priv->ui_settings = g_settings_new ("org.x.editor.preferences.ui");
@@ -3621,9 +3487,16 @@ xed_window_init (XedWindow *window)
gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (window)), "xed-window"); gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (window)), "xed-window");
main_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); main_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_container_add (GTK_CONTAINER (window), main_box); window->priv->fullscreen_overlay = gtk_overlay_new ();
gtk_container_add (GTK_CONTAINER (window->priv->fullscreen_overlay), main_box);
gtk_container_add (GTK_CONTAINER (window), window->priv->fullscreen_overlay);
gtk_widget_show (window->priv->fullscreen_overlay);
gtk_widget_show (main_box); gtk_widget_show (main_box);
window->priv->fullscreen_eventbox = gtk_event_box_new ();
gtk_widget_set_valign (window->priv->fullscreen_eventbox, GTK_ALIGN_START);
gtk_overlay_add_overlay (GTK_OVERLAY (window->priv->fullscreen_overlay), window->priv->fullscreen_eventbox);
/* Add menu bar and toolbar bar */ /* Add menu bar and toolbar bar */
create_menu_bar_and_toolbar (window, main_box); create_menu_bar_and_toolbar (window, main_box);
@@ -4322,7 +4195,8 @@ _xed_window_fullscreen (XedWindow *window)
gtk_widget_hide (window->priv->statusbar); gtk_widget_hide (window->priv->statusbar);
fullscreen_controls_build (window); fullscreen_controls_build (window);
fullscreen_controls_show (window);
gtk_widget_show_all (window->priv->fullscreen_eventbox);
} }
void void
@@ -4359,7 +4233,7 @@ _xed_window_unfullscreen (XedWindow *window)
} }
g_signal_handlers_unblock_by_func (window->priv->statusbar, statusbar_visibility_changed, window); g_signal_handlers_unblock_by_func (window->priv->statusbar, statusbar_visibility_changed, window);
gtk_widget_hide (window->priv->fullscreen_controls); gtk_widget_hide (window->priv->fullscreen_eventbox);
} }
gboolean gboolean