From 4ece118a4f06abb647dcd36ae5bbbb467e41cf9e Mon Sep 17 00:00:00 2001 From: Andrea Zagli Date: Sat, 16 Feb 2013 17:12:49 +0100 Subject: [PATCH] Gestione atti. --- .anjuta_sym_db.db | Bin 39936 -> 169984 bytes data/messi/form/Makefile.am | 5 +- data/messi/form/atto.form | 66 ++ data/messi/form/attoallegato.form | 38 + data/messi/form/trovaatti.form | 46 + data/messi/gui/messi.gui | 1488 ++++++++++++++++++++++++++--- docs/messi.sql | 68 +- src/Makefile.am | 10 +- src/atti.c | 671 +++++++++++++ src/atti.h | 65 ++ src/atto.c | 778 +++++++++++++++ src/atto.h | 65 ++ src/attoallegato.c | 446 +++++++++ src/attoallegato.h | 65 ++ src/main.c | 14 + src/trovaatti.c | 345 +++++++ src/trovaatti.h | 65 ++ 17 files changed, 4108 insertions(+), 127 deletions(-) create mode 100644 data/messi/form/atto.form create mode 100644 data/messi/form/attoallegato.form create mode 100644 data/messi/form/trovaatti.form create mode 100644 src/atti.c create mode 100644 src/atti.h create mode 100644 src/atto.c create mode 100644 src/atto.h create mode 100644 src/attoallegato.c create mode 100644 src/attoallegato.h create mode 100644 src/trovaatti.c create mode 100644 src/trovaatti.h diff --git a/.anjuta_sym_db.db b/.anjuta_sym_db.db index de7fcadba6c7facf3d934571aff58d3498cf269a..7aecda89f0679e1458ac419abddaa62515b30c1a 100644 GIT binary patch literal 169984 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 delta 3394 zcmZuze{56t5r6l+_nzN#?AT7?IF9pTJ8|MTP3SU6LXt%^q$LAH!wQq(j*44YO z?F56cm5aZ3_x;{|?|b*TJABr7_yRlTGKT~~@Y7%ZbG)S+Lg#k=sI2Oci2ughcpYEC zdCcM)_)9#rU~AceQ#dPBF6kHln^p9x69*E(P&gc&m>{k!2u2y5K+KWUSgT1wjsFgg z#*+~Vf3JvWhh6cpC<=m2K|ch8nZ$T79ZjV6Mk7YmfDV`lr^ch^GDJ-s3ngQdp;*+& z(6#WP#UdIydpo*&S9P7Q5=A58jDYXpIh-K}4`O!4^{lRz zpp|_Fm#`iO*bO|7DL94i<0aV7!t5^VVlT7rv%~ClJdH=-Eqr#tYib7rwn)P&fPVH6 zYcRBGQV(Bj?q}6gD_d-mmsYXV$ev($cYG}JB|q*K6v;x&eeHE-$w@!LspPJB?2%@Z z4s z=B$(&Y3(0R2g9jIa6BE#ur)O`Qadq2lbO`P*kqg}1?_%^{>35Yp6VcBCYnyiGpTeu zwJh$llPwZWq{iaoA=Xn>I6Ivhiv}k%(PSpdx+~3+W9ewtRZ-Yb6n5GQ&XGx;5NxHj zpgbOeNP1JQh-)_ zNA?FtQjr6N2YR&LB55Vu6`D!1Q>YW6cvAR|*DDQ>FneyURyp9Qm-_f=)3?FFw!6=- z7R7Q27X>P;TU1zAagoyQ3}zSCJWl+}0^Y%Q@egPl{%5N+yL)TKCl6THxj;aa)0=KDfdC@h=mPdw?w-V`< z6#5gW0P|6n3@+>|gc#)WW3oxP$i;rVNHJVMrMX}3Q#H~!bsM_Cefl|ZgAuO_9^4_| zHT)d~bdiwl=L8-<#h0jT=kR+J;G_60d;#C0=OApLXSqqYJ&2Pyj-$8>L--N?19#wd zy0Mug*C}yCRG^g;KPSzcG;!kNq>+;bPP`OsdLSY-oH#hC=ETlP6(^OPRB&SBgg*~h zI4S4E%!!GUGER&lPAQ<$jYWQZ9VZ@6+?)hBY2l=v6U~Tk3m)N)0Ixwc^w3=fg*&i- zU&dPYb@-e`*_&*U-DD1ShHYbAsIpJl96JJc;g4_<((nvkq!=B88JOWQE`G9YrW4W% zQKM%E8w<#-4WdTxp8E>ZsrRZ`s zL*~GEG!ora+~~B5P6s5SiIHfUz#*BbsTG}%fPVZcIO;{`%A#mE9SbGnv2-Yr2o-l$ z>!+RvZOSG(okgW>dE~3Ii%xHmGr%!){Z@j&$`U(yZbb7 zl&B0vLQm{3w>IB%KhH6jSRcxat}Wo9N&oD5@Pbhf_CQUwRdkTcJXQr1Xz+{L0O;@c zvj*AY6M2;+`k8y3yIR!T_g*D4x;-9=MKkpeXKN2<*XfT&z-4`KQaC>YVlQP*xp15p z;7hn0o7jicUyrjm>tzxg6aFXsf`kX@`@rW1!eG{GTAMxfLe(mNgH=$Sj4~e-x)p%3 z)a%re8)7au;3Y*nQ~E36#9T|AQkoeomz%bFNIn2cxD)gzk1%gGHuo49@lmx?2WnIVCH4qx;B?<^^w3;G|q<&C0v*Y{L8KuOM=2E z2W*1c4eB)5DIDGWLGoQRTQR=|O!~i$GU^U3q|;N-$xhGjfHFb`?^L^=?08G|Gfp%OLBm_*`*SE7VlYl$;KM8L3LFqs*;Lo@XLO1@Oiz^m9wjV z{XD@8>=$YEO3LLZhC# z1)ZxMvRx$v=g3`Jt6o0Jn^?KPcCvEzL-r2)7%Q=x=Aaj7GP;DfDa8K-!xnj1<*kV3 zp$$swpgf=w#PJbE|MMMa0FT~gV_mwxl0BneKfyNX^QWQK;E^?z5Kmt`4NgUCmIL|K Xk57TyRqvE7e6?>Wv;?jNIIR0W*Wx~x diff --git a/data/messi/form/Makefile.am b/data/messi/form/Makefile.am index 41a74cb..7be77d0 100644 --- a/data/messi/form/Makefile.am +++ b/data/messi/form/Makefile.am @@ -1,6 +1,9 @@ formdir = $(datadir)/$(PACKAGE)/form form_DATA = \ - tipoatto.form + atto.form \ + attoallegato.form \ + tipoatto.form \ + trovaatti.form EXTRA_DIST = $(form_DATA) diff --git a/data/messi/form/atto.form b/data/messi/form/atto.form new file mode 100644 index 0000000..59889ec --- /dev/null +++ b/data/messi/form/atto.form @@ -0,0 +1,66 @@ + + + + atti
+ + + + t + t + + + + + + t + + + + + + + SELECT descrizione FROM tipi_atto WHERE id = ##key0::gint + + + + t + + + + + + t + + + + + + date + %d/%m/%Y + now + + + + + + date + %d/%m/%Y + t + now + + + + + + date + %d/%m/%Y + t + now + + + + + + + +
diff --git a/data/messi/form/attoallegato.form b/data/messi/form/attoallegato.form new file mode 100644 index 0000000..03428d2 --- /dev/null +++ b/data/messi/form/attoallegato.form @@ -0,0 +1,38 @@ + + + + atto_allegati
+ + + + t + t + + + + + + + + + + t + + + + + + + + + + date + %d/%m/%Y + + + + + + + +
diff --git a/data/messi/form/trovaatti.form b/data/messi/form/trovaatti.form new file mode 100644 index 0000000..c2401c5 --- /dev/null +++ b/data/messi/form/trovaatti.form @@ -0,0 +1,46 @@ + + + + + + + SELECT CASE WHEN ragione_sociale <> '' THEN ragione_sociale + ELSE cognome || ' ' || nome END FROM beneficiari WHERE id = ##key0::gint + + + + + + + + + SELECT nome FROM uffici WHERE id = ##key0::gint + + + + + + + + + date + %d/%m/%Y + + + + + + date + %d/%m/%Y + + + + + + + + + + + + diff --git a/data/messi/gui/messi.gui b/data/messi/gui/messi.gui index 43e7a9c..53e0e0a 100644 --- a/data/messi/gui/messi.gui +++ b/data/messi/gui/messi.gui @@ -1,6 +1,7 @@ + False @@ -39,112 +40,51 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - False - - - True - False - 5 - 5 - - - True - False - 8 - 2 - 5 - 5 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - True - True - 0 - - - - - True - False - 5 - end - - - - - - - - - - - - False - True - 1 - - - - + + + + + + + - + False + Atti - Gestione messi notificatori True @@ -155,7 +95,7 @@ True False - <b>Albo pretorio</b> + <b>Atti</b> True @@ -172,9 +112,100 @@ automatic etched-in - + True True + lstore_atti + True + 1 + + + ID + + + + 0 + + + + + + + Numero + + + + 1 + + + + + + + Tipo + + + + 2 + + + + + + + Oggetto + + + + 3 + + + + + + + Ufficio + + + + 4 + + + + + + + Data ricezione + + + + 5 + + + + + + + Data inizio pubblicazione + + + + 6 + + + + + + + Data fine pubblicazione + + + + 7 + + + + @@ -191,7 +222,7 @@ 5 end - + gtk-new True True @@ -205,8 +236,859 @@ - - gtk-edit + + gtk-edit + True + True + True + True + + + False + False + 1 + + + + + gtk-delete + True + True + True + True + + + False + False + 2 + + + + + _Esporta + True + True + True + True + + + False + False + 3 + + + + + gtk-find + True + True + True + True + + + False + False + 4 + + + + + gtk-undo + True + True + True + True + + + False + False + 5 + + + + + gtk-ok + True + True + True + True + + + False + False + 6 + + + + + False + True + 2 + + + + + + + False + Atto - Gestione messi notificatori + True + center-on-parent + 600 + True + + + True + False + 5 + 5 + + + True + False + 10 + 2 + 5 + 5 + + + True + False + 0 + ID + + + GTK_FILL + GTK_FILL + + + + + True + False + 0 + lbl_id + + + 1 + 2 + GTK_FILL + + + + + True + False + 0 + Numero + + + 1 + 2 + GTK_FILL + GTK_FILL + + + + + True + True + 10 + • + False + False + True + True + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + True + False + 0 + Tipo + + + 2 + 3 + GTK_FILL + GTK_FILL + + + + + True + False + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + True + False + 0 + Oggetto + + + 3 + 4 + GTK_FILL + GTK_FILL + + + + + True + True + 255 + • + False + False + True + True + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + True + False + 0 + Data ricezione + + + 5 + 6 + GTK_FILL + GTK_FILL + + + + + True + False + 0 + Data inizio pubblicazione + + + 6 + 7 + GTK_FILL + GTK_FILL + + + + + True + False + 0 + Data fine pubblicazione + + + 7 + 8 + GTK_FILL + GTK_FILL + + + + + True + True + 10 + • + False + False + True + True + + + 1 + 2 + 5 + 6 + GTK_FILL + + + + + True + True + 10 + • + False + False + True + True + + + 1 + 2 + 6 + 7 + GTK_FILL + + + + + True + True + 10 + • + False + False + True + True + + + 1 + 2 + 7 + 8 + GTK_FILL + + + + + True + False + 0 + 0 + Note + + + 8 + 9 + GTK_FILL + GTK_FILL + + + + + True + True + automatic + automatic + etched-in + + + True + True + + + + + 1 + 2 + 8 + 9 + + + + + True + False + 0 + + + True + False + 5 + 5 + + + True + True + automatic + automatic + etched-in + + + True + True + lstore_atto_allegati + False + True + 0 + + + Titolo + + + + 1 + + + + + + + Descrizione + + + + 2 + + + + + + + + + True + True + 0 + + + + + True + False + 5 + start + + + gtk-new + True + True + True + True + + + False + False + 0 + + + + + gtk-edit + True + True + True + True + + + False + False + 1 + + + + + gtk-delete + True + True + True + True + + + False + False + 2 + + + + + gtk-open + True + True + True + True + + + False + False + 3 + + + + + False + True + 1 + + + + + + + True + False + <b>Allegati</b> + True + + + + + 2 + 9 + 10 + + + + + True + False + + + 1 + 2 + 4 + 5 + GTK_FILL + + + + + True + False + 0 + Ufficio + + + 4 + 5 + GTK_FILL + GTK_FILL + + + + + True + True + 0 + + + + + True + False + 5 + end + + + gtk-cancel + True + True + True + True + + + False + False + 0 + + + + + gtk-save + True + True + True + True + + + False + False + 1 + + + + + Salva e _chiudi + True + True + True + True + + + False + False + 2 + + + + + False + True + 1 + + + + + + + False + Allegato - Amministrazione aperta + True + center-on-parent + 480 + True + + + True + False + 5 + 5 + + + True + False + 7 + 2 + 5 + 5 + + + + + + True + False + 0 + ID + + + GTK_FILL + GTK_FILL + + + + + True + False + 0 + lbl_id + + + 1 + 2 + GTK_FILL + + + + + True + False + 0 + Descrizione + + + 2 + 3 + GTK_FILL + GTK_FILL + + + + + True + True + 255 + ● + True + True + False + False + True + True + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + True + False + 0 + 0 + Note + + + 4 + 5 + GTK_FILL + GTK_FILL + + + + + True + True + automatic + automatic + etched-in + + + True + True + + + + + 1 + 2 + 4 + 5 + + + + + True + False + 0 + Data documento + + + 3 + 4 + GTK_FILL + GTK_FILL + + + + + True + True + 10 + ● + True + True + False + False + True + True + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + True + False + 0 + Titolo + + + 1 + 2 + GTK_FILL + GTK_FILL + + + + + True + True + 255 + ● + True + True + False + False + True + True + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + True + False + 0 + + + True + False + 12 + + + + + + + + True + False + <b>File</b> + True + + + + + 2 + 5 + 6 + GTK_FILL + + + + + False + lbl_id_atti + + + 1 + 2 + 6 + 7 + GTK_FILL + GTK_FILL + + + + + True + True + 0 + + + + + True + False + 5 + end + + + gtk-cancel True True True @@ -215,42 +1097,44 @@ False False - 1 + 0 - - gtk-delete + + gtk-save True True + True + True True True False False - 2 + 1 - - gtk-find + + Salva e _chiudi True True True - True + True False False - 3 + 2 False True - 2 + 1 @@ -311,6 +1195,29 @@ False _Albo pretorio True + + + True + False + + + True + False + _Atti + True + + + + + + True + False + _Registro + True + + + + @@ -708,4 +1615,363 @@ + + False + Trova atti - Gestione messi notificatori + True + 450 + True + + + True + False + 5 + 5 + + + True + False + 6 + 2 + 5 + 5 + + + True + False + 0 + Tipo + + + 1 + 2 + GTK_FILL + GTK_FILL + + + + + True + False + True + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + True + False + True + + + 1 + 2 + 3 + 4 + GTK_FILL + + + + + True + False + 0 + Ufficio + + + 3 + 4 + GTK_FILL + GTK_FILL + + + + + True + False + 0 + Pubblicazione - da data + + + 5 + 6 + GTK_FILL + GTK_FILL + + + + + True + False + 5 + + + True + True + 10 + ● + True + False + False + True + True + + + True + True + 0 + + + + + True + False + 0 + a data + + + False + True + 1 + + + + + True + True + 10 + ● + True + False + False + True + True + + + True + True + 2 + + + + + 1 + 2 + 5 + 6 + GTK_FILL + + + + + True + False + 0 + Numero + + + GTK_FILL + GTK_FILL + + + + + True + True + 10 + • + False + False + True + True + + + 1 + 2 + GTK_FILL + + + + + True + False + 0 + Ricezione - da data + + + 4 + 5 + GTK_FILL + GTK_FILL + + + + + True + False + 5 + + + True + True + 10 + ● + True + False + False + True + True + + + True + True + 0 + + + + + True + False + 0 + a data + + + False + True + 1 + + + + + True + True + 10 + ● + True + False + False + True + True + + + True + True + 2 + + + + + 1 + 2 + 4 + 5 + GTK_FILL + + + + + True + False + 0 + Oggetto + + + 2 + 3 + GTK_FILL + GTK_FILL + + + + + True + True + 255 + • + False + False + True + True + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + True + True + 0 + + + + + True + False + 5 + end + + + gtk-clear + True + True + True + True + + + False + False + 0 + + + + + gtk-cancel + True + True + True + True + + + False + False + 1 + + + + + gtk-ok + True + True + True + True + True + True + + + False + False + 2 + + + + + False + True + 1 + + + + + diff --git a/docs/messi.sql b/docs/messi.sql index 313f861..9e0f945 100644 --- a/docs/messi.sql +++ b/docs/messi.sql @@ -4,7 +4,7 @@ -- Dumped from database version 9.1.8 -- Dumped by pg_dump version 9.1.8 --- Started on 2013-02-16 15:46:30 CET +-- Started on 2013-02-16 16:55:25 CET SET statement_timeout = 0; SET client_encoding = 'UTF8'; @@ -13,7 +13,7 @@ SET check_function_bodies = false; SET client_min_messages = warning; -- --- TOC entry 163 (class 3079 OID 11649) +-- TOC entry 164 (class 3079 OID 11649) -- Name: plpgsql; Type: EXTENSION; Schema: -; Owner: - -- @@ -21,8 +21,8 @@ CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog; -- --- TOC entry 1871 (class 0 OID 0) --- Dependencies: 163 +-- TOC entry 1890 (class 0 OID 0) +-- Dependencies: 164 -- Name: EXTENSION plpgsql; Type: COMMENT; Schema: -; Owner: - -- @@ -34,19 +34,49 @@ SET search_path = public, pg_catalog; SET default_with_oids = false; -- --- TOC entry 161 (class 1259 OID 18085) --- Dependencies: 6 +-- TOC entry 162 (class 1259 OID 18138) +-- Dependencies: 1867 1868 1869 1870 1871 1872 6 -- Name: atti; Type: TABLE; Schema: public; Owner: - -- CREATE TABLE atti ( - id integer NOT NULL + id integer NOT NULL, + numero character varying(10) DEFAULT ''::character varying, + id_tipi_atto integer DEFAULT 0, + oggetto character varying(255) DEFAULT ''::character varying, + id_uffici integer DEFAULT 0, + ricezione_data date, + pubblicazione_inizio_data date, + pubblicazione_fine_data date, + note text DEFAULT ''::text, + status character varying(1) DEFAULT ''::character varying ); -- --- TOC entry 162 (class 1259 OID 18097) --- Dependencies: 1859 1860 6 +-- TOC entry 163 (class 1259 OID 18235) +-- Dependencies: 1873 1874 1875 1876 1877 6 +-- Name: atto_allegati; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE atto_allegati ( + id integer NOT NULL, + id_atti integer, + titolo character varying(255) DEFAULT ''::character varying, + descrizione character varying DEFAULT ''::bpchar, + data_documento date, + note text DEFAULT ''::text, + percorso character varying(255) DEFAULT ''::character varying, + contenuto integer, + data_file timestamp without time zone, + dimensione_file bigint, + status character varying(1) DEFAULT ''::character varying +); + + +-- +-- TOC entry 161 (class 1259 OID 18097) +-- Dependencies: 1865 1866 6 -- Name: tipi_atto; Type: TABLE; Schema: public; Owner: - -- @@ -58,8 +88,8 @@ CREATE TABLE tipi_atto ( -- --- TOC entry 1862 (class 2606 OID 18089) --- Dependencies: 161 161 1866 +-- TOC entry 1881 (class 2606 OID 18151) +-- Dependencies: 162 162 1885 -- Name: atti_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- @@ -68,8 +98,18 @@ ALTER TABLE ONLY atti -- --- TOC entry 1864 (class 2606 OID 18103) --- Dependencies: 162 162 1866 +-- TOC entry 1883 (class 2606 OID 18247) +-- Dependencies: 163 163 1885 +-- Name: atto_allegati_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY atto_allegati + ADD CONSTRAINT atto_allegati_pkey PRIMARY KEY (id); + + +-- +-- TOC entry 1879 (class 2606 OID 18103) +-- Dependencies: 161 161 1885 -- Name: tipi_atto_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- @@ -77,7 +117,7 @@ ALTER TABLE ONLY tipi_atto ADD CONSTRAINT tipi_atto_pkey PRIMARY KEY (id); --- Completed on 2013-02-16 15:46:30 CET +-- Completed on 2013-02-16 16:55:26 CET -- -- PostgreSQL database dump complete diff --git a/src/Makefile.am b/src/Makefile.am index f501443..23307e4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -22,7 +22,15 @@ messi_SOURCES = \ commons.c \ commons.h \ main.c \ + atti.c \ + atti.h \ + atto.c \ + atto.h \ + attoallegato.c \ + attoallegato.h \ tipiatto.c \ tipiatto.h \ tipoatto.c \ - tipoatto.h + tipoatto.h \ + trovaatti.c \ + trovaatti.h diff --git a/src/atti.c b/src/atti.c new file mode 100644 index 0000000..e7517ab --- /dev/null +++ b/src/atti.c @@ -0,0 +1,671 @@ +/* + * Copyright (C) 2013 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include + +#include +#include + +#include + +#include "atti.h" +#include "atto.h" +#include "trovaatti.h" + +static void atti_class_init (AttiClass *klass); +static void atti_init (Atti *atti); + +static void atti_carica (Atti *atti); +static void atti_modifica (Atti *atti); + +static void atti_selezionato (Atti *atti); +static void atti_on_atto_aggiornato (gpointer instance, gpointer user_data); + +static void atti_on_filtra (gpointer instance, gpointer parametri, gpointer user_data); + +static void atti_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void atti_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +static gboolean atti_on_key_release_event (GtkWidget *widget, + GdkEventKey *event, + gpointer user_data); + +static void atti_on_btn_nuovo_clicked (GtkButton *button, + gpointer user_data); +static void atti_on_btn_modifica_clicked (GtkButton *button, + gpointer user_data); +static void atti_on_btn_elimina_clicked (GtkButton *button, + gpointer user_data); +static void atti_on_trv_atti_row_activated (GtkTreeView *tree_view, + GtkTreePath *tree_path, + GtkTreeViewColumn *column, + gpointer user_data); + +static void atti_on_btn_esporta_clicked (GtkButton *button, + gpointer user_data); +static void atti_on_btn_ricerca_clicked (GtkButton *button, + gpointer user_data); + +static void atti_on_btn_annulla_clicked (GtkButton *button, + gpointer user_data); +static void atti_on_btn_seleziona_clicked (GtkButton *button, + gpointer user_data); + +#define ATTI_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TYPE_ATTI, AttiPrivate)) + +enum +{ + COL_ID, + COL_NUMERO, + COL_TIPO, + COL_OGGETTO, + COL_UFFICIO, + COL_DATA_RICEZIONE, + COL_DATA_INIZIO_PUBBLICAZIONE, + COL_DATA_FINE_PUBBLICAZIONE +}; + +typedef struct _AttiPrivate AttiPrivate; +struct _AttiPrivate + { + Commons *commons; + + GtkWidget *widget; + GtkTreeSelection *selection; + GtkListStore *lstore_atti; + + GHashTable *parametri_ricerca; + + gboolean selezione; + }; + +G_DEFINE_TYPE (Atti, atti, G_TYPE_OBJECT) + +static void +atti_class_init (AttiClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (AttiPrivate)); + + object_class->set_property = atti_set_property; + object_class->get_property = atti_get_property; + + /** + * Atti::selezionato: + * @atti: + * + */ + klass->selezionato_signal_id = g_signal_new ("selezionato", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, + NULL, + g_cclosure_marshal_VOID__UINT, + G_TYPE_NONE, + 1, G_TYPE_UINT); +} + +static void +atti_init (Atti *atti) +{ + AttiPrivate *priv = ATTI_GET_PRIVATE (atti); + + priv->parametri_ricerca = NULL; +} + +/** + * atti_new: + * @commons: + * @selezione: + * + * Returns: the newly created #Atti object. + */ +Atti +*atti_new (Commons *commons, gboolean selezione) +{ + GError *error; + AutozIResource *ires1; + + Atti *a = ATTI (g_object_new (atti_get_type (), NULL)); + + AttiPrivate *priv = ATTI_GET_PRIVATE (a); + + priv->commons = commons; + priv->selezione = selezione; + + error = NULL; + gtk_builder_add_objects_from_file (priv->commons->gtkbuilder, priv->commons->guifile, + g_strsplit (g_strconcat ("lstore_atti|", + (selezione ? "w_atti" : "vbox2"), + NULL), + "|", -1), + &error); + if (error != NULL) + { + g_warning ("Errore: %s.", error->message); + return NULL; + } + + priv->widget = GTK_WIDGET (gtk_builder_get_object (priv->commons->gtkbuilder, (selezione ? "w_atti" : "vbox2"))); + priv->selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (gtk_builder_get_object (priv->commons->gtkbuilder, "treeview1"))); + priv->lstore_atti = GTK_LIST_STORE (gtk_builder_get_object (priv->commons->gtkbuilder, "lstore_atti")); + + g_signal_connect (priv->widget, + "key-release-event", G_CALLBACK (atti_on_key_release_event), (gpointer)a); + + g_signal_connect (gtk_builder_get_object (priv->commons->gtkbuilder, "button4"), + "clicked", G_CALLBACK (atti_on_btn_nuovo_clicked), (gpointer)a); + g_signal_connect (gtk_builder_get_object (priv->commons->gtkbuilder, "button5"), + "clicked", G_CALLBACK (atti_on_btn_modifica_clicked), (gpointer)a); + g_signal_connect (gtk_builder_get_object (priv->commons->gtkbuilder, "button6"), + "clicked", G_CALLBACK (atti_on_btn_elimina_clicked), (gpointer)a); + g_signal_connect (gtk_builder_get_object (priv->commons->gtkbuilder, "treeview1"), + "row-activated", G_CALLBACK (atti_on_trv_atti_row_activated), (gpointer)a); + + g_signal_connect (gtk_builder_get_object (priv->commons->gtkbuilder, "button8"), + "clicked", G_CALLBACK (atti_on_btn_esporta_clicked), (gpointer)a); + g_signal_connect (gtk_builder_get_object (priv->commons->gtkbuilder, "button7"), + "clicked", G_CALLBACK (atti_on_btn_ricerca_clicked), (gpointer)a); + + if (priv->selezione) + { + gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (priv->commons->gtkbuilder, "label2"))); + g_signal_connect (gtk_builder_get_object (priv->commons->gtkbuilder, "button9"), + "clicked", G_CALLBACK (atti_on_btn_annulla_clicked), (gpointer)a); + g_signal_connect (gtk_builder_get_object (priv->commons->gtkbuilder, "button10"), + "clicked", G_CALLBACK (atti_on_btn_seleziona_clicked), (gpointer)a); + } + else + { + gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (priv->commons->gtkbuilder, "button9"))); + gtk_widget_hide (GTK_WIDGET (gtk_builder_get_object (priv->commons->gtkbuilder, "button10"))); + } + + atti_carica (a); + + ires1 = autoz_get_resource_from_id (priv->commons->autoz, "messi_rw"); + if (!autoz_is_allowed (priv->commons->autoz, priv->commons->role_utente, ires1, FALSE)) + { + gtk_widget_set_sensitive (GTK_WIDGET (gtk_builder_get_object (commons->gtkbuilder, "button4")), FALSE); + gtk_widget_set_sensitive (GTK_WIDGET (gtk_builder_get_object (commons->gtkbuilder, "button6")), FALSE); + } + + return a; +} + +/** + * atti_get_widget: + * @atti: + * + */ +GtkWidget +*atti_get_widget (Atti *atti) +{ + AttiPrivate *priv = ATTI_GET_PRIVATE (atti); + + return priv->widget; +} + +/* PRIVATE */ +static void +atti_carica (Atti *atti) +{ + GValue *gval; + gchar *gcval; + guint gival; + GDateTime *gdtval; + + gchar *sql_where; + gchar *sql; + + GdaDataModel *dm; + + guint rows; + guint row; + + GtkTreeIter iter; + + AutozIResource *ires1; + + guint id_uffici; + + GHashTable *ht_ufficio; + GValue *gv_ufficio; + gchar *ufficio; + + AttiPrivate *priv = ATTI_GET_PRIVATE (atti); + + gtk_list_store_clear (priv->lstore_atti); + + sql_where = g_strdup (""); + + id_uffici = 0; + + if (priv->parametri_ricerca != NULL) + { + gival = g_value_get_int ((GValue *)g_hash_table_lookup (priv->parametri_ricerca, "id_beneficiari")); + if (gival != 0) + { + sql_where = g_strconcat (sql_where, " AND a.id_beneficiari = ", + g_strdup_printf ("%d", gival), + NULL); + } + id_uffici = g_value_get_int ((GValue *)g_hash_table_lookup (priv->parametri_ricerca, "id_uffici")); + if (id_uffici != 0) + { + sql_where = g_strconcat (sql_where, " AND a.id_uffici = ", + g_strdup_printf ("%d", id_uffici), + NULL); + } + gval = (GValue *)g_hash_table_lookup (priv->parametri_ricerca, "albo_da_data"); + if (gval != NULL && (gdtval = (GDateTime *)g_value_get_pointer (gval)) != NULL) + { + sql_where = g_strconcat (sql_where, " AND a.albo_data_inizio >= '", + g_date_time_format (gdtval, "%F"), + "'", + NULL); + } + gval = (GValue *)g_hash_table_lookup (priv->parametri_ricerca, "albo_a_data"); + if (gval != NULL && (gdtval = (GDateTime *)g_value_get_pointer (gval)) != NULL) + { + sql_where = g_strconcat (sql_where, " AND a.albo_data_inizio <= '", + g_date_time_format (gdtval, "%F"), + "'", + NULL); + } + } + + sql = g_strdup_printf ("SELECT a.id, a.numero," + " ta.descrizione AS tipo_atto," + " a.oggetto," + " a.ricezione_data, a.id_uffici," + " a.pubblicazione_inizio_data," + " a.pubblicazione_fine_data" + " FROM atti AS a" + " INNER JOIN tipi_atto AS ta ON a.id_tipi_atto = ta.id" + " WHERE a.status <> 'E'" + "%s" + " ORDER BY a.id", + sql_where); + dm = gdaex_query (priv->commons->gdaex, sql); + g_free (sql_where); + g_free (sql); + if (dm != NULL) + { + rows = gda_data_model_get_n_rows (dm); + for (row = 0; row < rows; row++) + { + if (id_uffici == 0) + { + /* controllo le autorizzazioni */ + ires1 = autoz_get_resource_from_id (priv->commons->autoz, g_strdup_printf ("opengov_u_%d_r_0", gdaex_data_model_get_field_value_integer_at (dm, row, "id_uffici"))); + if (ires1 != NULL && !autoz_is_allowed (priv->commons->autoz, priv->commons->role_utente, ires1, FALSE)) + { + continue; + } + } + + ht_ufficio = organigramma_ufficio_get_by_id (priv->commons->organigramma_commons, gdaex_data_model_get_field_value_integer_at (dm, row, "id_uffici")); + if (ht_ufficio == NULL) + { + ufficio = g_strdup (""); + } + else + { + gv_ufficio = g_hash_table_lookup (ht_ufficio, "nome"); + if (gda_value_is_null (gv_ufficio)) + { + ufficio = g_strdup (""); + } + else + { + ufficio = gda_value_stringify (gv_ufficio); + } + } + + gtk_list_store_append (priv->lstore_atti, &iter); + gtk_list_store_set (priv->lstore_atti, &iter, + COL_ID, gdaex_data_model_get_field_value_integer_at (dm, row, "id"), + COL_NUMERO, gdaex_data_model_get_field_value_stringify_at (dm, row, "numero"), + COL_TIPO, gdaex_data_model_get_field_value_stringify_at (dm, row, "tipo_atto"), + COL_OGGETTO, gdaex_data_model_get_field_value_stringify_at (dm, row, "oggetto"), + COL_UFFICIO, ufficio, + COL_DATA_RICEZIONE, solipa_gdatetime_format (gdaex_data_model_get_field_value_gdatetime_at (dm, row, "ricezione_data"), "%d/%m/%Y"), + COL_DATA_INIZIO_PUBBLICAZIONE, solipa_gdatetime_format (gdaex_data_model_get_field_value_gdatetime_at (dm, row, "pubblicazione_inizio_data"), "%d/%m/%Y"), + COL_DATA_FINE_PUBBLICAZIONE, solipa_gdatetime_format (gdaex_data_model_get_field_value_gdatetime_at (dm, row, "pubblicazione_fine_data"), "%d/%m/%Y"), + -1); + + g_free (ufficio); + } + g_object_unref (dm); + } +} + +static void +atti_modifica (Atti *atti) +{ + GtkTreeIter iter; + gint id; + + AttiPrivate *priv = ATTI_GET_PRIVATE (atti); + + if (gtk_tree_selection_get_selected (priv->selection, NULL, &iter)) + { + GtkWidget *w; + + gtk_tree_model_get (GTK_TREE_MODEL (priv->lstore_atti), &iter, + COL_ID, &id, + -1); + + Atto *c = atto_new (priv->commons, id); + + g_signal_connect (G_OBJECT (c), "aggiornato", + G_CALLBACK (atti_on_atto_aggiornato), (gpointer)atti); + + w = atto_get_widget (c); + if (priv->selezione) + { + gtk_window_set_transient_for (GTK_WINDOW (w), GTK_WINDOW (priv->widget)); + } + else + { + gtk_window_set_transient_for (GTK_WINDOW (w), GTK_WINDOW (gtk_builder_get_object (priv->commons->gtkbuilder, "w_main"))); + } + gtk_widget_show (w); + } + else + { + solipa_message_dialog (priv->selezione ? priv->widget : GTK_WIDGET (gtk_builder_get_object (priv->commons->gtkbuilder, "w_main")), + GTK_MESSAGE_WARNING, + GTK_BUTTONS_OK, + "Occorre prima selezionare un atto."); + } +} + +static void +atti_selezionato (Atti *atti) +{ + GtkTreeIter iter; + guint id; + + AttiClass *klass = ATTI_GET_CLASS (atti); + AttiPrivate *priv = ATTI_GET_PRIVATE (atti); + + if (gtk_tree_selection_get_selected (priv->selection, NULL, &iter)) + { + gtk_tree_model_get (GTK_TREE_MODEL (priv->lstore_atti), &iter, + COL_ID, &id, + -1); + + g_signal_emit (G_OBJECT (atti), klass->selezionato_signal_id, 0, id); + + gtk_widget_destroy (priv->widget); + g_object_unref (G_OBJECT (atti)); + } + else + { + solipa_message_dialog (priv->selezione ? priv->widget : GTK_WIDGET (gtk_builder_get_object (priv->commons->gtkbuilder, "w_main")), + GTK_MESSAGE_WARNING, + GTK_BUTTONS_OK, + "Occorre prima selezionare un atto."); + } +} + +static void +atti_on_atto_aggiornato (gpointer instance, gpointer user_data) +{ + atti_carica ((Atti *)user_data); +} + +static void +atti_on_filtra (gpointer instance, gpointer parametri, gpointer user_data) +{ + Atti *i = (Atti *)user_data; + AttiPrivate *priv = ATTI_GET_PRIVATE (i); + + priv->parametri_ricerca = (GHashTable *)parametri; + + atti_carica (i); +} + +static void +atti_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + Atti *atti = ATTI (object); + AttiPrivate *priv = ATTI_GET_PRIVATE (atti); + + switch (property_id) + { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +atti_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + Atti *atti = ATTI (object); + AttiPrivate *priv = ATTI_GET_PRIVATE (atti); + + switch (property_id) + { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +/* CALLBACK */ +static gboolean +atti_on_key_release_event (GtkWidget *widget, + GdkEventKey *event, + gpointer user_data) +{ + if (event->keyval == GDK_Escape) + { + AttiPrivate *priv = ATTI_GET_PRIVATE ((Atti *)user_data); + + if (priv->selezione) + { + gtk_button_clicked (GTK_BUTTON (gtk_builder_get_object (priv->commons->gtkbuilder, "button16"))); + return TRUE; + } + } + + return FALSE; +} + +static void +atti_on_btn_nuovo_clicked (GtkButton *button, + gpointer user_data) +{ + GtkWidget *w; + + Atti *atti = (Atti *)user_data; + AttiPrivate *priv = ATTI_GET_PRIVATE (atti); + + Atto *c = atto_new (priv->commons, 0); + + g_signal_connect (G_OBJECT (c), "aggiornato", + G_CALLBACK (atti_on_atto_aggiornato), user_data); + + w = atto_get_widget (c); + if (priv->selezione) + { + gtk_window_set_transient_for (GTK_WINDOW (w), GTK_WINDOW (priv->widget)); + } + else + { + gtk_window_set_transient_for (GTK_WINDOW (w), GTK_WINDOW (gtk_builder_get_object (priv->commons->gtkbuilder, "w_main"))); + } + gtk_widget_show (w); +} + +static void +atti_on_btn_modifica_clicked (GtkButton *button, + gpointer user_data) +{ + atti_modifica ((Atti *)user_data); +} + +static void +atti_on_btn_elimina_clicked (GtkButton *button, + gpointer user_data) +{ + GtkTreeIter iter; + gint id; + + Atti *atti = (Atti *)user_data; + AttiPrivate *priv = ATTI_GET_PRIVATE (atti); + + if (gtk_tree_selection_get_selected (priv->selection, NULL, &iter)) + { + if (solipa_message_dialog (GTK_WIDGET (gtk_builder_get_object (priv->commons->gtkbuilder, "w_main")), + GTK_MESSAGE_QUESTION, + GTK_BUTTONS_YES_NO, + "Sicuro di voler eliminare l'atto selezionato?") == GTK_RESPONSE_YES) + { + gtk_tree_model_get (GTK_TREE_MODEL (priv->lstore_atti), &iter, + COL_ID, &id, + -1); + + gdaex_execute (priv->commons->gdaex, + g_strdup_printf ("UPDATE atti SET status = 'E' WHERE id = %d", id)); + + atti_carica (atti); + } + } + else + { + solipa_message_dialog (priv->selezione ? priv->widget : GTK_WIDGET (gtk_builder_get_object (priv->commons->gtkbuilder, "w_main")), + GTK_MESSAGE_WARNING, + GTK_BUTTONS_OK, + "Occorre prima selezionare un atto."); + } +} + +static void +atti_on_trv_atti_row_activated (GtkTreeView *tree_view, + GtkTreePath *tree_path, + GtkTreeViewColumn *column, + gpointer user_data) +{ + AttiPrivate *priv = ATTI_GET_PRIVATE ((Atti *)user_data); + + if (priv->selezione) + { + atti_selezionato ((Atti *)user_data); + } + else + { + atti_modifica ((Atti *)user_data); + } +} + +static void +atti_on_btn_esporta_clicked (GtkButton *button, + gpointer user_data) +{ + GtkWidget *transient; + guint ret; + + AttiPrivate *priv = ATTI_GET_PRIVATE ((Atti *)user_data); + + gchar **columns_title = g_strsplit ("ID|Numero|Tipo|Oggetto|Data ricezione|Data inizio pubblicazione|Data fine pubblicazione", + "|", -1); + + if (priv->selezione) + { + transient = priv->widget; + } + else + { + transient = GTK_WIDGET (gtk_builder_get_object (priv->commons->gtkbuilder, "w_main")); + } + + ret = solipa_gtktreemodel_to_csv_gui (priv->commons->solipa, GTK_WINDOW (transient), GTK_TREE_MODEL (priv->lstore_atti), + columns_title, g_strv_length (columns_title)); + if (ret == 1) + { + solipa_message_dialog (transient, + GTK_MESSAGE_INFO, + GTK_BUTTONS_OK, + "Salvataggio eseguito con successo."); + } + else if (ret == 0) + { + solipa_message_dialog (transient, + GTK_MESSAGE_WARNING, + GTK_BUTTONS_OK, + "Errore durante il salvataggio."); + } + + g_strfreev (columns_title); +} + +static void +atti_on_btn_ricerca_clicked (GtkButton *button, + gpointer user_data) +{ + GtkWidget *w; + + AttiPrivate *priv = ATTI_GET_PRIVATE ((Atti *)user_data); + + TrovaAtti *rf = trova_atti_new (priv->commons, priv->parametri_ricerca); + + g_signal_connect (G_OBJECT (rf), "filtra", + G_CALLBACK (atti_on_filtra), (Atti *)user_data); + + w = trova_atti_get_widget (rf); + if (priv->selezione) + { + gtk_window_set_transient_for (GTK_WINDOW (w), GTK_WINDOW (priv->widget)); + } + else + { + gtk_window_set_transient_for (GTK_WINDOW (w), GTK_WINDOW (gtk_builder_get_object (priv->commons->gtkbuilder, "w_main"))); + } + gtk_widget_show (w); +} + +static void +atti_on_btn_annulla_clicked (GtkButton *button, + gpointer user_data) +{ + AttiPrivate *priv = ATTI_GET_PRIVATE ((Atti *)user_data); + + gtk_widget_destroy (priv->widget); + g_object_unref (G_OBJECT (user_data)); +} + +static void +atti_on_btn_seleziona_clicked (GtkButton *button, + gpointer user_data) +{ + atti_selezionato ((Atti *)user_data); +} diff --git a/src/atti.h b/src/atti.h new file mode 100644 index 0000000..c10ef4b --- /dev/null +++ b/src/atti.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2013 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __ATTI_H__ +#define __ATTI_H__ + +#include +#include + +#include + +#include "commons.h" + +G_BEGIN_DECLS + + +#define TYPE_ATTI (atti_get_type ()) +#define ATTI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_ATTI, Atti)) +#define ATTI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_ATTI, AttiClass)) +#define IS_ATTI(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_ATTI)) +#define IS_ATTI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_ATTI)) +#define ATTI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_ATTI, AttiClass)) + + +typedef struct _Atti Atti; +typedef struct _AttiClass AttiClass; + +struct _Atti + { + GObject parent; + }; + +struct _AttiClass + { + GObjectClass parent_class; + + guint selezionato_signal_id; + }; + +GType atti_get_type (void) G_GNUC_CONST; + +Atti *atti_new (Commons *commons, gboolean selezione); + +GtkWidget *atti_get_widget (Atti *atti); + + +G_END_DECLS + +#endif /* __ATTI_H__ */ diff --git a/src/atto.c b/src/atto.c new file mode 100644 index 0000000..75dfbf3 --- /dev/null +++ b/src/atto.c @@ -0,0 +1,778 @@ +/* + * Copyright (C) 2013 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "atto.h" +#include "tipiatto.h" +#include "attoallegato.h" + +static void atto_class_init (AttoClass *klass); +static void atto_init (Atto *atto); + +static void atto_carica (Atto *atto); +static void atto_salva (Atto *atto, gboolean chiudi); + +static void atto_carica_allegati (Atto *atto); + +static void atto_modifica_allegato (Atto *atto); + +static void atto_on_tipo_atto_selezionato (gpointer instance, guint id, gpointer user_data); +static void atto_on_ufficio_selezionato (gpointer instance, guint id, gpointer user_data); +static gboolean atto_on_ufficio_ask_toshow (gpointer instance, guint id, gpointer user_data); +static void atto_on_allegato_aggiornato (gpointer instance, gpointer user_data); + +static gboolean atto_conferma_chiusura (Atto *atto); + +static void atto_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void atto_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +static gboolean atto_on_key_release_event (GtkWidget *widget, + GdkEventKey *event, + gpointer user_data); + +static gboolean atto_on_w_atto_delete_event (GtkWidget *widget, + GdkEvent *event, + gpointer user_data); + +static void atto_on_btn_tipo_atto_clicked (GtkButton *button, + gpointer user_data); +static void atto_on_btn_ufficio_clicked (GtkButton *button, + gpointer user_data); + +static void atto_on_btn_allegato_nuovo_clicked (GtkButton *button, + gpointer user_data); +static void atto_on_btn_allegato_modifica_clicked (GtkButton *button, + gpointer user_data); +static void atto_on_btn_allegato_elimina_clicked (GtkButton *button, + gpointer user_data); +static void atto_on_btn_allegato_apri_clicked (GtkButton *button, + gpointer user_data); +static void atto_on_trv_allegati_row_activated (GtkTreeView *tree_view, + GtkTreePath *tree_path, + GtkTreeViewColumn *column, + gpointer user_data); + +static void atto_on_btn_annulla_clicked (GtkButton *button, + gpointer user_data); +static void atto_on_btn_salva_clicked (GtkButton *button, + gpointer user_data); +static void atto_on_btn_salvachiudi_clicked (GtkButton *button, + gpointer user_data); + +#define ATTO_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TYPE_ATTO, AttoPrivate)) + +enum +{ + LBL_ID, + LSTORE_ALLEGATI +}; + +enum +{ + COL_ALLEGATI_ID, + COL_ALLEGATI_TITOLO, + COL_ALLEGATI_DESCRIZIONE, + COL_ALLEGATI_PERCORSO, + COL_ALLEGATI_CONTENUTO +}; + +typedef struct _AttoPrivate AttoPrivate; +struct _AttoPrivate + { + Commons *commons; + + GtkForm *form; + + GtkWidget *w; + + GObject **objects; + + GtkTreeSelection *sel_allegati; + + gint id; + }; + +G_DEFINE_TYPE (Atto, atto, G_TYPE_OBJECT) + +static void +atto_class_init (AttoClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (AttoPrivate)); + + object_class->set_property = atto_set_property; + object_class->get_property = atto_get_property; + + /** + * Atto::aggiornato: + * @atto: + * + */ + klass->aggiornato_signal_id = g_signal_new ("aggiornato", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, + NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); +} + +static void +atto_init (Atto *atto) +{ + AttoPrivate *priv = ATTO_GET_PRIVATE (atto); +} + +/** + * atto_new: + * @commons: + * @id: + * + * Returns: the newly created #Atto object. + */ +Atto +*atto_new (Commons *commons, gint id) +{ + GError *error; + AutozIResource *ires1; + + Atto *a = ATTO (g_object_new (atto_get_type (), NULL)); + + AttoPrivate *priv = ATTO_GET_PRIVATE (a); + + priv->commons = commons; + + error = NULL; + gtk_builder_add_objects_from_file (priv->commons->gtkbuilder, priv->commons->guifile, + g_strsplit ("w_atto" + "|lstore_atto_allegati", + "|", -1), + &error); + if (error != NULL) + { + g_warning ("Errore: %s.", error->message); + return NULL; + } + + priv->form = gtk_form_new (); + g_object_set (priv->form, "gdaex", priv->commons->gdaex, NULL); + gtk_form_load_from_file (priv->form, g_build_filename (priv->commons->formdir, "atto.form", NULL), priv->commons->gtkbuilder); + + priv->w = GTK_WIDGET (gtk_builder_get_object (priv->commons->gtkbuilder, "w_atto")); + + priv->objects = gtk_form_get_objects_by_name (priv->form, + "label3", + "lstore_atto_allegati", + NULL); + + priv->sel_allegati = gtk_tree_view_get_selection (GTK_TREE_VIEW (gtk_builder_get_object (priv->commons->gtkbuilder, "treeview3"))); + + g_object_set (gtk_builder_get_object (priv->commons->gtkbuilder, "gtkformdecoder2"), + "gdaex", priv->commons->organigramma_commons->gdaex, + NULL); + + g_signal_connect (priv->w, + "key-release-event", G_CALLBACK (atto_on_key_release_event), (gpointer)a); + g_signal_connect (priv->w, + "delete-event", G_CALLBACK (atto_on_w_atto_delete_event), (gpointer)a); + + g_signal_connect (gtk_builder_get_object (priv->commons->gtkbuilder, "gtkformdecoder1"), + "btn-browse-clicked", G_CALLBACK (atto_on_btn_tipo_atto_clicked), (gpointer)a); + g_signal_connect (gtk_builder_get_object (priv->commons->gtkbuilder, "gtkformdecoder2"), + "btn-browse-clicked", G_CALLBACK (atto_on_btn_ufficio_clicked), (gpointer)a); + + g_signal_connect (gtk_builder_get_object (priv->commons->gtkbuilder, "button39"), + "clicked", G_CALLBACK (atto_on_btn_allegato_nuovo_clicked), (gpointer)a); + g_signal_connect (gtk_builder_get_object (priv->commons->gtkbuilder, "button40"), + "clicked", G_CALLBACK (atto_on_btn_allegato_modifica_clicked), (gpointer)a); + g_signal_connect (gtk_builder_get_object (priv->commons->gtkbuilder, "button41"), + "clicked", G_CALLBACK (atto_on_btn_allegato_elimina_clicked), (gpointer)a); + g_signal_connect (gtk_builder_get_object (priv->commons->gtkbuilder, "button42"), + "clicked", G_CALLBACK (atto_on_btn_allegato_apri_clicked), (gpointer)a); + g_signal_connect (gtk_builder_get_object (priv->commons->gtkbuilder, "treeview3"), + "row-activated", G_CALLBACK (atto_on_trv_allegati_row_activated), (gpointer)a); + + g_signal_connect (gtk_builder_get_object (priv->commons->gtkbuilder, "button1"), + "clicked", G_CALLBACK (atto_on_btn_annulla_clicked), (gpointer)a); + g_signal_connect (gtk_builder_get_object (priv->commons->gtkbuilder, "button2"), + "clicked", G_CALLBACK (atto_on_btn_salva_clicked), (gpointer)a); + g_signal_connect (gtk_builder_get_object (priv->commons->gtkbuilder, "button3"), + "clicked", G_CALLBACK (atto_on_btn_salvachiudi_clicked), (gpointer)a); + + gtk_form_clear (priv->form); + + priv->id = id; + + if (priv->id == 0) + { + gtk_label_set_text (GTK_LABEL (priv->objects[LBL_ID]), ""); + + gtk_entry_set_text (GTK_ENTRY (gtk_builder_get_object (priv->commons->gtkbuilder, "entry4")), + solipa_gdatetime_format (g_date_time_add_days (g_date_time_new_now_local (), 2), "%d/%m/%Y")); + gtk_entry_set_text (GTK_ENTRY (gtk_builder_get_object (priv->commons->gtkbuilder, "entry5")), + solipa_gdatetime_format (g_date_time_add_days (g_date_time_new_now_local (), 17), "%d/%m/%Y")); + + gtk_form_set_as_origin (priv->form); + + gtk_form_set_sensitive_by_name (priv->form, FALSE, + "hbox31", + NULL); + } + else + { + gtk_label_set_text (GTK_LABEL (priv->objects[LBL_ID]), g_strdup_printf ("%d", priv->id)); + atto_carica (a); + } + + ires1 = autoz_get_resource_from_id (priv->commons->autoz, "messi_rw"); + if (!autoz_is_allowed (priv->commons->autoz, priv->commons->role_utente, ires1, FALSE)) + { + gtk_form_set_sensitive_by_name (priv->form, FALSE, + "button39", + "button41", + "button2", + "button3", + NULL); + } + + return a; +} + +/** + * atto_get_widget: + * @atto: + * + */ +GtkWidget +*atto_get_widget (Atto *atto) +{ + AttoPrivate *priv = ATTO_GET_PRIVATE (atto); + + return priv->w; +} + +/* PRIVATE */ +static void +atto_carica (Atto *atto) +{ + AttoPrivate *priv = ATTO_GET_PRIVATE (atto); + + if (gtk_form_fill_from_table (priv->form)) + { + atto_carica_allegati (atto); + } +} + +static void +atto_salva (Atto *atto, gboolean chiudi) +{ + gchar *sql; + + AttoClass *klass = ATTO_GET_CLASS (atto); + + AttoPrivate *priv = ATTO_GET_PRIVATE (atto); + + if (!gtk_form_check (priv->form, (priv->id != 0), NULL, TRUE, priv->w, TRUE)) + { + return; + } + + if (priv->id == 0) + { + sql = gtk_form_get_sql (priv->form, GTK_FORM_SQL_INSERT); + } + else + { + sql = gtk_form_get_sql (priv->form, GTK_FORM_SQL_UPDATE); + } + + if (gdaex_execute (priv->commons->gdaex, sql) == 1) + { + g_signal_emit (atto, klass->aggiornato_signal_id, 0); + + gtk_form_set_as_origin (priv->form); + + gtk_form_set_sensitive_by_name (priv->form, TRUE, + "hbox31", + NULL); + + if (priv->id == 0) + { + priv->id = strtol (gtk_label_get_text (GTK_LABEL (priv->objects[LBL_ID])), NULL, 10); + } + + solipa_message_dialog (priv->w, + GTK_MESSAGE_INFO, + GTK_BUTTONS_OK, + "Salvataggio eseguito con successo."); + + if (chiudi) + { + gtk_widget_destroy (priv->w); + g_object_unref (atto); + } + } + else + { + if (priv->id == 0) + { + gtk_label_set_text (GTK_LABEL (priv->objects[LBL_ID]), ""); + } + + solipa_message_dialog (priv->w, + GTK_MESSAGE_WARNING, + GTK_BUTTONS_OK, + "Errore durante il salvataggio."); + } +} + +static void +atto_carica_allegati (Atto *atto) +{ + GtkListStore *lstore; + GtkTreeIter iter; + GdaDataModel *dm; + + gchar *sql; + + gint rows; + gint row; + + AttoPrivate *priv = ATTO_GET_PRIVATE (atto); + + lstore = GTK_LIST_STORE (priv->objects[LSTORE_ALLEGATI]); + gtk_list_store_clear (lstore); + + sql = g_strdup_printf ("SELECT aa.id, aa.titolo, aa.descrizione," + " aa.percorso, aa.contenuto" + " FROM atto_allegati AS aa" + " WHERE aa.status <> 'E' AND aa.id_atti = %d" + " ORDER BY aa.titolo, aa.descrizione", + priv->id); + dm = gdaex_query (priv->commons->gdaex, sql); + g_free (sql); + if (dm != NULL) + { + rows = gda_data_model_get_n_rows (dm); + for (row = 0; row < rows; row++) + { + gtk_list_store_append (lstore, &iter); + gtk_list_store_set (lstore, &iter, + COL_ALLEGATI_ID, gdaex_data_model_get_field_value_integer_at (dm, row, "id"), + COL_ALLEGATI_TITOLO, gdaex_data_model_get_field_value_stringify_at (dm, row, "titolo"), + COL_ALLEGATI_DESCRIZIONE, gdaex_data_model_get_field_value_stringify_at (dm, row, "descrizione"), + COL_ALLEGATI_PERCORSO, gdaex_data_model_get_field_value_stringify_at (dm, row, "percorso"), + COL_ALLEGATI_CONTENUTO, gdaex_data_model_get_field_value_integer_at (dm, row, "contenuto"), + -1); + } + + g_object_unref (dm); + } +} + +static void +atto_modifica_allegato (Atto *atto) +{ + GtkTreeIter iter; + guint id; + + AttoPrivate *priv = ATTO_GET_PRIVATE (atto); + + if (gtk_tree_selection_get_selected (priv->sel_allegati, NULL, &iter)) + { + GtkWidget *w; + + gtk_tree_model_get (GTK_TREE_MODEL (priv->objects[LSTORE_ALLEGATI]), &iter, + COL_ALLEGATI_ID, &id, + -1); + + AttoAllegato *c = atto_allegato_new (priv->commons, id, 0); + + g_signal_connect (G_OBJECT (c), "aggiornato", + G_CALLBACK (atto_on_allegato_aggiornato), (gpointer)atto); + + w = atto_allegato_get_widget (c); + gtk_window_set_transient_for (GTK_WINDOW (w), GTK_WINDOW (priv->w)); + gtk_widget_show (w); + } + else + { + solipa_message_dialog (priv->w, + GTK_MESSAGE_WARNING, + GTK_BUTTONS_OK, + "Occorre prima selezionare un allegato."); + } +} + +static void +atto_on_allegato_aggiornato (gpointer instance, gpointer user_data) +{ + atto_carica_allegati ((Atto *)user_data); +} + +static void +atto_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + Atto *atto = ATTO (object); + AttoPrivate *priv = ATTO_GET_PRIVATE (atto); + + switch (property_id) + { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +atto_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + Atto *atto = ATTO (object); + AttoPrivate *priv = ATTO_GET_PRIVATE (atto); + + switch (property_id) + { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static gboolean +atto_conferma_chiusura (Atto *atto) +{ + gboolean ret; + + AttoPrivate *priv = ATTO_GET_PRIVATE (atto); + + ret = TRUE; + if (gtk_form_is_changed (priv->form)) + { + if (solipa_message_dialog (priv->w, + GTK_MESSAGE_QUESTION, + GTK_BUTTONS_YES_NO, + "Sicuro di voler chiudere senza salvare?") == GTK_RESPONSE_NO) + { + ret = FALSE; + } + } + + return ret; +} + +/* CALLBACK */ +static void +atto_on_tipo_atto_selezionato (gpointer instance, guint id, gpointer user_data) +{ + Atto *a = (Atto *)user_data; + AttoPrivate *priv = ATTO_GET_PRIVATE (a); + + gtk_form_widget_set_value_stringify (gtk_form_get_form_widget_from_name (priv->form, "gtkformdecoder1"), + g_strdup_printf ("%d", id)); +} + +static void +atto_on_ufficio_selezionato (gpointer instance, guint id, gpointer user_data) +{ + Atto *a = (Atto *)user_data; + AttoPrivate *priv = ATTO_GET_PRIVATE (a); + + gtk_form_widget_set_value_stringify (gtk_form_get_form_widget_from_name (priv->form, "gtkformdecoder2"), + g_strdup_printf ("%d", id)); + gtk_form_widget_set_value_stringify (gtk_form_get_form_widget_from_name (priv->form, "gtkformdecoder3"), + "0"); +} + +static gboolean +atto_on_ufficio_ask_toshow (gpointer instance, guint id, gpointer user_data) +{ + gboolean ret; + + Atto *a = (Atto *)user_data; + AttoPrivate *priv = ATTO_GET_PRIVATE (a); + + AutozIResource *ires1; + + ret = TRUE; + + /* per adesso controllo solo gli uffici */ + ires1 = autoz_get_resource_from_id (priv->commons->autoz, g_strdup_printf ("opengov_u_%d_r_0", id)); + ret = autoz_is_allowed (priv->commons->autoz, priv->commons->role_utente, ires1, FALSE); + + return ret; +} + +static gboolean +atto_on_key_release_event (GtkWidget *widget, + GdkEventKey *event, + gpointer user_data) +{ + if (event->keyval == GDK_Escape) + { + AttoPrivate *priv = ATTO_GET_PRIVATE ((Atto *)user_data); + + gtk_button_clicked (GTK_BUTTON (gtk_builder_get_object (priv->commons->gtkbuilder, "button18"))); + return TRUE; + } + return FALSE; +} + +static gboolean +atto_on_w_atto_delete_event (GtkWidget *widget, + GdkEvent *event, + gpointer user_data) +{ + return !atto_conferma_chiusura ((Atto *)user_data); +} + +static void +atto_on_btn_tipo_atto_clicked (GtkButton *button, + gpointer user_data) +{ + GtkWidget *w; + + Atto *atto = (Atto *)user_data; + AttoPrivate *priv = ATTO_GET_PRIVATE (atto); + + TipiAtto *c = tipi_atto_new (priv->commons, TRUE); + + g_signal_connect (G_OBJECT (c), "selezionato", + G_CALLBACK (atto_on_tipo_atto_selezionato), user_data); + + w = tipi_atto_get_widget (c); + gtk_window_set_transient_for (GTK_WINDOW (w), GTK_WINDOW (priv->w)); + gtk_widget_show (w); +} + +static void +atto_on_btn_ufficio_clicked (GtkButton *button, + gpointer user_data) +{ + GtkWidget *w; + + Atto *atto = (Atto *)user_data; + AttoPrivate *priv = ATTO_GET_PRIVATE (atto); + + OrganigrammaUffici *c = organigramma_uffici_new (priv->commons->organigramma_commons, TRUE); + + g_signal_connect (G_OBJECT (c), "selezionato", + G_CALLBACK (atto_on_ufficio_selezionato), user_data); + g_signal_connect (G_OBJECT (c), "ask-toshow", + G_CALLBACK (atto_on_ufficio_ask_toshow), user_data); + + w = organigramma_uffici_get_widget (c); + gtk_window_set_transient_for (GTK_WINDOW (w), GTK_WINDOW (priv->w)); + gtk_widget_show (w); +} + +static void +atto_on_btn_allegato_nuovo_clicked (GtkButton *button, + gpointer user_data) +{ + GtkWidget *w; + + Atto *atto = (Atto *)user_data; + AttoPrivate *priv = ATTO_GET_PRIVATE (atto); + + AttoAllegato *c = atto_allegato_new (priv->commons, 0, priv->id); + + g_signal_connect (G_OBJECT (c), "aggiornato", + G_CALLBACK (atto_on_allegato_aggiornato), user_data); + + w = atto_allegato_get_widget (c); + gtk_window_set_transient_for (GTK_WINDOW (w), GTK_WINDOW (priv->w)); + gtk_widget_show (w); + +} + +static void +atto_on_btn_allegato_modifica_clicked (GtkButton *button, + gpointer user_data) +{ + atto_modifica_allegato ((Atto *)user_data); +} + +static void +atto_on_btn_allegato_elimina_clicked (GtkButton *button, + gpointer user_data) +{ + GtkTreeIter iter; + guint id; + + Atto *atto = (Atto *)user_data; + AttoPrivate *priv = ATTO_GET_PRIVATE (atto); + + if (gtk_tree_selection_get_selected (priv->sel_allegati, NULL, &iter)) + { + if (solipa_message_dialog (priv->w, + GTK_MESSAGE_QUESTION, + GTK_BUTTONS_YES_NO, + "Sicuro di voler eliminare l'allegato selezionato?") == GTK_RESPONSE_YES) + { + gtk_tree_model_get (GTK_TREE_MODEL (priv->objects[LSTORE_ALLEGATI]), &iter, + COL_ALLEGATI_ID, &id, + -1); + + gdaex_execute (priv->commons->gdaex, + g_strdup_printf ("UPDATE atto_allegati SET status = 'E' WHERE id = %d", id)); + + atto_carica_allegati (atto); + } + } + else + { + solipa_message_dialog (priv->w, + GTK_MESSAGE_WARNING, + GTK_BUTTONS_OK, + "Occorre prima selezionare un allegato."); + } +} + +static void +atto_on_btn_allegato_apri_clicked (GtkButton *button, + gpointer user_data) +{ + GtkTreeIter iter; + const gchar *percorso; + guint id; + + gchar *sql; + + Atto *atto = (Atto *)user_data; + AttoPrivate *priv = ATTO_GET_PRIVATE (atto); + + if (gtk_tree_selection_get_selected (priv->sel_allegati, NULL, &iter)) + { + gtk_tree_model_get (GTK_TREE_MODEL (priv->objects[LSTORE_ALLEGATI]), &iter, + COL_ALLEGATI_ID, &id, + -1); + + /* devo utilizzare le funzioni native di postgres + * perché quelle di libgda non sembrano funzionare sotto windows */ + GError *error; + GdaDataModel *dm; + gchar *filename_orig; + gchar *filename_tmp; + gint fin; + + sql = g_strdup_printf ("SELECT percorso, contenuto FROM atto_allegati WHERE id = %d", id); + dm = gdaex_query (priv->commons->gdaex, sql); + g_free (sql); + if (dm != NULL && gda_data_model_get_n_rows (dm) > 0) + { + filename_orig = g_path_get_basename (gdaex_data_model_get_field_value_stringify_at (dm, 0, "percorso")); + + error = NULL; + fin = g_file_open_tmp (g_strdup_printf ("opengov-XXXXXX-%s", + filename_orig), + &filename_tmp, &error); + if (fin < 1 || error != NULL) + { + solipa_message_dialog (priv->w, + GTK_MESSAGE_WARNING, + GTK_BUTTONS_OK, + g_strdup_printf ("Errore nell'apertura dell'allegato: %s", + error != NULL && error->message != NULL ? error->message : "nessun dettaglio")); + close (fin); + return; + } + close (fin); + +#ifdef G_OS_WIN32 + filename_tmp = g_strjoinv ("\\", g_strsplit (filename_tmp, "/", -1)); +#endif + + PQexec (priv->commons->pgcon, "BEGIN"); + + lo_export (priv->commons->pgcon, + gdaex_data_model_get_field_value_integer_at (dm, 0, "contenuto"), + filename_tmp); + + PQexec (priv->commons->pgcon, "COMMIT"); + + solipa_allegato_apri_allegato (GTK_WINDOW (priv->w), filename_tmp); + } + else + { + solipa_message_dialog (priv->w, + GTK_MESSAGE_WARNING, + GTK_BUTTONS_OK, + "Occorre prima selezionare un allegato."); + } + } + else + { + solipa_message_dialog (priv->w, + GTK_MESSAGE_WARNING, + GTK_BUTTONS_OK, + "Occorre prima selezionare un allegato."); + } +} + +static void +atto_on_trv_allegati_row_activated (GtkTreeView *tree_view, + GtkTreePath *tree_path, + GtkTreeViewColumn *column, + gpointer user_data) +{ + atto_modifica_allegato ((Atto *)user_data); +} + +static void +atto_on_btn_annulla_clicked (GtkButton *button, + gpointer user_data) +{ + Atto *atto = (Atto *)user_data; + AttoPrivate *priv = ATTO_GET_PRIVATE (atto); + + if (atto_conferma_chiusura (atto)) gtk_widget_destroy (priv->w); +} + +static void +atto_on_btn_salva_clicked (GtkButton *button, + gpointer user_data) +{ + atto_salva ((Atto *)user_data, FALSE); +} + +static void +atto_on_btn_salvachiudi_clicked (GtkButton *button, + gpointer user_data) +{ + atto_salva ((Atto *)user_data, TRUE); +} diff --git a/src/atto.h b/src/atto.h new file mode 100644 index 0000000..d3ee4f5 --- /dev/null +++ b/src/atto.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2013 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __ATTO_H__ +#define __ATTO_H__ + +#include +#include + +#include + +#include "commons.h" + +G_BEGIN_DECLS + + +#define TYPE_ATTO (atto_get_type ()) +#define ATTO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_ATTO, Atto)) +#define ATTO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_ATTO, AttoClass)) +#define IS_ATTO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_ATTO)) +#define IS_ATTO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_ATTO)) +#define ATTO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_ATTO, AttoClass)) + + +typedef struct _Atto Atto; +typedef struct _AttoClass AttoClass; + +struct _Atto + { + GObject parent; + }; + +struct _AttoClass + { + GObjectClass parent_class; + + guint aggiornato_signal_id; + }; + +GType atto_get_type (void) G_GNUC_CONST; + +Atto *atto_new (Commons *commons, gint id); + +GtkWidget *atto_get_widget (Atto *atto); + + +G_END_DECLS + +#endif /* __ATTO_H__ */ diff --git a/src/attoallegato.c b/src/attoallegato.c new file mode 100644 index 0000000..8726127 --- /dev/null +++ b/src/attoallegato.c @@ -0,0 +1,446 @@ +/* + * Copyright (C) 2012 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include + +#include +#include +#include + +#include "attoallegato.h" + +static void atto_allegato_class_init (AttoAllegatoClass *klass); +static void atto_allegato_init (AttoAllegato *atto_allegato); + +static void atto_allegato_carica (AttoAllegato *atto_allegato); +static void atto_allegato_salva (AttoAllegato *atto_allegato, gboolean chiudi); + +static gboolean atto_allegato_conferma_chiusura (AttoAllegato *atto_allegato); + +static void atto_allegato_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void atto_allegato_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +static gboolean atto_allegato_on_w_atto_allegato_delete_event (GtkWidget *widget, + GdkEvent *event, + gpointer user_data); + +static void atto_allegato_on_btn_annulla_clicked (GtkButton *button, + gpointer user_data); +static void atto_allegato_on_btn_salva_clicked (GtkButton *button, + gpointer user_data); +static void atto_allegato_on_btn_salvachiudi_clicked (GtkButton *button, + gpointer user_data); + +#define ATTO_ALLEGATO_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TYPE_ATTO_ALLEGATO, AttoAllegatoPrivate)) + +enum +{ + LBL_ID, + LBL_ID_ATTO +}; + +typedef struct _AttoAllegatoPrivate AttoAllegatoPrivate; +struct _AttoAllegatoPrivate + { + Commons *commons; + + GtkForm *form; + + GtkWidget *w; + SolipaAllegato *sallegato; + + GObject **objects; + + gint id; + }; + +G_DEFINE_TYPE (AttoAllegato, atto_allegato, G_TYPE_OBJECT) + +static void +atto_allegato_class_init (AttoAllegatoClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (AttoAllegatoPrivate)); + + object_class->set_property = atto_allegato_set_property; + object_class->get_property = atto_allegato_get_property; + + /** + * AttoAllegato::aggiornato: + * @atto_allegato: + * + */ + klass->aggiornato_signal_id = g_signal_new ("aggiornato", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, + NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, + 0); +} + +static void +atto_allegato_init (AttoAllegato *atto_allegato) +{ + AttoAllegatoPrivate *priv = ATTO_ALLEGATO_GET_PRIVATE (atto_allegato); +} + +/** + * atto_allegato_new: + * @commons: + * @id: + * @id_atto: + * + * Returns: the newly created #AttoAllegato object. + */ +AttoAllegato +*atto_allegato_new (Commons *commons, guint id, guint id_atto) +{ + GError *error; + AutozIResource *ires1; + + AttoAllegato *a = ATTO_ALLEGATO (g_object_new (atto_allegato_get_type (), NULL)); + + AttoAllegatoPrivate *priv = ATTO_ALLEGATO_GET_PRIVATE (a); + + priv->commons = commons; + + error = NULL; + gtk_builder_add_objects_from_file (priv->commons->gtkbuilder, priv->commons->guifile, + g_strsplit ("w_atto_allegato", "|", -1), + &error); + if (error != NULL) + { + g_warning ("Errore: %s.", error->message); + return NULL; + } + + priv->form = gtk_form_new (); + g_object_set (priv->form, "gdaex", priv->commons->gdaex, NULL); + gtk_form_load_from_file (priv->form, g_build_filename (priv->commons->formdir, "attoallegato.form", NULL), priv->commons->gtkbuilder); + + g_object_set (priv->form, "gdaex", priv->commons->gdaex, NULL); + + priv->w = GTK_WIDGET (gtk_builder_get_object (priv->commons->gtkbuilder, "w_atto_allegato")); + + priv->objects = gtk_form_get_objects_by_name (priv->form, + "label324", + "label330", + NULL); + + priv->sallegato = solipa_allegato_new (commons->solipa); + if (priv->sallegato != NULL) + { + solipa_allegato_add_to_gtkform (priv->sallegato, priv->form, + "percorso", "data_file", "dimensione_file"); + solipa_allegato_con_salva_in_db (priv->sallegato, FALSE); + gtk_container_add (GTK_CONTAINER (gtk_builder_get_object (priv->commons->gtkbuilder, "alignment32")), + solipa_allegato_get_widget (priv->sallegato)); + } + + g_signal_connect (priv->w, + "delete-event", G_CALLBACK (atto_allegato_on_w_atto_allegato_delete_event), (gpointer)a); + + g_signal_connect (gtk_builder_get_object (priv->commons->gtkbuilder, "button125"), + "clicked", G_CALLBACK (atto_allegato_on_btn_annulla_clicked), (gpointer)a); + g_signal_connect (gtk_builder_get_object (priv->commons->gtkbuilder, "button126"), + "clicked", G_CALLBACK (atto_allegato_on_btn_salva_clicked), (gpointer)a); + g_signal_connect (gtk_builder_get_object (priv->commons->gtkbuilder, "button31"), + "clicked", G_CALLBACK (atto_allegato_on_btn_salvachiudi_clicked), (gpointer)a); + + gtk_form_clear (priv->form); + + priv->id = id; + if (priv->id == 0) + { + gtk_label_set_text (GTK_LABEL (priv->objects[LBL_ID]), ""); + gtk_label_set_text (GTK_LABEL (priv->objects[LBL_ID_ATTO]), g_strdup_printf ("%d", id_atto)); + + if (priv->sallegato != NULL) + { + solipa_allegato_set_salva_in_db (priv->sallegato, TRUE); + } + + gtk_form_set_as_origin (priv->form); + } + else + { + gtk_label_set_text (GTK_LABEL (priv->objects[LBL_ID]), g_strdup_printf ("%d", priv->id)); + atto_allegato_carica (a); + } + + ires1 = autoz_get_resource_from_id (priv->commons->autoz, "opengov_rw"); + if (!autoz_is_allowed (priv->commons->autoz, priv->commons->role_utente, ires1, FALSE)) + { + gtk_widget_set_sensitive (GTK_WIDGET (gtk_builder_get_object (commons->gtkbuilder, "button126")), FALSE); + gtk_widget_set_sensitive (GTK_WIDGET (gtk_builder_get_object (commons->gtkbuilder, "button31")), FALSE); + } + + return a; +} + +/** + * atto_allegato_get_widget: + * @atto_allegato: + * + */ +GtkWidget +*atto_allegato_get_widget (AttoAllegato *atto_allegato) +{ + AttoAllegatoPrivate *priv = ATTO_ALLEGATO_GET_PRIVATE (atto_allegato); + + return priv->w; +} + +/* PRIVATE */ +static void +atto_allegato_carica (AttoAllegato *atto_allegato) +{ + AttoAllegatoPrivate *priv = ATTO_ALLEGATO_GET_PRIVATE (atto_allegato); + + if (gtk_form_fill_from_table (priv->form)) + { + solipa_allegato_set_salva_in_db (priv->sallegato, TRUE); + } +} + +static void +atto_allegato_salva (AttoAllegato *atto_allegato, gboolean chiudi) +{ + gchar *sql; + GtkWidget *dialog; + + AttoAllegatoClass *klass = ATTO_ALLEGATO_GET_CLASS (atto_allegato); + + AttoAllegatoPrivate *priv = ATTO_ALLEGATO_GET_PRIVATE (atto_allegato); + + if (!gtk_form_check (priv->form, (priv->id != 0), NULL, TRUE, priv->w, TRUE)) + { + return; + } + + if (priv->id == 0) + { + sql = gtk_form_get_sql (priv->form, GTK_FORM_SQL_INSERT); + } + else + { + sql = gtk_form_get_sql (priv->form, GTK_FORM_SQL_UPDATE); + } + + if (gdaex_execute (priv->commons->gdaex, sql) == 1) + { + g_free (sql); + + g_signal_emit (atto_allegato, klass->aggiornato_signal_id, 0); + + gtk_form_set_as_origin (priv->form); + + if (priv->id == 0) + { + priv->id = strtol (gtk_label_get_text (GTK_LABEL (priv->objects[LBL_ID])), NULL, 10); + } + + /* salvo l'atto_allegato nel db */ + /* devo utilizzare le funzioni native di postgres + * perché quelle di libgda non sembrano funzionare sotto windows */ + Oid oid; + const gchar *percorso; + + percorso = solipa_allegato_get_percorso (priv->sallegato); + + if (PQexec (priv->commons->pgcon, "BEGIN") == NULL) + { + if (priv->id == 0) + { + gtk_label_set_text (GTK_LABEL (priv->objects[LBL_ID]), ""); + } + + solipa_message_dialog (priv->w, + GTK_MESSAGE_WARNING, + GTK_BUTTONS_OK, + "Errore durante il salvataggio: allegato non importato nel database (impossibile aprire la transazione)."); + return; + } + + oid = lo_import (priv->commons->pgcon, percorso); + + if (oid > 0) + { + sql = g_strdup_printf ("UPDATE atto_allegati " + " SET contenuto = %d," + " percorso = '%s'" + " WHERE id = %d", + oid, + gdaex_strescape (g_path_get_basename (percorso), NULL), + priv->id); + if (gdaex_execute (priv->commons->gdaex, sql) < 1) + { + g_free (sql); + + if (priv->id == 0) + { + gtk_label_set_text (GTK_LABEL (priv->objects[LBL_ID]), ""); + } + + solipa_message_dialog (priv->w, + GTK_MESSAGE_WARNING, + GTK_BUTTONS_OK, + "Errore durante il salvataggio."); + return; + } + g_free (sql); + + atto_allegato_carica (atto_allegato); + } + else + { + if (priv->id == 0) + { + gtk_label_set_text (GTK_LABEL (priv->objects[LBL_ID]), ""); + } + + solipa_message_dialog (priv->w, + GTK_MESSAGE_WARNING, + GTK_BUTTONS_OK, + "Errore durante il salvataggio: allegato non importato nel database."); + return; + } + + PQexec (priv->commons->pgcon, "COMMIT"); + + solipa_message_dialog (priv->w, + GTK_MESSAGE_INFO, + GTK_BUTTONS_OK, + "Salvataggio eseguito con successo."); + + if (chiudi) + { + gtk_widget_destroy (priv->w); + g_object_unref (atto_allegato); + } + } + else + { + g_free (sql); + + if (priv->id == 0) + { + gtk_label_set_text (GTK_LABEL (priv->objects[LBL_ID]), ""); + } + + solipa_message_dialog (priv->w, + GTK_MESSAGE_WARNING, + GTK_BUTTONS_OK, + "Errore durante il salvataggio."); + } +} + +static void +atto_allegato_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + AttoAllegato *atto_allegato = ATTO_ALLEGATO (object); + AttoAllegatoPrivate *priv = ATTO_ALLEGATO_GET_PRIVATE (atto_allegato); + + switch (property_id) + { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +atto_allegato_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + AttoAllegato *atto_allegato = ATTO_ALLEGATO (object); + AttoAllegatoPrivate *priv = ATTO_ALLEGATO_GET_PRIVATE (atto_allegato); + + switch (property_id) + { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static gboolean +atto_allegato_conferma_chiusura (AttoAllegato *atto_allegato) +{ + gboolean ret; + + AttoAllegatoPrivate *priv = ATTO_ALLEGATO_GET_PRIVATE (atto_allegato); + + ret = TRUE; + if (gtk_form_is_changed (priv->form)) + { + if (solipa_message_dialog (priv->w, + GTK_MESSAGE_QUESTION, + GTK_BUTTONS_YES_NO, + "Sicuro di voler chiudere senza salvare?") == GTK_RESPONSE_NO) + { + ret = FALSE; + } + } + + return ret; +} + +/* CALLBACK */ +static gboolean +atto_allegato_on_w_atto_allegato_delete_event (GtkWidget *widget, + GdkEvent *event, + gpointer user_data) +{ + return !atto_allegato_conferma_chiusura ((AttoAllegato *)user_data); +} + +static void +atto_allegato_on_btn_annulla_clicked (GtkButton *button, + gpointer user_data) +{ + AttoAllegato *allegato = (AttoAllegato *)user_data; + + AttoAllegatoPrivate *priv = ATTO_ALLEGATO_GET_PRIVATE (allegato); + + if (atto_allegato_conferma_chiusura (allegato)) gtk_widget_destroy (priv->w); +} + +static void +atto_allegato_on_btn_salva_clicked (GtkButton *button, + gpointer user_data) +{ + atto_allegato_salva ((AttoAllegato *)user_data, FALSE); +} + +static void +atto_allegato_on_btn_salvachiudi_clicked (GtkButton *button, + gpointer user_data) +{ + atto_allegato_salva ((AttoAllegato *)user_data, TRUE); +} diff --git a/src/attoallegato.h b/src/attoallegato.h new file mode 100644 index 0000000..96687f4 --- /dev/null +++ b/src/attoallegato.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2012 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __ATTO_ALLEGATO_H__ +#define __ATTO_ALLEGATO_H__ + +#include +#include + +#include + +#include "commons.h" + +G_BEGIN_DECLS + + +#define TYPE_ATTO_ALLEGATO (atto_allegato_get_type ()) +#define ATTO_ALLEGATO(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_ATTO_ALLEGATO, AttoAllegato)) +#define ATTO_ALLEGATO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_ATTO_ALLEGATO, AttoAllegatoClass)) +#define IS_ATTO_ALLEGATO(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_ATTO_ALLEGATO)) +#define IS_ATTO_ALLEGATO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_ATTO_ALLEGATO)) +#define ATTO_ALLEGATO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_ATTO_ALLEGATO, AttoAllegatoClass)) + + +typedef struct _AttoAllegato AttoAllegato; +typedef struct _AttoAllegatoClass AttoAllegatoClass; + +struct _AttoAllegato + { + GObject parent; + }; + +struct _AttoAllegatoClass + { + GObjectClass parent_class; + + guint aggiornato_signal_id; + }; + +GType atto_allegato_get_type (void) G_GNUC_CONST; + +AttoAllegato *atto_allegato_new (Commons *commons, guint id, guint id_atto); + +GtkWidget *atto_allegato_get_widget (AttoAllegato *atto_allegato); + + +G_END_DECLS + +#endif /* __ATTO_ALLEGATO_H__ */ diff --git a/src/main.c b/src/main.c index fd8b17e..f712ebe 100644 --- a/src/main.c +++ b/src/main.c @@ -34,6 +34,7 @@ #include #include "commons.h" +#include "atti.h" #include "tipiatto.h" static Commons *commons; @@ -104,6 +105,19 @@ main_set_vbx_body_child (GtkWidget *wchild, GObject *ochild) gtk_widget_grab_focus (wchild); } +G_MODULE_EXPORT void +on_mnu_albo_atti_activate (GtkMenuItem *menuitem, + gpointer user_data) +{ + GtkWidget *vbx; + + Atti *m = atti_new (commons, FALSE); + + vbx = atti_get_widget (m); + + main_set_vbx_body_child (vbx, G_OBJECT (m)); +} + G_MODULE_EXPORT void on_mnu_tabelle_tipi_atto_activate (GtkMenuItem *menuitem, gpointer user_data) diff --git a/src/trovaatti.c b/src/trovaatti.c new file mode 100644 index 0000000..8195eff --- /dev/null +++ b/src/trovaatti.c @@ -0,0 +1,345 @@ +/* + * Copyright (C) 2013 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include + +#include +#include + +#include + +#include "trovaatti.h" +#include "tipiatto.h" + +static void trova_atti_class_init (TrovaAttiClass *klass); +static void trova_atti_init (TrovaAtti *ricerca_atti); + +static void trova_atti_on_tipo_atto_selezionato (gpointer instance, guint id, gpointer user_data); +static void trova_atti_on_ufficio_selezionato (gpointer instance, guint id, gpointer user_data); +static gboolean trova_atti_on_ufficio_ask_toshow (gpointer instance, guint id, gpointer user_data); + +static void trova_atti_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void trova_atti_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); + +static gboolean trova_atti_on_key_release_event (GtkWidget *widget, + GdkEventKey *event, + gpointer user_data); + +static void trova_atti_on_btn_tipo_atto_clicked (GtkButton *button, + gpointer user_data); + +static void trova_atti_on_btn_ufficio_clicked (GtkButton *button, + gpointer user_data); + +static void trova_atti_on_btn_pulisci_clicked (GtkButton *button, + gpointer user_data); +static void trova_atti_on_btn_annulla_clicked (GtkButton *button, + gpointer user_data); +static void trova_atti_on_btn_ok_clicked (GtkButton *button, + gpointer user_data); + +#define TROVA_ATTI_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TYPE_TROVA_ATTI, TrovaAttiPrivate)) + +typedef struct _TrovaAttiPrivate TrovaAttiPrivate; +struct _TrovaAttiPrivate + { + Commons *commons; + + GtkForm *form; + + GtkWidget *w; + }; + +G_DEFINE_TYPE (TrovaAtti, trova_atti, G_TYPE_OBJECT) + +static void +trova_atti_class_init (TrovaAttiClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (object_class, sizeof (TrovaAttiPrivate)); + + object_class->set_property = trova_atti_set_property; + object_class->get_property = trova_atti_get_property; + + /** + * TrovaAtti::filtra: + */ + klass->filtra_signal_id = g_signal_new ("filtra", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, + NULL, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, + 1, G_TYPE_POINTER); +} + +static void +trova_atti_init (TrovaAtti *ricerca_atti) +{ + TrovaAttiPrivate *priv = TROVA_ATTI_GET_PRIVATE (ricerca_atti); +} + +/** + * trova_atti_new: + * @commons: + * @values: + * + * Returns: the newly created #TrovaAtti object. + */ +TrovaAtti +*trova_atti_new (Commons *commons, GHashTable *values) +{ + GError *error; + + TrovaAtti *a = TROVA_ATTI (g_object_new (trova_atti_get_type (), NULL)); + + TrovaAttiPrivate *priv = TROVA_ATTI_GET_PRIVATE (a); + + priv->commons = commons; + + error = NULL; + gtk_builder_add_objects_from_file (priv->commons->gtkbuilder, priv->commons->guifile, + g_strsplit ("w_trova_atti", "|", -1), + &error); + if (error != NULL) + { + g_warning ("Errore: %s.", error->message); + return NULL; + } + + priv->form = gtk_form_new (); + g_object_set (priv->form, "gdaex", priv->commons->gdaex, NULL); + gtk_form_load_from_file (priv->form, g_build_filename (priv->commons->formdir, "trovaatti.form", NULL), priv->commons->gtkbuilder); + + priv->w = GTK_WIDGET (gtk_builder_get_object (priv->commons->gtkbuilder, "w_trova_atti")); + + g_signal_connect (priv->w, + "key-release-event", G_CALLBACK (trova_atti_on_key_release_event), (gpointer)a); + + g_object_set (gtk_builder_get_object (priv->commons->gtkbuilder, "gtkformdecoder15"), + "gdaex", priv->commons->organigramma_commons->gdaex, + NULL); + + g_signal_connect (gtk_builder_get_object (priv->commons->gtkbuilder, "gtkformdecoder4"), + "btn-browse-clicked", G_CALLBACK (trova_atti_on_btn_tipo_atto_clicked), (gpointer)a); + + g_signal_connect (gtk_builder_get_object (priv->commons->gtkbuilder, "gtkformdecoder15"), + "btn-browse-clicked", G_CALLBACK (trova_atti_on_btn_ufficio_clicked), (gpointer)a); + + g_signal_connect (gtk_builder_get_object (priv->commons->gtkbuilder, "button20"), + "clicked", G_CALLBACK (trova_atti_on_btn_pulisci_clicked), (gpointer)a); + g_signal_connect (gtk_builder_get_object (priv->commons->gtkbuilder, "button21"), + "clicked", G_CALLBACK (trova_atti_on_btn_annulla_clicked), (gpointer)a); + g_signal_connect (gtk_builder_get_object (priv->commons->gtkbuilder, "button22"), + "clicked", G_CALLBACK (trova_atti_on_btn_ok_clicked), (gpointer)a); + + gtk_form_clear (priv->form); + if (values != NULL) + { + gtk_form_fill_from_hashtable (priv->form, values); + } + + return a; +} + +/** + * trova_atti_get_widget: + * @ricerca_atti: + * + */ +GtkWidget +*trova_atti_get_widget (TrovaAtti *ricerca_atti) +{ + TrovaAttiPrivate *priv = TROVA_ATTI_GET_PRIVATE (ricerca_atti); + + return priv->w; +} + +/* PRIVATE */ +static void +trova_atti_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) +{ + TrovaAtti *ricerca_atti = TROVA_ATTI (object); + TrovaAttiPrivate *priv = TROVA_ATTI_GET_PRIVATE (ricerca_atti); + + switch (property_id) + { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +trova_atti_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) +{ + TrovaAtti *ricerca_atti = TROVA_ATTI (object); + TrovaAttiPrivate *priv = TROVA_ATTI_GET_PRIVATE (ricerca_atti); + + switch (property_id) + { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +/* CALLBACK */ +static void +trova_atti_on_tipo_atto_selezionato (gpointer instance, guint id, gpointer user_data) +{ + TrovaAtti *a = (TrovaAtti *)user_data; + TrovaAttiPrivate *priv = TROVA_ATTI_GET_PRIVATE (a); + + gtk_form_widget_set_value_stringify (gtk_form_get_form_widget_from_name (priv->form, "gtkformdecoder4"), + g_strdup_printf ("%d", id)); +} + +static void +trova_atti_on_ufficio_selezionato (gpointer instance, guint id, gpointer user_data) +{ + TrovaAtti *a = (TrovaAtti *)user_data; + TrovaAttiPrivate *priv = TROVA_ATTI_GET_PRIVATE (a); + + gtk_form_widget_set_value_stringify (gtk_form_get_form_widget_from_name (priv->form, "gtkformdecoder15"), + g_strdup_printf ("%d", id)); +} + +static gboolean +trova_atti_on_ufficio_ask_toshow (gpointer instance, guint id, gpointer user_data) +{ + gboolean ret; + + TrovaAtti *a = (TrovaAtti *)user_data; + TrovaAttiPrivate *priv = TROVA_ATTI_GET_PRIVATE (a); + + AutozIResource *ires1; + + ret = TRUE; + + /* per adesso controllo solo gli uffici */ + ires1 = autoz_get_resource_from_id (priv->commons->autoz, g_strdup_printf ("opengov_u_%d_r_0", id)); + ret = autoz_is_allowed (priv->commons->autoz, priv->commons->role_utente, ires1, FALSE); + + return ret; +} + +static gboolean +trova_atti_on_key_release_event (GtkWidget *widget, + GdkEventKey *event, + gpointer user_data) +{ + if (event->keyval == GDK_Escape) + { + TrovaAttiPrivate *priv = TROVA_ATTI_GET_PRIVATE ((TrovaAtti *)user_data); + + gtk_button_clicked (GTK_BUTTON (gtk_builder_get_object (priv->commons->gtkbuilder, "button21"))); + return TRUE; + } + + return FALSE; +} + +static void +trova_atti_on_btn_tipo_atto_clicked (GtkButton *button, + gpointer user_data) +{ + GtkWidget *w; + + TrovaAtti *trova_atti = (TrovaAtti *)user_data; + TrovaAttiPrivate *priv = TROVA_ATTI_GET_PRIVATE (trova_atti); + + TipiAtto *c = tipi_atto_new (priv->commons, TRUE); + + g_signal_connect (G_OBJECT (c), "selezionato", + G_CALLBACK (trova_atti_on_tipo_atto_selezionato), user_data); + + w = tipi_atto_get_widget (c); + gtk_window_set_transient_for (GTK_WINDOW (w), GTK_WINDOW (priv->w)); + gtk_widget_show (w); +} + +static void +trova_atti_on_btn_ufficio_clicked (GtkButton *button, + gpointer user_data) +{ + GtkWidget *w; + + TrovaAtti *trova_atti = (TrovaAtti *)user_data; + TrovaAttiPrivate *priv = TROVA_ATTI_GET_PRIVATE (trova_atti); + + OrganigrammaUffici *c = organigramma_uffici_new (priv->commons->organigramma_commons, TRUE); + + g_signal_connect (G_OBJECT (c), "selezionato", + G_CALLBACK (trova_atti_on_ufficio_selezionato), user_data); + g_signal_connect (G_OBJECT (c), "ask-toshow", + G_CALLBACK (trova_atti_on_ufficio_ask_toshow), user_data); + + w = organigramma_uffici_get_widget (c); + gtk_window_set_transient_for (GTK_WINDOW (w), GTK_WINDOW (priv->w)); + gtk_widget_show (w); +} + +static void +trova_atti_on_btn_pulisci_clicked (GtkButton *button, + gpointer user_data) +{ + TrovaAttiPrivate *priv = TROVA_ATTI_GET_PRIVATE ((TrovaAtti *)user_data); + + gtk_form_clear (priv->form); +} + +static void +trova_atti_on_btn_annulla_clicked (GtkButton *button, + gpointer user_data) +{ + TrovaAttiPrivate *priv = TROVA_ATTI_GET_PRIVATE ((TrovaAtti *)user_data); + + gtk_widget_destroy (priv->w); + g_object_unref (user_data); +} + +static void +trova_atti_on_btn_ok_clicked (GtkButton *button, + gpointer user_data) +{ + TrovaAtti *ricerca_atti = (TrovaAtti *)user_data; + TrovaAttiClass *klass = TROVA_ATTI_GET_CLASS (ricerca_atti); + + TrovaAttiPrivate *priv = TROVA_ATTI_GET_PRIVATE (ricerca_atti); + + if (!gtk_form_check (priv->form, FALSE, NULL, TRUE, priv->w, TRUE)) + { + return; + } + + g_signal_emit (ricerca_atti, klass->filtra_signal_id, 0, gtk_form_get_values_as_hashtable (priv->form)); + + gtk_widget_destroy (priv->w); + g_object_unref (user_data); +} diff --git a/src/trovaatti.h b/src/trovaatti.h new file mode 100644 index 0000000..ca8ede1 --- /dev/null +++ b/src/trovaatti.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2013 Andrea Zagli + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __TROVA_ATTI_H__ +#define __TROVA_ATTI_H__ + +#include +#include + +#include + +#include "commons.h" + +G_BEGIN_DECLS + + +#define TYPE_TROVA_ATTI (trova_atti_get_type ()) +#define TROVA_ATTI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_TROVA_ATTI, TrovaAtti)) +#define TROVA_ATTI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_TROVA_ATTI, TrovaAttiClass)) +#define IS_TROVA_ATTI(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_TROVA_ATTI)) +#define IS_TROVA_ATTI_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_TROVA_ATTI)) +#define TROVA_ATTI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_TROVA_ATTI, TrovaAttiClass)) + + +typedef struct _TrovaAtti TrovaAtti; +typedef struct _TrovaAttiClass TrovaAttiClass; + +struct _TrovaAtti + { + GObject parent; + }; + +struct _TrovaAttiClass + { + GObjectClass parent_class; + + guint filtra_signal_id; + }; + +GType trova_atti_get_type (void) G_GNUC_CONST; + +TrovaAtti *trova_atti_new (Commons *commons, GHashTable *values); + +GtkWidget *trova_atti_get_widget (TrovaAtti *trova_atti); + + +G_END_DECLS + +#endif /* __TROVA_ATTI_H__ */ -- 2.49.0