2453 lines
62 KiB
C++
2453 lines
62 KiB
C++
// Copyright (c) 1997-2001 Microsoft Corporation, All Rights Reserved
|
|
#include "precomp.h"
|
|
#include "resource.h"
|
|
#include "notify.h"
|
|
#include "icon.h"
|
|
#include "quals.h"
|
|
#include "hmomutil.h"
|
|
#include <afxcmn.h>
|
|
#include "SingleViewCtl.h"
|
|
#include "utils.h"
|
|
#include "globals.h"
|
|
#include "hmmverr.h"
|
|
#include "Methods.h"
|
|
#include "hmmvtab.h"
|
|
#include "ppgQualifiers.h"
|
|
#include "path.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define CX_MARGIN 8
|
|
#define CY_MARGIN 8
|
|
#define CY_HEADER 16
|
|
|
|
|
|
// Flags to mark the cells as having various characteristics
|
|
// The cell flags should be powers of two to form an appropriate bit mask.
|
|
#define CELL_TAG_EXISTS_IN_DATABASE 1
|
|
#define CELL_TAG_NEEDS_RENAME 2
|
|
#define CELL_TAG_STDQUAL 4
|
|
|
|
|
|
#define FIRST_SYNTESIZED_QUALIFIER_ID 1
|
|
|
|
// The default column widths. Note that the width of some columns
|
|
// may be computed at runtime and that the default value may not
|
|
// be used.
|
|
#define CX_COL_NAME 180
|
|
#define CX_COL_TYPE 65
|
|
#define CX_COL_PROPAGATE_TO_INSTANCE_FLAG 24
|
|
#define CX_COL_PROPAGATE_TO_CLASS_FLAG 24
|
|
#define CX_COL_OVERRIDABLE_FLAG 24
|
|
#define CX_COL_AMENDED_FLAG 24
|
|
#define CX_COL_ORIGIN 45
|
|
#define CX_COL_VALUE 160
|
|
#define CX_COL_MIN 40
|
|
#define DEFAULT_WIDTH (CX_COL_NAME + \
|
|
CX_COL_TYPE + \
|
|
CX_COL_PROPAGATE_TO_INSTANCE_FLAG + \
|
|
CX_COL_PROPAGATE_TO_CLASS_FLAG + \
|
|
CX_COL_OVERRIDABLE_FLAG + \
|
|
CX_COL_AMENDED_FLAG +\
|
|
CX_COL_ORIGIN + \
|
|
CX_COL_VALUE)
|
|
|
|
|
|
|
|
|
|
enum STDQUAL {
|
|
STDQUAL_ABSTRACT,
|
|
STDQUAL_ASSOC,
|
|
STDQUAL_CIMTYPE,
|
|
STDQUAL_CLASSCONTEXT,
|
|
STDQUAL_DYNAMIC,
|
|
STDQUAL_DYNPROPS,
|
|
STDQUAL_IMPLEMENTED,
|
|
STDQUAL_INDEXED,
|
|
STDQUAL_INSTANCECONTEXT,
|
|
STDQUAL_KEY,
|
|
STDQUAL_LEXICON,
|
|
STDQUAL_LOCALE,
|
|
STDQUAL_MAX,
|
|
STDQUAL_NOTNULL,
|
|
STDQUAL_OPTIONAL,
|
|
STDQUAL_PROPERTYCONTEXT,
|
|
STDQUAL_PROVIDER,
|
|
STDQUAL_READ,
|
|
STDQUAL_SINGLETON,
|
|
STDQUAL_STATIC,
|
|
STDQUAL_WRITE,
|
|
STDQUAL_IN_PARAM,
|
|
STDQUAL_OUT_PARAM,
|
|
STDQUAL_DESCRIPTION,
|
|
STDQUAL_END_OF_TABLE
|
|
};
|
|
|
|
#define FIELD_VALUE 1 // The value field
|
|
#define FIELD_IFLAG 2 // Propagate to instance
|
|
#define FIELD_CFLAG 4 // Propagate to class
|
|
#define FIELD_OFLAG 8 // Overrideable
|
|
#define FIELD_AFLAG 16 // Amended
|
|
|
|
#define FIELD_FLAGS (FIELD_IFLAG | FIELD_CFLAG | FIELD_OFLAG | FIELD_AFLAG)
|
|
|
|
|
|
|
|
class CStdQualTable
|
|
{
|
|
public:
|
|
LPCTSTR pszStdQual;
|
|
STDQUAL stdqual;
|
|
VARTYPE vt;
|
|
DWORD dwFieldsReadonly;
|
|
DWORD dwFieldsSet;
|
|
};
|
|
|
|
CStdQualTable aStdQualMethods[] =
|
|
{
|
|
{_T("Implemented"), STDQUAL_IMPLEMENTED, VT_BOOL, FIELD_VALUE, FIELD_FLAGS},
|
|
{_T("Static"), STDQUAL_STATIC, VT_BOOL, FIELD_VALUE, FIELD_FLAGS},
|
|
{NULL, STDQUAL_END_OF_TABLE, VT_NULL, 0, 0}
|
|
};
|
|
|
|
CStdQualTable aStdQualMethodParm[] =
|
|
{
|
|
{_T("IN"), STDQUAL_IN_PARAM, VT_BOOL, FIELD_VALUE, FIELD_FLAGS},
|
|
{_T("OUT"), STDQUAL_OUT_PARAM, VT_BOOL, FIELD_VALUE, FIELD_FLAGS},
|
|
{_T("Description"), STDQUAL_DESCRIPTION, VT_BSTR, 0, FIELD_FLAGS},
|
|
{NULL, STDQUAL_END_OF_TABLE, VT_NULL, 0, 0}
|
|
};
|
|
|
|
CStdQualTable aStdQualProps[] =
|
|
{
|
|
{_T("CIMTYPE"), STDQUAL_CIMTYPE, VT_BSTR, (FIELD_VALUE | FIELD_FLAGS), FIELD_FLAGS},
|
|
{_T("Description"), STDQUAL_DESCRIPTION, VT_BSTR, 0, FIELD_FLAGS},
|
|
{_T("dynamic"), STDQUAL_DYNAMIC, VT_BOOL, (FIELD_VALUE | FIELD_IFLAG), FIELD_IFLAG},
|
|
{_T("Implemented"), STDQUAL_IMPLEMENTED, VT_BOOL, FIELD_VALUE, FIELD_FLAGS},
|
|
{_T("Indexed"), STDQUAL_INDEXED, VT_BOOL, FIELD_VALUE, FIELD_FLAGS},
|
|
{_T("key"), STDQUAL_KEY, VT_BOOL, (FIELD_VALUE | FIELD_FLAGS), (FIELD_IFLAG | FIELD_CFLAG)},
|
|
{_T("Lexicon"), STDQUAL_LEXICON, VT_BSTR, 0, FIELD_FLAGS},
|
|
{_T("Max"), STDQUAL_MAX, VT_I4, 0, FIELD_FLAGS},
|
|
{_T("Not_null"), STDQUAL_NOTNULL, VT_BOOL, FIELD_VALUE, FIELD_FLAGS},
|
|
{_T("PropertyContext"), STDQUAL_PROPERTYCONTEXT, VT_BSTR, 0, FIELD_FLAGS},
|
|
{_T("read"), STDQUAL_READ, VT_BOOL, FIELD_VALUE, FIELD_FLAGS},
|
|
{_T("Static"), STDQUAL_STATIC, VT_BOOL, FIELD_VALUE, FIELD_FLAGS},
|
|
{_T("write"), STDQUAL_WRITE, VT_BOOL, FIELD_VALUE, FIELD_FLAGS},
|
|
{NULL, STDQUAL_END_OF_TABLE, VT_NULL, 0, 0}
|
|
};
|
|
|
|
CStdQualTable aStdQualClass[] =
|
|
{
|
|
{_T("abstract"), STDQUAL_ABSTRACT, VT_BOOL, FIELD_VALUE, FIELD_FLAGS},
|
|
{_T("Association"), STDQUAL_ASSOC, VT_BOOL, FIELD_VALUE, FIELD_FLAGS},
|
|
{_T("ClassContext"), STDQUAL_CLASSCONTEXT, VT_BSTR, 0, FIELD_FLAGS},
|
|
{_T("Description"), STDQUAL_DESCRIPTION, VT_BSTR, 0, FIELD_FLAGS},
|
|
{_T("dynamic"), STDQUAL_DYNAMIC, VT_BOOL, (FIELD_VALUE | FIELD_IFLAG), FIELD_IFLAG},
|
|
{_T("Dynprops"), STDQUAL_DYNPROPS, VT_BOOL, FIELD_VALUE, FIELD_FLAGS},
|
|
{_T("InstanceContext"), STDQUAL_INSTANCECONTEXT, VT_BSTR, 0, FIELD_FLAGS},
|
|
{_T("Lexicon"), STDQUAL_LEXICON, VT_BSTR, 0, FIELD_FLAGS},
|
|
{_T("Locale"), STDQUAL_LOCALE, VT_BSTR, 0, FIELD_FLAGS},
|
|
{_T("provider"), STDQUAL_PROVIDER, VT_BSTR, 0, FIELD_FLAGS},
|
|
{_T("Singleton"), STDQUAL_SINGLETON, VT_BOOL, FIELD_VALUE, FIELD_FLAGS},
|
|
{NULL, STDQUAL_END_OF_TABLE, VT_NULL, 0, 0}
|
|
};
|
|
|
|
CStdQualTable aStdQualInstance[] =
|
|
{
|
|
{_T("abstract"), STDQUAL_ABSTRACT, VT_BOOL, FIELD_VALUE, FIELD_FLAGS},
|
|
{_T("Association"), STDQUAL_ASSOC, VT_BOOL, FIELD_VALUE, FIELD_FLAGS},
|
|
{_T("ClassContext"), STDQUAL_CLASSCONTEXT, VT_BSTR, 0, FIELD_FLAGS},
|
|
{_T("Description"), STDQUAL_DESCRIPTION, VT_BSTR, 0, FIELD_FLAGS},
|
|
{_T("dynamic"), STDQUAL_DYNAMIC, VT_BOOL, (FIELD_VALUE | FIELD_IFLAG), FIELD_IFLAG},
|
|
{_T("Dynprops"), STDQUAL_DYNPROPS, VT_BOOL, FIELD_VALUE, FIELD_FLAGS},
|
|
{_T("InstanceContext"), STDQUAL_INSTANCECONTEXT, VT_BSTR, 0, FIELD_FLAGS},
|
|
{_T("Lexicon"), STDQUAL_LEXICON, VT_BSTR, 0, FIELD_FLAGS},
|
|
{_T("Locale"), STDQUAL_LOCALE, VT_BSTR, 0, FIELD_FLAGS},
|
|
{_T("provider"), STDQUAL_PROVIDER, VT_BSTR, 0, FIELD_FLAGS},
|
|
{_T("Singleton"), STDQUAL_SINGLETON, VT_BOOL, FIELD_VALUE, FIELD_FLAGS},
|
|
{NULL, STDQUAL_END_OF_TABLE, VT_NULL, 0, 0}
|
|
};
|
|
|
|
|
|
#ifdef DEBUG_QUALIFIERSGRID
|
|
class CValidateAttribs
|
|
{
|
|
public:
|
|
CValidateAttribs(CAttribGrid* pGrid);
|
|
~CValidateAttribs();
|
|
|
|
private:
|
|
CAttribGrid* m_pGrid;
|
|
};
|
|
|
|
CValidateAttribs::CValidateAttribs(CAttribGrid* pGrid)
|
|
{
|
|
m_pGrid = pGrid;
|
|
|
|
|
|
|
|
}
|
|
|
|
CValidateAttribs::~CValidateAttribs()
|
|
{
|
|
|
|
}
|
|
|
|
#define VALIDATE_ATTRIBGRID(x) CValidateAttribs validate_attribs(x)
|
|
|
|
#else
|
|
#define VALIDATE_ATTRIBGRID(x)
|
|
#endif
|
|
|
|
|
|
|
|
|
|
CAttribGrid::CAttribGrid(QUALGRID iGridType, CSingleViewCtrl* phmmv, CPpgQualifiers* ppgQuals)
|
|
{
|
|
m_bHasEmptyRow = FALSE;
|
|
m_iGridType = iGridType;
|
|
m_psv = phmmv;
|
|
m_ppgQuals = ppgQuals;
|
|
m_bReadonly = FALSE;
|
|
|
|
CString sTitle;
|
|
|
|
// Name
|
|
ASSERT(ICOL_QUAL_NAME == 0);
|
|
sTitle.LoadString(IDS_HEADER_TITLE_ATTRIB_NAME);
|
|
AddColumn(CX_COL_NAME, sTitle);
|
|
|
|
// Type
|
|
ASSERT(ICOL_QUAL_TYPE == 1);
|
|
sTitle.LoadString(IDS_HEADER_TITLE_ATTRIB_TYPE);
|
|
AddColumn(CX_COL_TYPE, sTitle);
|
|
|
|
// Propagate to instance flag
|
|
ASSERT(ICOL_QUAL_PROPAGATE_TO_INSTANCE_FLAG == 2);
|
|
sTitle = "I";
|
|
AddColumn(CX_COL_PROPAGATE_TO_INSTANCE_FLAG, sTitle);
|
|
|
|
// Propagate to class flag
|
|
ASSERT(ICOL_QUAL_PROPAGATE_TO_CLASS_FLAG == 3);
|
|
sTitle = "C";
|
|
AddColumn(CX_COL_PROPAGATE_TO_CLASS_FLAG, sTitle);
|
|
|
|
// Overridable flag
|
|
ASSERT(ICOL_QUAL_OVERRIDABLE_FLAG == 4);
|
|
sTitle = "O";
|
|
AddColumn(CX_COL_OVERRIDABLE_FLAG, sTitle);
|
|
|
|
// Amended flag
|
|
ASSERT(ICOL_QUAL_AMENDED_FLAG == 5);
|
|
sTitle = "A";
|
|
AddColumn(CX_COL_AMENDED_FLAG, sTitle);
|
|
|
|
|
|
// Origin
|
|
ASSERT(ICOL_QUAL_ORIGIN == 6);
|
|
sTitle = "Origin";
|
|
AddColumn(CX_COL_ORIGIN, sTitle);
|
|
|
|
|
|
// Value
|
|
ASSERT(ICOL_QUAL_VALUE == 7);
|
|
sTitle.LoadString(IDS_HEADER_TITLE_ATTRIB_VALUE);
|
|
AddColumn(CX_COL_VALUE, sTitle); // Value
|
|
|
|
m_iCurrentRow = NULL_INDEX;
|
|
m_iCurrentCol = NULL_INDEX;
|
|
m_bOnCellContentChange = FALSE;
|
|
|
|
m_pqs = NULL;
|
|
m_lNewQualID = FIRST_SYNTESIZED_QUALIFIER_ID;
|
|
|
|
ToBSTR(m_varCurrentName);
|
|
|
|
}
|
|
|
|
|
|
CAttribGrid::~CAttribGrid()
|
|
{
|
|
|
|
if (m_pqs) {
|
|
m_pqs->Release();
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//*******************************************************
|
|
// CAttribGrid::SizeColumnsToFitWindow
|
|
//
|
|
// Size the columns to fit the windows client rectangle.
|
|
//
|
|
// Parameters:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// Nothing.
|
|
//
|
|
//*******************************************************
|
|
void CAttribGrid::SizeColumnsToFitWindow()
|
|
{
|
|
CRect rcClient;
|
|
GetClientRect(rcClient);
|
|
|
|
|
|
const int nCols = ICOL_QUAL_VALUE + 1;
|
|
int cxTemp = 0;
|
|
int iCol;
|
|
for (iCol=0; iCol < ICOL_QUAL_VALUE; ++iCol) {
|
|
cxTemp += ColWidth(iCol);
|
|
}
|
|
|
|
int cxAllCols = cxTemp + ColWidth(ICOL_QUAL_VALUE);
|
|
int cxClient = rcClient.Width() - GetRowHandleWidth();
|
|
|
|
|
|
if (cxClient > cxAllCols) {
|
|
// All of the columns are visible, so grow the last column to fill the
|
|
// available space.
|
|
SetColumnWidth(ICOL_QUAL_VALUE, cxClient - cxTemp, TRUE);
|
|
}
|
|
|
|
// Make sure that no column is wider that the client area so that the user
|
|
// has a some way to grow or shrink the column.
|
|
for (iCol=0; iCol<nCols; ++iCol) {
|
|
int cxCol = ColWidth(iCol);
|
|
if ((cxCol > cxClient) && (cxClient > CX_COL_MIN)) {
|
|
SetColumnWidth(iCol, cxClient, TRUE);
|
|
}
|
|
}
|
|
|
|
// Make the value column an exact fit exactly so that the drop-down combo
|
|
// for the BOOL (true/false) value is visible. The dialog should be wide
|
|
// enough for the value column to be visible.
|
|
int ixColValue = GetColumnPos(ICOL_QUAL_VALUE);
|
|
if (ixColValue < cxClient) {
|
|
SetColumnWidth(ICOL_QUAL_VALUE, cxClient - ixColValue, TRUE);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//**************************************************************
|
|
// CAttribGrid::CanEditValuesOnly
|
|
//
|
|
// Check to see whether or not the user is allowed to do more
|
|
// than just edit values.
|
|
//
|
|
// Parameters:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// BOOL
|
|
// TRUE if the user is restricted to editing values only.
|
|
//
|
|
//***************************************************************
|
|
BOOL CAttribGrid::CanEditValuesOnly()
|
|
{
|
|
// BOOL bEditValuesOnly = !m_psv->ObjectIsClass() || !m_psv->IsInSchemaStudioMode();
|
|
BOOL bEditValuesOnly = !m_psv->CanEdit();
|
|
return bEditValuesOnly;
|
|
}
|
|
|
|
//************************************************************
|
|
// CAttribGrid::Sync
|
|
//
|
|
// Put the attribute to the class object. This syncronizes what the
|
|
// user sees on the screen with what is in the HMOM class object.
|
|
//
|
|
// Parameters:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// SCODE
|
|
// S_OK if successful.
|
|
// HMOM status code if a failure occurs.
|
|
//
|
|
//**************************************************************
|
|
SCODE CAttribGrid::Sync()
|
|
{
|
|
CGridSync sync(this);
|
|
|
|
SCODE sc = S_OK;
|
|
if (m_pqs) {
|
|
if (SelectedRowWasModified()) {
|
|
sc = PutQualifier(m_iCurrentRow);
|
|
}
|
|
}
|
|
return sc;
|
|
}
|
|
|
|
|
|
//***********************************************************
|
|
// CAttribGrid::Create
|
|
//
|
|
// We override the create method of the base class so that
|
|
// we can initialize the column widths to fill the client
|
|
// area.
|
|
//
|
|
// Parameters:
|
|
// CRect& rc
|
|
// The client rectangle
|
|
//
|
|
// CWnd* pwndParent
|
|
// The parent window
|
|
//
|
|
// BOOL bVisible
|
|
// TRUE if the window should be visible after creation.
|
|
//
|
|
// Returns:
|
|
// TRUE if successful, otherwise FALSE.
|
|
//
|
|
//************************************************************
|
|
BOOL CAttribGrid::Create(CRect& rc, CWnd* pwndParent, UINT nId, BOOL bVisible)
|
|
{
|
|
VALIDATE_ATTRIBGRID(this);
|
|
|
|
|
|
// Set the column widths of those columns who's width is computed from
|
|
// the client rectangle instead of using the default width. For the
|
|
// attributes grid, only the "Value" column width is computed.
|
|
int cxClient = rc.right - rc.left;
|
|
int cxUsed = CX_COL_NAME + CX_COL_TYPE;
|
|
int cxCol = 0;
|
|
if (cxClient > cxUsed) {
|
|
cxCol = cxClient - cxUsed;
|
|
}
|
|
|
|
SetColumnWidth(ICOL_QUAL_VALUE, cxCol, FALSE);
|
|
return CGrid::Create(rc, pwndParent, nId, bVisible);
|
|
}
|
|
|
|
|
|
|
|
|
|
//**************************************************************
|
|
// CAttribGrid::SetQualifierSet
|
|
//
|
|
// Set the "qualifier set" for the grid. This causes the contents
|
|
// of the grid to be loaded with the qualifiers in the "qualifier set"
|
|
//
|
|
// Params:
|
|
// [in] IWbemQualifierSet* pqs
|
|
// A pointer to the qualifier set.
|
|
//
|
|
// [in] BOOL bReadonly
|
|
// TRUE if the qualifier set is readonly.
|
|
//
|
|
// Returns:
|
|
// Nothing.
|
|
//
|
|
//***************************************************************
|
|
SCODE CAttribGrid::SetQualifierSet(IWbemQualifierSet* pqs, BOOL bReadonly)
|
|
{
|
|
VALIDATE_ATTRIBGRID(this);
|
|
m_bReadonly = bReadonly;
|
|
|
|
m_lNewQualID = FIRST_SYNTESIZED_QUALIFIER_ID;
|
|
|
|
|
|
if (m_pqs) {
|
|
m_pqs->Release();
|
|
m_pqs = NULL;
|
|
ClearRows();
|
|
}
|
|
|
|
ClearAllSortDirectionFlags();
|
|
|
|
if (pqs != NULL) {
|
|
pqs->AddRef();
|
|
}
|
|
|
|
m_pqs = pqs;
|
|
|
|
if (pqs == NULL) {
|
|
return S_OK;
|
|
}
|
|
else {
|
|
return LoadAttributes();
|
|
}
|
|
|
|
}
|
|
|
|
//**************************************************************
|
|
// CAttribGrid::UseQualifierSetFromClone
|
|
//
|
|
// When a cloned object replaces the current object, it is necessary
|
|
// to replace the qualifier set being edited with the equivalant qualifier
|
|
// set from the cloned object. This is done when the "Apply" button is clicked
|
|
// in the qualifier editing dialog.
|
|
//
|
|
// This method provides a way to continue editing the cloned object
|
|
// without having to reload and redaw the qualifiers.
|
|
//
|
|
//
|
|
// Params:
|
|
// IWbemQualifierSet* pAttribSet
|
|
// A pointer to the qualifier set.
|
|
//
|
|
// Returns:
|
|
// Nothing.
|
|
//
|
|
//***************************************************************
|
|
void CAttribGrid::UseQualifierSetFromClone(IWbemQualifierSet* pqs)
|
|
{
|
|
if (m_pqs) {
|
|
m_pqs->Release();
|
|
m_pqs = NULL;
|
|
}
|
|
|
|
if (pqs) {
|
|
pqs->AddRef();
|
|
}
|
|
m_pqs = pqs;
|
|
}
|
|
|
|
|
|
|
|
//************************************************************
|
|
// CAttribGrid::GetCellEnumStrings
|
|
//
|
|
// When the cell editor is selected, it calls this virtual method
|
|
// to load the cell enumeration strings. These are the strings
|
|
// that appear in the cell's drop-down combo. If no strings are
|
|
// loaded into the string array, then there will be no drop-down
|
|
// combo.
|
|
//
|
|
// This method is called for most, but not all cell types.
|
|
//
|
|
// Parameters:
|
|
// [in] int iRow
|
|
// The cell's row index.
|
|
//
|
|
// [in] int iCol
|
|
// The cell's column index.
|
|
//
|
|
// [out] CStringArray& sa
|
|
// The enumeration values are returned by this string array.
|
|
//
|
|
// Returns:
|
|
// Nothing.
|
|
//
|
|
//**************************************************************
|
|
void CAttribGrid::GetCellEnumStrings(int iRow, int iCol, CStringArray& sa)
|
|
{
|
|
if (iCol == ICOL_QUAL_NAME) {
|
|
sa.RemoveAll();
|
|
CStdQualTable* ptable;
|
|
|
|
switch(m_iGridType) {
|
|
case QUALGRID_PROPERTY:
|
|
ptable = aStdQualProps;
|
|
break;
|
|
case QUALGRID_METHODS:
|
|
ptable = aStdQualMethods;
|
|
break;
|
|
case QUALGRID_INSTANCE:
|
|
ptable = aStdQualInstance;
|
|
break;
|
|
case QUALGRID_CLASS:
|
|
ptable = aStdQualClass;
|
|
break;
|
|
case QUALGRID_METHOD_PARAM:
|
|
ptable = aStdQualMethodParm;
|
|
break;
|
|
default:
|
|
ASSERT(FALSE);
|
|
return;
|
|
}
|
|
|
|
while (ptable->stdqual != STDQUAL_END_OF_TABLE) {
|
|
if (ptable->stdqual != STDQUAL_CIMTYPE) {
|
|
sa.Add(ptable->pszStdQual);
|
|
}
|
|
++ptable;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//**************************************************************
|
|
// CAttribGrid::ClearRow
|
|
//
|
|
// Clear the row to its "emtpy" state.
|
|
//
|
|
// Paramters:
|
|
// [in] int iRow
|
|
// The row to clear.
|
|
//
|
|
// [in] BOOL bRedraw
|
|
// TRUE to redraw the row.
|
|
//
|
|
// Returns:
|
|
// Nothing.
|
|
//
|
|
//
|
|
//***************************************************************
|
|
void CAttribGrid::ClearRow(int iRow, BOOL bRedraw)
|
|
{
|
|
|
|
COleVariant varFlag;
|
|
varFlag.boolVal = FALSE;
|
|
|
|
|
|
|
|
|
|
varFlag.ChangeType(VT_BOOL);
|
|
CGridCell* pgc;
|
|
|
|
|
|
pgc = &GetAt(iRow, ICOL_QUAL_NAME);
|
|
pgc->SetValue(CELLTYPE_NAME, L"", CIM_STRING);
|
|
|
|
pgc = &GetAt(iRow, ICOL_QUAL_VALUE);
|
|
pgc->SetValue(CELLTYPE_CIMTYPE_SCALAR, L"", CIM_STRING);
|
|
|
|
|
|
|
|
|
|
pgc = &GetAt(iRow, ICOL_QUAL_PROPAGATE_TO_INSTANCE_FLAG);
|
|
pgc->SetValue(CELLTYPE_CHECKBOX, varFlag, CIM_BOOLEAN);
|
|
pgc->SetFlags(CELLFLAG_READONLY, CELLFLAG_READONLY);
|
|
|
|
pgc = &GetAt(iRow, ICOL_QUAL_PROPAGATE_TO_CLASS_FLAG);
|
|
pgc->SetValue(CELLTYPE_CHECKBOX, varFlag, CIM_BOOLEAN);
|
|
pgc->SetFlags(CELLFLAG_READONLY, CELLFLAG_READONLY);
|
|
|
|
pgc = &GetAt(iRow, ICOL_QUAL_OVERRIDABLE_FLAG);
|
|
pgc->SetValue(CELLTYPE_CHECKBOX, varFlag, CIM_BOOLEAN);
|
|
pgc->SetFlags(CELLFLAG_READONLY, CELLFLAG_READONLY);
|
|
|
|
pgc = &GetAt(iRow, ICOL_QUAL_AMENDED_FLAG);
|
|
pgc->SetValue(CELLTYPE_CHECKBOX, varFlag, CIM_BOOLEAN);
|
|
pgc->SetFlags(CELLFLAG_READONLY, CELLFLAG_READONLY);
|
|
|
|
pgc = &GetAt(iRow, ICOL_QUAL_ORIGIN);
|
|
pgc->SetFlags(CELLFLAG_READONLY, CELLFLAG_READONLY);
|
|
|
|
SetRowModified(iRow, FALSE);
|
|
|
|
if (bRedraw) {
|
|
RedrawRow(iRow);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//**************************************************************
|
|
// CAttribGrid::OnEnumSelection
|
|
//
|
|
// The grid calls this virtual method to get any enumerated
|
|
// values that should appear in the drop-down combo box when
|
|
// editing a grid cell. Note that this should not include the
|
|
// enumerated values that appear for the standard cell types.
|
|
//
|
|
// Parameters:
|
|
// [in] int iRow
|
|
// The cell's row index.
|
|
//
|
|
// [in] int iCol
|
|
// The cell's column index.
|
|
//
|
|
// Returns:
|
|
// Nothing.
|
|
//
|
|
//*************************************************************
|
|
void CAttribGrid::OnEnumSelection(int iRow, int iCol)
|
|
{
|
|
SCODE sc;
|
|
if (iCol == ICOL_QUAL_NAME) {
|
|
CString sName;
|
|
CGridCell& gcName = GetAt(iRow, ICOL_QUAL_NAME);
|
|
CIMTYPE cimtypeName;
|
|
gcName.GetValue(sName, cimtypeName);
|
|
|
|
int iEmptyRow = IndexOfEmptyRow();
|
|
if (iEmptyRow != NULL_INDEX && m_iCurrentRow == iEmptyRow) {
|
|
if (m_psv->CanEdit()) {
|
|
BOOL bWasModified = WasModified();
|
|
|
|
sc = CreateNewQualifier(sName);
|
|
if (FAILED(sc)) {
|
|
ClearRow(iEmptyRow, TRUE);
|
|
RefreshCellEditor();
|
|
SyncCellEditor();
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
StandardQualifierFixer();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//***********************************************************
|
|
// CAttribGrid::LoadAttributes
|
|
//
|
|
// Load the attributes into the grid.
|
|
//
|
|
// Parameters:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// Nothing.
|
|
//
|
|
//***********************************************************
|
|
SCODE CAttribGrid::LoadAttributes()
|
|
{
|
|
m_bHasEmptyRow = FALSE;
|
|
|
|
VALIDATE_ATTRIBGRID(this);
|
|
|
|
ASSERT(m_pqs != NULL);
|
|
|
|
|
|
if (m_pqs == NULL) {
|
|
return E_FAIL;
|
|
}
|
|
|
|
SCODE sc;
|
|
|
|
CMosNameArray aAttribNames;
|
|
sc = aAttribNames.LoadAttribNames(m_pqs);
|
|
if (FAILED(sc)) {
|
|
return sc;
|
|
}
|
|
|
|
ClearRows();
|
|
|
|
BOOL bEditValueOnly = !m_psv->CanEdit();
|
|
|
|
CGridCell* pgcName;
|
|
CGridCell* pgcType;
|
|
CGridCell* pgcValue;
|
|
CGridCell* pgc;
|
|
|
|
COleVariant varValue;
|
|
LPTSTR pszMessage = m_psv->MessageBuffer();
|
|
CString sName;
|
|
COleVariant varFlag;
|
|
varFlag.ChangeType(VT_BOOL);
|
|
|
|
long nAttribNames = aAttribNames.GetSize();
|
|
BOOL bDidWarnAboutInvalidValue = FALSE;
|
|
|
|
for (long lAttribIndex = 0; lAttribIndex < nAttribNames; ++lAttribIndex) {
|
|
BSTR bstrName = aAttribNames[lAttribIndex];
|
|
|
|
|
|
// Create a an empty row in the grid.
|
|
int iRow = AddRow();
|
|
CGridRow* pRow = &GetRowAt(lAttribIndex);
|
|
pgcName = &GetAt(iRow, ICOL_QUAL_NAME);
|
|
pgcType = &GetAt(iRow, ICOL_QUAL_TYPE);
|
|
pgcValue = &GetAt(iRow, ICOL_QUAL_VALUE);
|
|
|
|
// Set the value of the grid cell to the property name
|
|
sc = pgcName->SetValue(CELLTYPE_NAME, bstrName, CIM_STRING);
|
|
if (FAILED(sc)) {
|
|
if (!bDidWarnAboutInvalidValue) {
|
|
bDidWarnAboutInvalidValue = TRUE;
|
|
HmmvErrorMsg(IDS_ERR_INVALID_CELL_VALUE, sc, FALSE, NULL, _T(__FILE__), __LINE__);
|
|
}
|
|
}
|
|
|
|
varValue.Clear();
|
|
|
|
LONG lFlavor;
|
|
sc = m_pqs->Get(bstrName, 0, &varValue, &lFlavor);
|
|
if (SUCCEEDED(sc)) {
|
|
pRow->SetFlavor(lFlavor);
|
|
}
|
|
else {
|
|
pRow->SetFlavor(0);
|
|
lFlavor = 0;
|
|
}
|
|
|
|
|
|
CString sQualName;
|
|
sQualName = bstrName;
|
|
CellType celltype;
|
|
BOOL bIsCimtype = (sQualName.CompareNoCase(_T("CIMTYPE"))==0);
|
|
if (bIsCimtype) {
|
|
celltype = CELLTYPE_CIMTYPE_SCALAR;
|
|
}
|
|
else {
|
|
celltype = CELLTYPE_VARIANT;
|
|
}
|
|
|
|
CIMTYPE cimtype = CimtypeFromVt(varValue.vt);
|
|
|
|
sc = pgcValue->SetValue(celltype, varValue, cimtype);
|
|
if (FAILED(sc)) {
|
|
sName = bstrName;
|
|
_stprintf(pszMessage, _T("Qualifier \"%s\" contains a value that does not match its type. Using <empty> value instead."), (LPCTSTR) sName);
|
|
HmmvErrorMsgStr((LPCTSTR) pszMessage, sc, FALSE, NULL, _T(__FILE__), __LINE__);
|
|
pgcValue->SetToNull();
|
|
}
|
|
|
|
// For qualifiers "Values" or "ValueMap", we don't want to show row numbers on arrays
|
|
if(sQualName.CompareNoCase(_T("values")) == 0 || sQualName.CompareNoCase(_T("valuemap")) == 0)
|
|
pgcValue->SetShowArrayRowNumbers(FALSE);
|
|
|
|
CStdQualTable* ptable = FindStdQual(sQualName);
|
|
|
|
|
|
if (ptable) {
|
|
if (ptable->dwFieldsReadonly & FIELD_VALUE) {
|
|
pgcValue->SetFlags(CELLFLAG_READONLY, CELLFLAG_READONLY);
|
|
}
|
|
}
|
|
if ((ptable!=NULL) || bIsCimtype) {
|
|
pgcType->SetFlags(CELLFLAG_READONLY, CELLFLAG_READONLY);
|
|
}
|
|
|
|
|
|
|
|
CGridCell* pgcPropagateToInstance;
|
|
CGridCell* pgcPropagateToClass;
|
|
CGridCell* pgcOverrideable;
|
|
CGridCell* pgcOrigin;
|
|
CGridCell* pgcAmended;
|
|
pgcPropagateToInstance = &GetAt(iRow, ICOL_QUAL_PROPAGATE_TO_INSTANCE_FLAG);
|
|
BOOL bCanPropagateToInstance = lFlavor & WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE;
|
|
varFlag.boolVal = bCanPropagateToInstance?VARIANT_TRUE:VARIANT_FALSE;
|
|
pgcPropagateToInstance->SetValue(CELLTYPE_CHECKBOX, varFlag, CIM_BOOLEAN);
|
|
|
|
pgcPropagateToClass = &GetAt(iRow, ICOL_QUAL_PROPAGATE_TO_CLASS_FLAG);
|
|
BOOL bCanPropagateToClass = lFlavor & WBEM_FLAVOR_FLAG_PROPAGATE_TO_DERIVED_CLASS;
|
|
varFlag.boolVal = bCanPropagateToClass?VARIANT_TRUE:VARIANT_FALSE;
|
|
pgcPropagateToClass->SetValue(CELLTYPE_CHECKBOX, varFlag, CIM_BOOLEAN);
|
|
|
|
pgcOverrideable = &GetAt(iRow, ICOL_QUAL_OVERRIDABLE_FLAG);
|
|
BOOL bIsOverrideable = !(lFlavor & WBEM_FLAVOR_NOT_OVERRIDABLE);
|
|
varFlag.boolVal = bIsOverrideable?VARIANT_TRUE:VARIANT_FALSE;
|
|
pgcOverrideable->SetValue(CELLTYPE_CHECKBOX, varFlag, CIM_BOOLEAN);
|
|
|
|
pgcAmended = &GetAt(iRow, ICOL_QUAL_AMENDED_FLAG);
|
|
BOOL bIsAmended = lFlavor & WBEM_FLAVOR_AMENDED;
|
|
varFlag.boolVal = bIsAmended?VARIANT_TRUE:VARIANT_FALSE;
|
|
pgcAmended->SetValue(CELLTYPE_CHECKBOX, varFlag, CIM_BOOLEAN);
|
|
pgcAmended->SetFlags(CELLFLAG_READONLY, CELLFLAG_READONLY);
|
|
|
|
pgcOrigin = &GetAt(iRow, ICOL_QUAL_ORIGIN);
|
|
long lOrigin = lFlavor & WBEM_FLAVOR_MASK_ORIGIN;
|
|
CString sOrigin;
|
|
switch(lOrigin) {
|
|
case WBEM_FLAVOR_ORIGIN_LOCAL:
|
|
sOrigin = "local";
|
|
break;
|
|
case WBEM_FLAVOR_ORIGIN_PROPAGATED:
|
|
sOrigin = "propagated";
|
|
break;
|
|
case WBEM_FLAVOR_ORIGIN_SYSTEM:
|
|
sOrigin = "system";
|
|
break;
|
|
default:
|
|
sOrigin = "invalid";
|
|
break;
|
|
}
|
|
pgcOrigin->SetValue(CELLTYPE_VARIANT, sOrigin, CIM_STRING);
|
|
pgcOrigin->SetFlags(CELLFLAG_READONLY, CELLFLAG_READONLY);
|
|
|
|
|
|
|
|
pgcType->SetValueForQualifierType(varValue.vt);
|
|
|
|
// Finally get the value of the type name and set the grid cell
|
|
pgcType->SetBuddy(ICOL_QUAL_VALUE);
|
|
|
|
|
|
if (bEditValueOnly) {
|
|
pgcName->SetFlags(CELLFLAG_READONLY, CELLFLAG_READONLY);
|
|
pgcType->SetFlags(CELLFLAG_READONLY, CELLFLAG_READONLY);
|
|
}
|
|
SysFreeString(bstrName);
|
|
|
|
pgcName->SetTagValue(CELL_TAG_EXISTS_IN_DATABASE);
|
|
|
|
|
|
SetRowModified(lAttribIndex, FALSE);
|
|
if (m_bReadonly || (lFlavor & WBEM_FLAVOR_ORIGIN_PROPAGATED)) {
|
|
CGridRow& row = GetRowAt(iRow);
|
|
row.SetReadonlyEx(TRUE);
|
|
if (!m_bReadonly) {
|
|
// Control comes here for propagate qualifiers. For propagated qualifiers
|
|
// the value file may be writeable.
|
|
if ((ptable == NULL) || (ptable && ptable->dwFieldsReadonly & FIELD_VALUE)) {
|
|
// Ordinary qualifiers and standard qualifiers without the read-only attribute
|
|
// can be modified.
|
|
pgcValue->SetFlags(CELLFLAG_READONLY, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
int nRows = GetRows();
|
|
if (m_psv->CanEdit() && !m_bReadonly) {
|
|
// When viewing a class, give the capability
|
|
// Add an empty row at the bottom.
|
|
InsertRowAt(nAttribNames);
|
|
m_bHasEmptyRow = TRUE;
|
|
|
|
pgc = &GetAt(nAttribNames, ICOL_QUAL_PROPAGATE_TO_INSTANCE_FLAG);
|
|
varFlag.boolVal = FALSE;
|
|
pgc->SetValue(CELLTYPE_CHECKBOX, varFlag, CIM_BOOLEAN);
|
|
pgc->SetFlags(CELLFLAG_READONLY, CELLFLAG_READONLY);
|
|
|
|
pgc = &GetAt(nAttribNames, ICOL_QUAL_PROPAGATE_TO_CLASS_FLAG);
|
|
pgc->SetValue(CELLTYPE_CHECKBOX, varFlag, CIM_BOOLEAN);
|
|
pgc->SetFlags(CELLFLAG_READONLY, CELLFLAG_READONLY);
|
|
|
|
pgc = &GetAt(nAttribNames, ICOL_QUAL_OVERRIDABLE_FLAG);
|
|
pgc->SetValue(CELLTYPE_CHECKBOX, varFlag, CIM_BOOLEAN);
|
|
pgc->SetFlags(CELLFLAG_READONLY, CELLFLAG_READONLY);
|
|
|
|
pgc = &GetAt(nAttribNames, ICOL_QUAL_AMENDED_FLAG);
|
|
pgc->SetValue(CELLTYPE_CHECKBOX, varFlag, CIM_BOOLEAN);
|
|
pgc->SetFlags(CELLFLAG_READONLY, CELLFLAG_READONLY);
|
|
|
|
pgc = &GetAt(nAttribNames, ICOL_QUAL_ORIGIN);
|
|
pgc->SetFlags(CELLFLAG_READONLY, CELLFLAG_READONLY);
|
|
|
|
}
|
|
|
|
if (nRows > 0) {
|
|
int iLastRow = LastRowContainingData();
|
|
SortGrid(0, iLastRow, ICOL_QUAL_NAME);
|
|
}
|
|
|
|
if (m_hWnd != NULL) {
|
|
SetModified(FALSE);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//****************************************************************
|
|
// CAttribGrid::FindStdQual
|
|
//
|
|
// Find the specified standard qualifier.
|
|
//
|
|
// Parameters:
|
|
// [in] CString& sName
|
|
// The name of the standard qualifier to search for.
|
|
//
|
|
// Returns:
|
|
// CStdQualTable*
|
|
// A pointer to an entry in the standard qualifier table
|
|
// if the standard qualifier is found. NULL if the standard
|
|
// qualifier is not found.
|
|
//
|
|
//****************************************************************
|
|
CStdQualTable* CAttribGrid::FindStdQual(CString& sName)
|
|
{
|
|
CStdQualTable* ptable;
|
|
switch(m_iGridType) {
|
|
case QUALGRID_PROPERTY:
|
|
ptable = aStdQualProps;
|
|
break;
|
|
case QUALGRID_METHODS:
|
|
ptable = aStdQualMethods;
|
|
break;
|
|
case QUALGRID_INSTANCE:
|
|
ptable = aStdQualInstance;
|
|
break;
|
|
case QUALGRID_CLASS:
|
|
ptable = aStdQualClass;
|
|
break;
|
|
case QUALGRID_METHOD_PARAM:
|
|
ptable = aStdQualMethodParm;
|
|
break;
|
|
default:
|
|
ASSERT(FALSE);
|
|
return NULL;
|
|
}
|
|
|
|
while (ptable->stdqual != STDQUAL_END_OF_TABLE) {
|
|
if (sName.CompareNoCase(ptable->pszStdQual) == 0) {
|
|
return ptable;
|
|
}
|
|
++ptable;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void CAttribGrid::StandardQualifierFixer()
|
|
{
|
|
CGridCell& gcName = GetAt(m_iCurrentRow, ICOL_QUAL_NAME);
|
|
CGridCell& gcType = GetAt(m_iCurrentRow, ICOL_QUAL_TYPE);
|
|
CGridCell& gcValue = GetAt(m_iCurrentRow, ICOL_QUAL_VALUE);
|
|
CGridCell& gcPropagateToInstance = GetAt(m_iCurrentRow, ICOL_QUAL_PROPAGATE_TO_INSTANCE_FLAG);
|
|
CGridCell& gcPropagateToClass = GetAt(m_iCurrentRow, ICOL_QUAL_PROPAGATE_TO_CLASS_FLAG);
|
|
CGridCell& gcOverrideable = GetAt(m_iCurrentRow, ICOL_QUAL_OVERRIDABLE_FLAG);
|
|
CGridCell& gcAmended = GetAt(m_iCurrentRow, ICOL_QUAL_AMENDED_FLAG);
|
|
|
|
|
|
CString sName;
|
|
CIMTYPE cimtypeName;
|
|
gcName.GetValue(sName, cimtypeName);
|
|
|
|
DWORD_PTR dwTag = gcName.GetTagValue();
|
|
|
|
CStdQualTable* pstdqual = FindStdQual(sName);
|
|
CString sValue;
|
|
COleVariant var;
|
|
if (pstdqual != NULL) {
|
|
// This row contains a standard qualifier.
|
|
VARTYPE vtValue = gcValue.GetVariantType();
|
|
switch(pstdqual->vt) {
|
|
case VT_BSTR:
|
|
if (vtValue != VT_BSTR) {
|
|
|
|
gcType.SetValueForQualifierType(VT_BSTR);
|
|
gcValue.ChangeVariantType(VT_BSTR);
|
|
var.ChangeType(VT_BSTR);
|
|
var = "";
|
|
gcValue.SetValue(CELLTYPE_VARIANT, var, CIM_STRING);
|
|
}
|
|
break;
|
|
case VT_BOOL:
|
|
if (vtValue != VT_BOOL) {
|
|
gcType.SetValueForQualifierType(VT_BOOL);
|
|
var.ChangeType(VT_BOOL);
|
|
var.boolVal = TRUE;
|
|
gcValue.SetValue(CELLTYPE_VARIANT, var, CIM_BOOLEAN);
|
|
}
|
|
break;
|
|
case VT_I4:
|
|
if (vtValue != VT_I4) {
|
|
gcType.SetValueForQualifierType(VT_I4);
|
|
var.ChangeType(VT_I4);
|
|
var.lVal = 0;
|
|
gcValue.SetValue(CELLTYPE_VARIANT, var, CIM_SINT32);
|
|
}
|
|
break;
|
|
case VT_R8:
|
|
if (vtValue != VT_I4) {
|
|
gcType.SetValueForQualifierType(VT_R8);
|
|
var.ChangeType(VT_R8);
|
|
var.dblVal = 0.0;
|
|
gcValue.SetValue(CELLTYPE_VARIANT, var, CIM_REAL64);
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
gcType.SetFlags(CELLFLAG_READONLY, CELLFLAG_READONLY);
|
|
if (pstdqual->dwFieldsReadonly & FIELD_VALUE) {
|
|
gcValue.SetFlags(CELLFLAG_READONLY, CELLFLAG_READONLY);
|
|
}
|
|
else {
|
|
gcValue.SetFlags(CELLFLAG_READONLY, 0);
|
|
}
|
|
|
|
COleVariant varFlag;
|
|
varFlag.ChangeType(VT_BOOL);
|
|
|
|
// Handle the overrideable flag
|
|
if (pstdqual->dwFieldsSet & FIELD_OFLAG) {
|
|
varFlag.boolVal = TRUE;
|
|
}
|
|
else {
|
|
varFlag.boolVal = FALSE;
|
|
}
|
|
gcOverrideable.SetValue(CELLTYPE_CHECKBOX, varFlag, CIM_BOOLEAN);
|
|
|
|
if (pstdqual->dwFieldsReadonly & FIELD_OFLAG) {
|
|
gcOverrideable.SetFlags(CELLFLAG_READONLY, CELLFLAG_READONLY);
|
|
}
|
|
else {
|
|
gcOverrideable.SetFlags(CELLFLAG_READONLY, 0);
|
|
}
|
|
|
|
// Handle the propagate to derived class flag
|
|
if (pstdqual->dwFieldsSet & FIELD_CFLAG) {
|
|
varFlag.boolVal = TRUE;
|
|
}
|
|
else {
|
|
varFlag.boolVal = FALSE;
|
|
}
|
|
gcPropagateToClass.SetValue(CELLTYPE_CHECKBOX, varFlag, CIM_BOOLEAN);
|
|
|
|
if (pstdqual->dwFieldsReadonly & FIELD_CFLAG) {
|
|
gcPropagateToClass.SetFlags(CELLFLAG_READONLY, CELLFLAG_READONLY);
|
|
}
|
|
else {
|
|
gcPropagateToClass.SetFlags(CELLFLAG_READONLY, 0);
|
|
}
|
|
|
|
|
|
// Handle the propagate to instance flag
|
|
if (pstdqual->dwFieldsSet & FIELD_IFLAG) {
|
|
varFlag.boolVal = TRUE;
|
|
}
|
|
else {
|
|
varFlag.boolVal = FALSE;
|
|
}
|
|
gcPropagateToInstance.SetValue(CELLTYPE_CHECKBOX, varFlag, CIM_BOOLEAN);
|
|
|
|
if (pstdqual->dwFieldsReadonly & FIELD_IFLAG) {
|
|
gcPropagateToInstance.SetFlags(CELLFLAG_READONLY, CELLFLAG_READONLY);
|
|
}
|
|
else {
|
|
gcPropagateToInstance.SetFlags(CELLFLAG_READONLY, 0);
|
|
}
|
|
|
|
|
|
// Handle the amended flag
|
|
if (pstdqual->dwFieldsSet & FIELD_AFLAG) {
|
|
varFlag.boolVal = TRUE;
|
|
}
|
|
else {
|
|
varFlag.boolVal = FALSE;
|
|
}
|
|
gcPropagateToInstance.SetValue(CELLTYPE_CHECKBOX, varFlag, CIM_BOOLEAN);
|
|
|
|
if (pstdqual->dwFieldsReadonly & FIELD_AFLAG) {
|
|
gcPropagateToInstance.SetFlags(CELLFLAG_READONLY, CELLFLAG_READONLY);
|
|
}
|
|
else {
|
|
gcPropagateToInstance.SetFlags(CELLFLAG_READONLY, 0);
|
|
}
|
|
|
|
|
|
RedrawCell(m_iCurrentRow, ICOL_QUAL_TYPE);
|
|
RedrawCell(m_iCurrentRow, ICOL_QUAL_PROPAGATE_TO_INSTANCE_FLAG);
|
|
RedrawCell(m_iCurrentRow, ICOL_QUAL_PROPAGATE_TO_CLASS_FLAG);
|
|
RedrawCell(m_iCurrentRow, ICOL_QUAL_OVERRIDABLE_FLAG);
|
|
RedrawCell(m_iCurrentRow, ICOL_QUAL_AMENDED_FLAG);
|
|
RedrawCell(m_iCurrentRow, ICOL_QUAL_VALUE);
|
|
|
|
}
|
|
else {
|
|
// This row used to have a standard qualifier, but no
|
|
// longer does. Allow editing of the type and value when
|
|
// appropriate.
|
|
if (m_psv->CanEdit()) {
|
|
gcType.SetFlags(CELLFLAG_READONLY, 0);
|
|
}
|
|
else {
|
|
gcType.SetFlags(CELLFLAG_READONLY, CELLFLAG_READONLY);
|
|
}
|
|
gcValue.SetFlags(CELLFLAG_READONLY, 0);
|
|
}
|
|
}
|
|
|
|
//****************************************************************
|
|
// CAttribGrid::QualifierNameChanged.
|
|
//
|
|
// Check to see if the name of the selected qualifier has been changed.
|
|
//
|
|
// Parameters:
|
|
// int iRow
|
|
// The index of the row to check.
|
|
//
|
|
// Returns:
|
|
// BOOL
|
|
// TRUE if the currently selected qualifier needs to be renamed.
|
|
//
|
|
//*****************************************************************
|
|
BOOL CAttribGrid::QualifierNameChanged(int iRow)
|
|
{
|
|
VALIDATE_ATTRIBGRID(this);
|
|
|
|
// If no property is selected, it doesn't make sense to rename it.
|
|
if (m_iCurrentRow == NULL_INDEX) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (iRow != m_iCurrentRow) {
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
CGridCell* pgcName = &GetAt(m_iCurrentRow, ICOL_QUAL_NAME);
|
|
|
|
|
|
// If the name has been modified and it is not the same as its
|
|
// initial value when the focus was changed to the name cell,
|
|
// then it needs to be renamed.
|
|
if (pgcName->GetModified()) {
|
|
COleVariant varName;
|
|
CIMTYPE cimtypeName;
|
|
pgcName->GetValue(varName, cimtypeName);
|
|
ASSERT(varName.vt == VT_BSTR);
|
|
if (!IsEqual(varName.bstrVal, m_varCurrentName.bstrVal)) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
//**********************************************************************
|
|
// CAttribGrid::Serialize
|
|
//
|
|
// Write the current state to the HMOM database.
|
|
//
|
|
// Parameters:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// SCODE
|
|
// S_OK if successful, otherwise an error code.
|
|
//
|
|
//*********************************************************************
|
|
SCODE CAttribGrid::Serialize()
|
|
{
|
|
SCODE sc;
|
|
sc = SyncCellEditor();
|
|
if (FAILED(sc)) {
|
|
HmmvErrorMsg(IDS_ERR_INVALID_CELL_VALUE, sc, FALSE, NULL, _T(__FILE__), __LINE__);
|
|
return E_FAIL;
|
|
}
|
|
|
|
CGridSync sync(this);
|
|
if (FAILED(sync.m_sc)) {
|
|
HmmvErrorMsg(IDS_ERR_INVALID_CELL_VALUE, sync.m_sc, FALSE, NULL, _T(__FILE__), __LINE__);
|
|
return E_FAIL;
|
|
}
|
|
|
|
|
|
BeginSerialize();
|
|
if (m_pqs == NULL) {
|
|
EndSerialize();
|
|
return S_OK;
|
|
}
|
|
|
|
BOOL bPutFailed = FALSE;
|
|
|
|
int nRows = GetRows();
|
|
if (m_psv->CanEdit()) {
|
|
// When in studio mode there is an empty row at the bottom.
|
|
// Adjust the row count so that the empty row is not put to the database.
|
|
--nRows;
|
|
}
|
|
|
|
int iRow;
|
|
for (iRow=0; iRow < nRows; ++iRow) {
|
|
sc = PutQualifier(iRow);
|
|
if (FAILED(sc)) {
|
|
bPutFailed = TRUE;
|
|
}
|
|
}
|
|
|
|
|
|
if (bPutFailed) {
|
|
EndSerialize();
|
|
return E_FAIL;
|
|
}
|
|
|
|
|
|
for (iRow=0; iRow < nRows; ++iRow) {
|
|
SetRowModified(iRow, FALSE);
|
|
}
|
|
RedrawWindow();
|
|
RefreshCellEditor();
|
|
|
|
|
|
SetModified(FALSE);
|
|
EndSerialize();
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
//********************************************************************
|
|
// CAttribGrid::PutQualifier
|
|
//
|
|
// Put the qualifier in the specified row to the database.
|
|
//
|
|
// Parameters:
|
|
// int iRow
|
|
// The index of the row containing the property.
|
|
//
|
|
// Returns:
|
|
// SCODE
|
|
// S_OK if successful, otherwise a failure code.
|
|
//
|
|
//********************************************************************
|
|
SCODE CAttribGrid::PutQualifier(int iRow)
|
|
{
|
|
VALIDATE_ATTRIBGRID(this);
|
|
|
|
int iEmptyRow = IndexOfEmptyRow();
|
|
if (iRow == iEmptyRow) {
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
CGridSync sync(this);
|
|
CGridRow& row = GetRowAt(iRow);
|
|
|
|
|
|
SCODE sc = S_OK;
|
|
CGridCell* pgcName = &GetAt(iRow, ICOL_QUAL_NAME);
|
|
CGridCell* pgcType = &GetAt(iRow, ICOL_QUAL_TYPE);
|
|
CGridCell* pgcValue = &GetAt(iRow, ICOL_QUAL_VALUE);
|
|
|
|
|
|
long lFlavor = 0;
|
|
COleVariant var;
|
|
CIMTYPE cimtype;
|
|
CGridCell* pgc;
|
|
|
|
pgc = &GetAt(iRow, ICOL_QUAL_PROPAGATE_TO_INSTANCE_FLAG);
|
|
var.Clear();
|
|
pgc->GetValue(var, cimtype);
|
|
ASSERT(var.vt == VT_BOOL);
|
|
if (var.boolVal) {
|
|
lFlavor |= WBEM_FLAVOR_FLAG_PROPAGATE_TO_INSTANCE;
|
|
}
|
|
|
|
pgc = &GetAt(iRow, ICOL_QUAL_PROPAGATE_TO_CLASS_FLAG);
|
|
var.Clear();
|
|
pgc->GetValue(var, cimtype);
|
|
ASSERT(var.vt == VT_BOOL);
|
|
if (var.boolVal) {
|
|
lFlavor |= WBEM_FLAVOR_FLAG_PROPAGATE_TO_DERIVED_CLASS;
|
|
}
|
|
|
|
|
|
pgc = &GetAt(iRow, ICOL_QUAL_OVERRIDABLE_FLAG);
|
|
var.Clear();
|
|
pgc->GetValue(var, cimtype);
|
|
ASSERT(var.vt == VT_BOOL);
|
|
if (!var.boolVal) {
|
|
lFlavor |= WBEM_FLAVOR_NOT_OVERRIDABLE;
|
|
}
|
|
|
|
pgc = &GetAt(iRow, ICOL_QUAL_AMENDED_FLAG);
|
|
var.Clear();
|
|
pgc->GetValue(var, cimtype);
|
|
ASSERT(var.vt == VT_BOOL);
|
|
if (var.boolVal) {
|
|
lFlavor |= WBEM_FLAVOR_AMENDED;
|
|
}
|
|
|
|
|
|
CString sFormat;
|
|
COleVariant varName;
|
|
CIMTYPE cimtypeName;
|
|
pgcName->GetValue(varName, cimtypeName);
|
|
ASSERT(cimtypeName == CIM_STRING);
|
|
|
|
|
|
if (IsEmptyString(varName.bstrVal)) {
|
|
sFormat.LoadString(IDS_ERR_EMPTY_QUALIFIER_NAME);
|
|
HmmvErrorMsgStr((LPCTSTR) sFormat, S_OK, FALSE, NULL, _T(__FILE__), __LINE__);
|
|
SelectCell(iRow, ICOL_QUAL_NAME);
|
|
return E_FAIL;
|
|
}
|
|
|
|
COleVariant varValue;
|
|
CIMTYPE cimtypeValue;
|
|
pgcValue->GetValue(varValue, cimtypeValue);
|
|
|
|
LPTSTR pszMessage = m_psv->MessageBuffer();
|
|
CString sName;
|
|
|
|
CString sCurrentName;
|
|
|
|
BOOL bNeedsRename = (pgcName->GetTagValue() & CELL_TAG_NEEDS_RENAME)!=0;
|
|
BOOL bNameChanged = QualifierNameChanged(iRow);
|
|
|
|
if (bNameChanged) {
|
|
StandardQualifierFixer();
|
|
}
|
|
|
|
if (bNeedsRename || bNameChanged) {
|
|
// The name was changed, so rename the property.
|
|
ASSERT(iRow != NULL_INDEX && iRow==m_iCurrentRow);
|
|
|
|
// Rename step 1: First verify that there is currently no property with
|
|
// the new name.
|
|
COleVariant varTemp;
|
|
|
|
sc = m_pqs->Get(varName.bstrVal, 0, &varTemp, &lFlavor);
|
|
if (SUCCEEDED(sc)) {
|
|
// Duplicate qualifier name.
|
|
sFormat.LoadString(IDS_ERR_DUPLICATE_QUALIFIER_NAME);
|
|
sName = varName.bstrVal;
|
|
_stprintf(pszMessage, (LPCTSTR) sFormat, (LPCTSTR) sName);
|
|
HmmvErrorMsgStr(pszMessage, S_OK, FALSE, NULL, _T(__FILE__), __LINE__);
|
|
SelectCell(iRow, ICOL_QUAL_NAME);
|
|
return E_FAIL;
|
|
}
|
|
|
|
// Rename step 2: Create a qualifier with the new name.
|
|
sc = m_pqs->Put(varName.bstrVal, &varValue, lFlavor);
|
|
if (FAILED(sc)) {
|
|
sFormat.LoadString(IDS_ERR_RENAME_QUALIFIER_FAILED);
|
|
sName = varName.bstrVal;
|
|
|
|
|
|
CString sNamePrev;
|
|
sNamePrev = m_varCurrentName.bstrVal;
|
|
_stprintf(pszMessage, (LPCTSTR) sFormat, (LPCTSTR) sNamePrev, (LPCTSTR) sName);
|
|
HmmvErrorMsgStr(pszMessage, S_OK, FALSE, NULL, _T(__FILE__), __LINE__);
|
|
|
|
// Restore the qualifier's name to its original value so that the user
|
|
// doesn't get stuck in a "fix the name" mode forever.
|
|
pgcName->SetValue(CELLTYPE_NAME, m_varCurrentName, CIM_STRING);
|
|
pgcName->SetTagValue(pgcName->GetTagValue() & ~CELL_TAG_NEEDS_RENAME);
|
|
pgcName->SetModified(FALSE);
|
|
RefreshCellEditor();
|
|
SelectCell(iRow, ICOL_QUAL_NAME);
|
|
return sc;
|
|
}
|
|
|
|
|
|
DWORD_PTR dwTag = pgcName->GetTagValue();
|
|
BOOL bWasInDatabase = (dwTag & CELL_TAG_EXISTS_IN_DATABASE)!=0;
|
|
|
|
if (bWasInDatabase) {
|
|
// Step 3: Delete the old qualifier
|
|
sCurrentName = m_varCurrentName.bstrVal;
|
|
if (!sCurrentName.IsEmpty()) {
|
|
sc = m_pqs->Delete(m_varCurrentName.bstrVal);
|
|
if (FAILED(sc)) {
|
|
// Failed to delete the old qualifier.
|
|
m_pqs->Delete(varName.bstrVal);
|
|
pgcName->SetValue(CELLTYPE_NAME, m_varCurrentName, CIM_STRING);
|
|
pgcName->SetTagValue(pgcName->GetTagValue() & ~CELL_TAG_NEEDS_RENAME);
|
|
pgcName->SetModified(FALSE);
|
|
RefreshCellEditor();
|
|
|
|
// Report the error
|
|
|
|
sFormat.LoadString(IDS_ERR_RENAME_QUALIFIER_FAILED);
|
|
sName = varName.bstrVal;
|
|
_stprintf(pszMessage, (LPCTSTR) sFormat, (LPCTSTR) sCurrentName, (LPCTSTR) sName);
|
|
HmmvErrorMsgStr(pszMessage, S_OK, FALSE, NULL, _T(__FILE__), __LINE__);
|
|
return sc;
|
|
}
|
|
}
|
|
}
|
|
|
|
m_varCurrentName = varName;
|
|
pgcName->SetTagValue(CELL_TAG_EXISTS_IN_DATABASE);
|
|
lFlavor = row.GetFlavor();
|
|
lFlavor &= ~WBEM_FLAVOR_ORIGIN_PROPAGATED;
|
|
row.SetFlavor(lFlavor);
|
|
}
|
|
else if (RowWasModified(iRow)) {
|
|
|
|
|
|
// Control comes here the qualifier's name did not change.
|
|
sc = m_pqs->Put(varName.bstrVal, &varValue, lFlavor);
|
|
|
|
if (SUCCEEDED(sc)) {
|
|
pgcName->SetTagValue(CELL_TAG_EXISTS_IN_DATABASE);
|
|
}
|
|
else {
|
|
|
|
sCurrentName = m_varCurrentName.bstrVal;
|
|
sFormat.LoadString(IDS_ERR_PUT_QUALIFIER_FAILED);
|
|
sName = varName.bstrVal;
|
|
_stprintf(pszMessage, (LPCTSTR) sFormat, (LPCTSTR) sName);
|
|
HmmvErrorMsgStr(pszMessage, sc, FALSE, NULL, _T(__FILE__), __LINE__);
|
|
return sc;
|
|
}
|
|
}
|
|
|
|
return sc;
|
|
}
|
|
|
|
|
|
|
|
//********************************************************************
|
|
// CAttribGrid::OnCellFocusChange
|
|
//
|
|
// This virtual method is called by the CGrid base class to notify
|
|
// derived classes when the focus is about to change from one cell
|
|
// to another.
|
|
//
|
|
// Paramters:
|
|
// [in] int iRow
|
|
// The row index of the cell.
|
|
//
|
|
// [in] int iCol
|
|
// The column index of the cell. If iCol is NULL_INDEX and
|
|
// iRow is valid, then an entire row is being selected.
|
|
//
|
|
// [in] int iNextRow
|
|
// The next row that will be selected. This parameter is provided
|
|
// as a hint and is valid only if bGotFocus is FALSE.
|
|
//
|
|
// [in] int iNextCol
|
|
// The column index of the next cell that will get the focus when the
|
|
// current cell is loosing focus. This parameter is provided as a hint and
|
|
// is valid only if bGotFocus is FALSE.
|
|
//
|
|
// [in] BOOL bGotFocus
|
|
// TRUE if the cell is getting the focus, FALSE if the cell is
|
|
// about to loose the focus.
|
|
//
|
|
// Returns:
|
|
// TRUE if it is OK for the CGrid class to complete the focus change
|
|
// FALSE if the focus change should be aborted.
|
|
//
|
|
//*********************************************************************
|
|
BOOL CAttribGrid::OnCellFocusChange(int iRow, int iCol, int iNextRow, int iNextCol, BOOL bGotFocus)
|
|
{
|
|
SCODE sc;
|
|
if (!bGotFocus) {
|
|
// The current cell is losing focus, so put the row to the
|
|
// database.
|
|
int iEmptyRow = IndexOfEmptyRow();
|
|
if (iEmptyRow != NULL_INDEX && iRow==iEmptyRow) {
|
|
return TRUE;
|
|
}
|
|
sc = SyncCellEditor();
|
|
if (FAILED(sc)) {
|
|
HmmvErrorMsg(IDS_ERR_INVALID_CELL_VALUE, sc, FALSE, NULL, _T(__FILE__), __LINE__);
|
|
return FALSE;
|
|
}
|
|
|
|
if (m_iCurrentRow != NULL_INDEX) {
|
|
|
|
|
|
CGridCell& gcName = GetAt(m_iCurrentRow, ICOL_QUAL_NAME);
|
|
CGridCell& gcValue = GetAt(m_iCurrentRow, ICOL_QUAL_VALUE);
|
|
|
|
CString sName;
|
|
CIMTYPE cimtypeName;
|
|
gcName.GetValue(sName, cimtypeName);
|
|
if(sName.CompareNoCase(_T("values")) == 0 || sName.CompareNoCase(_T("valuemap")) == 0)
|
|
gcValue.SetShowArrayRowNumbers(FALSE);
|
|
else
|
|
gcValue.SetShowArrayRowNumbers(TRUE);
|
|
|
|
|
|
|
|
if (QualifierNameChanged(iRow)) {
|
|
CGridCell& gcName = GetAt(m_iCurrentRow, ICOL_QUAL_NAME);
|
|
gcName.SetTagValue(gcName.GetTagValue() | CELL_TAG_NEEDS_RENAME);
|
|
StandardQualifierFixer();
|
|
}
|
|
}
|
|
|
|
// If the cell selection will move to a different row, then the currently selected
|
|
// qualifier needs to be put to the database.
|
|
if (iRow != iNextRow) {
|
|
sc = Sync();
|
|
if (FAILED(sc)) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
m_iCurrentCol = NULL_INDEX;
|
|
}
|
|
else {
|
|
|
|
if (iRow != m_iCurrentRow) {
|
|
if (iRow == NULL_INDEX) {
|
|
m_varCurrentName = L"";
|
|
}
|
|
else {
|
|
CGridCell* pgcName = &GetAt(iRow, ICOL_QUAL_NAME);
|
|
CIMTYPE cimtype;
|
|
pgcName->GetValue(m_varCurrentName, cimtype);
|
|
ASSERT(cimtype == CIM_STRING);
|
|
}
|
|
|
|
|
|
m_iCurrentRow = iRow;
|
|
}
|
|
m_iCurrentCol = iCol;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//*************************************************************
|
|
// CAttribGrid::CreateNewQualifier
|
|
//
|
|
// Create a new qualifier by filling the last row in the grid
|
|
// with the default values and inserting a new "empty" row at
|
|
// the bottom.
|
|
//
|
|
// Parameters:
|
|
// [in] LPCTSTR pszName
|
|
// NULL to generate a default name for the qualifier, otherwise
|
|
// the qualifier name.
|
|
//
|
|
// Returns:
|
|
// SCODE
|
|
// A failure if the qualifier could not be created (because
|
|
// of a duplicate qualifier name for example).
|
|
//
|
|
//*************************************************************
|
|
SCODE CAttribGrid::CreateNewQualifier(LPCTSTR pszName)
|
|
{
|
|
|
|
VALIDATE_ATTRIBGRID(this);
|
|
int iRow = GetRows() - 1;
|
|
|
|
SCODE sc;
|
|
// We are editing the new row, what should we do?
|
|
// If the user clicked column zero, change the type
|
|
// of the other cells in the row and allow the user to
|
|
// enter the name.
|
|
|
|
// If the user clicked any other column, then make up a
|
|
// name.
|
|
|
|
COleVariant varTempName;
|
|
COleVariant varTempValue;
|
|
LONG lFlavor;
|
|
CString sSynthesizedName;
|
|
LPTSTR pszMessage = m_psv->MessageBuffer();
|
|
|
|
if (pszName == NULL) {
|
|
TCHAR szBuffer[32];
|
|
while(TRUE) {
|
|
sSynthesizedName.LoadString(IDS_NEW_QUALIFIER_BASE_NAME);
|
|
_stprintf(szBuffer, _T("%05d"), m_lNewQualID);
|
|
++m_lNewQualID;
|
|
sSynthesizedName = sSynthesizedName + szBuffer;
|
|
varTempName = sSynthesizedName;
|
|
|
|
sc = m_pqs->Get(varTempName.bstrVal, 0, &varTempValue, &lFlavor);
|
|
if (FAILED(sc)) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
varTempName = pszName;
|
|
|
|
sc = m_pqs->Get(varTempName.bstrVal, 0, &varTempValue, &lFlavor);
|
|
if (SUCCEEDED(sc)) {
|
|
// Duplicate qualifier name.
|
|
CString sFormat;
|
|
CString sName;
|
|
|
|
sFormat.LoadString(IDS_ERR_DUPLICATE_QUALIFIER_NAME);
|
|
sName = varTempName.bstrVal;
|
|
_stprintf(pszMessage, (LPCTSTR) sFormat, (LPCTSTR) sName);
|
|
HmmvErrorMsgStr(pszMessage, S_OK, FALSE, NULL, _T(__FILE__), __LINE__);
|
|
return E_FAIL;
|
|
}
|
|
|
|
|
|
sSynthesizedName = pszName;
|
|
}
|
|
|
|
|
|
CGridCell* pgcName;
|
|
CGridCell* pgcValue;
|
|
CGridCell* pgcPropagateToInst;
|
|
CGridCell* pgcType;
|
|
|
|
|
|
pgcName = &GetAt(iRow, ICOL_QUAL_NAME);
|
|
pgcValue = &GetAt(iRow, ICOL_QUAL_VALUE);
|
|
pgcType = &GetAt(iRow, ICOL_QUAL_TYPE);
|
|
pgcPropagateToInst = &GetAt(iRow, ICOL_QUAL_PROPAGATE_TO_INSTANCE_FLAG);
|
|
|
|
CGcType type(CELLTYPE_VARIANT, CIM_STRING);
|
|
pgcValue->SetValue(type, _T(""));
|
|
|
|
|
|
|
|
pgcName->SetValue(CELLTYPE_NAME, sSynthesizedName, CIM_STRING);
|
|
pgcName->SetModified(TRUE);
|
|
SetCellModified(iRow, ICOL_QUAL_NAME, TRUE);
|
|
pgcName->SetTagValue(pgcName->GetTagValue());
|
|
|
|
|
|
|
|
COleVariant varValue;
|
|
varValue = L"";
|
|
|
|
|
|
|
|
pgcType->SetValueForQualifierType(VT_BSTR);
|
|
pgcType->SetBuddy(ICOL_QUAL_VALUE);
|
|
pgcType->SetModified(TRUE);
|
|
SetCellModified(iRow, ICOL_QUAL_VALUE, TRUE);
|
|
|
|
|
|
if (iRow == m_iCurrentRow) {
|
|
CIMTYPE cimtype;
|
|
pgcName->GetValue(m_varCurrentName, cimtype);
|
|
ASSERT(cimtype == CIM_STRING);
|
|
}
|
|
|
|
|
|
COleVariant varFlag;
|
|
varFlag.ChangeType(VT_BOOL);
|
|
varFlag.boolVal = TRUE;
|
|
|
|
CGridCell* pgc;
|
|
|
|
pgc = &GetAt(iRow, ICOL_QUAL_PROPAGATE_TO_INSTANCE_FLAG);
|
|
pgc->SetValue(CELLTYPE_CHECKBOX, varFlag, CIM_BOOLEAN);
|
|
pgc->SetModified(TRUE);
|
|
pgc->SetFlags(CELLFLAG_READONLY, 0);
|
|
|
|
|
|
pgc = &GetAt(iRow, ICOL_QUAL_PROPAGATE_TO_CLASS_FLAG);
|
|
pgc->SetValue(CELLTYPE_CHECKBOX, varFlag, CIM_BOOLEAN);
|
|
pgc->SetModified(TRUE);
|
|
pgc->SetFlags(CELLFLAG_READONLY, 0);
|
|
|
|
pgc = &GetAt(iRow, ICOL_QUAL_OVERRIDABLE_FLAG);
|
|
pgc->SetValue(CELLTYPE_CHECKBOX, varFlag, CIM_BOOLEAN);
|
|
pgc->SetModified(TRUE);
|
|
pgc->SetFlags(CELLFLAG_READONLY, 0);
|
|
|
|
pgc = &GetAt(iRow, ICOL_QUAL_AMENDED_FLAG);
|
|
//if browsing localized namespace, qualifier is always amended.
|
|
//if browsing non-localized namespace, qualifier cannot be saved as amended:
|
|
//core wouldn't know where to save the qualifier
|
|
// a-jeffc: DOES NOT SEEM TO BE TRUE - You cannot 'CREATE' qualifiers with the 'ammended' attribute
|
|
COleVariant varFlag1;
|
|
varFlag1.ChangeType(VT_BOOL);
|
|
varFlag1.boolVal = FALSE;// m_psv->Selection().IsNamespaceLocalized();
|
|
pgc->SetValue(CELLTYPE_CHECKBOX, varFlag1, CIM_BOOLEAN);
|
|
pgc->SetModified(TRUE);
|
|
pgc->SetFlags(CELLFLAG_READONLY, CELLFLAG_READONLY);
|
|
|
|
pgc = &GetAt(iRow, ICOL_QUAL_ORIGIN);
|
|
pgc->SetValue(CELLTYPE_VARIANT, _T("local"), CIM_STRING);
|
|
pgc->SetModified(TRUE);
|
|
pgc->SetFlags(CELLFLAG_READONLY, CELLFLAG_READONLY);
|
|
|
|
|
|
RefreshCellEditor();
|
|
|
|
int iRowEmpty = GetRows();
|
|
InsertRowAt(iRowEmpty);
|
|
EnsureRowVisible(iRowEmpty);
|
|
|
|
|
|
pgc = &GetAt(iRowEmpty, ICOL_QUAL_PROPAGATE_TO_INSTANCE_FLAG);
|
|
varFlag.boolVal = FALSE;
|
|
pgc->SetValue(CELLTYPE_CHECKBOX, varFlag, CIM_BOOLEAN);
|
|
pgc->SetFlags(CELLFLAG_READONLY, CELLFLAG_READONLY);
|
|
|
|
pgc = &GetAt(iRowEmpty, ICOL_QUAL_PROPAGATE_TO_CLASS_FLAG);
|
|
pgc->SetValue(CELLTYPE_CHECKBOX, varFlag, CIM_BOOLEAN);
|
|
pgc->SetFlags(CELLFLAG_READONLY, CELLFLAG_READONLY);
|
|
|
|
pgc = &GetAt(iRowEmpty, ICOL_QUAL_OVERRIDABLE_FLAG);
|
|
pgc->SetValue(CELLTYPE_CHECKBOX, varFlag, CIM_BOOLEAN);
|
|
pgc->SetFlags(CELLFLAG_READONLY, CELLFLAG_READONLY);
|
|
|
|
pgc = &GetAt(iRowEmpty, ICOL_QUAL_AMENDED_FLAG);
|
|
pgc->SetValue(CELLTYPE_CHECKBOX, varFlag, CIM_BOOLEAN);
|
|
pgc->SetFlags(CELLFLAG_READONLY, CELLFLAG_READONLY);
|
|
|
|
pgc = &GetAt(iRowEmpty, ICOL_QUAL_ORIGIN);
|
|
pgc->SetFlags(CELLFLAG_READONLY, CELLFLAG_READONLY);
|
|
|
|
RedrawWindow();
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//*************************************************************
|
|
// CAttribGrid::OnCellContentChange
|
|
//
|
|
// This method is called by the CGrid base class when the content
|
|
// of the specified cell changes.
|
|
//
|
|
// Parameters:
|
|
// int iRow
|
|
// The cell's row index.
|
|
//
|
|
// int iCol
|
|
// The cell's column index.
|
|
//
|
|
// Returns:
|
|
// Nothing.
|
|
//
|
|
//*************************************************************
|
|
void CAttribGrid::OnCellContentChange(int iRow, int iCol)
|
|
{
|
|
if (m_hWnd == NULL) {
|
|
return;
|
|
}
|
|
|
|
BOOL bOnCellContentChange = m_bOnCellContentChange;
|
|
if (bOnCellContentChange) {
|
|
return;
|
|
}
|
|
|
|
|
|
SetModified(TRUE);
|
|
m_ppgQuals->NotifyQualModified();
|
|
}
|
|
|
|
|
|
|
|
|
|
//***********************************************************
|
|
// CAttribGrid::DeleteCurrentQualifier
|
|
//
|
|
// Delete the currently selected qualifier.
|
|
//
|
|
// Parameters:
|
|
// [in] int iRow
|
|
// The row containing the qualifier to delete.
|
|
//
|
|
// Returns:
|
|
// SCODE
|
|
// S_OK if the currently selected qualifier was deleted or
|
|
// there was not current qualifier, or if the user cancels
|
|
// the delete. A failure code is returned if there was
|
|
// an error in trying to do the delete.
|
|
//
|
|
//***********************************************************
|
|
SCODE CAttribGrid::DeleteQualifier(int iRow)
|
|
{
|
|
int iLastRow = LastRowContainingData();
|
|
if (iLastRow == NULL_INDEX || m_iCurrentRow > iLastRow) {
|
|
// The selection may be on the empty row at the bottom of the grid.
|
|
// If this is so, do nothing.
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CGridCell* pgcName = &GetAt(iRow, ICOL_QUAL_NAME);
|
|
|
|
COleVariant varName;
|
|
CIMTYPE cimtypeName;
|
|
pgcName->GetValue(varName, cimtypeName);
|
|
ASSERT(cimtypeName == CIM_STRING);
|
|
CString sName;
|
|
sName = varName.bstrVal;
|
|
|
|
LPTSTR pszMessage = m_psv->MessageBuffer();
|
|
CString sFormat;
|
|
SCODE sc;
|
|
|
|
|
|
CGridRow* pRow = &GetRowAt(iRow);
|
|
long lFlavor = pRow->GetFlavor();
|
|
if (lFlavor & WBEM_FLAVOR_ORIGIN_PROPAGATED) {
|
|
sFormat.LoadString(IDS_ERR_DELETE_INHERITED_QUALIFIER);
|
|
_stprintf(pszMessage, (LPCTSTR) sFormat);
|
|
sc = E_FAIL;
|
|
HmmvErrorMsgStr(pszMessage, sc, FALSE, NULL, _T(__FILE__), __LINE__);
|
|
return E_FAIL;
|
|
}
|
|
|
|
|
|
sFormat.LoadString(IDS_PROMPT_OK_TO_DELETE_QUALIFIER);
|
|
_stprintf(pszMessage, (LPCTSTR)sFormat, (LPCTSTR) sName);
|
|
|
|
if (HmmvMessageBox(pszMessage, MB_OKCANCEL | MB_SETFOREGROUND) != IDCANCEL) {
|
|
ASSERT(varName.vt == VT_BSTR);
|
|
|
|
|
|
|
|
sc = S_OK;
|
|
DWORD_PTR dwTag = pgcName->GetTagValue();
|
|
if ((dwTag & CELL_TAG_EXISTS_IN_DATABASE)!=0) {
|
|
sc = m_pqs->Delete(varName.bstrVal);
|
|
}
|
|
if (FAILED(sc)) {
|
|
|
|
sFormat.LoadString(IDS_ERR_DELETE_QUALIFIER_FAILED);
|
|
_stprintf(pszMessage, (LPCTSTR) sFormat, (LPCTSTR) sName);
|
|
HmmvErrorMsgStr(pszMessage, sc, FALSE, NULL, _T(__FILE__), __LINE__);
|
|
return sc;
|
|
}
|
|
else {
|
|
m_iCurrentRow = NULL_INDEX;
|
|
m_iCurrentCol = NULL_INDEX;
|
|
int iCol = m_iCurrentCol;
|
|
SelectCell(NULL_INDEX, NULL_INDEX);
|
|
DeleteRowAt(iRow, FALSE);
|
|
iLastRow = LastRowContainingData();
|
|
if (iLastRow == NULL_INDEX) {
|
|
m_iCurrentRow = NULL_INDEX;
|
|
m_iCurrentCol = NULL_INDEX;
|
|
}
|
|
else if (m_iCurrentRow > iLastRow) {
|
|
m_iCurrentRow = iLastRow;
|
|
}
|
|
|
|
SelectCell(m_iCurrentRow, m_iCurrentCol);
|
|
|
|
RedrawWindow();
|
|
m_bModified = TRUE;
|
|
SetModified(TRUE);
|
|
m_ppgQuals->NotifyQualModified();
|
|
|
|
}
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//*****************************************************************************
|
|
// CAttribGrid::OnRowKeyDown
|
|
//
|
|
// This is a virtual method that the CGrid base class calls to notify derived
|
|
// classes that a key was pressed while the focus was set to a grid cell.
|
|
//
|
|
// Parameters:
|
|
// int iRow
|
|
// The row index of the cell that the keystroke occurred in.
|
|
//
|
|
// UINT nChar
|
|
// The nChar parameter from window's OnKeyDown message.
|
|
//
|
|
// UINT nRepCnt
|
|
// The nRepCnt parameter from window's OnKeyDown message.
|
|
//
|
|
// UINT nFlags
|
|
// The nFlags parameter from window's OnKeyDown message.
|
|
//
|
|
// Returns:
|
|
// BOOL
|
|
// TRUE if this method handles the keydown message, FALSE otherwise.
|
|
//
|
|
//**********************************************************************
|
|
BOOL CAttribGrid::OnRowKeyDown(int iRow, UINT nChar, UINT nRepCnt, UINT nFlags)
|
|
{
|
|
if (nChar == VK_DELETE) {
|
|
if (CanEditValuesOnly()) {
|
|
MessageBeep(MB_ICONEXCLAMATION);
|
|
|
|
// Delete not allowed when editing only values.
|
|
return FALSE;
|
|
}
|
|
|
|
DeleteQualifier(iRow);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
// We don't handle this event
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//*****************************************************************************
|
|
// CAttribGrid::OnCellChar
|
|
//
|
|
// This is a virtual method that the CGrid base class calls to notify derived
|
|
// classes that a WM_CHAR message was recieved.
|
|
//
|
|
// Parameters:
|
|
// int iRow
|
|
// The row index of the cell that the keystroke occurred in.
|
|
//
|
|
// int iCol
|
|
// The column index of the cell that the keystroke occurred in.
|
|
//
|
|
// UINT nChar
|
|
// The nChar parameter from window's OnKeyDown message.
|
|
//
|
|
// UINT nRepCnt
|
|
// The nRepCnt parameter from window's OnKeyDown message.
|
|
//
|
|
// UINT nFlags
|
|
// The nFlags parameter from window's OnKeyDown message.
|
|
//
|
|
// Returns:
|
|
// BOOL
|
|
// TRUE if this method handles the keydown message, FALSE otherwise.
|
|
//
|
|
//**********************************************************************
|
|
BOOL CAttribGrid::OnCellChar(int iRow, int iCol, UINT nChar, UINT nRepCnt, UINT nFlags)
|
|
{
|
|
EnsureRowVisible(iRow);
|
|
|
|
// Check to see if we are on the "empty" row at the bottom of the grid.
|
|
// If so, then create a new qualifier.
|
|
int iEmptyRow = IndexOfEmptyRow();
|
|
if (iEmptyRow != NULL_INDEX && m_iCurrentRow == iEmptyRow) {
|
|
if (m_psv->CanEdit()) {
|
|
BOOL bGenerateDefaultName = iCol != ICOL_QUAL_NAME;
|
|
LPCTSTR pszName;
|
|
if (bGenerateDefaultName) {
|
|
pszName = NULL;
|
|
}
|
|
else {
|
|
pszName = _T("");
|
|
}
|
|
CreateNewQualifier(pszName);
|
|
}
|
|
}
|
|
|
|
// We don't handle this event.
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//***************************************************************
|
|
// CAttribGrid::LastRowContainingData
|
|
//
|
|
// Return the index of the last row in the grid containing data.
|
|
//
|
|
// Parameters:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// Nothing.
|
|
//
|
|
//****************************************************************
|
|
long CAttribGrid::LastRowContainingData()
|
|
{
|
|
long lMaxIndex = GetRows() - 1;
|
|
if (lMaxIndex < 0) {
|
|
return NULL_INDEX;
|
|
}
|
|
|
|
|
|
if (m_bHasEmptyRow) {
|
|
// We are in edit mode, so decrement the max index to adjust for
|
|
// the "empty" row at the bottom.
|
|
--lMaxIndex;
|
|
}
|
|
|
|
|
|
return lMaxIndex;
|
|
}
|
|
|
|
|
|
|
|
|
|
//*************************************************************
|
|
// CAttribGrid::SomeCellIsSelected
|
|
//
|
|
// Check to see whether or not a cell is selected.
|
|
//
|
|
// Parameters:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// BOOL
|
|
// TRUE if some cell is selected, otherwise FALSE.
|
|
//
|
|
//*************************************************************
|
|
BOOL CAttribGrid::SomeCellIsSelected()
|
|
{
|
|
return m_iCurrentRow!=NULL_INDEX && m_iCurrentCol!=NULL_INDEX;
|
|
}
|
|
|
|
|
|
|
|
//*********************************************************
|
|
// CAttribGrid::SelectedRowWasModified
|
|
//
|
|
// Check to see whether or not the selected row was modified.
|
|
//
|
|
// Parameters:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// TRUE if the selected row was modified, FALSE otherwise. If no
|
|
// row is selected, return FALSE.
|
|
//
|
|
//**********************************************************
|
|
BOOL CAttribGrid::SelectedRowWasModified()
|
|
{
|
|
if (m_iCurrentRow == NULL_INDEX) {
|
|
return FALSE;
|
|
}
|
|
else {
|
|
return RowWasModified(m_iCurrentRow);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//*****************************************************************
|
|
// CAttribGrid::RowWasModified
|
|
//
|
|
// Check to see if the specified row was modified.
|
|
//
|
|
// Parameters:
|
|
// int iRow.
|
|
//
|
|
// Returns:
|
|
// TRUE if the selected row was modified, FALSE otherwise.
|
|
//*****************************************************************
|
|
BOOL CAttribGrid::RowWasModified(int iRow)
|
|
{
|
|
return GetRowModified(iRow);
|
|
}
|
|
|
|
void CAttribGrid::OnCellClicked(int iRow, int iCol)
|
|
{
|
|
const int iEmptyRow = IndexOfEmptyRow();
|
|
if (iRow == iEmptyRow) {
|
|
OnCellDoubleClicked(iRow, iCol);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//**************************************************************
|
|
// CAttribGrid::OnCellDoubleClicked
|
|
//
|
|
// This virtual method is called by the CGrid base class to notify
|
|
// derived classes when a cell has been double clicked. This is used
|
|
// to implement qualifier creation -- when the user double-clicks the
|
|
// "empty" row at the bottom of the grid, a new qualifier is created.
|
|
//
|
|
// Parameters:
|
|
// int iRow
|
|
// The row index of the clicked cell.
|
|
//
|
|
// int iCol
|
|
// The column index of the clicked cell.
|
|
//
|
|
// Returns:
|
|
// Nothing.
|
|
//
|
|
//****************************************************************
|
|
void CAttribGrid::OnCellDoubleClicked(int iRow, int iCol)
|
|
{
|
|
SCODE sc;
|
|
int nRows = GetRows();
|
|
// if ((iRow == nRows - 1) && m_psv->ObjectIsClass() && m_psv->IsInSchemaStudioMode()) {
|
|
if ((iRow == nRows - 1) && m_psv->CanEdit()) {
|
|
sc = CreateNewQualifier(NULL);
|
|
if (FAILED(sc)) {
|
|
return;
|
|
}
|
|
|
|
SelectCell(iRow, iCol);
|
|
}
|
|
|
|
m_iCurrentRow = iRow;
|
|
m_iCurrentCol = iCol;
|
|
|
|
if (iRow!=NULL_INDEX && iCol!=NULL_INDEX) {
|
|
CGridCell* pgcName = &GetAt(iRow, ICOL_QUAL_NAME);
|
|
CIMTYPE cimtypeName;
|
|
pgcName->GetValue(m_varCurrentName, cimtypeName);
|
|
ASSERT(cimtypeName == CIM_STRING);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//**********************************************************************
|
|
// CAttribGrid::OnRowHandleDoubleClicked
|
|
//
|
|
// This virtual method is called by the base class when a double click is
|
|
// detected on a row handle.
|
|
//
|
|
// Parameters:
|
|
// int iRow
|
|
// The row index.
|
|
//
|
|
// Returns:
|
|
// Nothing.
|
|
//
|
|
//**********************************************************************
|
|
void CAttribGrid::OnRowHandleDoubleClicked(int iRow)
|
|
{
|
|
|
|
int iEmptyRow = IndexOfEmptyRow();
|
|
if (iEmptyRow != NULL_INDEX && iRow == iEmptyRow) {
|
|
OnCellDoubleClicked(iRow, ICOL_QUAL_NAME);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//*****************************************************************
|
|
// CAttribGrid::IndexOfEmptyRow
|
|
//
|
|
// Return the index of the empty row at the bottom of the grid when
|
|
// the control is in edit mode.
|
|
//
|
|
// Parameters:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// long
|
|
// The index of the empty row if it exists, otherwise NULL_INDEX.
|
|
//
|
|
//******************************************************************
|
|
long CAttribGrid::IndexOfEmptyRow()
|
|
{
|
|
// if (m_psv->ObjectIsClass() && m_psv->IsInSchemaStudioMode()) {
|
|
if (m_psv->CanEdit()) {
|
|
return GetRows() - 1;
|
|
}
|
|
return NULL_INDEX;
|
|
}
|
|
|
|
|
|
|
|
|
|
//*******************************************************************
|
|
// CAttribGrid::CompareRows
|
|
//
|
|
// This is a virtual method override that compares two rows in the grid
|
|
// using the column index as the sort criteria.
|
|
//
|
|
// Parameters:
|
|
// int iRow1
|
|
// The index of the first row.
|
|
//
|
|
// int iRow2
|
|
// The index of the second row.
|
|
//
|
|
// int iSortColumn
|
|
// The column index.
|
|
//
|
|
// Returns:
|
|
// >0 if row 1 is greater than row 2
|
|
// 0 if row 1 equal zero
|
|
// <0 if row 1 is less than zero.
|
|
//
|
|
//********************************************************************
|
|
int CAttribGrid::CompareRows(int iRow1, int iRow2, int iSortColumn)
|
|
{
|
|
int iResult;
|
|
int iCol;
|
|
|
|
switch (iSortColumn) {
|
|
case ICOL_QUAL_NAME:
|
|
// Sort first by name
|
|
iResult = CompareCells(iRow1, iRow2, ICOL_QUAL_NAME);
|
|
if (iResult != 0) {
|
|
return iResult;
|
|
}
|
|
|
|
// Then by type
|
|
iResult = CompareCells(iRow1, iRow2, ICOL_QUAL_TYPE);
|
|
if (iResult != 0) {
|
|
return iResult;
|
|
}
|
|
|
|
// Then by value.
|
|
iResult = CompareCells(iRow1, iRow2, ICOL_QUAL_VALUE);
|
|
if (iResult != 0) {
|
|
return iResult;
|
|
}
|
|
|
|
for (iCol = 0; iCol < COLUMN_COUNT_QUALIFIERS; ++iCol) {
|
|
switch(iCol) {
|
|
case ICOL_QUAL_TYPE:
|
|
case ICOL_QUAL_NAME:
|
|
case ICOL_QUAL_VALUE:
|
|
continue;
|
|
}
|
|
|
|
iResult = CompareCells(iRow1, iRow2, iCol);
|
|
if (iResult != 0) {
|
|
return iResult;
|
|
}
|
|
}
|
|
break;
|
|
case ICOL_QUAL_TYPE:
|
|
// Sort first by type
|
|
iResult = CompareCells(iRow1, iRow2, ICOL_QUAL_TYPE);
|
|
if (iResult != 0) {
|
|
return iResult;
|
|
}
|
|
|
|
// Then by name
|
|
iResult = CompareCells(iRow1, iRow2, ICOL_QUAL_NAME);
|
|
if (iResult != 0) {
|
|
return iResult;
|
|
}
|
|
|
|
// Then by value.
|
|
iResult = CompareCells(iRow1, iRow2, ICOL_QUAL_VALUE);
|
|
if (iResult != 0) {
|
|
return iResult;
|
|
}
|
|
|
|
for (iCol = 0; iCol < COLUMN_COUNT_QUALIFIERS; ++iCol) {
|
|
switch(iCol) {
|
|
case ICOL_QUAL_TYPE:
|
|
case ICOL_QUAL_NAME:
|
|
case ICOL_QUAL_VALUE:
|
|
continue;
|
|
}
|
|
|
|
iResult = CompareCells(iRow1, iRow2, iCol);
|
|
if (iResult != 0) {
|
|
return iResult;
|
|
}
|
|
}
|
|
return iResult;
|
|
break;
|
|
case ICOL_QUAL_VALUE:
|
|
// Sort first by value
|
|
iResult = CompareCells(iRow1, iRow2, ICOL_QUAL_VALUE);
|
|
if (iResult != 0) {
|
|
return iResult;
|
|
}
|
|
|
|
// Then by name
|
|
iResult = CompareCells(iRow1, iRow2, ICOL_QUAL_NAME);
|
|
if (iResult != 0) {
|
|
return iResult;
|
|
}
|
|
|
|
// Sort first by type
|
|
iResult = CompareCells(iRow1, iRow2, ICOL_QUAL_TYPE);
|
|
if (iResult != 0) {
|
|
return iResult;
|
|
}
|
|
|
|
for (iCol = 0; iCol < COLUMN_COUNT_QUALIFIERS; ++iCol) {
|
|
switch(iCol) {
|
|
case ICOL_QUAL_TYPE:
|
|
case ICOL_QUAL_NAME:
|
|
case ICOL_QUAL_VALUE:
|
|
continue;
|
|
}
|
|
|
|
iResult = CompareCells(iRow1, iRow2, iCol);
|
|
if (iResult != 0) {
|
|
return iResult;
|
|
}
|
|
}
|
|
return iResult;
|
|
break;
|
|
default:
|
|
// Then by origin
|
|
iResult = CompareCells(iRow1, iRow2, iSortColumn);
|
|
if (iResult != 0) {
|
|
return iResult;
|
|
}
|
|
|
|
// Sort first by name
|
|
iResult = CompareCells(iRow1, iRow2, ICOL_QUAL_NAME);
|
|
if (iResult != 0) {
|
|
return iResult;
|
|
}
|
|
|
|
// Then by type
|
|
iResult = CompareCells(iRow1, iRow2, ICOL_QUAL_TYPE);
|
|
if (iResult != 0) {
|
|
return iResult;
|
|
}
|
|
|
|
// Then by value.
|
|
iResult = CompareCells(iRow1, iRow2, ICOL_QUAL_VALUE);
|
|
if (iResult != 0) {
|
|
return iResult;
|
|
}
|
|
|
|
|
|
for (iCol = 0; iCol < COLUMN_COUNT_QUALIFIERS; ++iCol) {
|
|
switch(iCol) {
|
|
case ICOL_QUAL_NAME:
|
|
case ICOL_QUAL_TYPE:
|
|
case ICOL_QUAL_VALUE:
|
|
continue;
|
|
}
|
|
if (iCol == iSortColumn) {
|
|
continue;
|
|
}
|
|
|
|
iResult = CompareCells(iRow1, iRow2, iCol);
|
|
if (iResult != 0) {
|
|
return iResult;
|
|
}
|
|
}
|
|
return iResult;
|
|
break;
|
|
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
//**********************************************************************
|
|
// CAttribGrid::OnHeaderItemClick
|
|
//
|
|
// Catch the "header item clicked" notification message by overriding
|
|
// the base class' virtual method.
|
|
//
|
|
// Parameters:
|
|
// int iColumn
|
|
// The index of the column that was clicked.
|
|
//
|
|
// Returns:
|
|
// Nothing.
|
|
//
|
|
//***********************************************************************
|
|
void CAttribGrid::OnHeaderItemClick(int iColumn)
|
|
{
|
|
SyncCellEditor();
|
|
int iLastRow = LastRowContainingData();
|
|
if (iLastRow > 0) {
|
|
SortGrid(0, iLastRow, iColumn);
|
|
}
|
|
|
|
m_iCurrentRow = GetSelectedRow();
|
|
}
|
|
|
|
|
|
|
|
|
|
//*********************************************************************
|
|
// CAttribGrid::GetNotify
|
|
//
|
|
// This virtual method overrides the CGrid's GetNotify method. This
|
|
// gives the derived class a way to control what gets notified when
|
|
// events such as grid modification occur.
|
|
//
|
|
// Other classes need to be notified when the content of the grid
|
|
// changes and so on. We will distribute such events globally via
|
|
// the main control's global notification structure.
|
|
//
|
|
// The notification classes are used so that the grid doesn't have
|
|
// to have any knowledge of the classes that want to be notified.
|
|
//
|
|
// Parameters:
|
|
// None.
|
|
//
|
|
// Returns:
|
|
// CDistributeEvent*
|
|
// A pointer to the main control's global notification class.
|
|
//
|
|
//*********************************************************************
|
|
CDistributeEvent* CAttribGrid::GetNotify()
|
|
{
|
|
return m_psv->GetGlobalNotify();
|
|
}
|
|
|
|
|