jdruba
Anmeldungsdatum: 9. Dezember 2008
Beiträge: 48
Wohnort: WOLFENBÜTTEL - GERMANY
|
Guten Abend,
ich würde gerne ein ganz einfaches Gnome-Applet erstellen. Es soll einfach nur eine Zahl aus einer Datei, in der auch nur diese Zahl steht ausgegeben werden und ab und zu soll die zahl aktualisiert werden. Allerdings kann ich nirgends eine Anleitung finden, wie man gnome applets erstellt. Kennt jemand von euch eine (möglichst deutsche) Anleitung, oder kann mir jemand sonst irgendwie weiterhelfen ?
gruß
jdruba
|
YEPHENAS
Anmeldungsdatum: 8. Juni 2009
Beiträge: 352
|
jdruba schrieb: Guten Abend,
ich würde gerne ein ganz einfaches Gnome-Applet erstellen. Es soll einfach nur eine Zahl aus einer Datei, in der auch nur diese Zahl steht ausgegeben werden und ab und zu soll die zahl aktualisiert werden. Allerdings kann ich nirgends eine Anleitung finden, wie man gnome applets erstellt. Kennt jemand von euch eine (möglichst deutsche) Anleitung, oder kann mir jemand sonst irgendwie weiterhelfen ?
gruß
jdruba
Das Applet ist ein einfaches C-Programm: 1
2
3
4
5
6
7
8
9
10
11
12
13
14 | #include <gtk/gtk.h>
#include <panel-applet.h>
gboolean applet_main (PanelApplet *applet, const char *iid, gpointer data)
{
GtkWidget *label = gtk_label_new ("Hallo Welt!");
gtk_container_add (GTK_CONTAINER (applet), label);
gtk_widget_show_all (GTK_WIDGET (applet));
return TRUE;
}
PANEL_APPLET_BONOBO_FACTORY ("OAFIID:MeinApplet_Factory", PANEL_TYPE_APPLET,
"Mein erstes Applet", "0", applet_main, NULL);
|
In der applet_main-Funktion kannst du ganz normal Widgets erstellen und dem Applet hinzufügen (PanelApplet ist ein GtkContainer). Kompilieren mit: gcc myapplet.c -o myapplet `pkg-config libpanelapplet-2.0 --libs --cflags` (Ubuntu-Paket libpanel-applet2-dev muss installiert sein) Dann benötigst du noch eine XML-Datei mit der Dateiendung .server (z.B. myapplet.server): 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 | <oaf_info>
<oaf_server iid="OAFIID:MeinApplet_Factory" type="exe" location="/pfad/zu/myapplet">
<oaf_attribute name="repo_ids" type="stringv">
<item value="IDL:Bonobo/GenericFactory:1.0"/>
<item value="IDL:Bonobo/Unknown:1.0"/>
</oaf_attribute>
<oaf_attribute name="name" type="string" value="My Applet Factory"/>
<oaf_attribute name="description" type="string" value="Factory to create my applet"/>
</oaf_server>
<oaf_server iid="OAFIID:MeinApplet" type="factory" location="OAFIID:MeinApplet_Factory">
<oaf_attribute name="repo_ids" type="stringv">
<item value="IDL:GNOME/Vertigo/PanelAppletShell:1.0"/>
<item value="IDL:Bonobo/Control:1.0"/>
<item value="IDL:Bonobo/Unknown:1.0"/>
</oaf_attribute>
<oaf_attribute name="name" type="string" value="Mein erstes Applet"/>
<oaf_attribute name="description" type="string" value="Dies ist mein erstes Applet"/>
<oaf_attribute name="panel:category" type="string" value="Utility"/>
<oaf_attribute name="panel:icon" type="string" value="computer.png"/>
</oaf_server>
</oaf_info>
|
/pfad/zu/myapplet in Zeile 3 musst du ersetzen, so dass es auf dein kompiliertes Applet zeigt. Die IIDs im Programm und in der XML-Datei müssen übereinstimmen. Diese XML-Datei schiebst du nach /usr/lib/bonobo/servers/ Dann kannst du das Applet ganz normal zum Panel über die Auswahlliste hinzufügen oder separat in einem Fenster testen: panel-test-applets --iid "OAFIID:MeinApplet" Für dein weiteres Vorhaben wirst du wahrscheinlich diese Funktionen benötigen: g_timeout_add_seconds, g_file_get_contents, gtk_label_set_text
|
jdruba
(Themenstarter)
Anmeldungsdatum: 9. Dezember 2008
Beiträge: 48
Wohnort: WOLFENBÜTTEL - GERMANY
|
cool, danke für die ausführliche Hilfe, das Testapplet funktioniert super, den Rest werde ich wohl so schaffen .
|
jdruba
(Themenstarter)
Anmeldungsdatum: 9. Dezember 2008
Beiträge: 48
Wohnort: WOLFENBÜTTEL - GERMANY
|
oder auch nicht ☹
ich habe jetzt den quellcode hierhin abgeändert und musste feststellen dass es deutlich schwerer ist nen c-Programm zusammenzubasteln als nen bash-script ...
So sieht mein code jetzt aus:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 | #include <gtk/gtk.h>
#include <panel-applet.h>
gboolean applet_main (PanelApplet *applet, const char *iid, gpointer data)
{
gboolean asd;
gchar *contents;
//hallo welt output in label
GtkWidget *label = gtk_label_new ("Hallo welt!");
//text aus input.txt holen
asd = g_file_get_contents ("input.txt", &contents, NULL, NULL);
//ausgabe updaten
gtk_label_set_text(GTK_LABEL(label), contents);
gtk_container_add (GTK_CONTAINER (applet), label);
gtk_widget_show_all (GTK_WIDGET (applet));
return TRUE;
}
PANEL_APPLET_BONOBO_FACTORY ("OAFIID:MeinApplet_Factory", PANEL_TYPE_APPLET,
"Mein erstes Applet", "0", applet_main, NULL);
|
jetzt bekomme ich allerdings eine leere Ausgabe. Woran liegt das, oder habe ich ne falsche Variable benutzt?
|
YEPHENAS
Anmeldungsdatum: 8. Juni 2009
Beiträge: 352
|
jdruba schrieb: oder auch nicht ☹
ich habe jetzt den quellcode hierhin abgeändert und musste feststellen dass es deutlich schwerer ist nen c-Programm zusammenzubasteln als nen bash-script ...
So sieht mein code jetzt aus:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 | #include <gtk/gtk.h>
#include <panel-applet.h>
gboolean applet_main (PanelApplet *applet, const char *iid, gpointer data)
{
gboolean asd;
gchar *contents;
//hallo welt output in label
GtkWidget *label = gtk_label_new ("Hallo welt!");
//text aus input.txt holen
asd = g_file_get_contents ("input.txt", &contents, NULL, NULL);
//ausgabe updaten
gtk_label_set_text(GTK_LABEL(label), contents);
gtk_container_add (GTK_CONTAINER (applet), label);
gtk_widget_show_all (GTK_WIDGET (applet));
return TRUE;
}
PANEL_APPLET_BONOBO_FACTORY ("OAFIID:MeinApplet_Factory", PANEL_TYPE_APPLET,
"Mein erstes Applet", "0", applet_main, NULL);
|
jetzt bekomme ich allerdings eine leere Ausgabe. Woran liegt das, oder habe ich ne falsche Variable benutzt?
Nein, probier's mal mit: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 | gboolean applet_main (PanelApplet *applet, const char *iid, gpointer data)
{
GError *error = NULL;
gchar *contents;
// hallo welt output in label
GtkWidget *label = gtk_label_new ("Hallo welt!");
// text aus input.txt holen
g_file_get_contents ("input.txt", &contents, NULL, &error);
if (error != NULL) {
// ein Fehler ist aufgetreten
g_print ("Error: %s\n", error->message);
g_error_free (error);
}
// 'content' auf Konsole ausgeben
g_print ("content: '%s'\n", content);
// ausgabe updaten
gtk_label_set_text (GTK_LABEL (label), contents);
gtk_container_add (GTK_CONTAINER (applet), label);
gtk_widget_show_all (GTK_WIDGET (applet));
return TRUE;
}
|
Dann siehst du, ob da irgendwas beim Laden schiefgeht. Edit: Dazu solltest du es natürlich aus der Konsole mit
panel-test-applets --iid "OAFIID:MeinApplet"
starten, sonst siehst du die Ausgabe nicht.
|
dAnjou
Anmeldungsdatum: 8. Oktober 2007
Beiträge: 872
Wohnort: Berlin
|
Hier die Python-Alternative: http://projekte.f4.fhtw-berlin.de/~s0521788/dokuwiki/stuff:gpa Eigentlich sollte das mal ein ganz tolles Howto werden, ist aber - wie immer - aus Zeitgründen nichts geworden. –- Oder du guckst dir mal mein BuddyApplet an und suchst dir da was raus. Da ist auch ein install-Script dabei, wo du sehen kannst, wo die ganzen Dateien hinkommen.
|
YEPHENAS
Anmeldungsdatum: 8. Juni 2009
Beiträge: 352
|
Ich tippe übrigens darauf, dass wenn das Applet ausgeführt wird die Umgebung sich in einem anderen Arbeitsverzeichnis befindet. Versuch es also mal mit dem vollen Pfad zur Datei.
|
jdruba
(Themenstarter)
Anmeldungsdatum: 9. Dezember 2008
Beiträge: 48
Wohnort: WOLFENBÜTTEL - GERMANY
|
mit vollem Dateipfad und einem s bei contents funktioniert das, super 😀
jetzt bleibt ja nur noch die letzte Frage, und zwar wie ich "g_timeout_add_seconds ()" da noch mit reinbekomme.
Die Parameter sind ja: interval : the time between calls to the function, in seconds
function : function to call
data : data to pass to function interval ist klar.
kann ich als function die hauptfunktion aufrufen oder muss ich eine Funktion erstellen für auslesen und die ausgabe (wenn ja wie mache ich das?)
unklar ist mir auch was mit data gemeint ist, das ist einfach der wert den ich an die funktion übergebe oder wie, in diesem Fall also eher nebensächlich oder wie?
|
YEPHENAS
Anmeldungsdatum: 8. Juni 2009
Beiträge: 352
|
jdruba schrieb: mit vollem Dateipfad und einem s bei contents funktioniert das, super 😀
jetzt bleibt ja nur noch die letzte Frage, und zwar wie ich "g_timeout_add_seconds ()" da noch mit reinbekomme.
Die Parameter sind ja: interval : the time between calls to the function, in seconds
function : function to call
data : data to pass to function interval ist klar.
kann ich als function die hauptfunktion aufrufen oder muss ich eine Funktion erstellen für auslesen und die ausgabe (wenn ja wie mache ich das?)
unklar ist mir auch was mit data gemeint ist, das ist einfach der wert den ich an die funktion übergebe oder wie, in diesem Fall also eher nebensächlich oder wie?
Ja, du must eine neue Funktion erstellen, die von den Parametern und dem Rückgabewert auf GSourceFunc passt, z.B. gboolean update_label (gpointer data)
{
// Datei auslesen
// Label setzen
return TRUE;
} Als data kannst du NULL übergeben. Die Label-Variable musst du entweder global machen (damit sie in der neuen Funktion zugreifbar ist) oder du übergibst sie als data. Den Code zum Dateiauslesen und Labelsetzen brauchst du übrigens natürlich nicht duplizieren, es reicht wenn du ihn in die neue Funktion verlagerst und diese am Anfang einmal aufrufst. Und die weiteren Male wird sie ja dann vom Timeout aufgerufen.
|
jdruba
(Themenstarter)
Anmeldungsdatum: 9. Dezember 2008
Beiträge: 48
Wohnort: WOLFENBÜTTEL - GERMANY
|
ok, ich habe jetzt label global deklariert (glaube ich zumindest) und das Auslesen der Datei und das Label update in die funktion label_update geschoben. Wenn ich jetzt auf den Aufruf der Funktion über g_timeout_add_seconds verzichte dann funktioniert die Funktion label_update schonmal und der Text der vor der Funktion Hallo Welt lautet wird durch den Inhalt der Datei input.txt ersetzt. Jetzt habe ich nur noch das Problem mit dem g_timeout_add_second. wenn ich die Funktion damit aufrufen möchte dann gibt der mir beim Kompilieren die Fehlermeldung:
myapplet.c: In Funktion »applet_main«:
myapplet.c:28: Warnung: Übergabe des Arguments 2 von »g_timeout_add_seconds« erzeugt Zeiger von Ganzzahl ohne Typkonvertierung
der mag also den Datentyp anscheinend nicht. Insgesamt sieht der Code jetzt so aus: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 | #include <gtk/gtk.h>
#include <panel-applet.h>
gboolean applet_main (PanelApplet *applet, const char *iid, gpointer data)
{
GError *error = NULL;
gchar *contents;
// globale deklaration von label
GtkWidget *label = gtk_label_new ("Hallo welt!");
gboolean update_label (gpointer data)
{
// Datei auslesen
g_file_get_contents ("/opt/test/input.txt", &contents, NULL, &error);
if (error != NULL) {
// ein Fehler ist aufgetreten
g_print ("Error: %s\n", error->message);
g_error_free (error);
}
// Label setzen
gtk_label_set_text (GTK_LABEL (label), contents);
return TRUE;
}
//funktion aufrufen
g_timeout_add_seconds(5, update_label(NULL), NULL);
gtk_container_add (GTK_CONTAINER (applet), label);
gtk_widget_show_all (GTK_WIDGET (applet));
return TRUE;
}
PANEL_APPLET_BONOBO_FACTORY ("OAFIID:MeinApplet_Factory", PANEL_TYPE_APPLET,
"Mein erstes Applet", "0", applet_main, NULL);
|
wie muss ich jetzt den Aufruf mit g_timeout_add_seconds gestalten, damit ich keine Fehlermeldung bekomme?
|
YEPHENAS
Anmeldungsdatum: 8. Juni 2009
Beiträge: 352
|
jdruba schrieb: ok, ich habe jetzt label global deklariert (glaube ich zumindest) und das Auslesen der Datei und das Label update in die funktion label_update geschoben. Wenn ich jetzt auf den Aufruf der Funktion über g_timeout_add_seconds verzichte dann funktioniert die Funktion label_update schonmal und der Text der vor der Funktion Hallo Welt lautet wird durch den Inhalt der Datei input.txt ersetzt. Jetzt habe ich nur noch das Problem mit dem g_timeout_add_second. wenn ich die Funktion damit aufrufen möchte dann gibt der mir beim Kompilieren die Fehlermeldung:
myapplet.c: In Funktion »applet_main«:
myapplet.c:28: Warnung: Übergabe des Arguments 2 von »g_timeout_add_seconds« erzeugt Zeiger von Ganzzahl ohne Typkonvertierung
der mag also den Datentyp anscheinend nicht. Insgesamt sieht der Code jetzt so aus: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39 | #include <gtk/gtk.h>
#include <panel-applet.h>
gboolean applet_main (PanelApplet *applet, const char *iid, gpointer data)
{
GError *error = NULL;
gchar *contents;
// globale deklaration von label
GtkWidget *label = gtk_label_new ("Hallo welt!");
gboolean update_label (gpointer data)
{
// Datei auslesen
g_file_get_contents ("/opt/test/input.txt", &contents, NULL, &error);
if (error != NULL) {
// ein Fehler ist aufgetreten
g_print ("Error: %s\n", error->message);
g_error_free (error);
}
// Label setzen
gtk_label_set_text (GTK_LABEL (label), contents);
return TRUE;
}
//funktion aufrufen
g_timeout_add_seconds(5, update_label(NULL), NULL);
gtk_container_add (GTK_CONTAINER (applet), label);
gtk_widget_show_all (GTK_WIDGET (applet));
return TRUE;
}
PANEL_APPLET_BONOBO_FACTORY ("OAFIID:MeinApplet_Factory", PANEL_TYPE_APPLET,
"Mein erstes Applet", "0", applet_main, NULL);
|
wie muss ich jetzt den Aufruf mit g_timeout_add_seconds gestalten, damit ich keine Fehlermeldung bekomme?
Also Funktionen in Funktionen zu definieren ist in C eigentlich nicht so üblich, aber das ist nicht das Problem. Das Problem ist, dass du update_label(NULL) als zweites Argument an g_timeout_add_seconds übergibst, es sollte aber nur update_label sein, also die Funktion an sich und nicht das Ergebnis des Funktionsaufrufes. Ohne es ausprobiert zu haben, aber so sollte es gehen: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 | #include <gtk/gtk.h>
#include <panel-applet.h>
// Globale Deklaration von label
GtkWidget *label;
gboolean update_label (gpointer data)
{
GError *error = NULL;
gchar *contents;
// Datei auslesen
g_file_get_contents ("/opt/test/input.txt", &contents, NULL, &error);
if (error != NULL) {
// ein Fehler ist aufgetreten
g_print ("Error: %s\n", error->message);
g_error_free (error);
}
// Label setzen
gtk_label_set_text (GTK_LABEL (label), contents);
// String wieder freigeben
g_free (contents);
return TRUE;
}
gboolean applet_main (PanelApplet *applet, const char *iid, gpointer data)
{
// Label erzeugen
label = gtk_label_new ("Hallo welt!");
// Label initialisieren
update_label (NULL);
gtk_container_add (GTK_CONTAINER (applet), label);
gtk_widget_show_all (GTK_WIDGET (applet));
// Timeout setzen
g_timeout_add_seconds (5, update_label, NULL);
return TRUE;
}
PANEL_APPLET_BONOBO_FACTORY ("OAFIID:MeinApplet_Factory", PANEL_TYPE_APPLET,
"Mein erstes Applet", "0", applet_main, NULL);
|
|
jdruba
(Themenstarter)
Anmeldungsdatum: 9. Dezember 2008
Beiträge: 48
Wohnort: WOLFENBÜTTEL - GERMANY
|
ja es funktioniert, vielen Dank für deine ausführliche und schnelle Hilfe.
|
Marc_BlackJack_Rintsch
Ehemalige
Anmeldungsdatum: 16. Juni 2006
Beiträge: 4694
Wohnort: Berlin
|
@YEPHENAS: Funktionen in Funktionen zu definieren ist in C nicht nur unüblich, sondern verboten. Der GCC kann das übersetzen, aber es ist kein standardkonformes C.
|
funkypopcorn
Anmeldungsdatum: 14. Juni 2011
Beiträge: Zähle...
|
Hallo, erstmal danke für diese Anleitung! Bin genau danach vorgegangen und es hat alles wunderbar geklappt. Jedoch wollte ich das C-Programm nun ändern und zwar, dass immer in der update_label Funktion ein Script ausgeführt wird.
Mein Code sieht demnach so aus: 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 | #include <gtk/gtk.h>
#include <panel-applet.h>
#include <gtk/gtk.h>
#include <panel-applet.h>
#include <stdio.h>
// Globale Deklaration von label
GtkWidget *label;
gboolean update_label (gpointer data)
{
GError *error = NULL;
gchar *contents;
//Daten aus dem Internet holen
system("/bin/bash /home/username/Desktop/doCurlScript.sh");
// Datei auslesen
g_file_get_contents ("/home/username/Desktop/input.txt", &contents, NULL, &error);
if (error != NULL) {
// ein Fehler ist aufgetreten
g_print ("Error: %s\n", error->message);
g_error_free (error);
}
// Label setzen
gtk_label_set_text (GTK_LABEL (label), contents);
// String wieder freigeben
g_free (contents);
return TRUE;
}
gboolean applet_main (PanelApplet *applet, const char *iid, gpointer data)
{
// Label erzeugen
label = gtk_label_new ("Hallo welt!");
// Label initialisieren
update_label (NULL);
gtk_container_add (GTK_CONTAINER (applet), label);
gtk_widget_show_all (GTK_WIDGET (applet));
// Timeout setzen
g_timeout_add_seconds (5, update_label, NULL);
return TRUE;
}
PANEL_APPLET_BONOBO_FACTORY ("OAFIID:testapplet_Factory", PANEL_TYPE_APPLET,
"Mein erstes Applet", "0", applet_main, NULL);
|
folgender C-Code funktioniert aber einwandfrei:
| #include <stdio.h>
int main(int argc, char *argv[])
{
system("/bin/bash /home/username/Desktop/doCurlScript.sh");
}
|
Ist echt komisch und weiß nicht wieso das oben nicht funktioniert. Wäre cool wenn mir jemand weiterhelfen könnte. PS: Achja das Bash-Script sucht sich info via curl aus dem Netz und piped es in input.txt gruß
|