pidgin/pidgin
Clone
Summary
Browse
Changes
Graph
Add all of the purple preferences to our gschema
20 months ago, Gary Kramlich
64287dd40326
Add all of the purple preferences to our gschema
There's a number of preferences we will be dropping and a few that we will be
adding with this change. Of those that are dropping, some will be moved to
plugins instead.
Testing Done:
Compiled the schema
Reviewed at https://reviews.imfreedom.org/r/1866/
/*
* Purple - Internet Messaging Library
* Copyright (C) Pidgin Developers <devel@pidgin.im>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <https://www.gnu.org/licenses/>.
*/
#include
<glib/gi18n-lib.h>
#include
"purplenotificationmanager.h"
#include
"purpleprivate.h"
enum
{
PROP_ZERO
,
PROP_UNREAD_COUNT
,
N_PROPERTIES
,
};
static
GParamSpec
*
properties
[
N_PROPERTIES
]
=
{
NULL
,
};
enum
{
SIG_ADDED
,
SIG_REMOVED
,
SIG_READ
,
SIG_UNREAD
,
N_SIGNALS
,
};
static
guint
signals
[
N_SIGNALS
]
=
{
0
,
};
struct
_PurpleNotificationManager
{
GObject
parent
;
GListStore
*
notifications
;
guint
unread_count
;
};
G_DEFINE_TYPE
(
PurpleNotificationManager
,
purple_notification_manager
,
G_TYPE_OBJECT
);
static
PurpleNotificationManager
*
default_manager
=
NULL
;
/******************************************************************************
* Helpers
*****************************************************************************/
static
void
purple_notification_manager_set_unread_count
(
PurpleNotificationManager
*
manager
,
guint
unread_count
)
{
if
(
manager
->
unread_count
!=
unread_count
)
{
manager
->
unread_count
=
unread_count
;
g_object_notify_by_pspec
(
G_OBJECT
(
manager
),
properties
[
PROP_UNREAD_COUNT
]);
}
}
static
inline
void
purple_notification_manager_increment_unread_count
(
PurpleNotificationManager
*
manager
)
{
if
(
manager
->
unread_count
<
G_MAXUINT
)
{
purple_notification_manager_set_unread_count
(
manager
,
manager
->
unread_count
+
1
);
}
}
static
inline
void
purple_notification_manager_decrement_unread_count
(
PurpleNotificationManager
*
manager
)
{
if
(
manager
->
unread_count
>
0
)
{
purple_notification_manager_set_unread_count
(
manager
,
manager
->
unread_count
-
1
);
}
}
/******************************************************************************
* Callbacks
*****************************************************************************/
static
void
purple_notification_manager_notify_cb
(
GObject
*
obj
,
G_GNUC_UNUSED
GParamSpec
*
pspec
,
gpointer
data
)
{
PurpleNotification
*
notification
=
PURPLE_NOTIFICATION
(
obj
);
PurpleNotificationManager
*
manager
=
data
;
guint
signal_id
=
0
;
/* This function is called after the property is changed. So we need to
* get the new value to determine how the state changed.
*/
if
(
purple_notification_get_read
(
notification
))
{
purple_notification_manager_decrement_unread_count
(
manager
);
signal_id
=
signals
[
SIG_READ
];
}
else
{
purple_notification_manager_increment_unread_count
(
manager
);
signal_id
=
signals
[
SIG_UNREAD
];
}
g_signal_emit
(
manager
,
signal_id
,
0
,
notification
);
}
/******************************************************************************
* GObject Implementation
*****************************************************************************/
static
void
purple_notification_manager_get_property
(
GObject
*
obj
,
guint
param_id
,
GValue
*
value
,
GParamSpec
*
pspec
)
{
PurpleNotificationManager
*
manager
=
PURPLE_NOTIFICATION_MANAGER
(
obj
);
switch
(
param_id
)
{
case
PROP_UNREAD_COUNT
:
g_value_set_uint
(
value
,
purple_notification_manager_get_unread_count
(
manager
));
break
;
default
:
G_OBJECT_WARN_INVALID_PROPERTY_ID
(
obj
,
param_id
,
pspec
);
break
;
}
}
static
void
purple_notification_manager_finalize
(
GObject
*
obj
)
{
PurpleNotificationManager
*
manager
=
NULL
;
manager
=
PURPLE_NOTIFICATION_MANAGER
(
obj
);
g_clear_object
(
&
manager
->
notifications
);
G_OBJECT_CLASS
(
purple_notification_manager_parent_class
)
->
finalize
(
obj
);
}
static
void
purple_notification_manager_init
(
PurpleNotificationManager
*
manager
)
{
manager
->
notifications
=
g_list_store_new
(
PURPLE_TYPE_NOTIFICATION
);
}
static
void
purple_notification_manager_class_init
(
PurpleNotificationManagerClass
*
klass
)
{
GObjectClass
*
obj_class
=
G_OBJECT_CLASS
(
klass
);
obj_class
->
get_property
=
purple_notification_manager_get_property
;
obj_class
->
finalize
=
purple_notification_manager_finalize
;
/* Properties */
/**
* PurpleNotificationManager:unread-count:
*
* The number of unread notifications in the manager.
*
* Since: 3.0.0
*/
properties
[
PROP_UNREAD_COUNT
]
=
g_param_spec_uint
(
"unread-count"
,
"unread-count"
,
"The number of unread messages in the manager."
,
0
,
G_MAXUINT
,
0
,
G_PARAM_READABLE
|
G_PARAM_STATIC_STRINGS
);
g_object_class_install_properties
(
obj_class
,
N_PROPERTIES
,
properties
);
/* Signals */
/**
* PurpleNotificationManager::added:
* @manager: The instance.
* @notification: The [class@Notification] that was added.
*
* Emitted after @notification has been added to @manager.
*
* Since: 3.0.0
*/
signals
[
SIG_ADDED
]
=
g_signal_new_class_handler
(
"added"
,
G_OBJECT_CLASS_TYPE
(
klass
),
G_SIGNAL_RUN_LAST
,
NULL
,
NULL
,
NULL
,
NULL
,
G_TYPE_NONE
,
1
,
PURPLE_TYPE_NOTIFICATION
);
/**
* PurpleNotificationManager::removed:
* @manager: The instance.
* @notification: The [class@Notification] that was removed.
*
* Emitted after @notification has been removed from @manager.
*
* Since: 3.0.0
*/
signals
[
SIG_REMOVED
]
=
g_signal_new_class_handler
(
"removed"
,
G_OBJECT_CLASS_TYPE
(
klass
),
G_SIGNAL_RUN_LAST
,
NULL
,
NULL
,
NULL
,
NULL
,
G_TYPE_NONE
,
1
,
PURPLE_TYPE_NOTIFICATION
);
/**
* PurpleNotificationManager::read:
* @manager: The instance.
* @notification: The [class@Notification].
*
* Emitted after @notification has been marked as read.
*
* Since: 3.0.0
*/
signals
[
SIG_READ
]
=
g_signal_new_class_handler
(
"read"
,
G_OBJECT_CLASS_TYPE
(
klass
),
G_SIGNAL_RUN_LAST
,
NULL
,
NULL
,
NULL
,
NULL
,
G_TYPE_NONE
,
1
,
PURPLE_TYPE_NOTIFICATION
);
/**
* PurpleNotificationManager::unread:
* @manager: The instance.
* @notification: The [class@Notification].
*
* Emitted after @notification has been marked as unread.
*
* Since: 3.0.0
*/
signals
[
SIG_UNREAD
]
=
g_signal_new_class_handler
(
"unread"
,
G_OBJECT_CLASS_TYPE
(
klass
),
G_SIGNAL_RUN_LAST
,
NULL
,
NULL
,
NULL
,
NULL
,
G_TYPE_NONE
,
1
,
PURPLE_TYPE_NOTIFICATION
);
}
/******************************************************************************
* Private API
*****************************************************************************/
void
purple_notification_manager_startup
(
void
)
{
if
(
default_manager
==
NULL
)
{
default_manager
=
g_object_new
(
PURPLE_TYPE_NOTIFICATION_MANAGER
,
NULL
);
}
}
void
purple_notification_manager_shutdown
(
void
)
{
g_clear_object
(
&
default_manager
);
}
/******************************************************************************
* Public API
*****************************************************************************/
PurpleNotificationManager
*
purple_notification_manager_get_default
(
void
)
{
return
default_manager
;
}
void
purple_notification_manager_add
(
PurpleNotificationManager
*
manager
,
PurpleNotification
*
notification
)
{
g_return_if_fail
(
PURPLE_IS_NOTIFICATION_MANAGER
(
manager
));
g_return_if_fail
(
PURPLE_IS_NOTIFICATION
(
notification
));
if
(
g_list_store_find
(
manager
->
notifications
,
notification
,
NULL
))
{
const
gchar
*
id
=
purple_notification_get_id
(
notification
);
g_warning
(
"double add detected for notification %s"
,
id
);
return
;
}
g_list_store_insert_sorted
(
manager
->
notifications
,
notification
,
(
GCompareDataFunc
)
purple_notification_compare
,
NULL
);
/* Connect to the notify signal for the read property only so we can
* propagate out changes for any notification.
*/
g_signal_connect_object
(
notification
,
"notify::read"
,
G_CALLBACK
(
purple_notification_manager_notify_cb
),
manager
,
0
);
/* If the notification is not read, we need to increment the unread count.
*/
if
(
!
purple_notification_get_read
(
notification
))
{
purple_notification_manager_increment_unread_count
(
manager
);
}
g_signal_emit
(
G_OBJECT
(
manager
),
signals
[
SIG_ADDED
],
0
,
notification
);
}
void
purple_notification_manager_remove
(
PurpleNotificationManager
*
manager
,
PurpleNotification
*
notification
)
{
guint
position
;
g_return_if_fail
(
PURPLE_IS_NOTIFICATION_MANAGER
(
manager
));
g_return_if_fail
(
PURPLE_IS_NOTIFICATION
(
notification
));
if
(
g_list_store_find
(
manager
->
notifications
,
notification
,
&
position
))
{
/* Reference the notification so we can emit the signal after it's been
* removed from the hash table.
*/
g_object_ref
(
notification
);
/* Remove the notify signal handler for the read state incase someone
* else added a reference to the notification which would then mess
* with our unread count accounting.
*/
g_signal_handlers_disconnect_by_func
(
notification
,
G_CALLBACK
(
purple_notification_manager_notify_cb
),
manager
);
/* If the notification is not read, we need to decrement the unread
* count.
*/
if
(
!
purple_notification_get_read
(
notification
))
{
purple_notification_manager_decrement_unread_count
(
manager
);
}
g_list_store_remove
(
manager
->
notifications
,
position
);
g_signal_emit
(
G_OBJECT
(
manager
),
signals
[
SIG_REMOVED
],
0
,
notification
);
g_object_unref
(
notification
);
}
}
/*
This function uses the following algorithm to optimally remove items from the
GListStore. See the psuedo code below for an easier to follow version.
A
A B C
B C
A A B C
B A C
B A A C
B C A
B C A A
set len = number_of_items
set pos = 0
set have_same = false
while pos < len
check item at pos
if same
if not have_same
reset count = 0
set start = pos
set have_same = TRUE
set count = count + 1
else
if have_same
remove count items from start
set pos = pos - count
set len = len - count
set have_same = FALSE
set pos = pos + 1
if have_same
remove count items from start
*/
void
purple_notification_manager_remove_with_account
(
PurpleNotificationManager
*
manager
,
PurpleAccount
*
account
)
{
guint
pos
=
0
,
len
=
0
;
guint
start
=
0
,
count
=
0
;
gboolean
have_same
=
FALSE
;
g_return_if_fail
(
PURPLE_IS_NOTIFICATION_MANAGER
(
manager
));
g_return_if_fail
(
PURPLE_IS_ACCOUNT
(
account
));
len
=
g_list_model_get_n_items
(
G_LIST_MODEL
(
manager
->
notifications
));
for
(
pos
=
0
;
pos
<
len
;
pos
++
)
{
PurpleAccount
*
account2
=
NULL
;
PurpleNotification
*
notification
=
NULL
;
notification
=
g_list_model_get_item
(
G_LIST_MODEL
(
manager
->
notifications
),
pos
);
account2
=
purple_notification_get_account
(
notification
);
if
(
account
==
account2
)
{
/* If this is the first item with the right account store its position. */
if
(
!
have_same
)
{
count
=
0
;
start
=
pos
;
have_same
=
TRUE
;
}
/* Increment the count of items starting at the start position. */
count
++
;
}
else
{
if
(
have_same
)
{
/* Remove the run of items from the list. */
g_list_store_splice
(
manager
->
notifications
,
start
,
count
,
NULL
,
0
);
/* Adjust pos and len for the items that we removed. */
pos
=
pos
-
count
;
len
=
len
-
count
;
have_same
=
FALSE
;
}
}
g_clear_object
(
&
notification
);
}
/* Clean up the last bit if the last item needs to be removed. */
if
(
have_same
)
{
g_list_store_splice
(
manager
->
notifications
,
start
,
count
,
NULL
,
0
);
}
}
guint
purple_notification_manager_get_unread_count
(
PurpleNotificationManager
*
manager
)
{
g_return_val_if_fail
(
PURPLE_IS_NOTIFICATION_MANAGER
(
manager
),
0
);
return
manager
->
unread_count
;
}
GListModel
*
purple_notification_manager_get_model
(
PurpleNotificationManager
*
manager
)
{
g_return_val_if_fail
(
PURPLE_IS_NOTIFICATION_MANAGER
(
manager
),
NULL
);
if
(
manager
->
notifications
==
NULL
)
{
return
NULL
;
}
return
G_LIST_MODEL
(
g_object_ref
(
manager
->
notifications
));
}