Reimplemented how People works. The previously hard-coded attribute list
is now only a fallback attribute list which is install in case the Person MIME type has no attributes at all. Otherwise the GUI is completely driven by the current Person attributes, as configured (and sorted) by FileTypes. This has been on my mental TODO list since years. Finally one can add a "Cell phone" attribute in Filetypes and actually see and edit it in People. Or a birth day attribute. If I had read the previous code correctly, it was only due to a bug that People did not remove those any attributes on every launch. I've tested this quite a bit, but it wouldn't hurt to test it some more. The only "regression" I am aware of is that State and Zip code are not in one line anymore. Perhaps this feature could be reintroduced by looking at the display width and if two attributes are short, put them in one line... git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@40381 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
2099a79214
commit
bb5f99a5a6
57
src/apps/people/AttributeTextControl.cpp
Normal file
57
src/apps/people/AttributeTextControl.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2005-2010, Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Robert Polic
|
||||
*
|
||||
* Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||
* This file may be used under the terms of the Be Sample Code License.
|
||||
*/
|
||||
|
||||
|
||||
#include "AttributeTextControl.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include <Font.h>
|
||||
|
||||
|
||||
AttributeTextControl::AttributeTextControl(const char* label,
|
||||
const char* attribute)
|
||||
:
|
||||
BTextControl(NULL, "", NULL),
|
||||
fAttribute(attribute),
|
||||
fOriginalValue()
|
||||
{
|
||||
if (label != NULL && label[0] != 0)
|
||||
SetLabel(BString(label).Append(":"));
|
||||
SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT);
|
||||
}
|
||||
|
||||
|
||||
AttributeTextControl::~AttributeTextControl()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
AttributeTextControl::HasChanged()
|
||||
{
|
||||
return fOriginalValue != Text();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AttributeTextControl::Revert()
|
||||
{
|
||||
if (HasChanged())
|
||||
SetText(fOriginalValue);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AttributeTextControl::Update()
|
||||
{
|
||||
fOriginalValue = Text();
|
||||
}
|
36
src/apps/people/AttributeTextControl.h
Normal file
36
src/apps/people/AttributeTextControl.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2005-2010, Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Robert Polic
|
||||
*
|
||||
* Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||
* This file may be used under the terms of the Be Sample Code License.
|
||||
*/
|
||||
#ifndef TEXT_CONTROL_H
|
||||
#define TEXT_CONTROL_H
|
||||
|
||||
#include <String.h>
|
||||
#include <TextControl.h>
|
||||
|
||||
|
||||
class AttributeTextControl : public BTextControl {
|
||||
public:
|
||||
AttributeTextControl(const char* label,
|
||||
const char* attribute);
|
||||
virtual ~AttributeTextControl();
|
||||
|
||||
bool HasChanged();
|
||||
void Revert();
|
||||
void Update();
|
||||
|
||||
const BString& Attribute() const
|
||||
{ return fAttribute; }
|
||||
|
||||
private:
|
||||
BString fAttribute;
|
||||
BString fOriginalValue;
|
||||
};
|
||||
|
||||
#endif // TEXT_CONTROL_H
|
@ -1,10 +1,12 @@
|
||||
SubDir HAIKU_TOP src apps people ;
|
||||
|
||||
UsePrivateHeaders shared ;
|
||||
|
||||
Application People : main.cpp
|
||||
AttributeTextControl.cpp
|
||||
PeopleApp.cpp
|
||||
PeopleView.cpp
|
||||
PeopleWindow.cpp
|
||||
TTextControl.cpp
|
||||
: libbe.so libtracker.so $(TARGET_LIBSUPC++) $(HAIKU_LOCALE_LIBS)
|
||||
: People.rdef
|
||||
;
|
||||
|
@ -1,10 +1,11 @@
|
||||
/*
|
||||
* Copyright 2005-2009, Haiku, Inc. All rights reserved.
|
||||
* Copyright 2005-2010, Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Robert Polic
|
||||
* Axel Dörfler, axeld@pinc-software.de
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
*
|
||||
* Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||
* This file may be used under the terms of the Be Sample Code License.
|
||||
@ -12,6 +13,7 @@
|
||||
|
||||
|
||||
#include <Alert.h>
|
||||
#include <AutoDeleter.h>
|
||||
#include <Bitmap.h>
|
||||
#include <Catalog.h>
|
||||
#include <Directory.h>
|
||||
@ -34,8 +36,18 @@
|
||||
#define B_TRANSLATE_CONTEXT "People"
|
||||
|
||||
|
||||
struct people_field gFields[] = {
|
||||
{ "META:name", 120, B_TRANSLATE("Contact name") },
|
||||
struct DefaultAttribute {
|
||||
const char* attribute;
|
||||
int32 width;
|
||||
const char* name;
|
||||
};
|
||||
|
||||
// TODO: Add flags in attribute info message to find these.
|
||||
static const char* kNameAttribute = "META:name";
|
||||
static const char* kCategoryAttribute = "META:group";
|
||||
|
||||
struct DefaultAttribute sDefaultAttributes[] = {
|
||||
{ kNameAttribute, 120, B_TRANSLATE("Contact name") },
|
||||
{ "META:nickname", 120, B_TRANSLATE("Nickname") },
|
||||
{ "META:company", 120, B_TRANSLATE("Company") },
|
||||
{ "META:address", 120, B_TRANSLATE("Address") },
|
||||
@ -48,16 +60,19 @@ struct people_field gFields[] = {
|
||||
{ "META:fax", 90, B_TRANSLATE("Fax") },
|
||||
{ "META:email", 120, B_TRANSLATE("E-mail") },
|
||||
{ "META:url", 120, B_TRANSLATE("URL") },
|
||||
{ "META:group", 120, B_TRANSLATE("Group") },
|
||||
{ kCategoryAttribute, 120, B_TRANSLATE("Group") },
|
||||
{ NULL, 0, NULL }
|
||||
};
|
||||
|
||||
|
||||
TPeopleApp::TPeopleApp(void)
|
||||
: BApplication(APP_SIG),
|
||||
fWindowCount(0)
|
||||
TPeopleApp::TPeopleApp()
|
||||
:
|
||||
BApplication(APP_SIG),
|
||||
fWindowCount(0),
|
||||
fAttributes(20, true)
|
||||
{
|
||||
fPosition.Set(6, TITLE_BAR_HEIGHT, 6 + WIND_WIDTH, TITLE_BAR_HEIGHT + WIND_HEIGHT);
|
||||
fPosition.Set(6, TITLE_BAR_HEIGHT, 6 + WIND_WIDTH,
|
||||
TITLE_BAR_HEIGHT + WIND_HEIGHT);
|
||||
BPoint pos = fPosition.LeftTop();
|
||||
|
||||
BPath path;
|
||||
@ -65,7 +80,7 @@ TPeopleApp::TPeopleApp(void)
|
||||
|
||||
BDirectory dir(path.Path());
|
||||
BEntry entry;
|
||||
if (dir.FindEntry("People_data", &entry) == B_NO_ERROR) {
|
||||
if (dir.FindEntry("People_data", &entry) == B_OK) {
|
||||
fPrefs = new BFile(&entry, B_READ_WRITE);
|
||||
if (fPrefs->InitCheck() == B_NO_ERROR) {
|
||||
fPrefs->Read(&pos, sizeof(BPoint));
|
||||
@ -74,23 +89,15 @@ TPeopleApp::TPeopleApp(void)
|
||||
}
|
||||
} else {
|
||||
fPrefs = new BFile();
|
||||
if (dir.CreateFile("People_data", fPrefs) != B_NO_ERROR) {
|
||||
if (dir.CreateFile("People_data", fPrefs) != B_OK) {
|
||||
delete fPrefs;
|
||||
fPrefs = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// create indices on all volumes
|
||||
|
||||
BVolumeRoster volumeRoster;
|
||||
BVolume volume;
|
||||
while (volumeRoster.GetNextVolume(&volume) == B_OK) {
|
||||
for (int32 i = 0; gFields[i].attribute; i++) {
|
||||
fs_create_index(volume.Device(), gFields[i].attribute, B_STRING_TYPE, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// install person mime type
|
||||
// Read attributes from person mime type. If it does not exist,
|
||||
// or if it contains no attribute definitions, install a "clean"
|
||||
// person mime type from the hard-coded default attributes.
|
||||
|
||||
bool valid = false;
|
||||
BMimeType mime;
|
||||
@ -99,17 +106,42 @@ TPeopleApp::TPeopleApp(void)
|
||||
if (mime.IsInstalled()) {
|
||||
BMessage info;
|
||||
if (mime.GetAttrInfo(&info) == B_NO_ERROR) {
|
||||
const char *string;
|
||||
int32 index = 0;
|
||||
while (info.FindString("attr:name", index++, &string) == B_OK) {
|
||||
if (!strcmp(string, gFields[0].attribute)) {
|
||||
valid = true;
|
||||
while (true) {
|
||||
int32 type;
|
||||
if (info.FindInt32("attr:type", index, &type) != B_OK)
|
||||
break;
|
||||
bool editable;
|
||||
if (info.FindBool("attr:editable", index, &editable) != B_OK)
|
||||
break;
|
||||
|
||||
// TODO: Support other types besides string attributes.
|
||||
if (type != B_STRING_TYPE || !editable)
|
||||
break;
|
||||
|
||||
Attribute* attribute = new Attribute();
|
||||
ObjectDeleter<Attribute> deleter(attribute);
|
||||
if (info.FindString("attr:public_name", index,
|
||||
&attribute->name) != B_OK) {
|
||||
break;
|
||||
}
|
||||
if (info.FindString("attr:name", index,
|
||||
&attribute->attribute) != B_OK) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!fAttributes.AddItem(attribute))
|
||||
break;
|
||||
|
||||
deleter.Detach();
|
||||
index++;
|
||||
}
|
||||
if (!valid)
|
||||
mime.Delete();
|
||||
}
|
||||
if (fAttributes.CountItems() == 0) {
|
||||
valid = false;
|
||||
mime.Delete();
|
||||
} else
|
||||
valid = true;
|
||||
}
|
||||
if (!valid) {
|
||||
mime.Install();
|
||||
@ -121,154 +153,185 @@ TPeopleApp::TPeopleApp(void)
|
||||
mime.SetIcon(kPersonIcon, sizeof(kPersonIcon));
|
||||
mime.SetPreferredApp(APP_SIG);
|
||||
|
||||
// add relevant person fields to meta-mime type
|
||||
|
||||
// add default person fields to meta-mime type
|
||||
BMessage fields;
|
||||
for (int32 i = 0; gFields[i].attribute; i++) {
|
||||
fields.AddString("attr:public_name", gFields[i].name);
|
||||
fields.AddString("attr:name", gFields[i].attribute);
|
||||
for (int32 i = 0; sDefaultAttributes[i].attribute; i++) {
|
||||
fields.AddString("attr:public_name", sDefaultAttributes[i].name);
|
||||
fields.AddString("attr:name", sDefaultAttributes[i].attribute);
|
||||
fields.AddInt32("attr:type", B_STRING_TYPE);
|
||||
fields.AddBool("attr:viewable", true);
|
||||
fields.AddBool("attr:editable", true);
|
||||
fields.AddInt32("attr:width", gFields[i].width);
|
||||
fields.AddInt32("attr:width", sDefaultAttributes[i].width);
|
||||
fields.AddInt32("attr:alignment", B_ALIGN_LEFT);
|
||||
fields.AddBool("attr:extra", false);
|
||||
|
||||
// Add the default attribute to the attribute list, too.
|
||||
Attribute* attribute = new Attribute();
|
||||
attribute->name = sDefaultAttributes[i].name;
|
||||
attribute->attribute = sDefaultAttributes[i].attribute;
|
||||
if (!fAttributes.AddItem(attribute))
|
||||
delete attribute;
|
||||
}
|
||||
|
||||
mime.SetAttrInfo(&fields);
|
||||
}
|
||||
|
||||
// create indices on all volumes for the found attributes.
|
||||
|
||||
int32 count = fAttributes.CountItems();
|
||||
BVolumeRoster volumeRoster;
|
||||
BVolume volume;
|
||||
while (volumeRoster.GetNextVolume(&volume) == B_OK) {
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
Attribute* attribute = fAttributes.ItemAt(i);
|
||||
fs_create_index(volume.Device(), attribute->attribute,
|
||||
B_STRING_TYPE, 0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
TPeopleApp::~TPeopleApp(void)
|
||||
TPeopleApp::~TPeopleApp()
|
||||
{
|
||||
delete fPrefs;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TPeopleApp::AboutRequested(void)
|
||||
TPeopleApp::AboutRequested()
|
||||
{
|
||||
(new BAlert("", "...by Robert Polic", B_TRANSLATE("OK")))->Go();
|
||||
(new BAlert(B_TRANSLATE("About"), B_UTF8_ELLIPSIS "by Robert Polic",
|
||||
B_TRANSLATE("OK")))->Go();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TPeopleApp::ArgvReceived(int32 argc, char **argv)
|
||||
TPeopleApp::ArgvReceived(int32 argc, char** argv)
|
||||
{
|
||||
TPeopleWindow* window = NULL;
|
||||
BMessage message(B_REFS_RECEIVED);
|
||||
|
||||
for (int32 loop = 1; loop < argc; loop++) {
|
||||
char* arg = argv[loop];
|
||||
|
||||
int32 index;
|
||||
for (index = 0; gFields[index].attribute; index++) {
|
||||
if (!strncmp(gFields[index].attribute, arg, strlen(gFields[index].attribute)))
|
||||
break;
|
||||
}
|
||||
|
||||
if (gFields[index].attribute != NULL) {
|
||||
if (!window)
|
||||
window = NewWindow();
|
||||
|
||||
while (arg[0] && arg[0] != ' ' && arg[0] != '=')
|
||||
arg++;
|
||||
|
||||
if (arg[0]) {
|
||||
arg++;
|
||||
window->SetField(index, arg);
|
||||
}
|
||||
}
|
||||
for (int32 i = 1; i < argc; i++) {
|
||||
BEntry entry(argv[i]);
|
||||
entry_ref ref;
|
||||
if (entry.Exists() && entry.GetRef(&ref) == B_OK)
|
||||
message.AddRef("refs", &ref);
|
||||
}
|
||||
|
||||
RefsReceived(&message);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TPeopleApp::MessageReceived(BMessage *msg)
|
||||
TPeopleApp::MessageReceived(BMessage* message)
|
||||
{
|
||||
switch (msg->what) {
|
||||
switch (message->what) {
|
||||
case M_NEW:
|
||||
case B_SILENT_RELAUNCH:
|
||||
NewWindow();
|
||||
_NewWindow();
|
||||
break;
|
||||
|
||||
case M_WINDOW_QUITS:
|
||||
SavePreferences(msg);
|
||||
_SavePreferences(message);
|
||||
fWindowCount--;
|
||||
if (fWindowCount < 1)
|
||||
PostMessage(B_QUIT_REQUESTED);
|
||||
break;
|
||||
|
||||
default:
|
||||
BApplication::MessageReceived(msg);
|
||||
BApplication::MessageReceived(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TPeopleApp::RefsReceived(BMessage *message)
|
||||
TPeopleApp::RefsReceived(BMessage* message)
|
||||
{
|
||||
int32 index = 0;
|
||||
|
||||
while (message->HasRef("refs", index)) {
|
||||
entry_ref ref;
|
||||
message->FindRef("refs", index++, &ref);
|
||||
|
||||
TPeopleWindow* window = FindWindow(ref);
|
||||
TPeopleWindow* window = _FindWindow(ref);
|
||||
if (window != NULL)
|
||||
window->Activate(true);
|
||||
else {
|
||||
BFile file(&ref, B_READ_ONLY);
|
||||
if (file.InitCheck() == B_OK)
|
||||
NewWindow(&ref);
|
||||
_NewWindow(&ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TPeopleApp::ReadyToRun(void)
|
||||
TPeopleApp::ReadyToRun()
|
||||
{
|
||||
if (fWindowCount < 1)
|
||||
NewWindow();
|
||||
_NewWindow();
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
TPeopleWindow*
|
||||
TPeopleApp::NewWindow(entry_ref *ref)
|
||||
TPeopleApp::_NewWindow(entry_ref* ref)
|
||||
{
|
||||
TPeopleWindow *window;
|
||||
TPeopleWindow* window = new TPeopleWindow(fPosition,
|
||||
B_TRANSLATE("New person"), kNameAttribute,
|
||||
kCategoryAttribute, ref);
|
||||
|
||||
_AddAttributes(window);
|
||||
|
||||
window = new TPeopleWindow(fPosition, B_TRANSLATE("New person"), ref);
|
||||
window->Show();
|
||||
fWindowCount++;
|
||||
fPosition.OffsetBy(20, 20);
|
||||
|
||||
if (fPosition.bottom > BScreen(B_MAIN_SCREEN_ID).Frame().bottom)
|
||||
fWindowCount++;
|
||||
|
||||
// Offset the position for the next window which will be opened and
|
||||
// reset it if it would open outside the screen bounds.
|
||||
fPosition.OffsetBy(20, 20);
|
||||
BScreen screen(window);
|
||||
if (fPosition.bottom > screen.Frame().bottom)
|
||||
fPosition.OffsetTo(fPosition.left, TITLE_BAR_HEIGHT);
|
||||
if (fPosition.right > BScreen(B_MAIN_SCREEN_ID).Frame().right)
|
||||
if (fPosition.right > screen.Frame().right)
|
||||
fPosition.OffsetTo(6, fPosition.top);
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
|
||||
TPeopleWindow*
|
||||
TPeopleApp::FindWindow(entry_ref ref)
|
||||
void
|
||||
TPeopleApp::_AddAttributes(TPeopleWindow* window) const
|
||||
{
|
||||
TPeopleWindow* window;
|
||||
int32 index = 0;
|
||||
int32 count = fAttributes.CountItems();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
Attribute* attribute = fAttributes.ItemAt(i);
|
||||
const char* label = attribute->name;
|
||||
if (attribute->attribute == kNameAttribute)
|
||||
label = B_TRANSLATE("Name");
|
||||
|
||||
while ((window = (TPeopleWindow *)WindowAt(index++))) {
|
||||
if (window->FindView("PeopleView") != NULL && window->fRef && *window->fRef == ref)
|
||||
return window;
|
||||
window->AddAttribute(label, attribute->attribute);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TPeopleWindow*
|
||||
TPeopleApp::_FindWindow(const entry_ref& ref) const
|
||||
{
|
||||
for (int32 i = 0; BWindow* window = WindowAt(i); i++) {
|
||||
TPeopleWindow* personWindow = dynamic_cast<TPeopleWindow*>(window);
|
||||
if (personWindow == NULL)
|
||||
continue;
|
||||
if (personWindow->RefersPersonFile(ref))
|
||||
return personWindow;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TPeopleApp::SavePreferences(BMessage* message)
|
||||
TPeopleApp::_SavePreferences(BMessage* message) const
|
||||
{
|
||||
BRect frame;
|
||||
if (message->FindRect("frame", &frame) != B_OK)
|
||||
@ -276,7 +339,7 @@ TPeopleApp::SavePreferences(BMessage* message)
|
||||
|
||||
BPoint leftTop = frame.LeftTop();
|
||||
|
||||
if (fPrefs) {
|
||||
if (fPrefs != NULL) {
|
||||
fPrefs->Seek(0, 0);
|
||||
fPrefs->Write(&leftTop, sizeof(BPoint));
|
||||
}
|
||||
|
@ -1,51 +1,39 @@
|
||||
//--------------------------------------------------------------------
|
||||
//
|
||||
// PeopleApp.h
|
||||
//
|
||||
// Written by: Robert Polic
|
||||
//
|
||||
//--------------------------------------------------------------------
|
||||
/*
|
||||
Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||
This file may be used under the terms of the Be Sample Code License.
|
||||
*/
|
||||
|
||||
#ifndef PEOPLEAPP_H
|
||||
#define PEOPLEAPP_H
|
||||
* Copyright 2005-2010, Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Robert Polic
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
*
|
||||
* Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||
* This file may be used under the terms of the Be Sample Code License.
|
||||
*/
|
||||
#ifndef PEOPLE_APP_H
|
||||
#define PEOPLE_APP_H
|
||||
|
||||
|
||||
#include <Application.h>
|
||||
|
||||
class BFile;
|
||||
#include <ObjectList.h>
|
||||
#include <String.h>
|
||||
|
||||
|
||||
#define B_PERSON_MIMETYPE "application/x-person"
|
||||
#define APP_SIG "application/x-vnd.Be-PEPL"
|
||||
|
||||
struct people_field {
|
||||
const char* attribute;
|
||||
int32 width;
|
||||
const char* name;
|
||||
};
|
||||
extern people_field gFields[];
|
||||
|
||||
enum messages{
|
||||
M_NEW = 128, M_SAVE, M_SAVE_AS, M_REVERT,
|
||||
M_UNDO, M_SELECT, M_GROUP_MENU, M_WINDOW_QUITS
|
||||
};
|
||||
class BFile;
|
||||
|
||||
enum fields {
|
||||
F_NAME = 0, F_NICKNAME, F_COMPANY, F_ADDRESS,
|
||||
F_CITY, F_STATE, F_ZIP, F_COUNTRY, F_HPHONE,
|
||||
F_WPHONE, F_FAX, F_EMAIL, F_URL, F_GROUP, F_END
|
||||
enum {
|
||||
M_NEW = 'newp',
|
||||
M_SAVE_AS = 'svas',
|
||||
M_WINDOW_QUITS = 'wndq'
|
||||
};
|
||||
|
||||
class TPeopleWindow;
|
||||
|
||||
//====================================================================
|
||||
|
||||
class TPeopleApp : public BApplication {
|
||||
public:
|
||||
public:
|
||||
TPeopleApp();
|
||||
virtual ~TPeopleApp();
|
||||
|
||||
@ -54,17 +42,26 @@ class TPeopleApp : public BApplication {
|
||||
virtual void MessageReceived(BMessage*);
|
||||
virtual void RefsReceived(BMessage*);
|
||||
virtual void ReadyToRun();
|
||||
TPeopleWindow* FindWindow(entry_ref);
|
||||
TPeopleWindow* NewWindow(entry_ref* = NULL);
|
||||
|
||||
private:
|
||||
TPeopleWindow* _FindWindow(const entry_ref&) const;
|
||||
TPeopleWindow* _NewWindow(entry_ref* = NULL);
|
||||
void _AddAttributes(TPeopleWindow* window) const;
|
||||
void _SavePreferences(BMessage* message) const;
|
||||
|
||||
private:
|
||||
BFile* fPrefs;
|
||||
|
||||
private:
|
||||
void SavePreferences(BMessage* message);
|
||||
|
||||
uint32 fWindowCount;
|
||||
BRect fPosition;
|
||||
|
||||
struct Attribute {
|
||||
BString attribute;
|
||||
int32 width;
|
||||
BString name;
|
||||
};
|
||||
|
||||
BObjectList<Attribute> fAttributes;
|
||||
};
|
||||
|
||||
#endif /* PEOPLEAPP_H */
|
||||
#endif // PEOPLE_APP_H
|
||||
|
||||
|
@ -1,14 +1,15 @@
|
||||
//--------------------------------------------------------------------
|
||||
//
|
||||
// PeopleView.cpp
|
||||
//
|
||||
// Written by: Robert Polic
|
||||
//
|
||||
//--------------------------------------------------------------------
|
||||
/*
|
||||
Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||
This file may be used under the terms of the Be Sample Code License.
|
||||
*/
|
||||
* Copyright 2010, Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Robert Polic
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
*
|
||||
* Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||
* This file may be used under the terms of the Be Sample Code License.
|
||||
*/
|
||||
|
||||
|
||||
#include "PeopleView.h"
|
||||
|
||||
@ -29,88 +30,77 @@
|
||||
#include <VolumeRoster.h>
|
||||
#include <Window.h>
|
||||
|
||||
#include "TTextControl.h"
|
||||
#include "AttributeTextControl.h"
|
||||
|
||||
|
||||
#undef B_TRANSLATE_CONTEXT
|
||||
#define B_TRANSLATE_CONTEXT "People"
|
||||
|
||||
|
||||
TPeopleView::TPeopleView(const char* name, entry_ref *ref)
|
||||
TPeopleView::TPeopleView(const char* name, const char* categoryAttribute,
|
||||
const entry_ref *ref)
|
||||
:
|
||||
BGridView()
|
||||
BGridView(),
|
||||
fControls(20, false),
|
||||
fCategoryAttribute(categoryAttribute)
|
||||
{
|
||||
SetName(name);
|
||||
if (ref)
|
||||
fFile = new BFile(ref, O_RDWR);
|
||||
else
|
||||
fFile = NULL;
|
||||
|
||||
float spacing = be_control_look->DefaultItemSpacing();
|
||||
GridLayout()->SetInsets(spacing, spacing, spacing, spacing);
|
||||
}
|
||||
|
||||
|
||||
TPeopleView::~TPeopleView(void)
|
||||
TPeopleView::~TPeopleView()
|
||||
{
|
||||
delete fFile;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TPeopleView::AttachedToWindow(void)
|
||||
TPeopleView::AddAttribute(const char* label, const char* attribute)
|
||||
{
|
||||
// TODO: We could check if this attribute has already been added.
|
||||
|
||||
AttributeTextControl* control = new AttributeTextControl(label, attribute);
|
||||
fControls.AddItem(control);
|
||||
|
||||
BGridLayout* layout = GridLayout();
|
||||
int32 row = layout->CountRows();
|
||||
|
||||
int32 row = 0;
|
||||
for (int32 i = 0; gFields[i].attribute; i++, row++) {
|
||||
const char *name = gFields[i].name;
|
||||
if (fCategoryAttribute == attribute) {
|
||||
// Special case the category attribute. The Group popup field will
|
||||
// be added as the label instead.
|
||||
fGroups = new BPopUpMenu(label);
|
||||
fGroups->SetRadioMode(false);
|
||||
BuildGroupMenu();
|
||||
|
||||
if (i == F_NAME)
|
||||
name = B_TRANSLATE("Name");
|
||||
BMenuField* field = new BMenuField("", "", fGroups);
|
||||
field->SetEnabled(true);
|
||||
layout->AddView(field, 0, row);
|
||||
|
||||
char *text = NULL;
|
||||
attr_info info;
|
||||
if (fFile && fFile->GetAttrInfo(gFields[i].attribute, &info) == B_OK) {
|
||||
text = (char *)calloc(info.size, 1);
|
||||
fFile->ReadAttr(gFields[i].attribute, B_STRING_TYPE,
|
||||
0, text, info.size);
|
||||
}
|
||||
|
||||
fField[i] = new TTextControl(name, text);
|
||||
free(text);
|
||||
|
||||
int32 labelColumn = 0;
|
||||
int32 textViewColumn = 1;
|
||||
int32 textViewWidth = 3;
|
||||
if (i == F_STATE)
|
||||
textViewWidth = 1;
|
||||
else if (i == F_ZIP) {
|
||||
row--;
|
||||
labelColumn = 2;
|
||||
textViewColumn = 3;
|
||||
textViewWidth = 1;
|
||||
}
|
||||
|
||||
if (i != F_GROUP) {
|
||||
layout->AddItem(fField[i]->CreateLabelLayoutItem(),
|
||||
labelColumn, row, 1, 1);
|
||||
layout->AddItem(fField[i]->CreateTextViewLayoutItem(),
|
||||
textViewColumn, row, textViewWidth, 1);
|
||||
} else {
|
||||
fField[i]->SetLabel("");
|
||||
layout->AddView(fField[i], textViewColumn, row, textViewWidth, 1);
|
||||
}
|
||||
control->SetLabel("");
|
||||
layout->AddView(control, 1, row);
|
||||
} else {
|
||||
layout->AddItem(control->CreateLabelLayoutItem(), 0, row);
|
||||
layout->AddItem(control->CreateTextViewLayoutItem(), 1, row);
|
||||
}
|
||||
|
||||
fGroups = new BPopUpMenu(gFields[F_GROUP].name);
|
||||
fGroups->SetRadioMode(false);
|
||||
BMenuField *field = new BMenuField("", "", fGroups);
|
||||
field->SetEnabled(true);
|
||||
layout->AddView(field, 0, --row);
|
||||
SetAttribute(attribute, true);
|
||||
}
|
||||
|
||||
float spacing = be_control_look->DefaultItemSpacing();
|
||||
layout->SetSpacing(spacing, spacing);
|
||||
// TODO: remove this after #5614 is fixed
|
||||
layout->SetInsets(spacing, spacing, spacing, spacing);
|
||||
fField[F_NAME]->MakeFocus();
|
||||
|
||||
void
|
||||
TPeopleView::MakeFocus(bool focus)
|
||||
{
|
||||
if (focus && fControls.CountItems() > 0)
|
||||
fControls.ItemAt(0)->MakeFocus();
|
||||
else
|
||||
BView::MakeFocus(focus);
|
||||
}
|
||||
|
||||
|
||||
@ -123,25 +113,34 @@ TPeopleView::MessageReceived(BMessage* msg)
|
||||
break;
|
||||
|
||||
case M_REVERT:
|
||||
for (int32 loop = 0; loop < F_END; loop++)
|
||||
fField[loop]->Revert();
|
||||
for (int32 i = fControls.CountItems() - 1; i >= 0; i--)
|
||||
fControls.ItemAt(i)->Revert();
|
||||
break;
|
||||
|
||||
case M_SELECT:
|
||||
for (int32 loop = 0; loop < F_END; loop++) {
|
||||
BTextView* text = fField[loop]->TextView();
|
||||
for (int32 i = fControls.CountItems() - 1; i >= 0; i--) {
|
||||
BTextView* text = fControls.ItemAt(i)->TextView();
|
||||
if (text->IsFocus()) {
|
||||
text->Select(0, text->TextLength());
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
break;
|
||||
|
||||
case M_GROUP_MENU:
|
||||
{
|
||||
const char* name = NULL;
|
||||
if (msg->FindString("group", &name) == B_OK)
|
||||
SetAttribute(fCategoryAttribute, name, false);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TPeopleView::BuildGroupMenu(void)
|
||||
TPeopleView::BuildGroupMenu()
|
||||
{
|
||||
BMenuItem* item;
|
||||
while ((item = fGroups->ItemAt(0)) != NULL) {
|
||||
@ -149,7 +148,6 @@ TPeopleView::BuildGroupMenu(void)
|
||||
delete item;
|
||||
}
|
||||
|
||||
const char *groupAttribute = gFields[F_GROUP].attribute;
|
||||
int32 count = 0;
|
||||
|
||||
BVolumeRoster volumeRoster;
|
||||
@ -159,7 +157,7 @@ TPeopleView::BuildGroupMenu(void)
|
||||
query.SetVolume(&volume);
|
||||
|
||||
char buffer[256];
|
||||
sprintf(buffer, "%s=*", groupAttribute);
|
||||
snprintf(buffer, sizeof(buffer), "%s=*", fCategoryAttribute.String());
|
||||
query.SetPredicate(buffer);
|
||||
query.Fetch();
|
||||
|
||||
@ -169,13 +167,15 @@ TPeopleView::BuildGroupMenu(void)
|
||||
attr_info info;
|
||||
|
||||
if (file.InitCheck() == B_OK
|
||||
&& file.GetAttrInfo(groupAttribute, &info) == B_OK
|
||||
&& file.GetAttrInfo(fCategoryAttribute, &info) == B_OK
|
||||
&& info.size > 1) {
|
||||
if (info.size > sizeof(buffer))
|
||||
info.size = sizeof(buffer);
|
||||
|
||||
if (file.ReadAttr(groupAttribute, B_STRING_TYPE, 0, buffer, info.size) < B_OK)
|
||||
if (file.ReadAttr(fCategoryAttribute.String(), B_STRING_TYPE,
|
||||
0, buffer, info.size) < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const char *text = buffer;
|
||||
while (true) {
|
||||
@ -207,39 +207,19 @@ TPeopleView::BuildGroupMenu(void)
|
||||
}
|
||||
}
|
||||
|
||||
if (!count) {
|
||||
if (count == 0) {
|
||||
fGroups->AddItem(item = new BMenuItem(
|
||||
B_TRANSLATE_WITH_CONTEXT("none", "Groups list"),
|
||||
new BMessage(M_GROUP_MENU)));
|
||||
item->SetEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
TPeopleView::CheckSave(void)
|
||||
{
|
||||
for (int32 loop = 0; loop < F_END; loop++) {
|
||||
if (fField[loop]->Changed())
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
const char*
|
||||
TPeopleView::GetField(int32 index)
|
||||
{
|
||||
if (index < F_END)
|
||||
return fField[index]->Text();
|
||||
|
||||
return NULL;
|
||||
fGroups->SetTargetForItems(this);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TPeopleView::NewFile(entry_ref *ref)
|
||||
TPeopleView::CreateFile(const entry_ref* ref)
|
||||
{
|
||||
delete fFile;
|
||||
fFile = new BFile(ref, B_READ_WRITE);
|
||||
@ -247,68 +227,107 @@ TPeopleView::NewFile(entry_ref *ref)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TPeopleView::Save(void)
|
||||
bool
|
||||
TPeopleView::IsSaved() const
|
||||
{
|
||||
for (int32 i = 0; gFields[i].attribute; i++) {
|
||||
const char *text = fField[i]->Text();
|
||||
fFile->WriteAttr(gFields[i].attribute, B_STRING_TYPE, 0, text, strlen(text) + 1);
|
||||
fField[i]->Update();
|
||||
for (int32 i = fControls.CountItems() - 1; i >= 0; i--) {
|
||||
if (fControls.ItemAt(i)->HasChanged())
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TPeopleView::SetField(int32 index, bool update)
|
||||
TPeopleView::Save()
|
||||
{
|
||||
char *text = NULL;
|
||||
attr_info info;
|
||||
if (fFile && fFile->GetAttrInfo(gFields[index].attribute, &info) == B_OK) {
|
||||
text = (char *)calloc(info.size, 1);
|
||||
fFile->ReadAttr(gFields[index].attribute, B_STRING_TYPE, 0, text,
|
||||
info.size);
|
||||
int32 count = fControls.CountItems();
|
||||
for (int32 i = 0; i < count; i++) {
|
||||
AttributeTextControl* control = fControls.ItemAt(i);
|
||||
const char* value = control->Text();
|
||||
fFile->WriteAttr(control->Attribute().String(), B_STRING_TYPE, 0,
|
||||
value, strlen(value) + 1);
|
||||
control->Update();
|
||||
}
|
||||
}
|
||||
|
||||
SetField(index, text, update);
|
||||
|
||||
const char*
|
||||
TPeopleView::AttributeValue(const char* attribute) const
|
||||
{
|
||||
for (int32 i = fControls.CountItems() - 1; i >= 0; i--) {
|
||||
if (fControls.ItemAt(i)->Attribute() == attribute)
|
||||
return fControls.ItemAt(i)->Text();
|
||||
}
|
||||
|
||||
free(text);
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TPeopleView::SetField(int32 index, char *data, bool update)
|
||||
TPeopleView::SetAttribute(const char* attribute, bool update)
|
||||
{
|
||||
Window()->Lock();
|
||||
char* value = NULL;
|
||||
attr_info info;
|
||||
if (fFile != NULL && fFile->GetAttrInfo(attribute, &info) == B_OK) {
|
||||
value = (char*)calloc(info.size, 1);
|
||||
fFile->ReadAttr(attribute, B_STRING_TYPE, 0, value, info.size);
|
||||
}
|
||||
|
||||
SetAttribute(attribute, value, update);
|
||||
|
||||
free(value);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TPeopleView::SetAttribute(const char* attribute, const char* value,
|
||||
bool update)
|
||||
{
|
||||
if (!LockLooper())
|
||||
return;
|
||||
|
||||
AttributeTextControl* control = NULL;
|
||||
for (int32 i = fControls.CountItems() - 1; i >= 0; i--) {
|
||||
if (fControls.ItemAt(i)->Attribute() == attribute) {
|
||||
control = fControls.ItemAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (control == NULL)
|
||||
return;
|
||||
|
||||
if (update) {
|
||||
fField[index]->SetText(data);
|
||||
fField[index]->Update();
|
||||
control->SetText(value);
|
||||
control->Update();
|
||||
} else {
|
||||
BTextView* text = fField[index]->TextView();
|
||||
BTextView* text = control->TextView();
|
||||
|
||||
int32 start, end;
|
||||
text->GetSelection(&start, &end);
|
||||
if (start != end) {
|
||||
text->Delete();
|
||||
text->Insert(data);
|
||||
text->Insert(value);
|
||||
} else if ((end = text->TextLength())) {
|
||||
text->Select(end, end);
|
||||
text->Insert(",");
|
||||
text->Insert(data);
|
||||
text->Insert(value);
|
||||
text->Select(text->TextLength(), text->TextLength());
|
||||
} else
|
||||
fField[index]->SetText(data);
|
||||
control->SetText(value);
|
||||
}
|
||||
|
||||
Window()->Unlock();
|
||||
UnlockLooper();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
TPeopleView::TextSelected(void)
|
||||
TPeopleView::IsTextSelected() const
|
||||
{
|
||||
for (int32 loop = 0; loop < F_END; loop++) {
|
||||
BTextView* text = fField[loop]->TextView();
|
||||
for (int32 i = fControls.CountItems() - 1; i >= 0; i--) {
|
||||
BTextView* text = fControls.ItemAt(i)->TextView();
|
||||
|
||||
int32 start, end;
|
||||
text->GetSelection(&start, &end);
|
||||
|
@ -1,48 +1,69 @@
|
||||
//--------------------------------------------------------------------
|
||||
//
|
||||
// PeopleView.h
|
||||
//
|
||||
// Written by: Robert Polic
|
||||
//
|
||||
//--------------------------------------------------------------------
|
||||
/*
|
||||
Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||
This file may be used under the terms of the Be Sample Code License.
|
||||
*/
|
||||
* Copyright 2010, Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Robert Polic
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
*
|
||||
* Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||
* This file may be used under the terms of the Be Sample Code License.
|
||||
*/
|
||||
#ifndef PEOPLE_VIEW_H
|
||||
#define PEOPLE_VIEW_H
|
||||
|
||||
#ifndef PEOPLEVIEW_H
|
||||
#define PEOPLEVIEW_H
|
||||
|
||||
#include "PeopleApp.h"
|
||||
|
||||
#include <GridView.h>
|
||||
#include <ObjectList.h>
|
||||
#include <String.h>
|
||||
|
||||
|
||||
class AttributeTextControl;
|
||||
class BFile;
|
||||
class BPopUpMenu;
|
||||
class TTextControl;
|
||||
|
||||
enum {
|
||||
M_SAVE = 'save',
|
||||
M_REVERT = 'rvrt',
|
||||
M_SELECT = 'slct',
|
||||
M_GROUP_MENU = 'grmn',
|
||||
};
|
||||
|
||||
|
||||
class TPeopleView : public BGridView {
|
||||
public:
|
||||
TPeopleView(const char* name, entry_ref* ref);
|
||||
~TPeopleView(void);
|
||||
public:
|
||||
TPeopleView(const char* name,
|
||||
const char* categoryAttribute,
|
||||
const entry_ref* ref);
|
||||
virtual ~TPeopleView();
|
||||
|
||||
virtual void AttachedToWindow(void);
|
||||
virtual void MessageReceived(BMessage*);
|
||||
void BuildGroupMenu(void);
|
||||
bool CheckSave(void);
|
||||
const char* GetField(int32);
|
||||
void NewFile(entry_ref*);
|
||||
void Save(void);
|
||||
void SetField(int32, bool);
|
||||
void SetField(int32, char*, bool);
|
||||
bool TextSelected(void);
|
||||
virtual void MakeFocus(bool focus = true);
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
|
||||
private:
|
||||
BFile *fFile;
|
||||
BPopUpMenu *fGroups;
|
||||
TTextControl *fField[F_END];
|
||||
void AddAttribute(const char* label,
|
||||
const char* attribute);
|
||||
|
||||
void BuildGroupMenu();
|
||||
|
||||
void CreateFile(const entry_ref* ref);
|
||||
|
||||
bool IsSaved() const;
|
||||
void Save();
|
||||
|
||||
const char* AttributeValue(const char* attribute) const;
|
||||
void SetAttribute(const char* attribute, bool update);
|
||||
void SetAttribute(const char* attribute,
|
||||
const char* value, bool update);
|
||||
|
||||
bool IsTextSelected() const;
|
||||
|
||||
private:
|
||||
BFile* fFile;
|
||||
BPopUpMenu* fGroups;
|
||||
typedef BObjectList<AttributeTextControl> AttributeList;
|
||||
AttributeList fControls;
|
||||
|
||||
BString fCategoryAttribute;
|
||||
};
|
||||
|
||||
#endif /* PEOPLEVIEW_H */
|
||||
#endif // PEOPLE_VIEW_H
|
||||
|
@ -1,14 +1,14 @@
|
||||
//--------------------------------------------------------------------
|
||||
//
|
||||
// PeopleWindow.cpp
|
||||
//
|
||||
// Written by: Robert Polic
|
||||
//
|
||||
//--------------------------------------------------------------------
|
||||
/*
|
||||
Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||
This file may be used under the terms of the Be Sample Code License.
|
||||
*/
|
||||
* Copyright 2005-2010, Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Robert Polic
|
||||
* Stephan Aßmus <superstippi@gmx.de>
|
||||
*
|
||||
* Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||
* This file may be used under the terms of the Be Sample Code License.
|
||||
*/
|
||||
|
||||
#include "PeopleWindow.h"
|
||||
|
||||
@ -41,11 +41,14 @@
|
||||
#define B_TRANSLATE_CONTEXT "People"
|
||||
|
||||
|
||||
TPeopleWindow::TPeopleWindow(BRect frame, const char *title, entry_ref *ref)
|
||||
TPeopleWindow::TPeopleWindow(BRect frame, const char* title,
|
||||
const char* nameAttribute, const char* categoryAttribute,
|
||||
const entry_ref* ref)
|
||||
:
|
||||
BWindow(frame, title, B_TITLED_WINDOW, B_NOT_RESIZABLE | B_NOT_ZOOMABLE
|
||||
| B_AUTO_UPDATE_SIZE_LIMITS),
|
||||
fPanel(NULL)
|
||||
fPanel(NULL),
|
||||
fNameAttribute(nameAttribute)
|
||||
{
|
||||
BMenu* menu;
|
||||
BMenuItem* item;
|
||||
@ -55,7 +58,7 @@ TPeopleWindow::TPeopleWindow(BRect frame, const char *title, entry_ref *ref)
|
||||
menu->AddItem(item = new BMenuItem(
|
||||
B_TRANSLATE("New person" B_UTF8_ELLIPSIS),
|
||||
new BMessage(M_NEW), 'N'));
|
||||
item->SetTarget(NULL, be_app);
|
||||
item->SetTarget(be_app);
|
||||
menu->AddItem(new BMenuItem(B_TRANSLATE("Close"),
|
||||
new BMessage(B_QUIT_REQUESTED), 'W'));
|
||||
menu->AddSeparatorItem();
|
||||
@ -71,66 +74,59 @@ TPeopleWindow::TPeopleWindow(BRect frame, const char *title, entry_ref *ref)
|
||||
menu->AddSeparatorItem();
|
||||
item = new BMenuItem(B_TRANSLATE("Quit"),
|
||||
new BMessage(B_QUIT_REQUESTED), 'Q');
|
||||
item->SetTarget(NULL, be_app);
|
||||
item->SetTarget(be_app);
|
||||
menu->AddItem(item);
|
||||
menuBar->AddItem(menu);
|
||||
|
||||
menu = new BMenu(B_TRANSLATE("Edit"));
|
||||
menu->AddItem(fUndo = new BMenuItem(B_TRANSLATE("Undo"),
|
||||
new BMessage(B_UNDO), 'Z'));
|
||||
fUndo->SetTarget(NULL, this);
|
||||
fUndo->SetEnabled(false);
|
||||
menu->AddSeparatorItem();
|
||||
menu->AddItem(fCut = new BMenuItem(B_TRANSLATE("Cut"),
|
||||
new BMessage(B_CUT), 'X'));
|
||||
fCut->SetTarget(NULL, this);
|
||||
menu->AddItem(fCopy = new BMenuItem(B_TRANSLATE("Copy"),
|
||||
new BMessage(B_COPY), 'C'));
|
||||
fCopy->SetTarget(NULL, this);
|
||||
menu->AddItem(fPaste = new BMenuItem(B_TRANSLATE("Paste"),
|
||||
new BMessage(B_PASTE), 'V'));
|
||||
fPaste->SetTarget(NULL, this);
|
||||
menu->AddItem(item = new BMenuItem(B_TRANSLATE("Select all"),
|
||||
new BMessage(M_SELECT), 'A'));
|
||||
item->SetTarget(NULL, this);
|
||||
BMenuItem* selectAllItem = new BMenuItem(B_TRANSLATE("Select all"),
|
||||
new BMessage(M_SELECT), 'A');
|
||||
menu->AddItem(selectAllItem);
|
||||
menuBar->AddItem(menu);
|
||||
|
||||
if (ref) {
|
||||
fRef = new entry_ref(*ref);
|
||||
if (ref != NULL) {
|
||||
SetTitle(ref->name);
|
||||
WatchChanges(true);
|
||||
_SetToRef(new entry_ref(*ref));
|
||||
} else
|
||||
fRef = NULL;
|
||||
_SetToRef(NULL);
|
||||
|
||||
fView = new TPeopleView("PeopleView", fRef);
|
||||
fView = new TPeopleView("PeopleView", categoryAttribute, fRef);
|
||||
|
||||
BLayoutBuilder::Group<>(this, B_VERTICAL, 0)
|
||||
.SetInsets(0, 0, 0, 0)
|
||||
.Add(menuBar)
|
||||
.Add(fView);
|
||||
|
||||
fRevert->SetTarget(fView);
|
||||
selectAllItem->SetTarget(fView);
|
||||
}
|
||||
|
||||
|
||||
TPeopleWindow::~TPeopleWindow(void)
|
||||
TPeopleWindow::~TPeopleWindow()
|
||||
{
|
||||
if (fRef)
|
||||
WatchChanges(false);
|
||||
|
||||
delete fRef;
|
||||
_SetToRef(NULL);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TPeopleWindow::MenusBeginning(void)
|
||||
TPeopleWindow::MenusBeginning()
|
||||
{
|
||||
bool enabled;
|
||||
bool isRedo;
|
||||
|
||||
enabled = fView->CheckSave();
|
||||
bool enabled = !fView->IsSaved();
|
||||
fSave->SetEnabled(enabled);
|
||||
fRevert->SetEnabled(enabled);
|
||||
|
||||
undo_state state = ((BTextView *)CurrentFocus())->UndoState(&isRedo);
|
||||
bool isRedo = false;
|
||||
undo_state state = ((BTextView*)CurrentFocus())->UndoState(&isRedo);
|
||||
fUndo->SetEnabled(state != B_UNDO_UNAVAILABLE);
|
||||
|
||||
if (isRedo)
|
||||
@ -138,7 +134,7 @@ TPeopleWindow::MenusBeginning(void)
|
||||
else
|
||||
fUndo->SetLabel(B_TRANSLATE("Undo"));
|
||||
|
||||
enabled = fView->TextSelected();
|
||||
enabled = fView->IsTextSelected();
|
||||
fCut->SetEnabled(enabled);
|
||||
fCopy->SetEnabled(enabled);
|
||||
|
||||
@ -154,7 +150,6 @@ void
|
||||
TPeopleWindow::MessageReceived(BMessage* msg)
|
||||
{
|
||||
char str[256];
|
||||
entry_ref dir;
|
||||
BDirectory directory;
|
||||
BEntry entry;
|
||||
BFile file;
|
||||
@ -166,6 +161,7 @@ TPeopleWindow::MessageReceived(BMessage* msg)
|
||||
SaveAs();
|
||||
break;
|
||||
}
|
||||
// supposed to fall through
|
||||
case M_REVERT:
|
||||
case M_SELECT:
|
||||
fView->MessageReceived(msg);
|
||||
@ -175,16 +171,11 @@ TPeopleWindow::MessageReceived(BMessage* msg)
|
||||
SaveAs();
|
||||
break;
|
||||
|
||||
case M_GROUP_MENU:
|
||||
{
|
||||
char *name = NULL;
|
||||
msg->FindString("group", (const char **)&name);
|
||||
fView->SetField(F_GROUP, name, FALSE);
|
||||
break;
|
||||
}
|
||||
case B_SAVE_REQUESTED:
|
||||
if (msg->FindRef("directory", &dir) == B_NO_ERROR) {
|
||||
const char *name = NULL;
|
||||
{
|
||||
entry_ref dir;
|
||||
if (msg->FindRef("directory", &dir) == B_OK) {
|
||||
const char* name = NULL;
|
||||
msg->FindString("name", &name);
|
||||
directory.SetTo(&dir);
|
||||
if (directory.InitCheck() == B_NO_ERROR) {
|
||||
@ -196,14 +187,9 @@ TPeopleWindow::MessageReceived(BMessage* msg)
|
||||
|
||||
directory.FindEntry(name, &entry);
|
||||
entry.GetRef(&dir);
|
||||
if (fRef) {
|
||||
WatchChanges(false);
|
||||
delete fRef;
|
||||
}
|
||||
fRef = new entry_ref(dir);
|
||||
WatchChanges(true);
|
||||
_SetToRef(new entry_ref(dir));
|
||||
SetTitle(fRef->name);
|
||||
fView->NewFile(fRef);
|
||||
fView->CreateFile(fRef);
|
||||
}
|
||||
else {
|
||||
sprintf(str, B_TRANSLATE("Could not create %s."), name);
|
||||
@ -212,18 +198,15 @@ TPeopleWindow::MessageReceived(BMessage* msg)
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
case B_NODE_MONITOR:
|
||||
{
|
||||
int32 opcode;
|
||||
if (msg->FindInt32("opcode", &opcode) == B_OK) {
|
||||
switch (opcode) {
|
||||
case B_ENTRY_REMOVED:
|
||||
// We lost our file. Close the window by quiting its
|
||||
// looper.
|
||||
delete fRef;
|
||||
fRef = NULL;
|
||||
|
||||
// We lost our file. Close the window.
|
||||
PostMessage(B_QUIT_REQUESTED);
|
||||
break;
|
||||
|
||||
@ -244,7 +227,6 @@ TPeopleWindow::MessageReceived(BMessage* msg)
|
||||
delete fRef;
|
||||
fRef = new entry_ref(device, directory, name.String());
|
||||
|
||||
|
||||
// And our window title.
|
||||
SetTitle(name);
|
||||
|
||||
@ -255,11 +237,8 @@ TPeopleWindow::MessageReceived(BMessage* msg)
|
||||
&volume);
|
||||
BPath folder(fRef);
|
||||
folder.GetParent(&folder);
|
||||
if (folder == trash) {
|
||||
delete fRef;
|
||||
fRef = NULL;
|
||||
if (folder == trash)
|
||||
PostMessage(B_QUIT_REQUESTED);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
@ -268,13 +247,8 @@ TPeopleWindow::MessageReceived(BMessage* msg)
|
||||
{
|
||||
// An attribute was updated.
|
||||
BString attr;
|
||||
if (msg->FindString("attr", &attr) == B_OK) {
|
||||
for (int32 i = 0; gFields[i].attribute; i++) {
|
||||
if (attr == gFields[i].attribute) {
|
||||
fView->SetField(i, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (msg->FindString("attr", &attr) == B_OK)
|
||||
fView->SetAttribute(attr.String(), true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -289,11 +263,11 @@ TPeopleWindow::MessageReceived(BMessage* msg)
|
||||
|
||||
|
||||
bool
|
||||
TPeopleWindow::QuitRequested(void)
|
||||
TPeopleWindow::QuitRequested()
|
||||
{
|
||||
status_t result;
|
||||
|
||||
if (fView->CheckSave()) {
|
||||
if (!fView->IsSaved()) {
|
||||
result = (new BAlert("", B_TRANSLATE("Save changes before quitting?"),
|
||||
B_TRANSLATE("Cancel"), B_TRANSLATE("Quit"),
|
||||
B_TRANSLATE("Save")))->Go();
|
||||
@ -322,9 +296,68 @@ TPeopleWindow::QuitRequested(void)
|
||||
|
||||
|
||||
void
|
||||
TPeopleWindow::DefaultName(char *name)
|
||||
TPeopleWindow::Show()
|
||||
{
|
||||
strncpy(name, fView->GetField(F_NAME), B_FILE_NAME_LENGTH);
|
||||
fView->MakeFocus();
|
||||
BWindow::Show();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TPeopleWindow::AddAttribute(const char* label, const char* attribute)
|
||||
{
|
||||
fView->AddAttribute(label, attribute);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TPeopleWindow::SaveAs()
|
||||
{
|
||||
char name[B_FILE_NAME_LENGTH];
|
||||
_GetDefaultFileName(name);
|
||||
|
||||
if (fPanel == NULL) {
|
||||
BMessenger target(this);
|
||||
fPanel = new BFilePanel(B_SAVE_PANEL, &target);
|
||||
|
||||
BPath path;
|
||||
find_directory(B_USER_DIRECTORY, &path, true);
|
||||
|
||||
BDirectory dir;
|
||||
dir.SetTo(path.Path());
|
||||
|
||||
BEntry entry;
|
||||
if (dir.FindEntry("people", &entry) == B_OK
|
||||
|| (dir.CreateDirectory("people", &dir) == B_OK
|
||||
&& dir.GetEntry(&entry) == B_OK)) {
|
||||
fPanel->SetPanelDirectory(&entry);
|
||||
}
|
||||
}
|
||||
|
||||
if (fPanel->Window()->Lock()) {
|
||||
fPanel->SetSaveText(name);
|
||||
if (fPanel->Window()->IsHidden())
|
||||
fPanel->Window()->Show();
|
||||
else
|
||||
fPanel->Window()->Activate();
|
||||
fPanel->Window()->Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
TPeopleWindow::RefersPersonFile(const entry_ref& ref) const
|
||||
{
|
||||
if (fRef == NULL)
|
||||
return false;
|
||||
return *fRef == ref;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TPeopleWindow::_GetDefaultFileName(char* name)
|
||||
{
|
||||
strncpy(name, fView->AttributeValue(fNameAttribute), B_FILE_NAME_LENGTH);
|
||||
while (*name) {
|
||||
if (*name == '/')
|
||||
*name = '-';
|
||||
@ -334,52 +367,21 @@ TPeopleWindow::DefaultName(char *name)
|
||||
|
||||
|
||||
void
|
||||
TPeopleWindow::SetField(int32 index, char *text)
|
||||
TPeopleWindow::_SetToRef(entry_ref* ref)
|
||||
{
|
||||
fView->SetField(index, text, true);
|
||||
if (fRef != NULL) {
|
||||
_WatchChanges(false);
|
||||
delete fRef;
|
||||
}
|
||||
|
||||
fRef = ref;
|
||||
|
||||
_WatchChanges(true);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TPeopleWindow::SaveAs(void)
|
||||
{
|
||||
char name[B_FILE_NAME_LENGTH];
|
||||
BDirectory dir;
|
||||
BEntry entry;
|
||||
BMessenger window(this);
|
||||
BPath path;
|
||||
|
||||
DefaultName(name);
|
||||
if (!fPanel) {
|
||||
fPanel = new BFilePanel(B_SAVE_PANEL, &window);
|
||||
fPanel->SetSaveText(name);
|
||||
find_directory(B_USER_DIRECTORY, &path, true);
|
||||
dir.SetTo(path.Path());
|
||||
if (dir.FindEntry("people", &entry) == B_NO_ERROR)
|
||||
fPanel->SetPanelDirectory(&entry);
|
||||
else if (dir.CreateDirectory("people", &dir) == B_NO_ERROR) {
|
||||
dir.GetEntry(&entry);
|
||||
fPanel->SetPanelDirectory(&entry);
|
||||
}
|
||||
}
|
||||
else if (fPanel->Window()->Lock()) {
|
||||
if (!fPanel->Window()->IsHidden())
|
||||
fPanel->Window()->Activate();
|
||||
else
|
||||
fPanel->SetSaveText(name);
|
||||
fPanel->Window()->Unlock();
|
||||
}
|
||||
|
||||
if (fPanel->Window()->Lock()) {
|
||||
if (fPanel->Window()->IsHidden())
|
||||
fPanel->Window()->Show();
|
||||
fPanel->Window()->Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TPeopleWindow::WatchChanges(bool enable)
|
||||
TPeopleWindow::_WatchChanges(bool enable)
|
||||
{
|
||||
if (fRef == NULL)
|
||||
return;
|
||||
|
@ -1,56 +1,71 @@
|
||||
//--------------------------------------------------------------------
|
||||
//
|
||||
// PeopleWindow.h
|
||||
//
|
||||
// Written by: Robert Polic
|
||||
//
|
||||
//--------------------------------------------------------------------
|
||||
/*
|
||||
Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||
This file may be used under the terms of the Be Sample Code License.
|
||||
*/
|
||||
* Copyright 2010, Haiku, Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*
|
||||
* Authors:
|
||||
* Robert Polic
|
||||
*
|
||||
* Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||
* This file may be used under the terms of the Be Sample Code License.
|
||||
*/
|
||||
#ifndef PEOPLE_WINDOW_H
|
||||
#define PEOPLE_WINDOW_H
|
||||
|
||||
|
||||
#include <String.h>
|
||||
#include <Window.h>
|
||||
|
||||
#ifndef PEOPLEWINDOW_H
|
||||
#define PEOPLEWINDOW_H
|
||||
|
||||
#define TITLE_BAR_HEIGHT 25
|
||||
#define WIND_WIDTH 321
|
||||
#define WIND_HEIGHT 340
|
||||
|
||||
|
||||
class TPeopleView;
|
||||
class BFilePanel;
|
||||
class BMenuItem;
|
||||
|
||||
#include <Window.h>
|
||||
//====================================================================
|
||||
|
||||
class TPeopleWindow : public BWindow {
|
||||
|
||||
private:
|
||||
|
||||
void WatchChanges(bool);
|
||||
|
||||
BFilePanel *fPanel;
|
||||
BMenuItem *fCopy;
|
||||
BMenuItem *fCut;
|
||||
BMenuItem *fPaste;
|
||||
BMenuItem *fRevert;
|
||||
BMenuItem *fSave;
|
||||
BMenuItem *fUndo;
|
||||
TPeopleView *fView;
|
||||
|
||||
public:
|
||||
|
||||
entry_ref *fRef;
|
||||
TPeopleWindow(BRect frame, const char* title,
|
||||
const char* nameAttribute,
|
||||
const char* categoryAttribute,
|
||||
const entry_ref* ref);
|
||||
virtual ~TPeopleWindow();
|
||||
|
||||
TPeopleWindow(BRect, const char*, entry_ref*);
|
||||
~TPeopleWindow(void);
|
||||
virtual void MenusBeginning(void);
|
||||
virtual void MessageReceived(BMessage*);
|
||||
virtual bool QuitRequested(void);
|
||||
void DefaultName(char*);
|
||||
void SetField(int32, char*);
|
||||
void SaveAs(void);
|
||||
virtual void MenusBeginning();
|
||||
virtual void MessageReceived(BMessage* message);
|
||||
virtual bool QuitRequested();
|
||||
virtual void Show();
|
||||
|
||||
void AddAttribute(const char* label,
|
||||
const char* attribute);
|
||||
|
||||
void SaveAs();
|
||||
|
||||
bool RefersPersonFile(const entry_ref& ref) const;
|
||||
|
||||
private:
|
||||
void _GetDefaultFileName(char* name);
|
||||
void _SetToRef(entry_ref* ref);
|
||||
void _WatchChanges(bool doIt);
|
||||
|
||||
private:
|
||||
entry_ref* fRef;
|
||||
|
||||
BFilePanel* fPanel;
|
||||
BMenuItem* fCopy;
|
||||
BMenuItem* fCut;
|
||||
BMenuItem* fPaste;
|
||||
BMenuItem* fRevert;
|
||||
BMenuItem* fSave;
|
||||
BMenuItem* fUndo;
|
||||
TPeopleView* fView;
|
||||
|
||||
BString fNameAttribute;
|
||||
};
|
||||
|
||||
#endif /* PEOPLEWINDOW_H */
|
||||
|
||||
#endif // PEOPLE_WINDOW_H
|
||||
|
@ -1,66 +0,0 @@
|
||||
//--------------------------------------------------------------------
|
||||
//
|
||||
// TTextControl.cpp
|
||||
//
|
||||
// Written by: Robert Polic
|
||||
//
|
||||
//--------------------------------------------------------------------
|
||||
/*
|
||||
Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||
This file may be used under the terms of the Be Sample Code License.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include <Font.h>
|
||||
|
||||
#include "TTextControl.h"
|
||||
|
||||
|
||||
TTextControl::TTextControl(const char *label, const char *text)
|
||||
:
|
||||
BTextControl(NULL, text, NULL)
|
||||
{
|
||||
|
||||
if (label && label[0])
|
||||
SetLabel(BString(label).Append(":"));
|
||||
SetAlignment(B_ALIGN_RIGHT, B_ALIGN_LEFT);
|
||||
fOriginal = text;
|
||||
}
|
||||
|
||||
|
||||
TTextControl::~TTextControl()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TTextControl::AttachedToWindow()
|
||||
{
|
||||
BTextControl::AttachedToWindow();
|
||||
|
||||
BTextView* text = (BTextView *)ChildAt(0);
|
||||
text->SetMaxBytes(255);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
TTextControl::Changed()
|
||||
{
|
||||
return fOriginal != Text();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TTextControl::Revert(void)
|
||||
{
|
||||
if (Changed())
|
||||
SetText(fOriginal);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TTextControl::Update(void)
|
||||
{
|
||||
fOriginal = Text();
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
//--------------------------------------------------------------------
|
||||
//
|
||||
// TTextControl.h
|
||||
//
|
||||
// Written by: Robert Polic
|
||||
//
|
||||
//--------------------------------------------------------------------
|
||||
/*
|
||||
Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||
This file may be used under the terms of the Be Sample Code License.
|
||||
*/
|
||||
|
||||
#ifndef TEXTCONTROL_H
|
||||
#define TEXTCONTROL_H
|
||||
|
||||
#include <String.h>
|
||||
#include <TextControl.h>
|
||||
|
||||
class TTextControl : public BTextControl {
|
||||
public:
|
||||
TTextControl(const char* label, const char* text);
|
||||
virtual ~TTextControl();
|
||||
|
||||
virtual void AttachedToWindow();
|
||||
|
||||
bool Changed();
|
||||
void Revert();
|
||||
void Update();
|
||||
|
||||
private:
|
||||
BString fOriginal;
|
||||
};
|
||||
|
||||
#endif /* TEXTCONTROL_H */
|
@ -1,24 +1,19 @@
|
||||
//--------------------------------------------------------------------
|
||||
//
|
||||
// main.cpp
|
||||
//
|
||||
// Written by: Robert Polic
|
||||
//
|
||||
//--------------------------------------------------------------------
|
||||
/*
|
||||
Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||
This file may be used under the terms of the Be Sample Code License.
|
||||
*/
|
||||
* Copyright 1999, Be Incorporated. All Rights Reserved.
|
||||
* This file may be used under the terms of the Be Sample Code License.
|
||||
*
|
||||
* Authors:
|
||||
* Robert Polic
|
||||
*/
|
||||
|
||||
|
||||
#include "PeopleApp.h"
|
||||
|
||||
int main(void)
|
||||
|
||||
int
|
||||
main(int, char**)
|
||||
{
|
||||
TPeopleApp *app;
|
||||
|
||||
app = new TPeopleApp();
|
||||
app->Run();
|
||||
|
||||
delete app;
|
||||
TPeopleApp app;
|
||||
app.Run();
|
||||
return B_NO_ERROR;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user