From 9b6fa4593a4d2c26358ea2cd5713319ea541fd6f Mon Sep 17 00:00:00 2001 From: Joshua Strobl Date: Fri, 12 Feb 2021 12:56:41 +0200 Subject: [PATCH] Deprecate KotoFlipperButton, integrate flip functionality with an alt image into KotoButton. We are now leveraging KotoButton in the KotoPlayerBar and KotoExpander. Dropped Glade UI templating from KotoWindow, set its default size using gtk_widget_set_size_request to force a minimum window size, set window title, WMClass, and icon name. Start implementing KotoIndexedFile class to handle our provided audio files, setting its file name and attempting to parse the file name when we are not using ID3 data. The parsing is as follows: - All `_` are replaced with whitespace - We will attempt to remove nested references to the artist and album name (we need to implemented the relevant classes to leverage that). - Remove any references to ` - ` followed by any stragglers `-` (without the whitespace around it). - Split based on `.` and remove the trailing file extension, preserving the rest (so something like `Ch. 01.ogg` would be considered just `Ch. 01`). --- data/style.css | 7 +- src/indexer/file-indexer.c | 38 ++- src/indexer/file-indexer.h | 6 +- src/indexer/file.c | 274 ++++++++++++++++++ src/{koto-flipper-button.h => indexer/file.h} | 16 +- src/indexer/meson.build | 1 + src/koto-button.c | 129 ++++++--- src/koto-button.h | 11 +- src/koto-expander.c | 55 ++-- src/koto-expander.h | 7 +- src/koto-flipper-button.c | 129 --------- src/koto-nav.c | 6 +- src/koto-playerbar.c | 51 ++-- src/koto-utils.c | 28 -- src/koto-utils.h | 24 -- src/koto-window.c | 9 +- src/koto-window.ui | 10 - src/koto.gresource.xml | 1 - src/meson.build | 3 +- 19 files changed, 472 insertions(+), 333 deletions(-) create mode 100644 src/indexer/file.c rename src/{koto-flipper-button.h => indexer/file.h} (57%) delete mode 100644 src/koto-flipper-button.c delete mode 100644 src/koto-utils.c delete mode 100644 src/koto-utils.h delete mode 100644 src/koto-window.ui 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', ]