Skip to content

Commit e670f72

Browse files
committed
feat(save_as): add save_as button for snapshots
Allow to save snapshots with a different name and under a different location than specified in the configuration as default. Signed-off-by: Max Kunzelmann <maxdev@posteo.de>
1 parent 596b9a8 commit e670f72

File tree

14 files changed

+235
-75
lines changed

14 files changed

+235
-75
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ fill_shape=false
9797
- `Ctrl+z`: Undo
9898
- `Ctrl+Shift+z` or `Ctrl+y`: Redo
9999
- `Ctrl+s`: Save to file (see man page)
100+
- `Ctrl+Shift+s`: Open "Save As" dialog
100101
- `Ctrl+c`: Copy to clipboard
101102
- `Escape` or `q` or `Ctrl+w`: Quit swappy
102103

include/pixbuf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
GdkPixbuf *pixbuf_init_from_file(struct swappy_state *state);
66
GdkPixbuf *pixbuf_get_from_state(struct swappy_state *state);
7+
char *format_filename(char *filename_format);
78
void pixbuf_save_state_to_folder(GdkPixbuf *pixbuf, char *folder,
89
char *filename_format);
910
void pixbuf_save_to_file(GdkPixbuf *pixbuf, char *file);

res/swappy.glade

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@
3232
<property name="can_focus">False</property>
3333
<property name="icon_name">document-properties-symbolic</property>
3434
</object>
35+
<object class="GtkImage" id="img-save-as-surface">
36+
<property name="visible">True</property>
37+
<property name="can-focus">False</property>
38+
<property name="icon-name">document-save-as</property>
39+
</object>
3540
<object class="GtkImage" id="zoom-in">
3641
<property name="visible">True</property>
3742
<property name="can_focus">False</property>
@@ -781,6 +786,22 @@
781786
<property name="always_show_image">True</property>
782787
<signal name="clicked" handler="save_clicked_handler" swapped="no"/>
783788
</object>
789+
<packing>
790+
<property name="expand">False</property>
791+
<property name="fill">True</property>
792+
<property name="position">1</property>
793+
</packing>
794+
</child>
795+
<child>
796+
<object class="GtkButton" id="save-as">
797+
<property name="visible">True</property>
798+
<property name="can-focus">False</property>
799+
<property name="receives-default">True</property>
800+
<property name="tooltip-text" translatable="yes">Save Surface As</property>
801+
<property name="image">img-save-as-surface</property>
802+
<property name="always-show-image">True</property>
803+
<signal name="clicked" handler="save_as_clicked_handler" swapped="no"/>
804+
</object>
784805
<packing>
785806
<property name="expand">False</property>
786807
<property name="fill">True</property>

src/application.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include <gdk/gdk.h>
22
#include <glib-2.0/glib.h>
3+
#include <glib/gi18n-lib.h>
34
#include <glib/gstdio.h>
45
#include <gtk/gtk.h>
56
#include <stdio.h>
@@ -312,6 +313,37 @@ void save_clicked_handler(GtkWidget *widget, struct swappy_state *state) {
312313
save_state_to_file_or_folder(state, NULL);
313314
}
314315

