mirror of
https://github.com/xzeldon/htop.git
synced 2024-12-23 22:55:46 +00:00
Add option to change Header layout
This commit is contained in:
parent
7269faf651
commit
9060a4179d
@ -30,14 +30,15 @@ static void AvailableMetersPanel_delete(Object* object) {
|
||||
Panel* super = (Panel*) object;
|
||||
AvailableMetersPanel* this = (AvailableMetersPanel*) object;
|
||||
Panel_done(super);
|
||||
free(this->meterPanels);
|
||||
free(this);
|
||||
}
|
||||
|
||||
static inline void AvailableMetersPanel_addMeter(Header* header, Panel* panel, const MeterClass* type, unsigned int param, int column) {
|
||||
static inline void AvailableMetersPanel_addMeter(Header* header, MetersPanel* panel, const MeterClass* type, unsigned int param, size_t column) {
|
||||
const Meter* meter = Header_addMeterByClass(header, type, param, column);
|
||||
Panel_add(panel, (Object*) Meter_toListItem(meter, false));
|
||||
Panel_setSelected(panel, Panel_size(panel) - 1);
|
||||
MetersPanel_setMoving((MetersPanel*)panel, true);
|
||||
Panel_add((Panel*)panel, (Object*) Meter_toListItem(meter, false));
|
||||
Panel_setSelected((Panel*)panel, Panel_size((Panel*)panel) - 1);
|
||||
MetersPanel_setMoving(panel, true);
|
||||
}
|
||||
|
||||
static HandlerResult AvailableMetersPanel_eventHandler(Panel* super, int ch) {
|
||||
@ -58,7 +59,7 @@ static HandlerResult AvailableMetersPanel_eventHandler(Panel* super, int ch) {
|
||||
case 'l':
|
||||
case 'L':
|
||||
{
|
||||
AvailableMetersPanel_addMeter(header, this->leftPanel, Platform_meterTypes[type], param, 0);
|
||||
AvailableMetersPanel_addMeter(header, this->meterPanels[0], Platform_meterTypes[type], param, 0);
|
||||
result = HANDLED;
|
||||
update = true;
|
||||
break;
|
||||
@ -70,7 +71,7 @@ static HandlerResult AvailableMetersPanel_eventHandler(Panel* super, int ch) {
|
||||
case 'r':
|
||||
case 'R':
|
||||
{
|
||||
AvailableMetersPanel_addMeter(header, this->rightPanel, Platform_meterTypes[type], param, 1);
|
||||
AvailableMetersPanel_addMeter(header, this->meterPanels[this->columns - 1], Platform_meterTypes[type], param, this->columns - 1);
|
||||
result = (KEY_LEFT << 16) | SYNTH_KEY;
|
||||
update = true;
|
||||
break;
|
||||
@ -138,7 +139,7 @@ static void AvailableMetersPanel_addPlatformMeter(Panel* super, const MeterClass
|
||||
Panel_add(super, (Object*) ListItem_new(label, offset << 16));
|
||||
}
|
||||
|
||||
AvailableMetersPanel* AvailableMetersPanel_new(Settings* settings, Header* header, Panel* leftMeters, Panel* rightMeters, ScreenManager* scr, const ProcessList* pl) {
|
||||
AvailableMetersPanel* AvailableMetersPanel_new(Settings* settings, Header* header, size_t columns, MetersPanel** meterPanels, ScreenManager* scr, const ProcessList* pl) {
|
||||
AvailableMetersPanel* this = AllocThis(AvailableMetersPanel);
|
||||
Panel* super = (Panel*) this;
|
||||
FunctionBar* fuBar = FunctionBar_newEnterEsc("Add ", "Done ");
|
||||
@ -146,8 +147,8 @@ AvailableMetersPanel* AvailableMetersPanel_new(Settings* settings, Header* heade
|
||||
|
||||
this->settings = settings;
|
||||
this->header = header;
|
||||
this->leftPanel = leftMeters;
|
||||
this->rightPanel = rightMeters;
|
||||
this->columns = columns;
|
||||
this->meterPanels = meterPanels;
|
||||
this->scr = scr;
|
||||
|
||||
Panel_setHeader(super, "Available meters");
|
||||
|
@ -8,6 +8,7 @@ in the source distribution for its full text.
|
||||
*/
|
||||
|
||||
#include "Header.h"
|
||||
#include "MetersPanel.h"
|
||||
#include "Panel.h"
|
||||
#include "ProcessList.h"
|
||||
#include "ScreenManager.h"
|
||||
@ -20,12 +21,12 @@ typedef struct AvailableMetersPanel_ {
|
||||
|
||||
Settings* settings;
|
||||
Header* header;
|
||||
Panel* leftPanel;
|
||||
Panel* rightPanel;
|
||||
size_t columns;
|
||||
MetersPanel** meterPanels;
|
||||
} AvailableMetersPanel;
|
||||
|
||||
extern const PanelClass AvailableMetersPanel_class;
|
||||
|
||||
AvailableMetersPanel* AvailableMetersPanel_new(Settings* settings, Header* header, Panel* leftMeters, Panel* rightMeters, ScreenManager* scr, const ProcessList* pl);
|
||||
AvailableMetersPanel* AvailableMetersPanel_new(Settings* settings, Header* header, size_t columns, MetersPanel **meterPanels, ScreenManager* scr, const ProcessList* pl);
|
||||
|
||||
#endif
|
||||
|
@ -17,6 +17,8 @@ in the source distribution for its full text.
|
||||
#include "ColumnsPanel.h"
|
||||
#include "DisplayOptionsPanel.h"
|
||||
#include "FunctionBar.h"
|
||||
#include "Header.h"
|
||||
#include "HeaderOptionsPanel.h"
|
||||
#include "ListItem.h"
|
||||
#include "MetersPanel.h"
|
||||
#include "Object.h"
|
||||
@ -34,13 +36,23 @@ static void CategoriesPanel_delete(Object* object) {
|
||||
}
|
||||
|
||||
void CategoriesPanel_makeMetersPage(CategoriesPanel* this) {
|
||||
MetersPanel* leftMeters = MetersPanel_new(this->settings, "Left column", this->header->columns[0], this->scr);
|
||||
MetersPanel* rightMeters = MetersPanel_new(this->settings, "Right column", this->header->columns[1], this->scr);
|
||||
leftMeters->rightNeighbor = rightMeters;
|
||||
rightMeters->leftNeighbor = leftMeters;
|
||||
Panel* availableMeters = (Panel*) AvailableMetersPanel_new(this->settings, this->header, (Panel*) leftMeters, (Panel*) rightMeters, this->scr, this->pl);
|
||||
ScreenManager_add(this->scr, (Panel*) leftMeters, 20);
|
||||
ScreenManager_add(this->scr, (Panel*) rightMeters, 20);
|
||||
size_t columns = HeaderLayout_getColumns(this->scr->header->headerLayout);
|
||||
MetersPanel** meterPanels = xMallocArray(columns, sizeof(MetersPanel));
|
||||
|
||||
for (size_t i = 0; i < columns; i++) {
|
||||
char titleBuffer[32];
|
||||
xSnprintf(titleBuffer, sizeof(titleBuffer), "Column %zu", i + 1);
|
||||
meterPanels[i] = MetersPanel_new(this->settings, titleBuffer, this->header->columns[i], this->scr);
|
||||
|
||||
if (i != 0) {
|
||||
meterPanels[i]->leftNeighbor = meterPanels[i - 1];
|
||||
meterPanels[i - 1]->rightNeighbor = meterPanels[i];
|
||||
}
|
||||
|
||||
ScreenManager_add(this->scr, (Panel*) meterPanels[i], 20);
|
||||
}
|
||||
|
||||
Panel* availableMeters = (Panel*) AvailableMetersPanel_new(this->settings, this->header, columns, meterPanels, this->scr, this->pl);
|
||||
ScreenManager_add(this->scr, availableMeters, -1);
|
||||
}
|
||||
|
||||
@ -61,6 +73,11 @@ static void CategoriesPanel_makeColumnsPage(CategoriesPanel* this) {
|
||||
ScreenManager_add(this->scr, availableColumns, -1);
|
||||
}
|
||||
|
||||
static void CategoriesPanel_makeHeaderOptionsPage(CategoriesPanel* this) {
|
||||
Panel* colors = (Panel*) HeaderOptionsPanel_new(this->settings, this->scr);
|
||||
ScreenManager_add(this->scr, colors, -1);
|
||||
}
|
||||
|
||||
static HandlerResult CategoriesPanel_eventHandler(Panel* super, int ch) {
|
||||
CategoriesPanel* this = (CategoriesPanel*) super;
|
||||
|
||||
@ -111,6 +128,9 @@ static HandlerResult CategoriesPanel_eventHandler(Panel* super, int ch) {
|
||||
case 3:
|
||||
CategoriesPanel_makeColumnsPage(this);
|
||||
break;
|
||||
case 4:
|
||||
CategoriesPanel_makeHeaderOptionsPage(this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@ -139,5 +159,6 @@ CategoriesPanel* CategoriesPanel_new(ScreenManager* scr, Settings* settings, Hea
|
||||
Panel_add(super, (Object*) ListItem_new("Display options", 0));
|
||||
Panel_add(super, (Object*) ListItem_new("Colors", 0));
|
||||
Panel_add(super, (Object*) ListItem_new("Columns", 0));
|
||||
Panel_add(super, (Object*) ListItem_new("Header layout", 0));
|
||||
return this;
|
||||
}
|
||||
|
197
Header.c
197
Header.c
@ -7,6 +7,7 @@ in the source distribution for its full text.
|
||||
|
||||
#include "Header.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -22,15 +23,17 @@ in the source distribution for its full text.
|
||||
#include "XUtils.h"
|
||||
|
||||
|
||||
Header* Header_new(ProcessList* pl, Settings* settings, int nrColumns) {
|
||||
Header* Header_new(ProcessList* pl, Settings* settings, HeaderLayout hLayout) {
|
||||
Header* this = xCalloc(1, sizeof(Header));
|
||||
this->columns = xCalloc(nrColumns, sizeof(Vector*));
|
||||
this->columns = xMallocArray(HeaderLayout_getColumns(hLayout), sizeof(Vector*));
|
||||
this->settings = settings;
|
||||
this->pl = pl;
|
||||
this->nrColumns = nrColumns;
|
||||
this->headerLayout = hLayout;
|
||||
|
||||
Header_forEachColumn(this, i) {
|
||||
this->columns[i] = Vector_new(Class(Meter), true, DEFAULT_SIZE);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -38,37 +41,109 @@ void Header_delete(Header* this) {
|
||||
Header_forEachColumn(this, i) {
|
||||
Vector_delete(this->columns[i]);
|
||||
}
|
||||
|
||||
free(this->columns);
|
||||
free(this);
|
||||
}
|
||||
|
||||
void Header_populateFromSettings(Header* this) {
|
||||
Header_forEachColumn(this, col) {
|
||||
const MeterColumnSettings* colSettings = &this->settings->columns[col];
|
||||
for (int i = 0; i < colSettings->len; i++) {
|
||||
if (!Header_addMeterByName(this, colSettings->names[i], col)) {
|
||||
continue;
|
||||
void Header_setLayout(Header* this, HeaderLayout hLayout) {
|
||||
size_t oldColumns = HeaderLayout_getColumns(this->headerLayout);
|
||||
size_t newColumns = HeaderLayout_getColumns(hLayout);
|
||||
|
||||
this->headerLayout = hLayout;
|
||||
|
||||
if (newColumns == oldColumns)
|
||||
return;
|
||||
|
||||
if (newColumns > oldColumns) {
|
||||
this->columns = xReallocArray(this->columns, newColumns, sizeof(Vector*));
|
||||
for (size_t i = oldColumns; i < newColumns; i++)
|
||||
this->columns[i] = Vector_new(Class(Meter), true, DEFAULT_SIZE);
|
||||
} else {
|
||||
// move meters from to-be-deleted columns into last one
|
||||
for (size_t i = newColumns; i < oldColumns; i++) {
|
||||
for (int j = this->columns[i]->items - 1; j >= 0; j--) {
|
||||
Vector_add(this->columns[newColumns - 1], Vector_take(this->columns[i], j));
|
||||
}
|
||||
if (colSettings->modes[i] != 0) {
|
||||
Header_setMode(this, i, colSettings->modes[i], col);
|
||||
Vector_delete(this->columns[i]);
|
||||
}
|
||||
this->columns = xReallocArray(this->columns, newColumns, sizeof(Vector*));
|
||||
}
|
||||
|
||||
Header_calculateHeight(this);
|
||||
}
|
||||
|
||||
static void Header_addMeterByName(Header* this, const char* name, MeterModeId mode, unsigned int column) {
|
||||
assert(column < HeaderLayout_getColumns(this->headerLayout));
|
||||
|
||||
Vector* meters = this->columns[column];
|
||||
|
||||
const char* paren = strchr(name, '(');
|
||||
unsigned int param = 0;
|
||||
size_t nameLen;
|
||||
if (paren) {
|
||||
int ok = sscanf(paren, "(%10u)", ¶m); // CPUMeter
|
||||
if (!ok) {
|
||||
char* end, dynamic[32] = {0};
|
||||
if (sscanf(paren, "(%30s)", dynamic)) { // DynamicMeter
|
||||
if ((end = strrchr(dynamic, ')')) == NULL)
|
||||
return; // indicate htoprc parse failure
|
||||
*end = '\0';
|
||||
if (!DynamicMeter_search(this->pl->dynamicMeters, dynamic, ¶m))
|
||||
return; // indicates name lookup failure
|
||||
} else {
|
||||
param = 0;
|
||||
}
|
||||
}
|
||||
nameLen = paren - name;
|
||||
} else {
|
||||
nameLen = strlen(name);
|
||||
}
|
||||
|
||||
for (const MeterClass* const* type = Platform_meterTypes; *type; type++) {
|
||||
if (0 == strncmp(name, (*type)->name, nameLen) && (*type)->name[nameLen] == '\0') {
|
||||
Meter* meter = Meter_new(this->pl, param, *type);
|
||||
if (mode != 0) {
|
||||
Meter_setMode(meter, mode);
|
||||
}
|
||||
Vector_add(meters, meter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Header_populateFromSettings(Header* this) {
|
||||
Header_setLayout(this, this->settings->hLayout);
|
||||
|
||||
Header_forEachColumn(this, col) {
|
||||
const MeterColumnSetting* colSettings = &this->settings->hColumns[col];
|
||||
Vector_prune(this->columns[col]);
|
||||
for (size_t i = 0; i < colSettings->len; i++) {
|
||||
Header_addMeterByName(this, colSettings->names[i], colSettings->modes[i], col);
|
||||
}
|
||||
}
|
||||
|
||||
Header_calculateHeight(this);
|
||||
}
|
||||
|
||||
void Header_writeBackToSettings(const Header* this) {
|
||||
Header_forEachColumn(this, col) {
|
||||
MeterColumnSettings* colSettings = &this->settings->columns[col];
|
||||
Settings_setHeaderLayout(this->settings, this->headerLayout);
|
||||
|
||||
String_freeArray(colSettings->names);
|
||||
Header_forEachColumn(this, col) {
|
||||
MeterColumnSetting* colSettings = &this->settings->hColumns[col];
|
||||
|
||||
if (colSettings->names) {
|
||||
for (size_t j = 0; j < colSettings->len; j++)
|
||||
free(colSettings->names[j]);
|
||||
free(colSettings->names);
|
||||
}
|
||||
free(colSettings->modes);
|
||||
|
||||
const Vector* vec = this->columns[col];
|
||||
int len = Vector_size(vec);
|
||||
|
||||
colSettings->names = xCalloc(len + 1, sizeof(char*));
|
||||
colSettings->modes = xCalloc(len, sizeof(int));
|
||||
colSettings->names = len ? xCalloc(len, sizeof(char*)) : NULL;
|
||||
colSettings->modes = len ? xCalloc(len, sizeof(int)) : NULL;
|
||||
colSettings->len = len;
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
@ -88,50 +163,9 @@ void Header_writeBackToSettings(const Header* this) {
|
||||
}
|
||||
}
|
||||
|
||||
bool Header_addMeterByName(Header* this, const char* name, int column) {
|
||||
Vector* meters = this->columns[column];
|
||||
Meter* Header_addMeterByClass(Header* this, const MeterClass* type, unsigned int param, unsigned int column) {
|
||||
assert(column < HeaderLayout_getColumns(this->headerLayout));
|
||||
|
||||
char* paren = strchr(name, '(');
|
||||
unsigned int param = 0;
|
||||
if (paren) {
|
||||
char* end, dynamic[32] = {0};
|
||||
int ok = sscanf(paren, "(%10u)", ¶m); // CPUMeter
|
||||
if (!ok) {
|
||||
if (sscanf(paren, "(%30s)", dynamic)) { // DynamicMeter
|
||||
if ((end = strrchr(dynamic, ')')) == NULL)
|
||||
return false; // indicate htoprc parse failure
|
||||
*end = '\0';
|
||||
if (!DynamicMeter_search(this->pl->dynamicMeters, dynamic, ¶m))
|
||||
return false; // indicates name lookup failure
|
||||
}
|
||||
}
|
||||
*paren = '\0';
|
||||
}
|
||||
for (const MeterClass* const* type = Platform_meterTypes; *type; type++) {
|
||||
if (String_eq(name, (*type)->name)) {
|
||||
Meter* meter = Meter_new(this->pl, param, *type);
|
||||
Vector_add(meters, meter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (paren)
|
||||
*paren = '(';
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Header_setMode(Header* this, int i, MeterModeId mode, int column) {
|
||||
Vector* meters = this->columns[column];
|
||||
|
||||
if (i >= Vector_size(meters))
|
||||
return;
|
||||
|
||||
Meter* meter = (Meter*) Vector_get(meters, i);
|
||||
Meter_setMode(meter, mode);
|
||||
}
|
||||
|
||||
Meter* Header_addMeterByClass(Header* this, const MeterClass* type, unsigned int param, int column) {
|
||||
Vector* meters = this->columns[column];
|
||||
|
||||
Meter* meter = Meter_new(this->pl, param, type);
|
||||
@ -139,18 +173,6 @@ Meter* Header_addMeterByClass(Header* this, const MeterClass* type, unsigned int
|
||||
return meter;
|
||||
}
|
||||
|
||||
int Header_size(const Header* this, int column) {
|
||||
const Vector* meters = this->columns[column];
|
||||
return Vector_size(meters);
|
||||
}
|
||||
|
||||
MeterModeId Header_readMeterMode(const Header* this, int i, int column) {
|
||||
const Vector* meters = this->columns[column];
|
||||
|
||||
const Meter* meter = (const Meter*) Vector_get(meters, i);
|
||||
return meter->mode;
|
||||
}
|
||||
|
||||
void Header_reinit(Header* this) {
|
||||
Header_forEachColumn(this, col) {
|
||||
for (int i = 0; i < Vector_size(this->columns[col]); i++) {
|
||||
@ -169,25 +191,36 @@ void Header_draw(const Header* this) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
mvhline(y, 0, ' ', COLS);
|
||||
}
|
||||
const int width = COLS / this->nrColumns - pad;
|
||||
const int width = COLS - pad;
|
||||
int x = pad;
|
||||
float roundingLoss = 0.0f;
|
||||
|
||||
Header_forEachColumn(this, col) {
|
||||
Vector* meters = this->columns[col];
|
||||
float colWidth = (float)width * HeaderLayout_layouts[this->headerLayout].widths[col] / 100.0f;
|
||||
|
||||
roundingLoss += colWidth - floorf(colWidth);
|
||||
if (roundingLoss >= 1.0f) {
|
||||
colWidth += 1.0f;
|
||||
roundingLoss -= 1.0f;
|
||||
}
|
||||
|
||||
for (int y = (pad / 2), i = 0; i < Vector_size(meters); i++) {
|
||||
Meter* meter = (Meter*) Vector_get(meters, i);
|
||||
|
||||
int actualWidth;
|
||||
if (meter->mode == TEXT_METERMODE)
|
||||
actualWidth = meter->columnWidthCount * width + (meter->columnWidthCount - 1) * (2 * pad + 1);
|
||||
else
|
||||
actualWidth = width;
|
||||
float actualWidth = colWidth;
|
||||
if (meter->mode == TEXT_METERMODE) {
|
||||
for (int j = 1; j < meter->columnWidthCount; j++) {
|
||||
actualWidth += (float)width * HeaderLayout_layouts[this->headerLayout].widths[col + j] / 100.0f;
|
||||
}
|
||||
}
|
||||
|
||||
assert(meter->draw);
|
||||
meter->draw(meter, x, y, actualWidth);
|
||||
meter->draw(meter, x, y, floorf(actualWidth));
|
||||
y += meter->h;
|
||||
}
|
||||
x += width + pad;
|
||||
|
||||
x += floorf(colWidth);
|
||||
}
|
||||
}
|
||||
|
||||
@ -207,8 +240,8 @@ void Header_updateData(Header* this) {
|
||||
* by counting how many columns to the right are empty or contain a BlankMeter.
|
||||
* Returns the number of columns to span, i.e. if the direct neighbor is occupied 1.
|
||||
*/
|
||||
static int calcColumnWidthCount(const Header* this, const Meter* curMeter, const int pad, const int curColumn, const int curHeight) {
|
||||
for (int i = curColumn + 1; i < this->nrColumns; i++) {
|
||||
static int calcColumnWidthCount(const Header* this, const Meter* curMeter, const int pad, const unsigned int curColumn, const int curHeight) {
|
||||
for (size_t i = curColumn + 1; i < HeaderLayout_getColumns(this->headerLayout); i++) {
|
||||
const Vector* meters = this->columns[i];
|
||||
|
||||
int height = pad;
|
||||
@ -227,7 +260,7 @@ static int calcColumnWidthCount(const Header* this, const Meter* curMeter, const
|
||||
}
|
||||
}
|
||||
|
||||
return this->nrColumns - curColumn;
|
||||
return HeaderLayout_getColumns(this->headerLayout) - curColumn;
|
||||
}
|
||||
|
||||
int Header_calculateHeight(Header* this) {
|
||||
|
18
Header.h
18
Header.h
@ -17,30 +17,24 @@ typedef struct Header_ {
|
||||
Vector** columns;
|
||||
Settings* settings;
|
||||
ProcessList* pl;
|
||||
int nrColumns;
|
||||
HeaderLayout headerLayout;
|
||||
int pad;
|
||||
int height;
|
||||
} Header;
|
||||
|
||||
#define Header_forEachColumn(this_, i_) for (int (i_)=0; (i_) < (this_)->nrColumns; ++(i_))
|
||||
#define Header_forEachColumn(this_, i_) for (size_t (i_)=0; (i_) < HeaderLayout_getColumns((this_)->headerLayout); ++(i_))
|
||||
|
||||
Header* Header_new(ProcessList* pl, Settings* settings, int nrColumns);
|
||||
Header* Header_new(ProcessList* pl, Settings* settings, HeaderLayout hLayout);
|
||||
|
||||
void Header_delete(Header* this);
|
||||
|
||||
void Header_setLayout(Header* this, HeaderLayout hLayout);
|
||||
|
||||
void Header_populateFromSettings(Header* this);
|
||||
|
||||
void Header_writeBackToSettings(const Header* this);
|
||||
|
||||
bool Header_addMeterByName(Header* this, const char* name, int column);
|
||||
|
||||
void Header_setMode(Header* this, int i, MeterModeId mode, int column);
|
||||
|
||||
Meter* Header_addMeterByClass(Header* this, const MeterClass* type, unsigned int param, int column);
|
||||
|
||||
int Header_size(const Header* this, int column);
|
||||
|
||||
MeterModeId Header_readMeterMode(const Header* this, int i, int column);
|
||||
Meter* Header_addMeterByClass(Header* this, const MeterClass* type, unsigned int param, unsigned int column);
|
||||
|
||||
void Header_reinit(Header* this);
|
||||
|
||||
|
54
HeaderLayout.h
Normal file
54
HeaderLayout.h
Normal file
@ -0,0 +1,54 @@
|
||||
#ifndef HEADER_HeaderLayout
|
||||
#define HEADER_HeaderLayout
|
||||
/*
|
||||
htop - HeaderLayout.h
|
||||
(C) 2021 htop dev team
|
||||
Released under the GNU GPLv2, see the COPYING file
|
||||
in the source distribution for its full text.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "Macros.h"
|
||||
|
||||
|
||||
typedef enum HeaderLayout_ {
|
||||
HF_TWO_50_50,
|
||||
HF_TWO_33_67,
|
||||
HF_TWO_67_33,
|
||||
HF_THREE_33_34_33,
|
||||
HF_THREE_25_25_50,
|
||||
HF_THREE_25_50_25,
|
||||
HF_THREE_50_25_25,
|
||||
HF_THREE_40_20_40,
|
||||
HF_FOUR_25_25_25_25,
|
||||
LAST_HEADER_LAYOUT
|
||||
} HeaderLayout;
|
||||
|
||||
static const struct {
|
||||
uint8_t columns;
|
||||
const uint8_t widths[4];
|
||||
const char* description;
|
||||
} HeaderLayout_layouts[LAST_HEADER_LAYOUT] = {
|
||||
[HF_TWO_50_50] = { 2, { 50, 50, 0, 0 }, "2 columns - 50/50 (default)", },
|
||||
[HF_TWO_33_67] = { 2, { 33, 67, 0, 0 }, "2 columns - 33/67", },
|
||||
[HF_TWO_67_33] = { 2, { 67, 33, 0, 0 }, "2 columns - 67/33", },
|
||||
[HF_THREE_33_34_33] = { 3, { 33, 34, 33, 0 }, "3 columns - 33/34/33", },
|
||||
[HF_THREE_25_25_50] = { 3, { 25, 25, 50, 0 }, "3 columns - 25/25/50", },
|
||||
[HF_THREE_25_50_25] = { 3, { 25, 50, 25, 0 }, "3 columns - 25/50/25", },
|
||||
[HF_THREE_50_25_25] = { 3, { 50, 25, 25, 0 }, "3 columns - 50/25/25", },
|
||||
[HF_THREE_40_20_40] = { 3, { 40, 20, 40, 0 }, "3 columns - 40/20/40", },
|
||||
[HF_FOUR_25_25_25_25] = { 4, { 25, 25, 25, 25 }, "4 columns - 25/25/25/25", },
|
||||
};
|
||||
|
||||
static inline size_t HeaderLayout_getColumns(HeaderLayout hLayout) {
|
||||
/* assert the layout is initialized */
|
||||
assert(0 <= hLayout);
|
||||
assert(hLayout < LAST_HEADER_LAYOUT);
|
||||
assert(HeaderLayout_layouts[hLayout].description[0]);
|
||||
return HeaderLayout_layouts[hLayout].columns;
|
||||
}
|
||||
|
||||
#endif /* HEADER_HeaderLayout */
|
87
HeaderOptionsPanel.c
Normal file
87
HeaderOptionsPanel.c
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
htop - HeaderOptionsPanel.c
|
||||
(C) 2021 htop dev team
|
||||
Released under the GNU GPLv2, see the COPYING file
|
||||
in the source distribution for its full text.
|
||||
*/
|
||||
|
||||
#include "HeaderOptionsPanel.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "CRT.h"
|
||||
#include "FunctionBar.h"
|
||||
#include "Header.h"
|
||||
#include "Object.h"
|
||||
#include "OptionItem.h"
|
||||
#include "ProvideCurses.h"
|
||||
#include "RichString.h"
|
||||
#include "Vector.h"
|
||||
|
||||
|
||||
static const char* const HeaderOptionsFunctions[] = {" ", " ", " ", " ", " ", " ", " ", " ", " ", "Done ", NULL};
|
||||
|
||||
static void HeaderOptionsPanel_delete(Object* object) {
|
||||
Panel* super = (Panel*) object;
|
||||
HeaderOptionsPanel* this = (HeaderOptionsPanel*) object;
|
||||
Panel_done(super);
|
||||
free(this);
|
||||
}
|
||||
|
||||
static HandlerResult HeaderOptionsPanel_eventHandler(Panel* super, int ch) {
|
||||
HeaderOptionsPanel* this = (HeaderOptionsPanel*) super;
|
||||
|
||||
HandlerResult result = IGNORED;
|
||||
int mark;
|
||||
|
||||
switch(ch) {
|
||||
case 0x0a:
|
||||
case 0x0d:
|
||||
case KEY_ENTER:
|
||||
case KEY_MOUSE:
|
||||
case KEY_RECLICK:
|
||||
case ' ':
|
||||
mark = Panel_getSelectedIndex(super);
|
||||
assert(mark >= 0);
|
||||
assert(mark < LAST_HEADER_LAYOUT);
|
||||
|
||||
for (int i = 0; i < LAST_HEADER_LAYOUT; i++)
|
||||
CheckItem_set((CheckItem*)Panel_get(super, i), false);
|
||||
CheckItem_set((CheckItem*)Panel_get(super, mark), true);
|
||||
|
||||
Header_setLayout(this->scr->header, mark);
|
||||
this->settings->changed = true;
|
||||
|
||||
ScreenManager_resize(this->scr);
|
||||
|
||||
result = HANDLED;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
const PanelClass HeaderOptionsPanel_class = {
|
||||
.super = {
|
||||
.extends = Class(Panel),
|
||||
.delete = HeaderOptionsPanel_delete
|
||||
},
|
||||
.eventHandler = HeaderOptionsPanel_eventHandler
|
||||
};
|
||||
|
||||
HeaderOptionsPanel* HeaderOptionsPanel_new(Settings* settings, ScreenManager* scr) {
|
||||
HeaderOptionsPanel* this = AllocThis(HeaderOptionsPanel);
|
||||
Panel* super = (Panel*) this;
|
||||
FunctionBar* fuBar = FunctionBar_new(HeaderOptionsFunctions, NULL, NULL);
|
||||
Panel_init(super, 1, 1, 1, 1, Class(CheckItem), true, fuBar);
|
||||
|
||||
this->scr = scr;
|
||||
this->settings = settings;
|
||||
|
||||
Panel_setHeader(super, "Header Layout");
|
||||
for (int i = 0; i < LAST_HEADER_LAYOUT; i++) {
|
||||
Panel_add(super, (Object*) CheckItem_newByVal(HeaderLayout_layouts[i].description, false));
|
||||
}
|
||||
CheckItem_set((CheckItem*)Panel_get(super, settings->hLayout), true);
|
||||
return this;
|
||||
}
|
26
HeaderOptionsPanel.h
Normal file
26
HeaderOptionsPanel.h
Normal file
@ -0,0 +1,26 @@
|
||||
#ifndef HEADER_HeaderOptionsPanel
|
||||
#define HEADER_HeaderOptionsPanel
|
||||
/*
|
||||
htop - ColorsPanel.h
|
||||
(C) 2021 htop dev team
|
||||
Released under the GNU GPLv2, see the COPYING file
|
||||
in the source distribution for its full text.
|
||||
*/
|
||||
|
||||
#include "Panel.h"
|
||||
#include "ScreenManager.h"
|
||||
#include "Settings.h"
|
||||
|
||||
|
||||
typedef struct HeaderOptionsPanel_ {
|
||||
Panel super;
|
||||
|
||||
ScreenManager* scr;
|
||||
Settings* settings;
|
||||
} HeaderOptionsPanel;
|
||||
|
||||
extern const PanelClass HeaderOptionsPanel_class;
|
||||
|
||||
HeaderOptionsPanel* HeaderOptionsPanel_new(Settings* settings, ScreenManager* scr);
|
||||
|
||||
#endif /* HEADER_HeaderOptionsPanel */
|
@ -45,6 +45,7 @@ myhtopsources = \
|
||||
FunctionBar.c \
|
||||
Hashtable.c \
|
||||
Header.c \
|
||||
HeaderOptionsPanel.c \
|
||||
HostnameMeter.c \
|
||||
IncSet.c \
|
||||
InfoScreen.c \
|
||||
@ -102,6 +103,8 @@ myhtopheaders = \
|
||||
FunctionBar.h \
|
||||
Hashtable.h \
|
||||
Header.h \
|
||||
HeaderLayout.h \
|
||||
HeaderOptionsPanel.h \
|
||||
HostnameMeter.h \
|
||||
IncSet.h \
|
||||
InfoScreen.h \
|
||||
|
@ -185,7 +185,6 @@ static HandlerResult MetersPanel_eventHandler(Panel* super, int ch) {
|
||||
Header* header = this->scr->header;
|
||||
this->settings->changed = true;
|
||||
Header_calculateHeight(header);
|
||||
Header_draw(header);
|
||||
ScreenManager_resize(this->scr);
|
||||
}
|
||||
return result;
|
||||
|
149
Settings.c
149
Settings.c
@ -25,21 +25,27 @@ in the source distribution for its full text.
|
||||
void Settings_delete(Settings* this) {
|
||||
free(this->filename);
|
||||
free(this->fields);
|
||||
for (unsigned int i = 0; i < ARRAYSIZE(this->columns); i++) {
|
||||
String_freeArray(this->columns[i].names);
|
||||
free(this->columns[i].modes);
|
||||
for (unsigned int i = 0; i < HeaderLayout_getColumns(this->hLayout); i++) {
|
||||
if (this->hColumns[i].names) {
|
||||
for (uint8_t j = 0; j < this->hColumns[i].len; j++)
|
||||
free(this->hColumns[i].names[j]);
|
||||
free(this->hColumns[i].names);
|
||||
}
|
||||
free(this->hColumns[i].modes);
|
||||
}
|
||||
free(this->hColumns);
|
||||
free(this);
|
||||
}
|
||||
|
||||
static void Settings_readMeters(Settings* this, const char* line, int column) {
|
||||
static void Settings_readMeters(Settings* this, const char* line, unsigned int column) {
|
||||
char* trim = String_trim(line);
|
||||
char** ids = String_split(trim, ' ', NULL);
|
||||
free(trim);
|
||||
this->columns[column].names = ids;
|
||||
column = MINIMUM(column, HeaderLayout_getColumns(this->hLayout) - 1);
|
||||
this->hColumns[column].names = ids;
|
||||
}
|
||||
|
||||
static void Settings_readMeterModes(Settings* this, const char* line, int column) {
|
||||
static void Settings_readMeterModes(Settings* this, const char* line, unsigned int column) {
|
||||
char* trim = String_trim(line);
|
||||
char** ids = String_split(trim, ' ', NULL);
|
||||
free(trim);
|
||||
@ -47,13 +53,14 @@ static void Settings_readMeterModes(Settings* this, const char* line, int column
|
||||
for (int i = 0; ids[i]; i++) {
|
||||
len++;
|
||||
}
|
||||
this->columns[column].len = len;
|
||||
column = MINIMUM(column, HeaderLayout_getColumns(this->hLayout) - 1);
|
||||
this->hColumns[column].len = len;
|
||||
int* modes = len ? xCalloc(len, sizeof(int)) : NULL;
|
||||
for (int i = 0; i < len; i++) {
|
||||
modes[i] = atoi(ids[i]);
|
||||
}
|
||||
String_freeArray(ids);
|
||||
this->columns[column].modes = modes;
|
||||
this->hColumns[column].modes = modes;
|
||||
}
|
||||
|
||||
static void Settings_defaultMeters(Settings* this, unsigned int initialCpuCount) {
|
||||
@ -62,50 +69,50 @@ static void Settings_defaultMeters(Settings* this, unsigned int initialCpuCount)
|
||||
sizes[1]++;
|
||||
}
|
||||
for (int i = 0; i < 2; i++) {
|
||||
this->columns[i].names = xCalloc(sizes[i] + 1, sizeof(char*));
|
||||
this->columns[i].modes = xCalloc(sizes[i], sizeof(int));
|
||||
this->columns[i].len = sizes[i];
|
||||
this->hColumns[i].names = xCalloc(sizes[i] + 1, sizeof(char*));
|
||||
this->hColumns[i].modes = xCalloc(sizes[i], sizeof(int));
|
||||
this->hColumns[i].len = sizes[i];
|
||||
}
|
||||
int r = 0;
|
||||
|
||||
if (initialCpuCount > 128) {
|
||||
// Just show the average, ricers need to config for impressive screenshots
|
||||
this->columns[0].names[0] = xStrdup("CPU");
|
||||
this->columns[0].modes[0] = BAR_METERMODE;
|
||||
this->hColumns[0].names[0] = xStrdup("CPU");
|
||||
this->hColumns[0].modes[0] = BAR_METERMODE;
|
||||
} else if (initialCpuCount > 32) {
|
||||
this->columns[0].names[0] = xStrdup("LeftCPUs8");
|
||||
this->columns[0].modes[0] = BAR_METERMODE;
|
||||
this->columns[1].names[r] = xStrdup("RightCPUs8");
|
||||
this->columns[1].modes[r++] = BAR_METERMODE;
|
||||
this->hColumns[0].names[0] = xStrdup("LeftCPUs8");
|
||||
this->hColumns[0].modes[0] = BAR_METERMODE;
|
||||
this->hColumns[1].names[r] = xStrdup("RightCPUs8");
|
||||
this->hColumns[1].modes[r++] = BAR_METERMODE;
|
||||
} else if (initialCpuCount > 16) {
|
||||
this->columns[0].names[0] = xStrdup("LeftCPUs4");
|
||||
this->columns[0].modes[0] = BAR_METERMODE;
|
||||
this->columns[1].names[r] = xStrdup("RightCPUs4");
|
||||
this->columns[1].modes[r++] = BAR_METERMODE;
|
||||
this->hColumns[0].names[0] = xStrdup("LeftCPUs4");
|
||||
this->hColumns[0].modes[0] = BAR_METERMODE;
|
||||
this->hColumns[1].names[r] = xStrdup("RightCPUs4");
|
||||
this->hColumns[1].modes[r++] = BAR_METERMODE;
|
||||
} else if (initialCpuCount > 8) {
|
||||
this->columns[0].names[0] = xStrdup("LeftCPUs2");
|
||||
this->columns[0].modes[0] = BAR_METERMODE;
|
||||
this->columns[1].names[r] = xStrdup("RightCPUs2");
|
||||
this->columns[1].modes[r++] = BAR_METERMODE;
|
||||
this->hColumns[0].names[0] = xStrdup("LeftCPUs2");
|
||||
this->hColumns[0].modes[0] = BAR_METERMODE;
|
||||
this->hColumns[1].names[r] = xStrdup("RightCPUs2");
|
||||
this->hColumns[1].modes[r++] = BAR_METERMODE;
|
||||
} else if (initialCpuCount > 4) {
|
||||
this->columns[0].names[0] = xStrdup("LeftCPUs");
|
||||
this->columns[0].modes[0] = BAR_METERMODE;
|
||||
this->columns[1].names[r] = xStrdup("RightCPUs");
|
||||
this->columns[1].modes[r++] = BAR_METERMODE;
|
||||
this->hColumns[0].names[0] = xStrdup("LeftCPUs");
|
||||
this->hColumns[0].modes[0] = BAR_METERMODE;
|
||||
this->hColumns[1].names[r] = xStrdup("RightCPUs");
|
||||
this->hColumns[1].modes[r++] = BAR_METERMODE;
|
||||
} else {
|
||||
this->columns[0].names[0] = xStrdup("AllCPUs");
|
||||
this->columns[0].modes[0] = BAR_METERMODE;
|
||||
this->hColumns[0].names[0] = xStrdup("AllCPUs");
|
||||
this->hColumns[0].modes[0] = BAR_METERMODE;
|
||||
}
|
||||
this->columns[0].names[1] = xStrdup("Memory");
|
||||
this->columns[0].modes[1] = BAR_METERMODE;
|
||||
this->columns[0].names[2] = xStrdup("Swap");
|
||||
this->columns[0].modes[2] = BAR_METERMODE;
|
||||
this->columns[1].names[r] = xStrdup("Tasks");
|
||||
this->columns[1].modes[r++] = TEXT_METERMODE;
|
||||
this->columns[1].names[r] = xStrdup("LoadAverage");
|
||||
this->columns[1].modes[r++] = TEXT_METERMODE;
|
||||
this->columns[1].names[r] = xStrdup("Uptime");
|
||||
this->columns[1].modes[r++] = TEXT_METERMODE;
|
||||
this->hColumns[0].names[1] = xStrdup("Memory");
|
||||
this->hColumns[0].modes[1] = BAR_METERMODE;
|
||||
this->hColumns[0].names[2] = xStrdup("Swap");
|
||||
this->hColumns[0].modes[2] = BAR_METERMODE;
|
||||
this->hColumns[1].names[r] = xStrdup("Tasks");
|
||||
this->hColumns[1].modes[r++] = TEXT_METERMODE;
|
||||
this->hColumns[1].names[r] = xStrdup("LoadAverage");
|
||||
this->hColumns[1].modes[r++] = TEXT_METERMODE;
|
||||
this->hColumns[1].names[r] = xStrdup("Uptime");
|
||||
this->hColumns[1].modes[r++] = TEXT_METERMODE;
|
||||
}
|
||||
|
||||
static void Settings_readFields(Settings* settings, const char* line) {
|
||||
@ -250,6 +257,12 @@ static bool Settings_read(Settings* this, const char* fileName, unsigned int ini
|
||||
} else if (String_eq(option[0], "enable_mouse")) {
|
||||
this->enableMouse = atoi(option[1]);
|
||||
#endif
|
||||
} else if (String_eq(option[0], "header_layout")) {
|
||||
this->hLayout = atoi(option[1]);
|
||||
if (this->hLayout < 0 || this->hLayout >= LAST_HEADER_LAYOUT)
|
||||
this->hLayout = HF_TWO_50_50;
|
||||
free(this->hColumns);
|
||||
this->hColumns = xCalloc(HeaderLayout_getColumns(this->hLayout), sizeof(MeterColumnSetting));
|
||||
} else if (String_eq(option[0], "left_meters")) {
|
||||
Settings_readMeters(this, option[1], 0);
|
||||
didReadMeters = true;
|
||||
@ -262,6 +275,12 @@ static bool Settings_read(Settings* this, const char* fileName, unsigned int ini
|
||||
} else if (String_eq(option[0], "right_meter_modes")) {
|
||||
Settings_readMeterModes(this, option[1], 1);
|
||||
didReadMeters = true;
|
||||
} else if (String_startsWith(option[0], "column_meters_")) {
|
||||
Settings_readMeters(this, option[1], atoi(option[0] + strlen("column_meters_")));
|
||||
didReadMeters = true;
|
||||
} else if (String_startsWith(option[0], "column_meter_modes_")) {
|
||||
Settings_readMeterModes(this, option[1], atoi(option[0] + strlen("column_meter_modes_")));
|
||||
didReadMeters = true;
|
||||
} else if (String_eq(option[0], "hide_function_bar")) {
|
||||
this->hideFunctionBar = atoi(option[1]);
|
||||
#ifdef HAVE_LIBHWLOC
|
||||
@ -294,19 +313,19 @@ static void writeFields(FILE* fd, const ProcessField* fields, Hashtable* columns
|
||||
fprintf(fd, "\n");
|
||||
}
|
||||
|
||||
static void writeMeters(const Settings* this, FILE* fd, int column) {
|
||||
static void writeMeters(const Settings* this, FILE* fd, unsigned int column) {
|
||||
const char* sep = "";
|
||||
for (int i = 0; i < this->columns[column].len; i++) {
|
||||
fprintf(fd, "%s%s", sep, this->columns[column].names[i]);
|
||||
for (uint8_t i = 0; i < this->hColumns[column].len; i++) {
|
||||
fprintf(fd, "%s%s", sep, this->hColumns[column].names[i]);
|
||||
sep = " ";
|
||||
}
|
||||
fprintf(fd, "\n");
|
||||
}
|
||||
|
||||
static void writeMeterModes(const Settings* this, FILE* fd, int column) {
|
||||
static void writeMeterModes(const Settings* this, FILE* fd, unsigned int column) {
|
||||
const char* sep = "";
|
||||
for (int i = 0; i < this->columns[column].len; i++) {
|
||||
fprintf(fd, "%s%d", sep, this->columns[column].modes[i]);
|
||||
for (uint8_t i = 0; i < this->hColumns[column].len; i++) {
|
||||
fprintf(fd, "%s%d", sep, this->hColumns[column].modes[i]);
|
||||
sep = " ";
|
||||
}
|
||||
fprintf(fd, "\n");
|
||||
@ -365,10 +384,13 @@ int Settings_write(const Settings* this, bool onCrash) {
|
||||
fprintf(fd, "enable_mouse=%d\n", (int) this->enableMouse);
|
||||
#endif
|
||||
fprintf(fd, "delay=%d\n", (int) this->delay);
|
||||
fprintf(fd, "left_meters="); writeMeters(this, fd, 0);
|
||||
fprintf(fd, "left_meter_modes="); writeMeterModes(this, fd, 0);
|
||||
fprintf(fd, "right_meters="); writeMeters(this, fd, 1);
|
||||
fprintf(fd, "right_meter_modes="); writeMeterModes(this, fd, 1);
|
||||
fprintf(fd, "header_layout=%d\n", (int) this->hLayout);
|
||||
for (unsigned int i = 0; i < HeaderLayout_getColumns(this->hLayout); i++) {
|
||||
fprintf(fd, "column_meters_%u=", i);
|
||||
writeMeters(this, fd, i);
|
||||
fprintf(fd, "column_meter_modes_%u=", i);
|
||||
writeMeterModes(this, fd, i);
|
||||
}
|
||||
fprintf(fd, "hide_function_bar=%d\n", (int) this->hideFunctionBar);
|
||||
#ifdef HAVE_LIBHWLOC
|
||||
fprintf(fd, "topology_affinity=%d\n", (int) this->topologyAffinity);
|
||||
@ -392,6 +414,8 @@ Settings* Settings_new(unsigned int initialCpuCount, Hashtable* dynamicColumns)
|
||||
Settings* this = xCalloc(1, sizeof(Settings));
|
||||
|
||||
this->dynamicColumns = dynamicColumns;
|
||||
this->hLayout = HF_TWO_50_50;
|
||||
this->hColumns = xCalloc(HeaderLayout_getColumns(this->hLayout), sizeof(MeterColumnSetting));
|
||||
this->sortKey = PERCENT_CPU;
|
||||
this->treeSortKey = PID;
|
||||
this->direction = -1;
|
||||
@ -521,3 +545,26 @@ void Settings_enableReadonly(void) {
|
||||
bool Settings_isReadonly(void) {
|
||||
return readonly;
|
||||
}
|
||||
|
||||
void Settings_setHeaderLayout(Settings* this, HeaderLayout hLayout) {
|
||||
unsigned int oldColumns = HeaderLayout_getColumns(this->hLayout);
|
||||
unsigned int newColumns = HeaderLayout_getColumns(hLayout);
|
||||
|
||||
if (newColumns > oldColumns) {
|
||||
this->hColumns = xReallocArray(this->hColumns, newColumns, sizeof(MeterColumnSetting));
|
||||
memset(this->hColumns + oldColumns, 0, (newColumns - oldColumns) * sizeof(MeterColumnSetting));
|
||||
} else if (newColumns < oldColumns) {
|
||||
for (unsigned int i = newColumns; i < oldColumns; i++) {
|
||||
if (this->hColumns[i].names) {
|
||||
for (uint8_t j = 0; j < this->hColumns[i].len; j++)
|
||||
free(this->hColumns[i].names[j]);
|
||||
free(this->hColumns[i].names);
|
||||
}
|
||||
free(this->hColumns[i].modes);
|
||||
}
|
||||
this->hColumns = xReallocArray(this->hColumns, newColumns, sizeof(MeterColumnSetting));
|
||||
}
|
||||
|
||||
this->hLayout = hLayout;
|
||||
this->changed = true;
|
||||
}
|
||||
|
10
Settings.h
10
Settings.h
@ -13,20 +13,22 @@ in the source distribution for its full text.
|
||||
#include <stdint.h>
|
||||
|
||||
#include "Hashtable.h"
|
||||
#include "HeaderLayout.h"
|
||||
#include "Process.h"
|
||||
|
||||
|
||||
#define DEFAULT_DELAY 15
|
||||
|
||||
typedef struct {
|
||||
int len;
|
||||
uint8_t len;
|
||||
char** names;
|
||||
int* modes;
|
||||
} MeterColumnSettings;
|
||||
} MeterColumnSetting;
|
||||
|
||||
typedef struct Settings_ {
|
||||
char* filename;
|
||||
MeterColumnSettings columns[2];
|
||||
HeaderLayout hLayout;
|
||||
MeterColumnSetting* hColumns;
|
||||
Hashtable* dynamicColumns;
|
||||
|
||||
ProcessField* fields;
|
||||
@ -104,4 +106,6 @@ void Settings_enableReadonly(void);
|
||||
|
||||
bool Settings_isReadonly(void);
|
||||
|
||||
void Settings_setHeaderLayout(Settings* this, HeaderLayout hLayout);
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user