diff --git a/data/style.css b/data/style.css index 5329f46..1e3d5d1 100644 --- a/data/style.css +++ b/data/style.css @@ -1,4 +1,4 @@ -.primary-nav > .frame > box >.koto-button { +.primary-nav > .frame > box >.koto-button > box { padding: 10px 0; } @@ -6,11 +6,12 @@ padding-bottom: 10px; } -.expander > revealer > box > .koto-button { +.expander > revealer > box > .koto-button, +.expander > revealer > box > .koto-button > box { min-height: 40px; } -.koto-button > image { +.koto-button > box > image { margin-right: 10px; } diff --git a/src/indexer/file-indexer.c b/src/indexer/file-indexer.c index a6588ab..5a9b55b 100644 --- a/src/indexer/file-indexer.c +++ b/src/indexer/file-indexer.c @@ -18,14 +18,9 @@ #include #include #include +#include "file.h" #include "file-indexer.h" -struct KotoIndexedFile { - GObject parent_instance; - gchar *file_name; - gchar *path; -}; - struct KotoIndexedAlbum { GObject parent_instance; gboolean has_album_art; @@ -41,7 +36,7 @@ struct _KotoIndexedArtist { gchar *artist_name; GHashTable *albums; gchar *path; -} +}; struct _KotoIndexedLibrary { GObject parent_instance; @@ -74,12 +69,16 @@ static void koto_indexed_library_class_init(KotoIndexedLibraryClass *c) { "Path", "Path to Music", NULL, - G_PARAM_CONSTRUCT_ONLY|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE + G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE ); g_object_class_install_properties(gobject_class, N_PROPERTIES, props); } +static void koto_indexed_library_init(KotoIndexedLibrary *self) { + self->music_artists = g_hash_table_new(g_str_hash, g_str_equal); +} + static void koto_indexed_library_get_property(GObject *obj, guint prop_id, GValue *val, GParamSpec *spec) { KotoIndexedLibrary *self = KOTO_INDEXED_LIBRARY(obj); @@ -175,18 +174,29 @@ void index_file(KotoIndexedLibrary *self, gchar *path) { g_str_has_prefix(mime_info[0], "audio/") || // Is audio g_str_has_prefix(mime_info[0], "image/") // Is image ) { - g_message("File Name: %s", path); + //g_message("File Name: %s", path); + } + + if (g_str_has_prefix(mime_info[0], "audio/")) { // Is an audio file + KotoIndexedFile *file = koto_indexed_file_new(path); + gchar *filepath; + gchar *parsed_name; + + g_object_get(file, + "path", &filepath, + "parsed-name", &parsed_name, + NULL); + + g_free(filepath); + g_free(parsed_name); + g_object_unref(file); } g_strfreev(mime_info); // Free our mimeinfo } -static void koto_indexed_library_init(KotoIndexedLibrary *self) { - self->files = g_hash_table_new(g_str_hash, g_str_equal); -} - KotoIndexedLibrary* koto_indexed_library_new(const gchar *path) { - return g_object_new(KOTO_INDEXED_TYPE_LIBRARY, + return g_object_new(KOTO_TYPE_INDEXED_LIBRARY, "path", path, NULL ); diff --git a/src/indexer/file-indexer.h b/src/indexer/file-indexer.h index f5f61f2..f5a5155 100644 --- a/src/indexer/file-indexer.h +++ b/src/indexer/file-indexer.h @@ -20,14 +20,10 @@ G_BEGIN_DECLS -#define KOTO_INDEXED_TYPE_FILE koto_indexed_file_get_type() -G_DECLARE_FINAL_TYPE(KotoIndexedFile, koto_indexed_file, KOTO, INDEXED_FILE, GObject); - -#define KOTO_INDEXED_TYPE_LIBRARY koto_indexed_library_get_type() +#define KOTO_TYPE_INDEXED_LIBRARY koto_indexed_library_get_type() G_DECLARE_FINAL_TYPE(KotoIndexedLibrary, koto_indexed_library, KOTO, INDEXED_LIBRARY, GObject); KotoIndexedLibrary* koto_indexed_library_new(const gchar *path); -KotoIndexedFile* koto_indexed_file_new(gchar *path); void start_indexing(KotoIndexedLibrary *self); void index_folder(KotoIndexedLibrary *self, gchar *path); diff --git a/src/indexer/file.c b/src/indexer/file.c new file mode 100644 index 0000000..c9052b5 --- /dev/null +++ b/src/indexer/file.c @@ -0,0 +1,274 @@ +/* file.c + * + * Copyright 2021 Joshua Strobl + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "file.h" + +struct _KotoIndexedFile { + GObject parent_instance; + gchar *path; + gchar *file_name; + gchar *parsed_name; + gchar *artist; + gchar *album; + + guint position; + gboolean acquired_metadata_from_id3; +}; + +G_DEFINE_TYPE(KotoIndexedFile, koto_indexed_file, G_TYPE_OBJECT); + +enum { + PROP_0, + PROP_PATH, + PROP_ARTIST, + PROP_ALBUM, + PROP_FILE_NAME, + PROP_PARSED_NAME, + PROP_POSITION, + N_PROPERTIES +}; + +static GParamSpec *props[N_PROPERTIES] = { NULL }; + +static void koto_indexed_file_get_property(GObject *obj, guint prop_id, GValue *val, GParamSpec *spec); +static void koto_indexed_file_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec); + +static void koto_indexed_file_class_init(KotoIndexedFileClass *c) { + GObjectClass *gobject_class; + gobject_class = G_OBJECT_CLASS(c); + gobject_class->set_property = koto_indexed_file_set_property; + gobject_class->get_property = koto_indexed_file_get_property; + + props[PROP_PATH] = g_param_spec_string( + "path", + "Path", + "Path to File", + NULL, + G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE + ); + + props[PROP_ARTIST] = g_param_spec_string( + "artist", + "Name of Artist", + "Name of Artist", + NULL, + G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE + ); + + props[PROP_ALBUM] = g_param_spec_string( + "album", + "Name of Album", + "Name of Album", + NULL, + G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE + ); + + props[PROP_FILE_NAME] = g_param_spec_string( + "file-name", + "Name of File", + "Name of File", + NULL, + G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE + ); + + props[PROP_PARSED_NAME] = g_param_spec_string( + "parsed-name", + "Parsed Name of File", + "Parsed Name of File", + NULL, + G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE + ); + + props[PROP_POSITION] = g_param_spec_uint( + "position", + "Position in Audiobook, Album, etc.", + "Position in Audiobook, Album, etc.", + 0, + G_MAXUINT16, + 0, + G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE + ); + + g_object_class_install_properties(gobject_class, N_PROPERTIES, props); +} + +static void koto_indexed_file_init(KotoIndexedFile *self) { + self->acquired_metadata_from_id3 = FALSE; +} + +static void koto_indexed_file_get_property(GObject *obj, guint prop_id, GValue *val, GParamSpec *spec) { + KotoIndexedFile *self = KOTO_INDEXED_FILE(obj); + + switch (prop_id) { + case PROP_PATH: + g_value_set_string(val, self->path); + break; + case PROP_ARTIST: + g_value_set_string(val, self->artist); + break; + case PROP_ALBUM: + g_value_set_string(val, self->album); + break; + case PROP_FILE_NAME: + g_value_set_string(val, self->file_name); + break; + case PROP_PARSED_NAME: + g_value_set_string(val, self->parsed_name); + break; + case PROP_POSITION: + g_value_set_uint(val, self->position); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, prop_id, spec); + break; + } +} + +static void koto_indexed_file_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec) { + KotoIndexedFile *self = KOTO_INDEXED_FILE(obj); + + switch (prop_id) { + case PROP_PATH: + self->path = g_strdup(g_value_get_string(val)); // Update our path + koto_indexed_file_set_file_name(self, g_path_get_basename(self->path)); // Update our file name + break; + case PROP_ARTIST: + self->artist = g_strdup(g_value_get_string(val)); + break; + case PROP_ALBUM: + self->album = g_strdup(g_value_get_string(val)); + break; + case PROP_FILE_NAME: + koto_indexed_file_set_file_name(self, g_strdup(g_value_get_string(val))); // Update the file name + break; + case PROP_PARSED_NAME: + koto_indexed_file_set_parsed_name(self, g_strdup(g_value_get_string(val))); + break; + case PROP_POSITION: + self->position = g_value_get_uint(val); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, prop_id, spec); + break; + } +} + +void koto_indexed_file_set_file_name(KotoIndexedFile *self, gchar *new_file_name) { + if (new_file_name == NULL) { + return; + } + + if ((self->file_name != NULL) && (strcmp(self->file_name, new_file_name) == 0)) { // Not null and the same + return; // Don't do anything + } + + if (self->file_name != NULL) { // If it is defined + g_free(self->file_name); + } + + self->file_name = g_strdup(new_file_name); + g_object_notify_by_pspec(G_OBJECT(self), props[PROP_FILE_NAME]); + + if (!self->acquired_metadata_from_id3) { // Haven't acquired our information from ID3 + koto_indexed_file_parse_name(self); // Update our parsed name + } +} + +void koto_indexed_file_set_parsed_name(KotoIndexedFile *self, gchar *new_parsed_name) { + if (new_parsed_name == NULL) { + return; + } + + if ((self->parsed_name != NULL) && (strcmp(self->parsed_name, new_parsed_name) == 0)) { // Not null and the same + return; // Don't do anything + } + + if (self->parsed_name != NULL) { + g_free(self->parsed_name); + } + + self->parsed_name = g_strdup(new_parsed_name); + g_object_notify_by_pspec(G_OBJECT(self), props[PROP_PARSED_NAME]); +} + +void koto_indexed_file_parse_name(KotoIndexedFile *self) { + gchar *copied_file_name = g_strdelimit(g_strdup(self->file_name), "_", ' '); // Replace _ with whitespace for starters + + if (self->artist != NULL && strcmp(self->artist, "") != 0) { // If we have artist set + gchar **split = g_strsplit(copied_file_name, self->artist, -1); // Split whenever we encounter the artist + copied_file_name = g_strjoinv("", split); // Remove the artist + g_strfreev(split); + } + + if (self->artist != NULL && strcmp(self->album, "") != 0) { // If we have album set + gchar **split = g_strsplit(copied_file_name, self->album, -1); // Split whenever we encounter the album + copied_file_name = g_strjoinv("", split); // Remove the album + g_strfreev(split); + + split = g_strsplit(copied_file_name, g_utf8_strdown(self->album, g_utf8_strlen(self->album, -1)), -1); // Split whenever we encounter the album lowercased + copied_file_name = g_strjoin("", split, NULL); // Remove the lowercased album + g_strfreev(split); + } + + if (g_str_match_string(copied_file_name, "-", FALSE)) { // Contains - like a heathen + gchar **split = g_strsplit(copied_file_name, " - ", -1); // Split whenever we encounter " - " + copied_file_name = g_strjoin("", split, NULL); // Remove entirely + g_strfreev(split); + + if (g_str_match_string(copied_file_name, "-", FALSE)) { // If we have any stragglers + split = g_strsplit(copied_file_name, "-", -1); // Split whenever we encounter - + copied_file_name = g_strjoin("", split, NULL); // Remove entirely + g_strfreev(split); + } + } + + gchar **split = g_strsplit(copied_file_name, ".", -1); // Split every time we see . + g_free(copied_file_name); + guint len_of_extension_split = g_strv_length(split); + + if (len_of_extension_split == 2) { // Only have two elements + copied_file_name = g_strdup(split[0]); // Get the first element + } else { + gchar *new_parsed_name = ""; + for (guint i = 0; i < len_of_extension_split - 1; i++) { // Iterate over everything except the last item + if (g_strcmp0(new_parsed_name, "") == 0) { // Currently empty + new_parsed_name = g_strdup(split[i]); // Just duplicate this string + } else { + gchar *tmp_copy = g_strdup(new_parsed_name); + g_free(new_parsed_name); // Free the old + new_parsed_name = g_strdup(g_strjoin(".", tmp_copy, split[i], NULL)); // Join the two strings with a . again and duplicate it, setting it to our new_parsed_name + g_free(tmp_copy); // Free our temporary copy + } + } + + copied_file_name = g_strdup(new_parsed_name); + g_free(new_parsed_name); + } + + g_strfreev(split); + + koto_indexed_file_set_parsed_name(self, copied_file_name); + g_free(copied_file_name); +} + +KotoIndexedFile* koto_indexed_file_new(const gchar *path) { + return g_object_new(KOTO_TYPE_INDEXED_FILE, + "path", path, + NULL + ); +} diff --git a/src/koto-flipper-button.h b/src/indexer/file.h similarity index 57% rename from src/koto-flipper-button.h rename to src/indexer/file.h index 711e607..669d9f4 100644 --- a/src/koto-flipper-button.h +++ b/src/indexer/file.h @@ -1,4 +1,4 @@ -/* koto-flipper-button.h +/* file.h * * Copyright 2021 Joshua Strobl * @@ -16,17 +16,17 @@ */ #pragma once - -#include +#include G_BEGIN_DECLS -#define KOTO_TYPE_FLIPPER_BUTTON (koto_flipper_button_get_type()) +#define KOTO_TYPE_INDEXED_FILE koto_indexed_file_get_type() +G_DECLARE_FINAL_TYPE(KotoIndexedFile, koto_indexed_file, KOTO, INDEXED_FILE, GObject); -G_DECLARE_FINAL_TYPE (KotoFlipperButton, koto_flipper_button, KOTO, FLIPPER_BUTTON, GtkButton) +KotoIndexedFile* koto_indexed_file_new(const gchar *path); -KotoFlipperButton* koto_flipper_button_new(gchar *initial_icon, gchar *flipped_icon, GtkIconSize size); -void koto_flipper_button_flip(KotoFlipperButton *self); -void koto_flipper_button_set_icon(KotoFlipperButton *self, gchar *name); +void koto_indexed_file_set_file_name(KotoIndexedFile *self, gchar *new_file_name); +void koto_indexed_file_set_parsed_name(KotoIndexedFile *self, gchar *new_parsed_name); +void koto_indexed_file_parse_name(KotoIndexedFile *self); G_END_DECLS diff --git a/src/indexer/meson.build b/src/indexer/meson.build index df7c618..e923e85 100644 --- a/src/indexer/meson.build +++ b/src/indexer/meson.build @@ -1,4 +1,5 @@ indexer_sources = [ + 'file.c', 'file-indexer.c', ] diff --git a/src/koto-button.c b/src/koto-button.c index 7857fd6..7067b9a 100644 --- a/src/koto-button.c +++ b/src/koto-button.c @@ -50,19 +50,21 @@ guint koto_get_pixbuf_size(KotoButtonPixbufSize s) { } enum { - PROP_0, + PROP_BTN_0, PROP_PIX_SIZE, PROP_TEXT, PROP_BADGE_TEXT, PROP_PIX, PROP_ICON_NAME, - N_PROPERTIES + PROP_ALT_ICON_NAME, + N_BTN_PROPERTIES }; -static GParamSpec *props[N_PROPERTIES] = { NULL, }; +static GParamSpec *btn_props[N_BTN_PROPERTIES] = { NULL, }; struct _KotoButton { - GtkBox parent_instance; + GtkEventBox parent_instance; + GtkBox *content; guint pix_size; GtkWidget *button_image; @@ -71,16 +73,18 @@ struct _KotoButton { gchar *badge_text; gchar *icon_name; + gchar *alt_icon_name; gchar *text; GdkPixbuf *pix; + gboolean currently_showing_alt; }; struct _KotoButtonClass { GtkBoxClass parent_class; }; -G_DEFINE_TYPE(KotoButton, koto_button, GTK_TYPE_BOX); +G_DEFINE_TYPE(KotoButton, koto_button, GTK_TYPE_EVENT_BOX); static void koto_button_get_property(GObject *obj, guint prop_id, GValue *val, GParamSpec *spec); static void koto_button_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec); @@ -91,7 +95,7 @@ static void koto_button_class_init(KotoButtonClass *c) { gobject_class->set_property = koto_button_set_property; gobject_class->get_property = koto_button_get_property; - props[PROP_PIX_SIZE] = g_param_spec_uint( + btn_props[PROP_PIX_SIZE] = g_param_spec_uint( "pixbuf-size", "Pixbuf Size", "Size of the pixbuf", @@ -101,7 +105,7 @@ static void koto_button_class_init(KotoButtonClass *c) { G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE ); - props[PROP_TEXT] = g_param_spec_string( + btn_props[PROP_TEXT] = g_param_spec_string( "button-text", "Button Text", "Text of Button", @@ -109,7 +113,7 @@ static void koto_button_class_init(KotoButtonClass *c) { G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE ); - props[PROP_BADGE_TEXT] = g_param_spec_string( + btn_props[PROP_BADGE_TEXT] = g_param_spec_string( "badge-text", "Badge Text", "Text of Badge", @@ -117,7 +121,7 @@ static void koto_button_class_init(KotoButtonClass *c) { G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE ); - props[PROP_PIX] = g_param_spec_object( + btn_props[PROP_PIX] = g_param_spec_object( "pixbuf", "Pixbuf", "Pixbuf", @@ -125,7 +129,7 @@ static void koto_button_class_init(KotoButtonClass *c) { G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE ); - props[PROP_ICON_NAME] = g_param_spec_string( + btn_props[PROP_ICON_NAME] = g_param_spec_string( "icon-name", "Icon Name", "Name of Icon", @@ -133,12 +137,23 @@ static void koto_button_class_init(KotoButtonClass *c) { G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE ); - g_object_class_install_properties(gobject_class, N_PROPERTIES, props); + btn_props[PROP_ALT_ICON_NAME] = g_param_spec_string( + "alt-icon-name", + "Name of an Alternate Icon", + "Name of an Alternate Icon", + NULL, + G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE + ); + + g_object_class_install_properties(gobject_class, N_BTN_PROPERTIES, btn_props); } static void koto_button_init(KotoButton *self) { GtkStyleContext *style = gtk_widget_get_style_context(GTK_WIDGET(self)); gtk_style_context_add_class(style, "koto-button"); + self->currently_showing_alt = FALSE; + self->content = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0)); + gtk_container_add(GTK_CONTAINER(self), GTK_WIDGET(self->content)); } static void koto_button_get_property(GObject *obj, guint prop_id, GValue *val, GParamSpec *spec) { @@ -157,6 +172,9 @@ static void koto_button_get_property(GObject *obj, guint prop_id, GValue *val, G case PROP_ICON_NAME: g_value_set_string(val, self->icon_name); break; + case PROP_ALT_ICON_NAME: + g_value_set_string(val, self->alt_icon_name); + break; case PROP_PIX: g_value_set_object(val, self->pix); break; @@ -183,7 +201,16 @@ static void koto_button_set_property(GObject *obj, guint prop_id, const GValue * koto_button_set_pixbuf(self, (GdkPixbuf*) g_value_get_object(val)); break; case PROP_ICON_NAME: - koto_button_set_icon_name(self, g_strdup(g_value_get_string(val))); + koto_button_set_icon_name(self, g_strdup(g_value_get_string(val)), FALSE); + if (!self->currently_showing_alt) { // Not showing alt + koto_button_show_image(self, FALSE); + } + break; + case PROP_ALT_ICON_NAME: + koto_button_set_icon_name(self, g_strdup(g_value_get_string(val)), TRUE); + if (self->currently_showing_alt) { // Currently showing the alt image + koto_button_show_image(self, TRUE); + } break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, prop_id, spec); @@ -191,6 +218,10 @@ static void koto_button_set_property(GObject *obj, guint prop_id, const GValue * } } +void koto_button_flip(KotoButton *self) { + koto_button_show_image(self, !self->currently_showing_alt); +} + void koto_button_set_badge_text(KotoButton *self, gchar *text) { if ((text == NULL) || (strcmp(text, "") == 0)) { // If the text is empty self->badge_text = g_strdup(""); @@ -203,7 +234,7 @@ void koto_button_set_badge_text(KotoButton *self, gchar *text) { gtk_label_set_text(GTK_LABEL(self->badge_label), self->badge_text); } else { self->badge_label = gtk_label_new(self->badge_text); // Create our label - gtk_box_pack_end(GTK_BOX(self), self->badge_label, FALSE, FALSE, 0); // Add to the end of the box + gtk_box_pack_end(self->content, self->badge_label, FALSE, FALSE, 0); // Add to the end of the box } if (strcmp(self->badge_text, "") != 0) { // Empty badge @@ -212,17 +243,34 @@ void koto_button_set_badge_text(KotoButton *self, gchar *text) { gtk_widget_show(self->badge_label); // Show our badge } - g_object_notify_by_pspec(G_OBJECT(self), props[PROP_BADGE_TEXT]); + g_object_notify_by_pspec(G_OBJECT(self), btn_props[PROP_BADGE_TEXT]); } -void koto_button_set_icon_name(KotoButton *self, gchar *icon_name) { +void koto_button_set_icon_name(KotoButton *self, gchar *icon_name, gboolean for_alt) { gchar *copied_icon_name = g_strdup(icon_name); - g_message("icon name set in koto button: %s", icon_name); - g_free(self->icon_name); - self->icon_name = copied_icon_name; - if ((self->icon_name == NULL) || (strcmp(self->icon_name,"") == 0)) { // Have no icon name now - g_message("Have no icon name now?"); + if (for_alt) { // Is for the alternate icon + if ((self->alt_icon_name != NULL) && strcmp(icon_name, self->alt_icon_name) != 0) { // If the icons are different + g_free(self->alt_icon_name); + } + + self->alt_icon_name = copied_icon_name; + } else { + if ((self->icon_name != NULL) && strcmp(icon_name, self->icon_name) != 0) { + g_free(self->icon_name); + } + + self->icon_name = copied_icon_name; + } + + gboolean hide_image = FALSE; + if (for_alt && self->currently_showing_alt && ((self->alt_icon_name == NULL) || strcmp(self->alt_icon_name, "") == 0)) { // For alt, alt is currently showing, and no longer have alt + hide_image = TRUE; + } else if (!for_alt && ((self->icon_name == NULL) || (strcmp(self->icon_name,"") == 0))) { // Not for alt, no icon + hide_image = TRUE; + } + + if (hide_image) { // Should hide the image if (GTK_IS_IMAGE(self->button_image)) { // If we already have a button image gtk_widget_hide(self->button_image); // Hide } @@ -230,12 +278,7 @@ void koto_button_set_icon_name(KotoButton *self, gchar *icon_name) { return; } - GtkIconTheme *theme = gtk_icon_theme_get_default(); // Get the default icon theme - GdkPixbuf* icon_pix = gtk_icon_theme_load_icon_for_scale(theme, self->icon_name, (gint) self->pix_size, 1, GTK_ICON_LOOKUP_USE_BUILTIN & GTK_ICON_LOOKUP_GENERIC_FALLBACK, NULL); - g_return_if_fail(GDK_IS_PIXBUF(icon_pix)); // Return if not a pixbuf - koto_button_set_pixbuf(self, icon_pix); - - g_object_notify_by_pspec(G_OBJECT(self), props[PROP_ICON_NAME]); + g_object_notify_by_pspec(G_OBJECT(self), for_alt ? btn_props[PROP_ALT_ICON_NAME] : btn_props[PROP_ICON_NAME]); } void koto_button_set_pixbuf(KotoButton *self, GdkPixbuf *pix) { @@ -260,11 +303,11 @@ void koto_button_set_pixbuf(KotoButton *self, GdkPixbuf *pix) { GtkWidget *new_image = gtk_image_new_from_pixbuf(use_pix); // Create our new image g_return_if_fail(GTK_IS_IMAGE(new_image)); // Return if we failed to create our image self->button_image = new_image; - gtk_box_pack_start(GTK_BOX(self), self->button_image, FALSE, FALSE, 0); // Prepend the image - gtk_box_reorder_child(GTK_BOX(self), self->button_image, 0); + gtk_box_pack_start(self->content, self->button_image, FALSE, FALSE, 0); // Prepend the image + gtk_box_reorder_child(self->content, self->button_image, 0); } - g_object_notify_by_pspec(G_OBJECT(self), props[PROP_PIX]); + g_object_notify_by_pspec(G_OBJECT(self), btn_props[PROP_PIX]); } void koto_button_set_pixbuf_size(KotoButton *self, guint size) { @@ -276,7 +319,7 @@ void koto_button_set_pixbuf_size(KotoButton *self, guint size) { koto_button_set_pixbuf(self, self->pix); } - g_object_notify_by_pspec(G_OBJECT(self), props[PROP_PIX_SIZE]); + g_object_notify_by_pspec(G_OBJECT(self), btn_props[PROP_PIX_SIZE]); } void koto_button_set_text(KotoButton *self, gchar *text) { @@ -300,30 +343,43 @@ void koto_button_set_text(KotoButton *self, gchar *text) { if (strcmp(self->text, "") != 0) { // If we have text self->button_label = gtk_label_new(self->text); // Create our label gtk_label_set_xalign(GTK_LABEL(self->button_label), 0); - gtk_box_pack_start(GTK_BOX(self), self->button_label, FALSE, FALSE, 0); // Add to the beginning of the box + gtk_box_pack_start(self->content, self->button_label, FALSE, FALSE, 0); // Add to the beginning of the box if (GTK_IS_IMAGE(self->button_image)) { // If we have an image - gtk_box_reorder_child(GTK_BOX(self), self->button_image, 0); // Move to the beginning + gtk_box_reorder_child(self->content, self->button_image, 0); // Move to the beginning } } } - g_object_notify_by_pspec(G_OBJECT(self), props[PROP_TEXT]); + g_object_notify_by_pspec(G_OBJECT(self), btn_props[PROP_TEXT]); +} + +void koto_button_show_image(KotoButton *self, gboolean use_alt) { + if (use_alt && ((self->alt_icon_name == NULL) || (strcmp(self->alt_icon_name, "") == 0))) { // Don't have an alt icon set + return; + } else if (!use_alt && ((self->icon_name == NULL) || (strcmp(self->icon_name, "") == 0))) { // Don't have icon set + return; + } + + GtkIconTheme *theme = gtk_icon_theme_get_default(); // Get the default icon theme + GdkPixbuf* icon_pix = gtk_icon_theme_load_icon_for_scale(theme, use_alt ? self->alt_icon_name : self->icon_name, (gint) self->pix_size, 1, GTK_ICON_LOOKUP_USE_BUILTIN & GTK_ICON_LOOKUP_GENERIC_FALLBACK, NULL); + g_return_if_fail(GDK_IS_PIXBUF(icon_pix)); // Return if not a pixbuf + koto_button_set_pixbuf(self, icon_pix); + self->currently_showing_alt = use_alt; } KotoButton* koto_button_new_plain(gchar *label) { return g_object_new(KOTO_TYPE_BUTTON, "button-text", label, - "orientation", GTK_ORIENTATION_HORIZONTAL, NULL ); } -KotoButton* koto_button_new_with_icon(gchar *label, gchar *icon_name, KotoButtonPixbufSize size) { +KotoButton* koto_button_new_with_icon(gchar *label, gchar *icon_name, gchar *alt_icon_name, KotoButtonPixbufSize size) { return g_object_new(KOTO_TYPE_BUTTON, "button-text", label, "icon-name", icon_name, - "orientation", GTK_ORIENTATION_HORIZONTAL, + "alt-icon-name", alt_icon_name, "pixbuf-size", koto_get_pixbuf_size(size), NULL ); @@ -333,7 +389,6 @@ KotoButton* koto_button_new_with_pixbuf(gchar *label, GdkPixbuf *pix, KotoButton return g_object_new(KOTO_TYPE_BUTTON, "button-text", label, "pixbuf", pix, - "orientation", GTK_ORIENTATION_HORIZONTAL, "pixbuf-size", koto_get_pixbuf_size(size), NULL ); diff --git a/src/koto-button.h b/src/koto-button.h index 4f99950..c267247 100644 --- a/src/koto-button.h +++ b/src/koto-button.h @@ -16,9 +16,6 @@ */ #pragma once -#ifndef __GTK_ENUMS_H__ -#define __GTK_ENUMS_H__ -#endif #include #include @@ -40,18 +37,20 @@ typedef enum { #define KOTO_TYPE_BUTTON (koto_button_get_type()) -G_DECLARE_FINAL_TYPE (KotoButton, koto_button, KOTO, BUTTON, GtkBox) +G_DECLARE_FINAL_TYPE (KotoButton, koto_button, KOTO, BUTTON, GtkEventBox) guint koto_get_pixbuf_size(KotoButtonPixbufSize size); KotoButton* koto_button_new_plain(gchar *label); -KotoButton* koto_button_new_with_icon(gchar *label, gchar *icon_name, KotoButtonPixbufSize size); +KotoButton* koto_button_new_with_icon(gchar *label, gchar *icon_name, gchar *alt_icon_name, KotoButtonPixbufSize size); KotoButton* koto_button_new_with_pixbuf(gchar *label, GdkPixbuf *pix, KotoButtonPixbufSize size); +void koto_button_flip(KotoButton *self); void koto_button_set_badge_text(KotoButton *self, gchar *text); -void koto_button_set_icon_name(KotoButton *self, gchar *icon_name); +void koto_button_set_icon_name(KotoButton *self, gchar *icon_name, gboolean for_alt); void koto_button_set_pixbuf(KotoButton *self, GdkPixbuf *pix); void koto_button_set_pixbuf_size(KotoButton *self, guint size); void koto_button_set_text(KotoButton *self, gchar *text); +void koto_button_show_image(KotoButton *self, gboolean use_alt); G_END_DECLS diff --git a/src/koto-expander.c b/src/koto-expander.c index 3ecae3d..639da81 100644 --- a/src/koto-expander.c +++ b/src/koto-expander.c @@ -19,20 +19,18 @@ #include #include "koto-config.h" #include "koto-button.h" -#include "koto-flipper-button.h" #include "koto-expander.h" -#include "koto-utils.h" enum { - PROP_0, + PROP_EXP_0, PROP_HEADER_ICON_NAME, PROP_HEADER_LABEL, PROP_HEADER_SECONDARY_BUTTON, PROP_CONTENT, - N_PROPERTIES + N_EXP_PROPERTIES }; -static GParamSpec *props[N_PROPERTIES] = { NULL, }; +static GParamSpec *expander_props[N_EXP_PROPERTIES] = { NULL, }; struct _KotoExpander { GtkBox parent_instance; @@ -43,8 +41,8 @@ struct _KotoExpander { gchar *icon_name; gchar *label; - GtkWidget *header_secondary_button; - KotoFlipperButton *header_expand_button; + KotoButton *header_secondary_button; + KotoButton *header_expand_button; GtkWidget *revealer; GtkWidget *content; @@ -65,7 +63,7 @@ static void koto_expander_class_init(KotoExpanderClass *c) { gobject_class->set_property = koto_expander_set_property; gobject_class->get_property = koto_expander_get_property; - props[PROP_HEADER_ICON_NAME] = g_param_spec_string( + expander_props[PROP_HEADER_ICON_NAME] = g_param_spec_string( "icon-name", "Icon Name", "Name of the icon to use in the Expander", @@ -73,7 +71,7 @@ static void koto_expander_class_init(KotoExpanderClass *c) { G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE ); - props[PROP_HEADER_LABEL] = g_param_spec_string( + expander_props[PROP_HEADER_LABEL] = g_param_spec_string( "label", "Label", "Label for the Expander", @@ -81,15 +79,15 @@ static void koto_expander_class_init(KotoExpanderClass *c) { G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE ); - props[PROP_HEADER_SECONDARY_BUTTON] = g_param_spec_object( + expander_props[PROP_HEADER_SECONDARY_BUTTON] = g_param_spec_object( "secondary-button", "Secondary Button", "Secondary Button to be placed next to Expander button", - GTK_TYPE_WIDGET, + KOTO_TYPE_BUTTON, G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE ); - props[PROP_CONTENT] = g_param_spec_object( + expander_props[PROP_CONTENT] = g_param_spec_object( "content", "Content", "Content inside the Expander", @@ -97,7 +95,7 @@ static void koto_expander_class_init(KotoExpanderClass *c) { G_PARAM_EXPLICIT_NOTIFY|G_PARAM_READWRITE ); - g_object_class_install_properties(gobject_class, N_PROPERTIES, props); + g_object_class_install_properties(gobject_class, N_EXP_PROPERTIES, expander_props); } static void koto_expander_get_property(GObject *obj, guint prop_id, GValue *val, GParamSpec *spec) { @@ -126,7 +124,7 @@ static void koto_expander_set_property(GObject *obj, guint prop_id, const GValue KotoExpander *self = KOTO_EXPANDER(obj); if (!GTK_IS_WIDGET(self->header_button)) { // Header Button is not a widget - KotoButton *new_button = koto_button_new_with_icon("Temporary Text", "emblem-favorite-symbolic", KOTO_BUTTON_PIXBUF_SIZE_SMALL); + KotoButton *new_button = koto_button_new_with_icon("Temporary Text", "emblem-favorite-symbolic", NULL, KOTO_BUTTON_PIXBUF_SIZE_SMALL); if (GTK_IS_WIDGET(new_button)) { // Created our widget successfully self->header_button = new_button; @@ -137,14 +135,14 @@ static void koto_expander_set_property(GObject *obj, guint prop_id, const GValue switch (prop_id) { case PROP_HEADER_ICON_NAME: g_return_if_fail(GTK_IS_WIDGET(self->header_button)); - koto_button_set_icon_name(self->header_button, g_strdup(g_value_get_string(val))); + koto_button_set_icon_name(self->header_button, g_strdup(g_value_get_string(val)), FALSE); break; case PROP_HEADER_LABEL: g_return_if_fail(GTK_IS_WIDGET(self->header_button)); koto_button_set_text(self->header_button, g_strdup(g_value_get_string(val))); break; case PROP_HEADER_SECONDARY_BUTTON: - koto_expander_set_secondary_button(self, (GtkWidget*) g_value_get_object(val)); + koto_expander_set_secondary_button(self, (KotoButton*) g_value_get_object(val)); break; case PROP_CONTENT: koto_expander_set_content(self, (GtkWidget*) g_value_get_object(val)); @@ -171,7 +169,7 @@ static void koto_expander_init(KotoExpander *self) { gtk_revealer_set_reveal_child(GTK_REVEALER(self->revealer), TRUE); // Set to be revealed by default gtk_revealer_set_transition_type(GTK_REVEALER(self->revealer), GTK_REVEALER_TRANSITION_TYPE_SLIDE_DOWN); - self->header_expand_button = koto_flipper_button_new("pan-down-symbolic", "pan-up-symbolic", GTK_ICON_SIZE_SMALL_TOOLBAR); + self->header_expand_button = koto_button_new_with_icon("", "pan-down-symbolic", "pan-up-symbolic", KOTO_BUTTON_PIXBUF_SIZE_SMALL); gtk_box_pack_end(GTK_BOX(self->header), GTK_WIDGET(self->header_expand_button), FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(self), self->header, FALSE, FALSE, 0); @@ -179,27 +177,26 @@ static void koto_expander_init(KotoExpander *self) { self->constructed = TRUE; - g_signal_connect(self->header_expand_button, "clicked", G_CALLBACK(koto_expander_toggle_content), self); + g_signal_connect(self->header_expand_button, "button-release-event", G_CALLBACK(koto_expander_toggle_content), self); } -void koto_expander_set_secondary_button(KotoExpander *self, GtkWidget *new_button) { +void koto_expander_set_secondary_button(KotoExpander *self, KotoButton *new_button) { if (!self->constructed) { return; } - if (!GTK_IS_BUTTON(new_button)) { + if (!GTK_IS_WIDGET(new_button)) { return; } - if (GTK_IS_BUTTON(self->header_secondary_button)) { // Already have a button - gtk_container_remove(GTK_CONTAINER(self->header), self->header_secondary_button); - //g_free(self->header_secondary_button); + if (GTK_IS_WIDGET(self->header_secondary_button)) { // Already have a button + gtk_container_remove(GTK_CONTAINER(self->header), GTK_WIDGET(self->header_secondary_button)); } self->header_secondary_button = new_button; - gtk_box_pack_end(GTK_BOX(self->header), self->header_secondary_button, FALSE, FALSE, 0); + gtk_box_pack_end(GTK_BOX(self->header), GTK_WIDGET(self->header_secondary_button), FALSE, FALSE, 0); - g_object_notify_by_pspec(G_OBJECT(self), props[PROP_HEADER_SECONDARY_BUTTON]); + g_object_notify_by_pspec(G_OBJECT(self), expander_props[PROP_HEADER_SECONDARY_BUTTON]); } void koto_expander_set_content(KotoExpander *self, GtkWidget *new_content) { @@ -215,12 +212,12 @@ void koto_expander_set_content(KotoExpander *self, GtkWidget *new_content) { self->content = new_content; gtk_container_add(GTK_CONTAINER(self->revealer), self->content); - g_object_notify_by_pspec(G_OBJECT(self), props[PROP_CONTENT]); + g_object_notify_by_pspec(G_OBJECT(self), expander_props[PROP_CONTENT]); } -void koto_expander_toggle_content(GtkWidget *button, gpointer data) { +void koto_expander_toggle_content(GtkWidget *button, GdkEvent *event, gpointer data) { KotoExpander* self = data; - koto_flipper_button_flip(KOTO_FLIPPER_BUTTON(button)); + koto_button_flip(KOTO_BUTTON(button)); GtkRevealer* rev = GTK_REVEALER(self->revealer); gtk_revealer_set_reveal_child(rev, !gtk_revealer_get_reveal_child(rev)); // Invert our values } @@ -234,7 +231,7 @@ KotoExpander* koto_expander_new(gchar *primary_icon_name, gchar *primary_label_t ); } -KotoExpander* koto_expander_new_with_button(gchar *primary_icon_name, gchar *primary_label_text, GtkWidget *secondary_button) { +KotoExpander* koto_expander_new_with_button(gchar *primary_icon_name, gchar *primary_label_text, KotoButton *secondary_button) { return g_object_new(KOTO_TYPE_EXPANDER, "orientation", GTK_ORIENTATION_VERTICAL, "icon-name", primary_icon_name, diff --git a/src/koto-expander.h b/src/koto-expander.h index c047ab7..6d82a94 100644 --- a/src/koto-expander.h +++ b/src/koto-expander.h @@ -18,6 +18,7 @@ #pragma once #include +#include "koto-button.h" G_BEGIN_DECLS @@ -26,11 +27,11 @@ G_BEGIN_DECLS G_DECLARE_FINAL_TYPE (KotoExpander, koto_expander, KOTO, EXPANDER, GtkBox) KotoExpander* koto_expander_new(gchar *primary_icon_name, gchar *primary_label_text); -KotoExpander* koto_expander_new_with_button(gchar *primary_icon_name, gchar *primary_label_text, GtkWidget *secondary_button); +KotoExpander* koto_expander_new_with_button(gchar *primary_icon_name, gchar *primary_label_text, KotoButton *secondary_button); void koto_expander_set_icon_name(KotoExpander *self, const gchar *in); void koto_expander_set_label(KotoExpander *self, const gchar *label); -void koto_expander_set_secondary_button(KotoExpander *self, GtkWidget *new_button); +void koto_expander_set_secondary_button(KotoExpander *self, KotoButton *new_button); void koto_expander_set_content(KotoExpander *self, GtkWidget *new_content); -void koto_expander_toggle_content(GtkWidget *button, gpointer data); +void koto_expander_toggle_content(GtkWidget *button, GdkEvent *event, gpointer data); G_END_DECLS diff --git a/src/koto-flipper-button.c b/src/koto-flipper-button.c deleted file mode 100644 index 510bf0d..0000000 --- a/src/koto-flipper-button.c +++ /dev/null @@ -1,129 +0,0 @@ -/* koto-flipper-button.c - * - * Copyright 2021 Joshua Strobl - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include "koto-config.h" -#include "koto-flipper-button.h" - -enum { - PROP_0, - PROP_SIZE, - PROP_INITIAL_IMAGE, - PROP_FLIPPED_IMAGE, - N_PROPERTIES -}; - -static GParamSpec *props[N_PROPERTIES] = { NULL, }; - -struct _KotoFlipperButton { - GtkButton parent_instance; - GtkIconSize size; - gboolean flipped; - - gchar *initial_image; - gchar *flipped_image; -}; - -struct _KotoFlipperButtonClass { - GtkButtonClass parent_class; -}; - -G_DEFINE_TYPE(KotoFlipperButton, koto_flipper_button, GTK_TYPE_BUTTON); -static void koto_flipper_button_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec); - -static void koto_flipper_button_class_init(KotoFlipperButtonClass *c) { - GObjectClass *gobject_class; - gobject_class = G_OBJECT_CLASS(c); - gobject_class->set_property = koto_flipper_button_set_property; - - props[PROP_SIZE] = g_param_spec_enum( - "size", - "Icon Size", - "Size of the icon", - GTK_TYPE_ICON_SIZE, - GTK_ICON_SIZE_MENU, - G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_WRITABLE - ); - - props[PROP_INITIAL_IMAGE] = g_param_spec_string( - "initial-image", - "Initial Image", - "Image to use initially for the button", - NULL, - G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_WRITABLE - ); - - props[PROP_FLIPPED_IMAGE] = g_param_spec_string( - "flipped-image", - "Flipped Image", - "Image to use when the button is flipped", - NULL, - G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY|G_PARAM_WRITABLE - ); - - g_object_class_install_properties(gobject_class, N_PROPERTIES, props); -} - -static void koto_flipper_button_set_property(GObject *obj, guint prop_id, const GValue *val, GParamSpec *spec) { - KotoFlipperButton *self = KOTO_FLIPPER_BUTTON(obj); - - if (prop_id == PROP_INITIAL_IMAGE) { - g_free(self->initial_image); - self->initial_image = g_strdup(g_value_get_string(val)); - koto_flipper_button_set_icon(self, self->initial_image); - } else if (prop_id == PROP_FLIPPED_IMAGE) { - g_free(self->flipped_image); - self->flipped_image = g_strdup(g_value_get_string(val)); - } else if (prop_id == PROP_SIZE) { - self->size = (GtkIconSize) g_value_get_enum(val); - - if (self->initial_image != NULL && !self->flipped) { - koto_flipper_button_set_icon(self, self->flipped ? self->initial_image : self->flipped_image); - } - } else { - G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, prop_id, spec); - return; - } - - g_object_notify_by_pspec(obj, props[prop_id]); -} - -static void koto_flipper_button_init(KotoFlipperButton *self) { - self->flipped = FALSE; - - GtkStyleContext *button_style = gtk_widget_get_style_context(GTK_WIDGET(self)); // Get the styling for the flipper button - gtk_style_context_add_class(button_style, "flat"); // Set it to flat -} - -void koto_flipper_button_flip(KotoFlipperButton *self) { - koto_flipper_button_set_icon(self, self->flipped ? self->initial_image : self->flipped_image); - self->flipped = !self->flipped; -} - -void koto_flipper_button_set_icon(KotoFlipperButton *self, gchar *name) { - GtkWidget *new_image = gtk_image_new_from_icon_name(name, self->size); - gtk_button_set_image(GTK_BUTTON(self), new_image); -} - -KotoFlipperButton* koto_flipper_button_new(gchar *initial_icon, gchar *flipped_icon, GtkIconSize size) { - return g_object_new(KOTO_TYPE_FLIPPER_BUTTON, - "initial-image", initial_icon, - "flipped-image", flipped_icon, - "size", size, - NULL - ); -} diff --git a/src/koto-nav.c b/src/koto-nav.c index 15ec21f..63b643c 100644 --- a/src/koto-nav.c +++ b/src/koto-nav.c @@ -20,7 +20,6 @@ #include "koto-button.h" #include "koto-expander.h" #include "koto-nav.h" -#include "koto-utils.h" struct _KotoNav { GtkScrolledWindow parent_instance; @@ -68,7 +67,7 @@ static void koto_nav_init(KotoNav *self) { gtk_container_add(GTK_CONTAINER(self), self->content); - KotoButton *h_button = koto_button_new_with_icon("Home", "user-home-symbolic", KOTO_BUTTON_PIXBUF_SIZE_SMALL); + KotoButton *h_button = koto_button_new_with_icon("Home", "user-home-symbolic", NULL, KOTO_BUTTON_PIXBUF_SIZE_SMALL); if (h_button != NULL) { self->home_button = h_button; @@ -80,8 +79,7 @@ static void koto_nav_init(KotoNav *self) { koto_nav_create_podcasts_section(self); - - GtkWidget *playlist_add_button = koto_create_flat_icon_button("list-add-symbolic", GTK_ICON_SIZE_SMALL_TOOLBAR); + KotoButton *playlist_add_button = koto_button_new_with_icon("", "list-add-symbolic", NULL, KOTO_BUTTON_PIXBUF_SIZE_SMALL); KotoExpander *pl_expander = koto_expander_new_with_button("playlist-symbolic", "Playlists", playlist_add_button); if (pl_expander != NULL) { diff --git a/src/koto-playerbar.c b/src/koto-playerbar.c index 307f0d7..66abab8 100644 --- a/src/koto-playerbar.c +++ b/src/koto-playerbar.c @@ -15,10 +15,9 @@ * limitations under the License. */ -#include +#include "koto-button.h" #include "koto-config.h" #include "koto-playerbar.h" -#include "koto-utils.h" struct _KotoPlayerBar { GtkBox parent_instance; @@ -29,13 +28,13 @@ struct _KotoPlayerBar { GtkWidget *secondary_controls_section; /* Primary Buttons */ - GtkWidget *back_button; - GtkWidget *play_pause_button; - GtkWidget *forward_button; - GtkWidget *repeat_button; - GtkWidget *shuffle_button; - GtkWidget *playlist_button; - GtkWidget *eq_button; + KotoButton *back_button; + KotoButton *play_pause_button; + KotoButton *forward_button; + KotoButton *repeat_button; + KotoButton *shuffle_button; + KotoButton *playlist_button; + KotoButton *eq_button; GtkWidget *volume_button; /* Selected Playback Section */ @@ -113,9 +112,9 @@ void koto_playerbar_create_playback_details(KotoPlayerBar* bar) { gtk_box_pack_start(GTK_BOX(bar->playback_section), bar->artwork, FALSE, FALSE, 0); } - bar->playback_title = gtk_label_new(_("Title")); - bar->playback_album = gtk_label_new(_("Album")); - bar->playback_artist = gtk_label_new(_("Artist")); + bar->playback_title = gtk_label_new("Title"); + bar->playback_album = gtk_label_new("Album"); + bar->playback_artist = gtk_label_new("Artist"); gtk_box_pack_start(GTK_BOX(bar->playback_details_section), GTK_WIDGET(bar->playback_title), TRUE, TRUE, 0); gtk_box_pack_start(GTK_BOX(bar->playback_details_section), GTK_WIDGET(bar->playback_album), TRUE, TRUE, 0); @@ -125,45 +124,45 @@ void koto_playerbar_create_playback_details(KotoPlayerBar* bar) { } void koto_playerbar_create_primary_controls(KotoPlayerBar* bar) { - bar->back_button = koto_create_flat_icon_button("media-skip-backward-symbolic", GTK_ICON_SIZE_LARGE_TOOLBAR); - bar->play_pause_button = koto_create_flat_icon_button("media-playback-start-symbolic", GTK_ICON_SIZE_DND); // TODO: Have this take in a state and switch to a different icon if necessary - bar->forward_button = koto_create_flat_icon_button("media-skip-forward-symbolic", GTK_ICON_SIZE_LARGE_TOOLBAR); + bar->back_button = koto_button_new_with_icon("", "media-skip-backward-symbolic", NULL, KOTO_BUTTON_PIXBUF_SIZE_NORMAL); + bar->play_pause_button = koto_button_new_with_icon("", "media-playback-start-symbolic", NULL, KOTO_BUTTON_PIXBUF_SIZE_LARGE); // TODO: Have this take in a state and switch to a different icon if necessary + bar->forward_button = koto_button_new_with_icon("", "media-skip-forward-symbolic", NULL, KOTO_BUTTON_PIXBUF_SIZE_NORMAL); if (bar->back_button != NULL) { - gtk_box_pack_start(GTK_BOX(bar->primary_controls_section), bar->back_button, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(bar->primary_controls_section), GTK_WIDGET(bar->back_button), FALSE, FALSE, 0); } if (bar->play_pause_button != NULL) { - gtk_box_pack_start(GTK_BOX(bar->primary_controls_section), bar->play_pause_button, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(bar->primary_controls_section), GTK_WIDGET(bar->play_pause_button), FALSE, FALSE, 0); } if (bar->forward_button != NULL) { - gtk_box_pack_start(GTK_BOX(bar->primary_controls_section), bar->forward_button, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(bar->primary_controls_section), GTK_WIDGET(bar->forward_button), FALSE, FALSE, 0); } } void koto_playerbar_create_secondary_controls(KotoPlayerBar* bar) { - bar->repeat_button = koto_create_flat_icon_button("media-playlist-repeat-symbolic", GTK_ICON_SIZE_LARGE_TOOLBAR); - bar->shuffle_button = koto_create_flat_icon_button("media-playlist-shuffle-symbolic", GTK_ICON_SIZE_LARGE_TOOLBAR); - bar->playlist_button = koto_create_flat_icon_button("playlist-symbolic", GTK_ICON_SIZE_LARGE_TOOLBAR); - bar->eq_button = koto_create_flat_icon_button("multimedia-equalizer-symbolic", GTK_ICON_SIZE_LARGE_TOOLBAR); + bar->repeat_button = koto_button_new_with_icon("", "media-playlist-repeat-symbolic", NULL, KOTO_BUTTON_PIXBUF_SIZE_NORMAL); + bar->shuffle_button = koto_button_new_with_icon("", "media-playlist-shuffle-symbolic", NULL, KOTO_BUTTON_PIXBUF_SIZE_NORMAL); + bar->playlist_button = koto_button_new_with_icon("", "playlist-symbolic", NULL, KOTO_BUTTON_PIXBUF_SIZE_NORMAL); + bar->eq_button = koto_button_new_with_icon("", "multimedia-equalizer-symbolic", NULL, KOTO_BUTTON_PIXBUF_SIZE_NORMAL); bar->volume_button = gtk_volume_button_new(); // Have this take in a state and switch to a different icon if necessary gtk_scale_button_set_value(GTK_SCALE_BUTTON(bar->volume_button), 0.5); if (bar->repeat_button != NULL) { - gtk_box_pack_start(GTK_BOX(bar->secondary_controls_section), bar->repeat_button, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(bar->secondary_controls_section), GTK_WIDGET(bar->repeat_button), FALSE, FALSE, 0); } if (bar->shuffle_button != NULL) { - gtk_box_pack_start(GTK_BOX(bar->secondary_controls_section), bar->shuffle_button, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(bar->secondary_controls_section), GTK_WIDGET(bar->shuffle_button), FALSE, FALSE, 0); } if (bar->playlist_button != NULL) { - gtk_box_pack_start(GTK_BOX(bar->secondary_controls_section), bar->playlist_button, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(bar->secondary_controls_section), GTK_WIDGET(bar->playlist_button), FALSE, FALSE, 0); } if (bar->eq_button != NULL) { - gtk_box_pack_start(GTK_BOX(bar->secondary_controls_section), bar->eq_button, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(bar->secondary_controls_section), GTK_WIDGET(bar->eq_button), FALSE, FALSE, 0); } if (bar->volume_button != NULL) { diff --git a/src/koto-utils.c b/src/koto-utils.c deleted file mode 100644 index 985c787..0000000 --- a/src/koto-utils.c +++ /dev/null @@ -1,28 +0,0 @@ -/* koto-utils.c - * - * Copyright 2021 Joshua Strobl - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "koto-utils.h" - -GtkWidget* koto_create_flat_icon_button(gchar *icon_name, GtkIconSize size) { - GtkWidget* button; - button = gtk_button_new_from_icon_name(icon_name, size); - - GtkStyleContext *button_style = gtk_widget_get_style_context(button); - gtk_style_context_add_class(button_style, "flat"); - - return button; -} diff --git a/src/koto-utils.h b/src/koto-utils.h deleted file mode 100644 index 0a13d1c..0000000 --- a/src/koto-utils.h +++ /dev/null @@ -1,24 +0,0 @@ -/* koto-utils.h - * - * Copyright 2021 Joshua Strobl - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -G_BEGIN_DECLS - -GtkWidget* koto_create_flat_icon_button(gchar *icon_name, GtkIconSize size); - -G_END_DECLS diff --git a/src/koto-window.c b/src/koto-window.c index b86d565..53116dc 100644 --- a/src/koto-window.c +++ b/src/koto-window.c @@ -37,12 +37,9 @@ G_DEFINE_TYPE (KotoWindow, koto_window, GTK_TYPE_APPLICATION_WINDOW) static void koto_window_class_init (KotoWindowClass *klass) { GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); - - gtk_widget_class_set_template_from_resource (widget_class, "/com/github/joshstrobl/koto/koto-window.ui"); } static void koto_window_init (KotoWindow *self) { - gtk_widget_init_template (GTK_WIDGET (self)); GtkCssProvider* provider = gtk_css_provider_new(); gtk_css_provider_load_from_resource(provider, "/com/github/joshstrobl/koto/style.css"); gtk_style_context_add_provider_for_screen(gdk_screen_get_default(), GTK_STYLE_PROVIDER(provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); @@ -75,8 +72,12 @@ static void koto_window_init (KotoWindow *self) { } gtk_container_add(GTK_CONTAINER(self), self->primary_layout); - gtk_widget_show_all(GTK_WIDGET(self)); + gtk_widget_set_size_request(GTK_WIDGET(self), 1200, 675); + gtk_window_set_title(GTK_WINDOW(self), "Koto"); + gtk_window_set_wmclass(GTK_WINDOW(self), "com.github.joshstrobl.koto", "com.github.joshstrobl.koto"); + gtk_window_set_icon_name(GTK_WINDOW(self), "audio-headphones"); + gtk_widget_show_all(GTK_WIDGET(self)); g_thread_new("load-library", load_library, self); } diff --git a/src/koto-window.ui b/src/koto-window.ui deleted file mode 100644 index a1da769..0000000 --- a/src/koto-window.ui +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - diff --git a/src/koto.gresource.xml b/src/koto.gresource.xml index 5e969dc..250bec4 100644 --- a/src/koto.gresource.xml +++ b/src/koto.gresource.xml @@ -2,7 +2,6 @@ koto-headerbar.ui - koto-window.ui ../data/style.css diff --git a/src/meson.build b/src/meson.build index ff11a8d..b0b252b 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,13 +1,12 @@ koto_sources = [ + 'indexer/file.c', 'indexer/file-indexer.c', 'main.c', 'koto-button.c', 'koto-expander.c', - 'koto-flipper-button.c', 'koto-headerbar.c', 'koto-nav.c', 'koto-playerbar.c', - 'koto-utils.c', 'koto-window.c', ]