316+
void save_as_clicked_handler(GtkWidget *widget, struct swappy_state *state) {
317+
gchar *filename_suggestion;
318+
GtkWidget *dialog;
319+
GtkFileChooser *chooser;
320+
GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_SAVE;
321+
gint res;
322+
323+
commit_state(state);
324+
filename_suggestion = format_filename(state->config->save_filename_format);
325+
326+
dialog = gtk_file_chooser_dialog_new(NULL, state->ui->window, action,
327+
_("_Cancel"), GTK_RESPONSE_CANCEL,
328+
_("_Save"), GTK_RESPONSE_ACCEPT, NULL);
329+
chooser = GTK_FILE_CHOOSER(dialog);
330+
gtk_file_chooser_set_do_overwrite_confirmation(chooser, TRUE);
331+
gtk_file_chooser_set_current_folder(chooser, state->config->save_dir);
332+
gtk_file_chooser_set_current_name(chooser, filename_suggestion);
333+
g_free(filename_suggestion);
334+
335+
res = gtk_dialog_run(GTK_DIALOG(dialog));
336+
if (res == GTK_RESPONSE_ACCEPT) {
337+
gchar *filename;
338+
339+
filename = gtk_file_chooser_get_filename(chooser);
340+
save_state_to_file_or_folder(state, filename);
341+
g_free(filename);
342+
}
343+
344+
gtk_widget_destroy(dialog);
345+
}
346+
315347
void clear_clicked_handler(GtkWidget *widget, struct swappy_state *state) {
316348
action_clear(state);
317349
}
@@ -353,6 +385,9 @@ void window_keypress_handler(GtkWidget *widget, GdkEventKey *event,
353385
case GDK_KEY_s:
354386
save_state_to_file_or_folder(state, NULL);
355387
break;
388+
case GDK_KEY_S:
389+
save_as_clicked_handler(NULL, state);
390+
break;
356391
case GDK_KEY_b:
357392
action_toggle_painting_panel(state, NULL);
358393
break;

src/main.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,22 @@
11
#define _POSIX_C_SOURCE 200809L
22

3+
#include <libintl.h>
4+
#include <locale.h>
5+
36
#include "application.h"
47
#include "config.h"
58

69
int main(int argc, char *argv[]) {
710
struct swappy_state state = {0};
811
int status;
912

13+
// set locales according to environment variables
14+
setlocale(LC_ALL, "");
15+
// set base directory for translated messages
16+
bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
17+
// explicitly set encoding of message translations to UTF-8
18+
bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
19+
1020
state.argc = argc;
1121
state.argv = argv;
1222
state.mode = SWAPPY_PAINT_MODE_BRUSH;

src/pixbuf.c

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,26 +22,35 @@ static void write_file(GdkPixbuf *pixbuf, char *path) {
2222
}
2323
}
2424

25-
void pixbuf_save_state_to_folder(GdkPixbuf *pixbuf, char *folder,
26-
char *filename_format) {
25+
char *format_filename(char *filename_format) {
2726
time_t current_time = time(NULL);
2827
char *c_time_string;
2928
char filename[255];
30-
char path[MAX_PATH];
31-
size_t bytes_formated;
29+
size_t bytes_formatted;
3230

3331
c_time_string = ctime(&current_time);
3432
c_time_string[strlen(c_time_string) - 1] = '\0';
35-
bytes_formated = strftime(filename, sizeof(filename), filename_format,
36-
localtime(&current_time));
37-
if (!bytes_formated) {
33+
bytes_formatted = strftime(filename, sizeof(filename), filename_format,
34+
localtime(&current_time));
35+
if (!bytes_formatted) {
3836
g_warning(
3937
"filename_format: %s overflows filename limit - file cannot be saved",
4038
filename_format);
41-
return;
39+
return NULL;
4240
}
4341

42+
return g_strdup(filename);
43+
}
44+
45+
void pixbuf_save_state_to_folder(GdkPixbuf *pixbuf, char *folder,
46+
char *filename_format) {
47+
char path[MAX_PATH];
48+
char *filename;
49+
filename = format_filename(filename_format);
50+
if (filename == NULL) return;
51+
4452
g_snprintf(path, MAX_PATH, "%s/%s", folder, filename);
53+
g_free(filename);
4554
g_info("saving surface to path: %s", path);
4655
write_file(pixbuf, path);
4756
}

src/po/POTFILES

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
res/swappy.glade
2+
src/application.c

src/po/de.po

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ msgid ""
77
msgstr ""
88
"Project-Id-Version: swappy\n"
99
"Report-Msgid-Bugs-To: \n"
10-
"POT-Creation-Date: 2022-11-18 16:07-0500\n"
10+
"POT-Creation-Date: 2022-12-04 22:52+0100\n"
1111
"PO-Revision-Date: 2020-11-19 18:03+0300\n"
1212
"Last-Translator: Brodi <me@brodi.ml>\n"
1313
"Language-Team: none\n"
@@ -17,42 +17,54 @@ msgstr ""
1717
"Content-Transfer-Encoding: 8bit\n"
1818
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
1919

20-
#: res/swappy.glade:456
20+
#: res/swappy.glade:461
2121
msgid "Line Width"
2222
msgstr "Linienstärke"
2323

24-
#: res/swappy.glade:526
24+
#: res/swappy.glade:531
2525
msgid "Text Size"
2626
msgstr "Textgröße"
2727

28-
#: res/swappy.glade:592
28+
#: res/swappy.glade:597
2929
msgid "Fill shape"
3030
msgstr ""
3131

32-
#: res/swappy.glade:597
32+
#: res/swappy.glade:602
3333
msgid "Toggle shape filling"
3434
msgstr ""
3535

36-
#: res/swappy.glade:671
36+
#: res/swappy.glade:676
3737
msgid "Toggle Paint Panel"
3838
msgstr "Farbtafel umschalten"
3939

40-
#: res/swappy.glade:697
40+
#: res/swappy.glade:702
4141
msgid "Undo Last Paint"
4242
msgstr "Letzte Bemalung rückgängig machen"
4343

44-
#: res/swappy.glade:716
44+
#: res/swappy.glade:721
4545
msgid "Redo Previous Paint"
4646
msgstr "Vorherige Bemalung wiederherstellen"
4747

48-
#: res/swappy.glade:735
48+
#: res/swappy.glade:740
4949
msgid "Clear Paints"
5050
msgstr "Bemalung löschen"
5151

52-
#: res/swappy.glade:763
52+
#: res/swappy.glade:768
5353
msgid "Copy Surface"
5454
msgstr "Fläche kopieren"
5555

56-
#: res/swappy.glade:779
56+
#: res/swappy.glade:784
5757
msgid "Save Surface"
5858
msgstr "Fläche speichern"
59+
60+
#: res/swappy.glade:800
61+
msgid "Save Surface As"
62+
msgstr "Fläche speichern unter"
63+
64+
#: src/application.c:327
65+
msgid "_Cancel"
66+
msgstr "_Abbrechen"
67+
68+
#: src/application.c:328
69+
msgid "_Save"
70+
msgstr "_Speichern"

src/po/en.po

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ msgid ""
77
msgstr ""
88
"Project-Id-Version: swappy\n"
99
"Report-Msgid-Bugs-To: \n"
10-
"POT-Creation-Date: 2022-11-18 16:07-0500\n"
10+
"POT-Creation-Date: 2022-12-04 22:52+0100\n"
1111
"PO-Revision-Date: 2020-06-21 21:57-0400\n"
1212
"Last-Translator: Automatically generated\n"
1313
"Language-Team: none\n"
@@ -17,42 +17,54 @@ msgstr ""
1717
"Content-Transfer-Encoding: 8bit\n"
1818
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
1919

20-
#: res/swappy.glade:456
20+
#: res/swappy.glade:461
2121
msgid "Line Width"
2222
msgstr "Line Width"
2323

24-
#: res/swappy.glade:526
24+
#: res/swappy.glade:531
2525
msgid "Text Size"
2626
msgstr "Text Size"
2727

28-
#: res/swappy.glade:592
28+
#: res/swappy.glade:597
2929
msgid "Fill shape"
3030
msgstr "Fill shape"
3131

32-
#: res/swappy.glade:597
32+
#: res/swappy.glade:602
3333
msgid "Toggle shape filling"
3434
msgstr "Toggle shape filling"
3535

36-
#: res/swappy.glade:671
36+
#: res/swappy.glade:676
3737
msgid "Toggle Paint Panel"
3838
msgstr "Toggle Paint Panel"
3939

40-
#: res/swappy.glade:697
40+
#: res/swappy.glade:702
4141
msgid "Undo Last Paint"
4242
msgstr "Undo Last Paint"
4343

44-
#: res/swappy.glade:716
44+
#: res/swappy.glade:721
4545
msgid "Redo Previous Paint"
4646
msgstr "Redo Previous Paint"
4747

48-
#: res/swappy.glade:735
48+
#: res/swappy.glade:740
4949
msgid "Clear Paints"
5050
msgstr "Clear Paints"
5151

52-
#: res/swappy.glade:763
52+
#: res/swappy.glade:768
5353
msgid "Copy Surface"
5454
msgstr "Copy Surface"
5555

56-
#: res/swappy.glade:779
56+
#: res/swappy.glade:784
5757
msgid "Save Surface"
5858
msgstr "Save Surface"
59+
60+
#: res/swappy.glade:800
61+
msgid "Save Surface As"
62+
msgstr "Save Surface As"
63+
64+
#: src/application.c:327
65+
msgid "_Cancel"
66+
msgstr "_Cancel"
67+
68+
#: src/application.c:328
69+
msgid "_Save"
70+
msgstr "_Save"

src/po/fr.po

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ msgid ""
77
msgstr ""
88
"Project-Id-Version: swappy\n"
99
"Report-Msgid-Bugs-To: \n"
10-
"POT-Creation-Date: 2022-11-18 16:07-0500\n"
10+
"POT-Creation-Date: 2022-12-04 22:52+0100\n"
1111
"PO-Revision-Date: 2021-02-20 21:00-0500\n"
1212
"Last-Translator: Jeremy Attali <contact@jtheoof.me>\n"
1313
"Language-Team: none\n"
@@ -17,42 +17,55 @@ msgstr ""
1717
"Content-Transfer-Encoding: 8bit\n"
1818
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
1919

20-
#: res/swappy.glade:456
20+
#: res/swappy.glade:461
2121
msgid "Line Width"
2222
msgstr "Epaisseur de ligne"
2323

24-
#: res/swappy.glade:526
24+
#: res/swappy.glade:531
2525
msgid "Text Size"
2626
msgstr "Taille du texte"
2727

28-
#: res/swappy.glade:592
28+
#: res/swappy.glade:597
2929
msgid "Fill shape"
3030
msgstr "Remplir la forme"
3131

32-
#: res/swappy.glade:597
32+
#: res/swappy.glade:602
3333
msgid "Toggle shape filling"
3434
msgstr "Activer/Désactiver le remplissage de forme"
3535

36-
#: res/swappy.glade:671
36+
#: res/swappy.glade:676
3737
msgid "Toggle Paint Panel"
3838
msgstr "Afficher/Cacher le panneau de peinture"
3939

40-
#: res/swappy.glade:697
40+
#: res/swappy.glade:702
4141
msgid "Undo Last Paint"
4242
msgstr "Annuler la dernière peinture"
4343

44-
#: res/swappy.glade:716
44+
#: res/swappy.glade:721
4545
msgid "Redo Previous Paint"
4646
msgstr "Rétablir la dernière peinture"
4747

48-
#: res/swappy.glade:735
48+
#: res/swappy.glade:740
4949
msgid "Clear Paints"
5050
msgstr "Supprimer les peintures"
5151

52-
#: res/swappy.glade:763
52+
#: res/swappy.glade:768
5353
msgid "Copy Surface"
5454
msgstr "Copier la surface"
5555

56-
#: res/swappy.glade:779
56+
#: res/swappy.glade:784
5757
msgid "Save Surface"
5858
msgstr "Sauvegarder la surface"
59+
60+
#: res/swappy.glade:800
61+
#, fuzzy
62+
msgid "Save Surface As"
63+
msgstr "Sauvegarder la surface"
64+
65+
#: src/application.c:327
66+
msgid "_Cancel"
67+
msgstr ""
68+
69+
#: src/application.c:328
70+
msgid "_Save"
71+
msgstr ""

0 commit comments

Comments
 (0)