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`).
This commit is contained in:
parent
625c1be645
commit
9b6fa4593a
19 changed files with 472 additions and 333 deletions
|
@ -18,14 +18,9 @@
|
|||
#include <dirent.h>
|
||||
#include <magic.h>
|
||||
#include <sys/stat.h>
|
||||
#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
|
||||
);
|
||||
|
|
|
@ -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);
|
||||
|
|
274
src/indexer/file.c
Normal file
274
src/indexer/file.c
Normal file
|
@ -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 <glib-2.0/glib.h>
|
||||
#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
|
||||
);
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
/* koto-flipper-button.h
|
||||
/* file.h
|
||||
*
|
||||
* Copyright 2021 Joshua Strobl
|
||||
*
|
||||
|
@ -16,17 +16,17 @@
|
|||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gtk-3.0/gtk/gtk.h>
|
||||
#include <glib-2.0/glib-object.h>
|
||||
|
||||
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
|
|
@ -1,4 +1,5 @@
|
|||
indexer_sources = [
|
||||
'file.c',
|
||||
'file-indexer.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
|
||||
);
|
||||
|
|
|
@ -16,9 +16,6 @@
|
|||
*/
|
||||
|
||||
#pragma once
|
||||
#ifndef __GTK_ENUMS_H__
|
||||
#define __GTK_ENUMS_H__
|
||||
#endif
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <gdk-pixbuf-2.0/gdk-pixbuf/gdk-pixbuf.h>
|
||||
|
@ -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
|
||||
|
|
|
@ -19,20 +19,18 @@
|
|||
#include <gtk-3.0/gtk/gtk.h>
|
||||
#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,
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <gtk-3.0/gtk/gtk.h>
|
||||
#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
|
||||
|
|
|
@ -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 <gtk-3.0/gtk/gtk.h>
|
||||
#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
|
||||
);
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -15,10 +15,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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 <gtk-3.0/gtk/gtk.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
GtkWidget* koto_create_flat_icon_button(gchar *icon_name, GtkIconSize size);
|
||||
|
||||
G_END_DECLS
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated with glade 3.38.2 -->
|
||||
<interface>
|
||||
<requires lib="gtk+" version="3.24"/>
|
||||
<template class="KotoWindow" parent="GtkApplicationWindow">
|
||||
<property name="can-focus">False</property>
|
||||
<property name="default-width">1200</property>
|
||||
<property name="default-height">675</property>
|
||||
</template>
|
||||
</interface>
|
|
@ -2,7 +2,6 @@
|
|||
<gresources>
|
||||
<gresource prefix="/com/github/joshstrobl/koto">
|
||||
<file>koto-headerbar.ui</file>
|
||||
<file>koto-window.ui</file>
|
||||
<file alias="style.css">../data/style.css</file>
|
||||
</gresource>
|
||||
</gresources>
|
||||
|
|
|
@ -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',
|
||||
]
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue