1 /*
2  * This file is part of gtkD.
3  *
4  * gtkD is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License
6  * as published by the Free Software Foundation; either version 3
7  * of the License, or (at your option) any later version, with
8  * some exceptions, please read the COPYING file.
9  *
10  * gtkD is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with gtkD; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
18  */
19 
20 // generated automatically - do not change
21 // find conversion definition on APILookup.txt
22 // implement new conversion functionalities on the wrap.utils pakage
23 
24 
25 module gio.FileMonitor;
26 
27 private import gio.File;
28 private import gio.FileIF;
29 private import gobject.ObjectG;
30 private import gobject.Signals;
31 public  import gtkc.gdktypes;
32 private import gtkc.gio;
33 public  import gtkc.giotypes;
34 private import std.algorithm;
35 
36 
37 /**
38  * Monitors a file or directory for changes.
39  * 
40  * To obtain a #GFileMonitor for a file or directory, use
41  * g_file_monitor(), g_file_monitor_file(), or
42  * g_file_monitor_directory().
43  * 
44  * To get informed about changes to the file or directory you are
45  * monitoring, connect to the #GFileMonitor::changed signal. The
46  * signal will be emitted in the
47  * [thread-default main context][g-main-context-push-thread-default]
48  * of the thread that the monitor was created in
49  * (though if the global default main context is blocked, this may
50  * cause notifications to be blocked even if the thread-default
51  * context is still running).
52  */
53 public class FileMonitor : ObjectG
54 {
55 	/** the main Gtk struct */
56 	protected GFileMonitor* gFileMonitor;
57 
58 	/** Get the main Gtk struct */
59 	public GFileMonitor* getFileMonitorStruct()
60 	{
61 		return gFileMonitor;
62 	}
63 
64 	/** the main Gtk struct as a void* */
65 	protected override void* getStruct()
66 	{
67 		return cast(void*)gFileMonitor;
68 	}
69 
70 	protected override void setStruct(GObject* obj)
71 	{
72 		gFileMonitor = cast(GFileMonitor*)obj;
73 		super.setStruct(obj);
74 	}
75 
76 	/**
77 	 * Sets our main struct and passes it to the parent class.
78 	 */
79 	public this (GFileMonitor* gFileMonitor, bool ownedRef = false)
80 	{
81 		this.gFileMonitor = gFileMonitor;
82 		super(cast(GObject*)gFileMonitor, ownedRef);
83 	}
84 
85 
86 	/** */
87 	public static GType getType()
88 	{
89 		return g_file_monitor_get_type();
90 	}
91 
92 	/**
93 	 * Cancels a file monitor.
94 	 *
95 	 * Return: always %TRUE
96 	 */
97 	public bool cancel()
98 	{
99 		return g_file_monitor_cancel(gFileMonitor) != 0;
100 	}
101 
102 	/**
103 	 * Emits the #GFileMonitor::changed signal if a change
104 	 * has taken place. Should be called from file monitor
105 	 * implementations only.
106 	 *
107 	 * Implementations are responsible to call this method from the
108 	 * [thread-default main context][g-main-context-push-thread-default] of the
109 	 * thread that the monitor was created in.
110 	 *
111 	 * Params:
112 	 *     child = a #GFile.
113 	 *     otherFile = a #GFile.
114 	 *     eventType = a set of #GFileMonitorEvent flags.
115 	 */
116 	public void emitEvent(FileIF child, FileIF otherFile, GFileMonitorEvent eventType)
117 	{
118 		g_file_monitor_emit_event(gFileMonitor, (child is null) ? null : child.getFileStruct(), (otherFile is null) ? null : otherFile.getFileStruct(), eventType);
119 	}
120 
121 	/**
122 	 * Returns whether the monitor is canceled.
123 	 *
124 	 * Return: %TRUE if monitor is canceled. %FALSE otherwise.
125 	 */
126 	public bool isCancelled()
127 	{
128 		return g_file_monitor_is_cancelled(gFileMonitor) != 0;
129 	}
130 
131 	/**
132 	 * Sets the rate limit to which the @monitor will report
133 	 * consecutive change events to the same file.
134 	 *
135 	 * Params:
136 	 *     limitMsecs = a non-negative integer with the limit in milliseconds
137 	 *         to poll for changes
138 	 */
139 	public void setRateLimit(int limitMsecs)
140 	{
141 		g_file_monitor_set_rate_limit(gFileMonitor, limitMsecs);
142 	}
143 
144 	protected class OnChangedDelegateWrapper
145 	{
146 		void delegate(FileIF, FileIF, GFileMonitorEvent, FileMonitor) dlg;
147 		gulong handlerId;
148 		ConnectFlags flags;
149 		this(void delegate(FileIF, FileIF, GFileMonitorEvent, FileMonitor) dlg, gulong handlerId, ConnectFlags flags)
150 		{
151 			this.dlg = dlg;
152 			this.handlerId = handlerId;
153 			this.flags = flags;
154 		}
155 	}
156 	protected OnChangedDelegateWrapper[] onChangedListeners;
157 
158 	/**
159 	 * Emitted when @file has been changed.
160 	 *
161 	 * If using %G_FILE_MONITOR_WATCH_MOVES on a directory monitor, and
162 	 * the information is available (and if supported by the backend),
163 	 * @event_type may be %G_FILE_MONITOR_EVENT_RENAMED,
164 	 * %G_FILE_MONITOR_EVENT_MOVED_IN or %G_FILE_MONITOR_EVENT_MOVED_OUT.
165 	 *
166 	 * In all cases @file will be a child of the monitored directory.  For
167 	 * renames, @file will be the old name and @other_file is the new
168 	 * name.  For "moved in" events, @file is the name of the file that
169 	 * appeared and @other_file is the old name that it was moved from (in
170 	 * another directory).  For "moved out" events, @file is the name of
171 	 * the file that used to be in this directory and @other_file is the
172 	 * name of the file at its new location.
173 	 *
174 	 * It makes sense to treat %G_FILE_MONITOR_EVENT_MOVED_IN as
175 	 * equivalent to %G_FILE_MONITOR_EVENT_CREATED and
176 	 * %G_FILE_MONITOR_EVENT_MOVED_OUT as equivalent to
177 	 * %G_FILE_MONITOR_EVENT_DELETED, with extra information.
178 	 * %G_FILE_MONITOR_EVENT_RENAMED is equivalent to a delete/create
179 	 * pair.  This is exactly how the events will be reported in the case
180 	 * that the %G_FILE_MONITOR_WATCH_MOVES flag is not in use.
181 	 *
182 	 * If using the deprecated flag %G_FILE_MONITOR_SEND_MOVED flag and @event_type is
183 	 * #G_FILE_MONITOR_EVENT_MOVED, @file will be set to a #GFile containing the
184 	 * old path, and @other_file will be set to a #GFile containing the new path.
185 	 *
186 	 * In all the other cases, @other_file will be set to #NULL.
187 	 *
188 	 * Params:
189 	 *     file = a #GFile.
190 	 *     otherFile = a #GFile or #NULL.
191 	 *     eventType = a #GFileMonitorEvent.
192 	 */
193 	gulong addOnChanged(void delegate(FileIF, FileIF, GFileMonitorEvent, FileMonitor) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
194 	{
195 		onChangedListeners ~= new OnChangedDelegateWrapper(dlg, 0, connectFlags);
196 		onChangedListeners[onChangedListeners.length - 1].handlerId = Signals.connectData(
197 			this,
198 			"changed",
199 			cast(GCallback)&callBackChanged,
200 			cast(void*)onChangedListeners[onChangedListeners.length - 1],
201 			cast(GClosureNotify)&callBackChangedDestroy,
202 			connectFlags);
203 		return onChangedListeners[onChangedListeners.length - 1].handlerId;
204 	}
205 	
206 	extern(C) static void callBackChanged(GFileMonitor* filemonitorStruct, GFile* file, GFile* otherFile, GFileMonitorEvent eventType,OnChangedDelegateWrapper wrapper)
207 	{
208 		wrapper.dlg(ObjectG.getDObject!(File, FileIF)(file), ObjectG.getDObject!(File, FileIF)(otherFile), eventType, wrapper.outer);
209 	}
210 	
211 	extern(C) static void callBackChangedDestroy(OnChangedDelegateWrapper wrapper, GClosure* closure)
212 	{
213 		wrapper.outer.internalRemoveOnChanged(wrapper);
214 	}
215 
216 	protected void internalRemoveOnChanged(OnChangedDelegateWrapper source)
217 	{
218 		foreach(index, wrapper; onChangedListeners)
219 		{
220 			if (wrapper.dlg == source.dlg && wrapper.flags == source.flags && wrapper.handlerId == source.handlerId)
221 			{
222 				onChangedListeners[index] = null;
223 				onChangedListeners = std.algorithm.remove(onChangedListeners, index);
224 				break;
225 			}
226 		}
227 	}
228 	
229 }