HaikuDepot: Restore logged in user across sessions.
* Store the username in the app settings. The password was already stored in the keyring. Restore the username upon next launch. * Display the logged in user in the main window. * Added "Log out" menu entry. * When the password could not be retrieved from the keyring (also because the user rejects the keyring dialog), unset the username. * Allow unsetting the username by passing an empty name.
This commit is contained in:
parent
3e3d0effdc
commit
8f03a0f9f2
|
@ -30,14 +30,19 @@
|
|||
static const char* kHaikuDepotKeyring = "HaikuDepot";
|
||||
|
||||
|
||||
// #pragma mark - PackageFilters
|
||||
|
||||
|
||||
PackageFilter::~PackageFilter()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ModelListener::~ModelListener()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - PackageFilters
|
||||
|
||||
|
||||
class AnyFilter : public PackageFilter {
|
||||
public:
|
||||
virtual bool AcceptsPackage(const PackageInfoRef& package) const
|
||||
|
@ -368,6 +373,13 @@ Model::~Model()
|
|||
}
|
||||
|
||||
|
||||
bool
|
||||
Model::AddListener(const ModelListenerRef& listener)
|
||||
{
|
||||
return fListeners.Add(listener);
|
||||
}
|
||||
|
||||
|
||||
PackageList
|
||||
Model::CreatePackageList() const
|
||||
{
|
||||
|
@ -661,14 +673,27 @@ Model::StopPopulatingAllPackages()
|
|||
|
||||
|
||||
void
|
||||
Model::SetUser(const BString& username)
|
||||
Model::SetUsername(BString username)
|
||||
{
|
||||
BPasswordKey key;
|
||||
BKeyStore keyStore;
|
||||
if (keyStore.GetKey(kHaikuDepotKeyring, B_KEY_TYPE_PASSWORD, username,
|
||||
key) == B_OK) {
|
||||
SetAuthorization(username, key.Password(), false);
|
||||
BString password;
|
||||
if (username.Length() > 0) {
|
||||
BPasswordKey key;
|
||||
BKeyStore keyStore;
|
||||
if (keyStore.GetKey(kHaikuDepotKeyring, B_KEY_TYPE_PASSWORD, username,
|
||||
key) == B_OK) {
|
||||
password = key.Password();
|
||||
} else {
|
||||
username = "";
|
||||
}
|
||||
}
|
||||
SetAuthorization(username, password, false);
|
||||
}
|
||||
|
||||
|
||||
const BString&
|
||||
Model::Username() const
|
||||
{
|
||||
return fWebAppInterface.Username();
|
||||
}
|
||||
|
||||
|
||||
|
@ -676,7 +701,7 @@ void
|
|||
Model::SetAuthorization(const BString& username, const BString& password,
|
||||
bool storePassword)
|
||||
{
|
||||
if (storePassword) {
|
||||
if (storePassword && username.Length() > 0 && password.Length() > 0) {
|
||||
BPasswordKey key(password, B_KEY_PURPOSE_WEB, username);
|
||||
BKeyStore keyStore;
|
||||
keyStore.AddKeyring(kHaikuDepotKeyring);
|
||||
|
@ -685,6 +710,8 @@ Model::SetAuthorization(const BString& username, const BString& password,
|
|||
|
||||
BAutolock locker(&fLock);
|
||||
fWebAppInterface.SetAuthorization(username, password);
|
||||
|
||||
_NotifyAuthorizationChanged();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1146,3 +1173,18 @@ Model::_HasNativeIcon(const BMessage& message) const
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark - listener notification methods
|
||||
|
||||
|
||||
void
|
||||
Model::_NotifyAuthorizationChanged()
|
||||
{
|
||||
for (int32 i = fListeners.CountItems() - 1; i >= 0; i--) {
|
||||
const ModelListenerRef& listener = fListeners.ItemAtFast(i);
|
||||
if (listener.Get() != NULL)
|
||||
listener->AuthorizationChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,17 @@ public:
|
|||
typedef BReference<PackageFilter> PackageFilterRef;
|
||||
|
||||
|
||||
class ModelListener : public BReferenceable {
|
||||
public:
|
||||
virtual ~ModelListener();
|
||||
|
||||
virtual void AuthorizationChanged() = 0;
|
||||
};
|
||||
|
||||
typedef BReference<ModelListener> ModelListenerRef;
|
||||
typedef List<ModelListenerRef, false> ModelListenerList;
|
||||
|
||||
|
||||
class Model {
|
||||
public:
|
||||
Model();
|
||||
|
@ -33,6 +44,8 @@ public:
|
|||
BLocker* Lock()
|
||||
{ return &fLock; }
|
||||
|
||||
bool AddListener(const ModelListenerRef& listener);
|
||||
|
||||
// !Returns new PackageInfoList from current parameters
|
||||
PackageList CreatePackageList() const;
|
||||
|
||||
|
@ -110,7 +123,8 @@ public:
|
|||
const BString& PreferredLanguage() const
|
||||
{ return fPreferredLanguage; }
|
||||
|
||||
void SetUser(const BString& username);
|
||||
void SetUsername(BString username);
|
||||
const BString& Username() const;
|
||||
void SetAuthorization(const BString& username,
|
||||
const BString& password,
|
||||
bool storePassword);
|
||||
|
@ -139,6 +153,8 @@ private:
|
|||
int32 scaledWidth,
|
||||
bool fromCacheOnly);
|
||||
|
||||
void _NotifyAuthorizationChanged();
|
||||
|
||||
private:
|
||||
BLocker fLock;
|
||||
|
||||
|
@ -182,6 +198,8 @@ private:
|
|||
BString fPreferredLanguage;
|
||||
|
||||
WebAppInterface fWebAppInterface;
|
||||
|
||||
ModelListenerList fListeners;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -28,6 +28,9 @@ public:
|
|||
|
||||
void SetAuthorization(const BString& username,
|
||||
const BString& password);
|
||||
const BString& Username() const
|
||||
{ return fUsername; }
|
||||
|
||||
void SetPreferredLanguage(const BString& language);
|
||||
void SetArchitecture(const BString& architecture);
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <MenuItem.h>
|
||||
#include <Messenger.h>
|
||||
#include <PopUpMenu.h>
|
||||
#include <StringView.h>
|
||||
#include <TextControl.h>
|
||||
|
||||
#include "Model.h"
|
||||
|
@ -37,16 +38,23 @@ add_categories_to_menu(const CategoryList& categories, BMenu* menu)
|
|||
}
|
||||
|
||||
|
||||
static void
|
||||
set_small_font(BView* view)
|
||||
{
|
||||
BFont font;
|
||||
view->GetFont(&font);
|
||||
font.SetSize(ceilf(font.Size() * 0.8));
|
||||
view->SetFont(&font);
|
||||
}
|
||||
|
||||
|
||||
static BCheckBox*
|
||||
create_check_box(const char* label, const char* name)
|
||||
{
|
||||
BMessage* message = new BMessage(MSG_FILTER_SELECTED);
|
||||
message->AddString("name", name);
|
||||
BCheckBox* checkBox = new BCheckBox(label, message);
|
||||
BFont font;
|
||||
checkBox->GetFont(&font);
|
||||
font.SetSize(ceilf(font.Size() * 0.75));
|
||||
checkBox->SetFont(&font);
|
||||
set_small_font(checkBox);
|
||||
return checkBox;
|
||||
}
|
||||
|
||||
|
@ -90,6 +98,11 @@ FilterView::FilterView()
|
|||
fSourceCodeCheckBox = create_check_box(
|
||||
B_TRANSLATE("Source code"), "source code");
|
||||
|
||||
// Logged in user label
|
||||
fUsername = new BStringView("logged in user", "");
|
||||
set_small_font(fUsername);
|
||||
fUsername->SetHighColor(80, 80, 80);
|
||||
|
||||
// Build layout
|
||||
BLayoutBuilder::Group<>(this)
|
||||
.AddGroup(B_HORIZONTAL)
|
||||
|
@ -107,6 +120,7 @@ FilterView::FilterView()
|
|||
.Add(fDevelopmentCheckBox)
|
||||
.Add(fSourceCodeCheckBox)
|
||||
.AddGlue(0.5f)
|
||||
.Add(fUsername)
|
||||
.End()
|
||||
|
||||
.SetInsets(B_USE_DEFAULT_SPACING)
|
||||
|
@ -200,3 +214,17 @@ FilterView::AdoptCheckmarks(const Model& model)
|
|||
fSourceCodeCheckBox->SetValue(model.ShowSourcePackages());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FilterView::SetUsername(const BString& username)
|
||||
{
|
||||
BString label;
|
||||
if (username.Length() == 0) {
|
||||
label = B_TRANSLATE("Not logged in");
|
||||
} else {
|
||||
label = B_TRANSLATE("Logged in as %User%");
|
||||
label.ReplaceAll("%User%", username);
|
||||
}
|
||||
fUsername->SetText(label);
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
class BCheckBox;
|
||||
class BMenuField;
|
||||
class BStringView;
|
||||
class BTextControl;
|
||||
class Model;
|
||||
|
||||
|
@ -30,8 +31,10 @@ public:
|
|||
virtual void AttachedToWindow();
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
|
||||
virtual void AdoptModel(const Model& model);
|
||||
virtual void AdoptCheckmarks(const Model& model);
|
||||
void AdoptModel(const Model& model);
|
||||
void AdoptCheckmarks(const Model& model);
|
||||
|
||||
void SetUsername(const BString& username);
|
||||
|
||||
private:
|
||||
BMenuField* fShowField;
|
||||
|
@ -42,6 +45,8 @@ private:
|
|||
BCheckBox* fInstalledCheckBox;
|
||||
BCheckBox* fDevelopmentCheckBox;
|
||||
BCheckBox* fSourceCodeCheckBox;
|
||||
|
||||
BStringView* fUsername;
|
||||
};
|
||||
|
||||
#endif // FILTER_VIEW_H
|
||||
|
|
|
@ -53,12 +53,14 @@
|
|||
|
||||
|
||||
enum {
|
||||
MSG_MODEL_WORKER_DONE = 'mmwd',
|
||||
MSG_REFRESH_DEPOTS = 'mrdp',
|
||||
MSG_LOG_IN = 'lgin',
|
||||
MSG_PACKAGE_STATE_CHANGED = 'mpsc',
|
||||
MSG_SHOW_SOURCE_PACKAGES = 'ssrc',
|
||||
MSG_SHOW_DEVELOP_PACKAGES = 'sdvl'
|
||||
MSG_MODEL_WORKER_DONE = 'mmwd',
|
||||
MSG_REFRESH_DEPOTS = 'mrdp',
|
||||
MSG_LOG_IN = 'lgin',
|
||||
MSG_LOG_OUT = 'lgot',
|
||||
MSG_AUTHORIZATION_CHANGED = 'athc',
|
||||
MSG_PACKAGE_STATE_CHANGED = 'mpsc',
|
||||
MSG_SHOW_SOURCE_PACKAGES = 'ssrc',
|
||||
MSG_SHOW_DEVELOP_PACKAGES = 'sdvl'
|
||||
};
|
||||
|
||||
|
||||
|
@ -83,11 +85,31 @@ struct RefreshWorkerParameters {
|
|||
};
|
||||
|
||||
|
||||
class MessageModelListener : public ModelListener {
|
||||
public:
|
||||
MessageModelListener(const BMessenger& messenger)
|
||||
:
|
||||
fMessenger(messenger)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void AuthorizationChanged()
|
||||
{
|
||||
if (fMessenger.IsValid())
|
||||
fMessenger.SendMessage(MSG_AUTHORIZATION_CHANGED);
|
||||
}
|
||||
|
||||
private:
|
||||
BMessenger fMessenger;
|
||||
};
|
||||
|
||||
|
||||
MainWindow::MainWindow(BRect frame, const BMessage& settings)
|
||||
:
|
||||
BWindow(frame, B_TRANSLATE_SYSTEM_NAME("HaikuDepot"),
|
||||
B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
|
||||
B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS),
|
||||
fModelListener(new MessageModelListener(BMessenger(this)), true),
|
||||
fTerminating(false),
|
||||
fModelWorker(B_BAD_THREAD_ID)
|
||||
{
|
||||
|
@ -117,6 +139,8 @@ MainWindow::MainWindow(BRect frame, const BMessage& settings)
|
|||
fSplitView->SetCollapsible(0, false);
|
||||
fSplitView->SetCollapsible(1, false);
|
||||
|
||||
fModel.AddListener(fModelListener);
|
||||
|
||||
// Restore settings
|
||||
BMessage columnSettings;
|
||||
if (settings.FindMessage("column settings", &columnSettings) == B_OK)
|
||||
|
@ -128,6 +152,13 @@ MainWindow::MainWindow(BRect frame, const BMessage& settings)
|
|||
if (settings.FindBool("show source packages", &showOption) == B_OK)
|
||||
fModel.SetShowSourcePackages(showOption);
|
||||
|
||||
BString username;
|
||||
if (settings.FindString("username", &username) == B_OK
|
||||
&& username.Length() > 0) {
|
||||
fModel.SetUsername(username);
|
||||
}
|
||||
|
||||
// start worker threads
|
||||
BPackageRoster().StartWatching(this,
|
||||
B_WATCH_PACKAGE_INSTALLATION_LOCATIONS);
|
||||
|
||||
|
@ -212,6 +243,14 @@ MainWindow::MessageReceived(BMessage* message)
|
|||
_OpenLoginWindow();
|
||||
break;
|
||||
|
||||
case MSG_LOG_OUT:
|
||||
fModel.SetUsername("");
|
||||
break;
|
||||
|
||||
case MSG_AUTHORIZATION_CHANGED:
|
||||
_UpdateAuthorization();
|
||||
break;
|
||||
|
||||
case MSG_SHOW_SOURCE_PACKAGES:
|
||||
{
|
||||
BAutolock locker(fModel.Lock());
|
||||
|
@ -358,6 +397,8 @@ MainWindow::StoreSettings(BMessage& settings) const
|
|||
|
||||
settings.AddBool("show develop packages", fModel.ShowDevelopPackages());
|
||||
settings.AddBool("show source packages", fModel.ShowSourcePackages());
|
||||
|
||||
settings.AddString("username", fModel.Username());
|
||||
}
|
||||
|
||||
|
||||
|
@ -401,8 +442,12 @@ MainWindow::_BuildMenu(BMenuBar* menuBar)
|
|||
BMenu* menu = new BMenu(B_TRANSLATE("Tools"));
|
||||
menu->AddItem(new BMenuItem(B_TRANSLATE("Refresh depots"),
|
||||
new BMessage(MSG_REFRESH_DEPOTS)));
|
||||
menu->AddItem(new BMenuItem(B_TRANSLATE("Log in"),
|
||||
menu->AddSeparatorItem();
|
||||
menu->AddItem(new BMenuItem(B_TRANSLATE("Log in" B_UTF8_ELLIPSIS),
|
||||
new BMessage(MSG_LOG_IN)));
|
||||
fLogOutItem = new BMenuItem(B_TRANSLATE("Log out"),
|
||||
new BMessage(MSG_LOG_OUT));
|
||||
menu->AddItem(fLogOutItem);
|
||||
menuBar->AddItem(menu);
|
||||
|
||||
// menu = new BMenu(B_TRANSLATE("Options"));
|
||||
|
@ -858,3 +903,11 @@ MainWindow::_OpenLoginWindow()
|
|||
window->Show();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
MainWindow::_UpdateAuthorization()
|
||||
{
|
||||
BString username(fModel.Username());
|
||||
fLogOutItem->SetEnabled(username.Length() > 0);
|
||||
fFilterView->SetUsername(username);
|
||||
}
|
||||
|
|
|
@ -72,16 +72,19 @@ private:
|
|||
const char* message);
|
||||
|
||||
void _OpenLoginWindow();
|
||||
void _UpdateAuthorization();
|
||||
|
||||
private:
|
||||
FilterView* fFilterView;
|
||||
PackageListView* fPackageListView;
|
||||
PackageInfoView* fPackageInfoView;
|
||||
BSplitView* fSplitView;
|
||||
BMenuItem* fLogOutItem;
|
||||
BMenuItem* fShowDevelopPackagesItem;
|
||||
BMenuItem* fShowSourcePackagesItem;
|
||||
|
||||
Model fModel;
|
||||
ModelListenerRef fModelListener;
|
||||
PackageList fVisiblePackages;
|
||||
|
||||
bool fTerminating;
|
||||
|
|
Loading…
Reference in New Issue