Replace emit with Q_EMIT
This commit is contained in:
@@ -65,7 +65,7 @@ void CddaDevice::Refresh() {
|
||||
void CddaDevice::SongsLoaded(const SongList &songs) {
|
||||
|
||||
model_->Reset();
|
||||
emit SongsDiscovered(songs);
|
||||
Q_EMIT SongsDiscovered(songs);
|
||||
song_count_ = songs.size();
|
||||
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ bool CddaLister::Init() {
|
||||
#endif
|
||||
if (!devices_list_.contains(device)) {
|
||||
devices_list_ << device;
|
||||
emit DeviceAdded(device);
|
||||
Q_EMIT DeviceAdded(device);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -143,7 +143,7 @@ void CddaSongLoader::LoadSongs() {
|
||||
song.set_track(track_number);
|
||||
songs << song;
|
||||
}
|
||||
emit SongsLoaded(songs);
|
||||
Q_EMIT SongsLoaded(songs);
|
||||
|
||||
|
||||
gst_tag_register_musicbrainz_tags();
|
||||
@@ -189,7 +189,7 @@ void CddaSongLoader::LoadSongs() {
|
||||
}
|
||||
gst_message_unref(msg_toc);
|
||||
}
|
||||
emit SongsDurationLoaded(songs);
|
||||
Q_EMIT SongsDurationLoaded(songs);
|
||||
|
||||
#ifdef HAVE_MUSICBRAINZ
|
||||
// Handle TAG message: generate MusicBrainz DiscId
|
||||
@@ -241,7 +241,7 @@ void CddaSongLoader::AudioCDTagsLoaded(const QString &artist, const QString &alb
|
||||
song.set_url(GetUrlFromTrack(track_number++));
|
||||
songs << song;
|
||||
}
|
||||
emit SongsMetadataLoaded(songs);
|
||||
Q_EMIT SongsMetadataLoaded(songs);
|
||||
|
||||
}
|
||||
#endif
|
||||
@@ -264,6 +264,6 @@ bool CddaSongLoader::HasChanged() {
|
||||
void CddaSongLoader::Error(const QString &error) {
|
||||
|
||||
qLog(Error) << error;
|
||||
emit SongsDurationLoaded(SongList(), error);
|
||||
Q_EMIT SongsDurationLoaded(SongList(), error);
|
||||
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ void ConnectedDevice::InitBackendDirectory(const QString &mount_point, const boo
|
||||
|
||||
}
|
||||
|
||||
void ConnectedDevice::ConnectAsync() { emit DeviceConnectFinished(unique_id_, true); }
|
||||
void ConnectedDevice::ConnectAsync() { Q_EMIT DeviceConnectFinished(unique_id_, true); }
|
||||
|
||||
void ConnectedDevice::Close() {
|
||||
|
||||
@@ -115,7 +115,7 @@ void ConnectedDevice::Close() {
|
||||
|
||||
void ConnectedDevice::BackendCloseFinished() {
|
||||
|
||||
emit DeviceCloseFinished(unique_id_);
|
||||
Q_EMIT DeviceCloseFinished(unique_id_);
|
||||
|
||||
}
|
||||
|
||||
@@ -167,5 +167,5 @@ Song::FileType ConnectedDevice::GetTranscodeFormat() const {
|
||||
|
||||
void ConnectedDevice::BackendTotalSongCountUpdated(int count) {
|
||||
song_count_ = count;
|
||||
emit SongCountUpdated(count);
|
||||
Q_EMIT SongCountUpdated(count);
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ void DeviceDatabaseBackend::Exit() {
|
||||
Q_ASSERT(QThread::currentThread() == thread());
|
||||
Close();
|
||||
moveToThread(original_thread_);
|
||||
emit ExitFinished();
|
||||
Q_EMIT ExitFinished();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ void DeviceLister::UnmountDeviceAsync(const QString &id) {
|
||||
}
|
||||
|
||||
void DeviceLister::MountDevice(const QString &id, const int request_id) {
|
||||
emit DeviceMounted(id, request_id, true);
|
||||
Q_EMIT DeviceMounted(id, request_id, true);
|
||||
}
|
||||
|
||||
void DeviceLister::ExitAsync() {
|
||||
@@ -96,7 +96,7 @@ void DeviceLister::Exit() {
|
||||
if (thread_) {
|
||||
moveToThread(original_thread_);
|
||||
}
|
||||
emit ExitFinished();
|
||||
Q_EMIT ExitFinished();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -202,7 +202,7 @@ void DeviceManager::BackendClosed() {
|
||||
QObject::disconnect(obj, nullptr, this, nullptr);
|
||||
qLog(Debug) << obj << "successfully closed.";
|
||||
wait_for_exit_.removeAll(obj);
|
||||
if (wait_for_exit_.isEmpty()) emit ExitFinished();
|
||||
if (wait_for_exit_.isEmpty()) Q_EMIT ExitFinished();
|
||||
|
||||
}
|
||||
|
||||
@@ -236,7 +236,7 @@ void DeviceManager::LoadAllDevices() {
|
||||
for (const DeviceDatabaseBackend::Device &device : devices) {
|
||||
DeviceInfo *info = new DeviceInfo(DeviceInfo::Type::Device, root_);
|
||||
info->InitFromDb(device);
|
||||
emit DeviceCreatedFromDB(info);
|
||||
Q_EMIT DeviceCreatedFromDB(info);
|
||||
}
|
||||
|
||||
// This is done in a concurrent thread so close the unique DB connection.
|
||||
@@ -260,7 +260,7 @@ void DeviceManager::AddDeviceFromDB(DeviceInfo *info) {
|
||||
existing->icon_name_ = info->icon_name_;
|
||||
existing->icon_ = info->icon_;
|
||||
QModelIndex idx = ItemToIndex(existing);
|
||||
if (idx.isValid()) emit dataChanged(idx, idx);
|
||||
if (idx.isValid()) Q_EMIT dataChanged(idx, idx);
|
||||
root_->Delete(info->row);
|
||||
}
|
||||
else {
|
||||
@@ -460,7 +460,7 @@ void DeviceManager::PhysicalDeviceAdded(const QString &id) {
|
||||
}
|
||||
}
|
||||
QModelIndex idx = ItemToIndex(info);
|
||||
if (idx.isValid()) emit dataChanged(idx, idx);
|
||||
if (idx.isValid()) Q_EMIT dataChanged(idx, idx);
|
||||
}
|
||||
else {
|
||||
// Check if we have another device with the same URL
|
||||
@@ -476,7 +476,7 @@ void DeviceManager::PhysicalDeviceAdded(const QString &id) {
|
||||
info->LoadIcon(lister->DeviceIcons(id), info->friendly_name_);
|
||||
}
|
||||
QModelIndex idx = ItemToIndex(info);
|
||||
if (idx.isValid()) emit dataChanged(idx, idx);
|
||||
if (idx.isValid()) Q_EMIT dataChanged(idx, idx);
|
||||
}
|
||||
else {
|
||||
// It's a completely new device
|
||||
@@ -518,9 +518,9 @@ void DeviceManager::PhysicalDeviceRemoved(const QString &id) {
|
||||
info->device_->Close();
|
||||
}
|
||||
|
||||
if (!info->device_) emit DeviceDisconnected(idx);
|
||||
if (!info->device_) Q_EMIT DeviceDisconnected(idx);
|
||||
|
||||
emit dataChanged(idx, idx);
|
||||
Q_EMIT dataChanged(idx, idx);
|
||||
}
|
||||
else {
|
||||
// If this was the last lister for the device then remove it from the model
|
||||
@@ -661,7 +661,7 @@ SharedPtr<ConnectedDevice> DeviceManager::Connect(DeviceInfo *info) {
|
||||
QModelIndex idx = ItemToIndex(info);
|
||||
if (!idx.isValid()) return ret;
|
||||
|
||||
emit dataChanged(idx, idx);
|
||||
Q_EMIT dataChanged(idx, idx);
|
||||
|
||||
QObject::connect(&*info->device_, &ConnectedDevice::TaskStarted, this, &DeviceManager::DeviceTaskStarted);
|
||||
QObject::connect(&*info->device_, &ConnectedDevice::SongCountUpdated, this, &DeviceManager::DeviceSongCountUpdated);
|
||||
@@ -681,7 +681,7 @@ void DeviceManager::DeviceConnectFinished(const QString &id, const bool success)
|
||||
if (!idx.isValid()) return;
|
||||
|
||||
if (success) {
|
||||
emit DeviceConnected(idx);
|
||||
Q_EMIT DeviceConnected(idx);
|
||||
}
|
||||
else {
|
||||
info->device_->Close();
|
||||
@@ -699,8 +699,8 @@ void DeviceManager::DeviceCloseFinished(const QString &id) {
|
||||
QModelIndex idx = ItemToIndex(info);
|
||||
if (!idx.isValid()) return;
|
||||
|
||||
emit DeviceDisconnected(idx);
|
||||
emit dataChanged(idx, idx);
|
||||
Q_EMIT DeviceDisconnected(idx);
|
||||
Q_EMIT dataChanged(idx, idx);
|
||||
|
||||
if (info->unmount_ && info->BestBackend() && info->BestBackend()->lister_) {
|
||||
info->BestBackend()->lister_->UnmountDeviceAsync(info->BestBackend()->unique_id_);
|
||||
@@ -799,7 +799,7 @@ void DeviceManager::RemoveFromDB(DeviceInfo *info, const QModelIndex &idx) {
|
||||
|
||||
info->friendly_name_ = info->BestBackend()->lister_->MakeFriendlyName(id);
|
||||
info->LoadIcon(info->BestBackend()->lister_->DeviceIcons(id), info->friendly_name_);
|
||||
emit dataChanged(idx, idx);
|
||||
Q_EMIT dataChanged(idx, idx);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -816,7 +816,7 @@ void DeviceManager::SetDeviceOptions(const QModelIndex &idx, const QString &frie
|
||||
info->transcode_mode_ = mode;
|
||||
info->transcode_format_ = format;
|
||||
|
||||
emit dataChanged(idx, idx);
|
||||
Q_EMIT dataChanged(idx, idx);
|
||||
|
||||
if (info->database_id_ != -1) {
|
||||
backend_->SetDeviceOptions(info->database_id_, friendly_name, icon_name, mode, format);
|
||||
@@ -836,7 +836,7 @@ void DeviceManager::DeviceTaskStarted(const int id) {
|
||||
if (!index.isValid()) continue;
|
||||
active_tasks_[id] = index;
|
||||
info->task_percentage_ = 0;
|
||||
emit dataChanged(index, index);
|
||||
Q_EMIT dataChanged(index, index);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -862,7 +862,7 @@ void DeviceManager::TasksChanged() {
|
||||
info->task_percentage_ = 0;
|
||||
}
|
||||
|
||||
emit dataChanged(idx, idx);
|
||||
Q_EMIT dataChanged(idx, idx);
|
||||
finished_tasks.removeAll(idx);
|
||||
|
||||
}
|
||||
@@ -875,7 +875,7 @@ void DeviceManager::TasksChanged() {
|
||||
if (!info) continue;
|
||||
|
||||
info->task_percentage_ = -1;
|
||||
emit dataChanged(idx, idx);
|
||||
Q_EMIT dataChanged(idx, idx);
|
||||
|
||||
active_tasks_.remove(active_tasks_.key(idx));
|
||||
}
|
||||
@@ -918,7 +918,7 @@ void DeviceManager::DeviceSongCountUpdated(const int count) {
|
||||
QModelIndex idx = ItemToIndex(info);
|
||||
if (!idx.isValid()) return;
|
||||
|
||||
emit dataChanged(idx, idx);
|
||||
Q_EMIT dataChanged(idx, idx);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -44,13 +44,13 @@ bool DeviceStateFilterModel::filterAcceptsRow(int row, const QModelIndex&) const
|
||||
|
||||
void DeviceStateFilterModel::ProxyRowCountChanged(const QModelIndex&, const int, const int) {
|
||||
|
||||
emit IsEmptyChanged(rowCount() == 0);
|
||||
Q_EMIT IsEmptyChanged(rowCount() == 0);
|
||||
|
||||
}
|
||||
|
||||
void DeviceStateFilterModel::ProxyReset() {
|
||||
|
||||
emit IsEmptyChanged(rowCount() == 0);
|
||||
Q_EMIT IsEmptyChanged(rowCount() == 0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -398,12 +398,12 @@ void DeviceView::Load() {
|
||||
if (MimeData *mimedata = qobject_cast<MimeData*>(q_mimedata)) {
|
||||
mimedata->clear_first_ = true;
|
||||
}
|
||||
emit AddToPlaylistSignal(q_mimedata);
|
||||
Q_EMIT AddToPlaylistSignal(q_mimedata);
|
||||
|
||||
}
|
||||
|
||||
void DeviceView::AddToPlaylist() {
|
||||
emit AddToPlaylistSignal(model()->mimeData(selectedIndexes()));
|
||||
Q_EMIT AddToPlaylistSignal(model()->mimeData(selectedIndexes()));
|
||||
}
|
||||
|
||||
void DeviceView::OpenInNewPlaylist() {
|
||||
@@ -412,7 +412,7 @@ void DeviceView::OpenInNewPlaylist() {
|
||||
if (MimeData *mimedata = qobject_cast<MimeData*>(q_mimedata)) {
|
||||
mimedata->open_in_new_playlist_ = true;
|
||||
}
|
||||
emit AddToPlaylistSignal(q_mimedata);
|
||||
Q_EMIT AddToPlaylistSignal(q_mimedata);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -113,7 +113,7 @@ void FilesystemDevice::ExitFinished() {
|
||||
qLog(Debug) << obj << "successfully exited.";
|
||||
wait_for_exit_.removeAll(obj);
|
||||
if (wait_for_exit_.isEmpty()) {
|
||||
emit DeviceCloseFinished(unique_id());
|
||||
Q_EMIT DeviceCloseFinished(unique_id());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -314,7 +314,7 @@ void GioLister::VolumeAdded(GVolume *volume) {
|
||||
devices_[info.unique_id()] = info;
|
||||
}
|
||||
|
||||
emit DeviceAdded(info.unique_id());
|
||||
Q_EMIT DeviceAdded(info.unique_id());
|
||||
|
||||
}
|
||||
|
||||
@@ -330,7 +330,7 @@ void GioLister::VolumeRemoved(GVolume *volume) {
|
||||
devices_.remove(id);
|
||||
}
|
||||
|
||||
emit DeviceRemoved(id);
|
||||
Q_EMIT DeviceRemoved(id);
|
||||
}
|
||||
|
||||
void GioLister::MountAdded(GMount *mount) {
|
||||
@@ -370,7 +370,7 @@ void GioLister::MountAdded(GMount *mount) {
|
||||
// If the ID has changed (for example, after it's been mounted), we need
|
||||
// to remove the old device.
|
||||
devices_.remove(old_id);
|
||||
emit DeviceRemoved(old_id);
|
||||
Q_EMIT DeviceRemoved(old_id);
|
||||
|
||||
old_id = QString();
|
||||
}
|
||||
@@ -378,10 +378,10 @@ void GioLister::MountAdded(GMount *mount) {
|
||||
}
|
||||
|
||||
if (old_id.isEmpty()) {
|
||||
emit DeviceAdded(info.unique_id());
|
||||
Q_EMIT DeviceAdded(info.unique_id());
|
||||
}
|
||||
else {
|
||||
emit DeviceChanged(old_id);
|
||||
Q_EMIT DeviceChanged(old_id);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -409,7 +409,7 @@ void GioLister::MountChanged(GMount *mount) {
|
||||
devices_[id] = new_info;
|
||||
}
|
||||
|
||||
emit DeviceChanged(id);
|
||||
Q_EMIT DeviceChanged(id);
|
||||
|
||||
}
|
||||
|
||||
@@ -424,7 +424,7 @@ void GioLister::MountRemoved(GMount *mount) {
|
||||
devices_.remove(id);
|
||||
}
|
||||
|
||||
emit DeviceRemoved(id);
|
||||
Q_EMIT DeviceRemoved(id);
|
||||
|
||||
}
|
||||
|
||||
@@ -598,7 +598,7 @@ void GioLister::UpdateDeviceFreeSpace(const QString &id) {
|
||||
g_object_unref(root);
|
||||
}
|
||||
|
||||
emit DeviceChanged(id);
|
||||
Q_EMIT DeviceChanged(id);
|
||||
|
||||
}
|
||||
|
||||
@@ -613,19 +613,19 @@ void GioLister::MountDevice(const QString &id, const int request_id) {
|
||||
|
||||
QMutexLocker l(&mutex_);
|
||||
if (!devices_.contains(id)) {
|
||||
emit DeviceMounted(id, request_id, false);
|
||||
Q_EMIT DeviceMounted(id, request_id, false);
|
||||
return;
|
||||
}
|
||||
|
||||
const DeviceInfo device_info = devices_.value(id);
|
||||
if (device_info.mount_ptr) {
|
||||
// Already mounted
|
||||
emit DeviceMounted(id, request_id, true);
|
||||
Q_EMIT DeviceMounted(id, request_id, true);
|
||||
return;
|
||||
}
|
||||
|
||||
g_volume_mount(device_info.volume_ptr, G_MOUNT_MOUNT_NONE, nullptr, nullptr, VolumeMountFinished, nullptr);
|
||||
emit DeviceMounted(id, request_id, true);
|
||||
Q_EMIT DeviceMounted(id, request_id, true);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -129,7 +129,7 @@ void GPodDevice::LoadFinished(Itdb_iTunesDB *db, const bool success) {
|
||||
ConnectedDevice::Close();
|
||||
}
|
||||
else {
|
||||
emit DeviceConnectFinished(unique_id_, success);
|
||||
Q_EMIT DeviceConnectFinished(unique_id_, success);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -52,14 +52,14 @@ GPodLoader::~GPodLoader() = default;
|
||||
void GPodLoader::LoadDatabase() {
|
||||
|
||||
int task_id = task_manager_->StartTask(tr("Loading iPod database"));
|
||||
emit TaskStarted(task_id);
|
||||
Q_EMIT TaskStarted(task_id);
|
||||
|
||||
Itdb_iTunesDB *db = TryLoad();
|
||||
|
||||
moveToThread(original_thread_);
|
||||
|
||||
task_manager_->SetTaskFinished(task_id);
|
||||
emit LoadFinished(db, !abort_);
|
||||
Q_EMIT LoadFinished(db, !abort_);
|
||||
|
||||
}
|
||||
|
||||
@@ -74,11 +74,11 @@ Itdb_iTunesDB *GPodLoader::TryLoad() {
|
||||
if (!db) {
|
||||
if (error) {
|
||||
qLog(Error) << "loading database failed:" << error->message;
|
||||
emit Error(QString::fromUtf8(error->message));
|
||||
Q_EMIT Error(QString::fromUtf8(error->message));
|
||||
g_error_free(error);
|
||||
}
|
||||
else {
|
||||
emit Error(tr("An error occurred loading the iTunes database"));
|
||||
Q_EMIT Error(tr("An error occurred loading the iTunes database"));
|
||||
}
|
||||
|
||||
return db;
|
||||
|
||||
@@ -124,7 +124,7 @@ void MtpDevice::LoadFinished(const bool success, MtpConnection *connection) {
|
||||
ConnectedDevice::Close();
|
||||
}
|
||||
else {
|
||||
emit DeviceConnectFinished(unique_id_, success);
|
||||
Q_EMIT DeviceConnectFinished(unique_id_, success);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -53,14 +53,14 @@ bool MtpLoader::Init() { return true; }
|
||||
void MtpLoader::LoadDatabase() {
|
||||
|
||||
int task_id = task_manager_->StartTask(tr("Loading MTP device"));
|
||||
emit TaskStarted(task_id);
|
||||
Q_EMIT TaskStarted(task_id);
|
||||
|
||||
bool success = TryLoad();
|
||||
|
||||
moveToThread(original_thread_);
|
||||
|
||||
task_manager_->SetTaskFinished(task_id);
|
||||
emit LoadFinished(success, connection_.release());
|
||||
Q_EMIT LoadFinished(success, connection_.release());
|
||||
|
||||
}
|
||||
|
||||
@@ -69,12 +69,12 @@ bool MtpLoader::TryLoad() {
|
||||
connection_ = make_unique<MtpConnection>(url_);
|
||||
|
||||
if (!connection_) {
|
||||
emit Error(tr("Error connecting MTP device %1").arg(url_.toString()));
|
||||
Q_EMIT Error(tr("Error connecting MTP device %1").arg(url_.toString()));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!connection_->is_valid()) {
|
||||
emit Error(tr("Error connecting MTP device %1: %2").arg(url_.toString(), connection_->error_text()));
|
||||
Q_EMIT Error(tr("Error connecting MTP device %1: %2").arg(url_.toString(), connection_->error_text()));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -176,7 +176,7 @@ void Udisks2Lister::UnmountDevice(const QString &id) {
|
||||
}
|
||||
|
||||
device_data_.remove(id);
|
||||
emit DeviceRemoved(id);
|
||||
Q_EMIT DeviceRemoved(id);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -184,7 +184,7 @@ void Udisks2Lister::UnmountDevice(const QString &id) {
|
||||
void Udisks2Lister::UpdateDeviceFreeSpace(const QString &id) {
|
||||
QWriteLocker locker(&device_data_lock_);
|
||||
device_data_[id].free_space = Utilities::FileSystemFreeSpace(device_data_.value(id).mount_paths.value(0));
|
||||
emit DeviceChanged(id);
|
||||
Q_EMIT DeviceChanged(id);
|
||||
}
|
||||
|
||||
bool Udisks2Lister::Init() {
|
||||
@@ -212,7 +212,7 @@ bool Udisks2Lister::Init() {
|
||||
|
||||
const QStringList ids = device_data_.keys();
|
||||
for (const QString &id : ids) {
|
||||
emit DeviceAdded(id);
|
||||
Q_EMIT DeviceAdded(id);
|
||||
}
|
||||
|
||||
QObject::connect(&*udisks2_interface_, &OrgFreedesktopDBusObjectManagerInterface::InterfacesAdded, this, &Udisks2Lister::DBusInterfaceAdded);
|
||||
@@ -293,7 +293,7 @@ void Udisks2Lister::RemoveDevice(const QDBusObjectPath &device_path) {
|
||||
qLog(Debug) << "UDisks2 device removed: " << device_path.path();
|
||||
device_data_.remove(id);
|
||||
|
||||
emit DeviceRemoved(id);
|
||||
Q_EMIT DeviceRemoved(id);
|
||||
|
||||
}
|
||||
|
||||
@@ -342,7 +342,7 @@ void Udisks2Lister::HandleFinishedMountJob(const PartitionData &partition_data)
|
||||
QWriteLocker locker(&device_data_lock_);
|
||||
device_data_[partition_data.unique_id()] = partition_data;
|
||||
|
||||
emit DeviceAdded(partition_data.unique_id());
|
||||
Q_EMIT DeviceAdded(partition_data.unique_id());
|
||||
|
||||
}
|
||||
|
||||
@@ -362,7 +362,7 @@ void Udisks2Lister::HandleFinishedUnmountJob(const PartitionData &partition_data
|
||||
if (!id.isEmpty()) {
|
||||
qLog(Debug) << "Partition " << partition_data.dbus_path << " has no more mount points, removing it from device list";
|
||||
device_data_.remove(id);
|
||||
emit DeviceRemoved(id);
|
||||
Q_EMIT DeviceRemoved(id);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user