vdr-plugin-tvguide/recmenuitem.h

698 lines
21 KiB
C
Raw Normal View History

2013-07-09 00:17:42 +02:00
#ifndef __TVGUIDE_RECMENUITEM_H
#define __TVGUIDE_RECMENUITEM_H
#define AUTO_ADVANCE_TIMEOUT 1500
2013-12-07 15:51:50 +01:00
#include <string>
#include <vdr/tools.h>
#include "styledpixmap.h"
#include "timerconflict.h"
#include "searchtimer.h"
2013-12-07 15:51:50 +01:00
2013-07-09 00:17:42 +02:00
enum eRecMenuState {
rmsConsumed,
rmsNotConsumed,
rmsRefresh,
rmsContinue,
rmsClose,
rmsDisabled,
//INSTANT TIMER
2013-07-09 00:17:42 +02:00
rmsInstantRecord,
rmsInstantRecordFolder,
2013-07-09 00:17:42 +02:00
rmsIgnoreTimerConflict,
rmsDeleteTimerConflictMenu,
rmsEditTimerConflictMenu,
rmsSearchRerunsTimerConflictMenu,
2013-07-09 00:17:42 +02:00
rmsSaveTimerConflictMenu,
rmsTimerConflictShowInfo,
2020-08-04 15:08:37 +02:00
rmsOnOffTimer,
2013-07-09 00:17:42 +02:00
rmsDeleteTimer,
rmsDeleteTimerConfirmation,
rmsEditTimer,
rmsSaveTimer,
//SEARCH
2013-07-09 00:17:42 +02:00
rmsSearch,
rmsSearchWithOptions,
rmsSearchPerform,
rmsSearchShowInfo,
rmsSearchRecord,
rmsSearchRecordConfirm,
rmsSearchNothingFoundConfirm,
//SERIES TIMER
2013-07-09 00:17:42 +02:00
rmsSeriesTimer,
rmsSeriesTimerFolder,
2013-07-09 00:17:42 +02:00
rmsSeriesTimerCreate,
//SEARCHTIMER
2013-07-09 00:17:42 +02:00
rmsSearchTimer,
rmsSearchTimerOptions,
rmsSearchTimers,
rmsSearchTimerEdit,
rmsSearchTimerTest,
rmsSearchTimerSave,
rmsSearchTimerCreateWithTemplate,
rmsSearchTimerDeleteConfirm,
rmsSearchTimerDelete,
rmsSearchTimerDeleteWithTimers,
rmsSearchTimerRecord,
//SWITCHTIMER
2013-07-09 00:17:42 +02:00
rmsSwitchTimer,
rmsSwitchTimerCreate,
rmsSwitchTimerDelete,
//RECORDINGS SEARCH
2013-07-09 00:17:42 +02:00
rmsRecordingSearch,
rmsRecordingSearchResult,
//TIMER CONFLICTS
2013-07-09 00:17:42 +02:00
rmsTimerConflict,
rmsTimerConflicts,
rmsTimerConflictIgnoreReruns,
rmsTimerConflictRecordRerun,
//TIMELINE
rmsTimeline,
2014-01-03 11:56:45 +01:00
rmsTimelineTimerEdit,
rmsTimelineTimerSave,
rmsTimelineTimerDelete,
//FAVORITES
rmsFavoritesRecord,
rmsFavoritesRecordConfirm,
rmsFavoritesNow,
rmsFavoritesNext,
rmsFavoritesUser1,
rmsFavoritesUser2,
rmsFavoritesUser3,
rmsFavoritesUser4,
2013-07-09 00:17:42 +02:00
};
enum eDependend {
eGreater,
eLower,
};
2013-07-09 00:17:42 +02:00
// --- cRecMenuItem -------------------------------------------------------------
class cRecMenuItem : public cListObject, public cStyledPixmap {
protected:
int x, y;
int width, height;
bool selectable;
bool active;
bool defaultBackground;
2013-07-09 00:17:42 +02:00
bool drawn;
eRecMenuState action;
tColor colorText;
tColor colorTextBack;
const cFont *font;
const cFont *fontSmall;
const cFont *fontLarge;
2013-07-09 00:17:42 +02:00
public:
cRecMenuItem(void);
virtual ~cRecMenuItem(void);
void SetGeometry(int x, int y, int width);
virtual void SetPixmaps(void);
virtual int GetHeight(void) { return height; };
virtual int GetWidth(void) { return 0; };
virtual void CalculateHeight(int textWidth) {};
2019-11-10 13:54:35 +01:00
virtual void SetActive(void) { this->active = true; }
virtual void setInactive(void) { this->active = false; }
2013-07-09 00:17:42 +02:00
bool isSelectable(void) { return selectable; }
2019-11-10 13:52:16 +01:00
bool IsActive(void) { return active; }
2013-07-09 00:17:42 +02:00
virtual void setBackground(void);
virtual void Draw(void) {};
virtual void Hide(void) { if (pixmap) pixmap->SetLayer(-1);};
virtual void Show(void) { if (pixmap) pixmap->SetLayer(4);};
2013-07-09 00:17:42 +02:00
virtual int GetIntValue(void) { return -1; };
virtual time_t GetTimeValue(void) { return 0; };
virtual bool GetBoolValue(void) { return false; };
virtual cString GetStringValue(void) { return cString(""); };
2019-11-10 13:45:48 +01:00
virtual const cEvent *GetEvent(void) { return NULL; };
2013-07-09 00:17:42 +02:00
virtual eRecMenuState ProcessKey(eKeys Key) { return rmsNotConsumed; };
};
// --- cRecMenuItemButton -------------------------------------------------------
class cRecMenuItemButton : public cRecMenuItem {
private:
cString text;
bool halfWidth;
2013-07-20 11:48:00 +02:00
bool alignLeft;
const cFont *fontButtons;
2014-01-10 23:07:52 +01:00
cPixmap *pixmapText;
2013-07-09 00:17:42 +02:00
public:
cRecMenuItemButton(const char *text, eRecMenuState action, bool active, bool halfWidth = false, bool alignLeft = false, bool largeFont = false);
2013-07-09 00:17:42 +02:00
virtual ~cRecMenuItemButton(void);
int GetWidth(void);
void SetPixmaps(void);
void Draw(void);
2014-01-10 23:07:52 +01:00
void Hide(void);
void Show(void);
cString GetStringValue(void) { return text; };
2013-07-09 00:17:42 +02:00
eRecMenuState ProcessKey(eKeys Key);
};
// --- cRecMenuItemButtonYesNo -------------------------------------------------------
class cRecMenuItemButtonYesNo : public cRecMenuItem {
private:
cString textYes;
cString textNo;
eRecMenuState actionNo;
bool yesActive;
cStyledPixmap *pixmapNo;
tColor colorTextNo;
tColor colorTextNoBack;
2013-07-09 00:17:42 +02:00
public:
cRecMenuItemButtonYesNo(cString textYes,
cString textNo,
eRecMenuState actionYes,
eRecMenuState actionNo,
bool active);
virtual ~cRecMenuItemButtonYesNo(void);
void SetPixmaps(void);
void setBackground(void);
void Hide(void);
void Show(void);
eRecMenuState ProcessKey(eKeys Key);
void Draw(void);
};
// --- cRecMenuItemInfo -------------------------------------------------------
class cRecMenuItemInfo : public cRecMenuItem {
private:
2019-11-09 11:22:02 +01:00
int numLines;
2013-07-09 00:17:42 +02:00
cString text;
2019-11-09 11:22:02 +01:00
std::string line1;
std::string line2;
std::string line3;
std::string line4;
2013-07-09 00:17:42 +02:00
cTextWrapper wrapper;
int border;
const cFont *fontInfo;
2013-07-09 00:17:42 +02:00
public:
cRecMenuItemInfo(const char *text, bool largeFont = false);
2019-11-09 11:22:02 +01:00
cRecMenuItemInfo(std::string line1, int numLines = 1, std::string line2 = "", std::string line3 = "", std::string line4 = "", int width = 80, bool largeFont = false);
2013-07-09 00:17:42 +02:00
virtual ~cRecMenuItemInfo(void);
void setBackground(void);
void CalculateHeight(int textWidth);
void Draw(void);
};
// --- cRecMenuItemInt -------------------------------------------------------
class cRecMenuItemInt : public cRecMenuItem {
private:
cString text;
int currentVal;
int *callback;
2013-07-09 00:17:42 +02:00
int minVal;
int maxVal;
cPixmap *pixmapVal;
bool fresh;
void DrawValue(void);
public:
cRecMenuItemInt(cString text,
int minVal,
int maxVal,
bool active = false,
int *callback = NULL,
2019-07-15 15:23:14 +02:00
eRecMenuState action = rmsNotConsumed);
2013-07-09 00:17:42 +02:00
virtual ~cRecMenuItemInt(void);
void SetPixmaps(void);
void Hide(void);
void Show(void);
void setBackground(void);
eRecMenuState ProcessKey(eKeys Key);
void Draw(void);
int GetIntValue(void) { return currentVal; };
};
// --- cRecMenuItemBool -------------------------------------------------------
class cRecMenuItemBool : public cRecMenuItem {
private:
cString text;
bool yes;
bool *callback;
2013-07-09 00:17:42 +02:00
cPixmap *pixmapVal;
bool refresh;
void DrawValue(void);
public:
cRecMenuItemBool(cString text,
bool active = false,
bool *callback = NULL,
2019-06-16 14:48:20 +02:00
eRecMenuState action = rmsNotConsumed,
2019-07-15 15:23:14 +02:00
bool refresh = false);
2019-06-16 14:48:20 +02:00
cRecMenuItemBool(cString text,
bool active = false,
int *callback = NULL,
eRecMenuState action = rmsNotConsumed,
2019-07-15 15:23:14 +02:00
bool refresh = false);
2013-07-09 00:17:42 +02:00
virtual ~cRecMenuItemBool(void);
void SetPixmaps(void);
void Hide(void);
void Show(void);
eRecMenuState ProcessKey(eKeys Key);
void Draw(void);
bool GetBoolValue(void) { return yes; };
};
// --- cRecMenuItemSelect -------------------------------------------------------
class cRecMenuItemSelect : public cRecMenuItem {
private:
cString text;
int currentVal;
int *callback;
bool refresh;
std::vector<std::string> strings;
2013-07-09 00:17:42 +02:00
int numValues;
cPixmap *pixmapVal;
void DrawValue(void);
public:
cRecMenuItemSelect(cString text,
std::vector<std::string> Strings,
bool active = false,
int *callback = NULL,
eRecMenuState action = rmsNotConsumed,
2019-07-15 15:23:14 +02:00
bool refresh = false);
2013-07-09 00:17:42 +02:00
virtual ~cRecMenuItemSelect(void);
void SetPixmaps(void);
void Hide(void);
void Show(void);
eRecMenuState ProcessKey(eKeys Key);
void Draw(void);
int GetIntValue(void) { return currentVal; };
cString GetStringValue(void) { return strings[currentVal].c_str(); };
2013-07-09 00:17:42 +02:00
};
// --- cRecMenuItemSelectDirectory -------------------------------------------------------
class cRecMenuItemSelectDirectory : public cRecMenuItem {
private:
cString text;
std::string originalFolder;
std::vector<std::string> folders;
int currentVal;
char *callback;
int numValues;
cPixmap *pixmapVal;
void DrawValue(void);
int GetInitial(void);
void SetCallback(void);
public:
cRecMenuItemSelectDirectory(cString text,
std::string originalFolder,
bool active = false,
char *callback = NULL,
eRecMenuState action = rmsNotConsumed,
2019-07-15 15:23:14 +02:00
bool isSearchTimer = false);
virtual ~cRecMenuItemSelectDirectory(void);
void SetPixmaps(void);
void Hide(void);
void Show(void);
eRecMenuState ProcessKey(eKeys Key);
void Draw(void);
};
2013-07-09 00:17:42 +02:00
// --- cRecMenuItemText -------------------------------------------------------
class cRecMenuItemText : public cRecMenuItem {
private:
cString title;
char *value;
char *callback;
2013-07-09 00:17:42 +02:00
int length;
const char *allowed;
int pos, offset;
bool insert, newchar, uppercase;
int lengthUtf8;
uint *valueUtf8;
uint *allowedUtf8;
uint *charMapUtf8;
uint *currentCharUtf8;
eKeys lastKey;
cTimeMs autoAdvanceTimeout;
cPixmap *pixmapVal;
cStyledPixmap *pixmapKeyboard;
cPixmap *pixmapKeyboardHighlight;
cPixmap *pixmapKeyboardIcons;
int keyboardWidth;
int gridWidth;
int gridHeight;
int keyboardHeight;
bool keyboardDrawn;
uint *IsAllowed(uint c);
void AdvancePos(void);
uint Inc(uint c, bool Up);
void Type(uint c);
void Insert(void);
void Delete(void);
void EnterEditMode(void);
void LeaveEditMode(bool SaveValue = false);
bool InEditMode(void) { return valueUtf8 != NULL; };
void SetText(void);
void ActivateKeyboard(void);
void DeactivateKeyboard(void);
void HighlightSMSKey(int num);
void ClearSMSKey(void);
char *GetSMSKeys(int num);
void DrawValue(char *newValue);
public:
cRecMenuItemText(cString title,
int length,
bool active = false,
char *callback = NULL);
2013-07-09 00:17:42 +02:00
virtual ~cRecMenuItemText(void);
void SetPixmaps(void);
void Hide(void);
void Show(void);
void setBackground(void);
eRecMenuState ProcessKey(eKeys Key);
void Draw(void);
cString GetStringValue(void) { return value; };
};
// --- cRecMenuItemTime -------------------------------------------------------
class cRecMenuItemTime : public cRecMenuItem {
private:
cString text;
int value;
int *callback;
2013-07-09 00:17:42 +02:00
int mm;
int hh;
int pos;
bool fresh;
cPixmap *pixmapVal;
void DrawValue(void);
public:
cRecMenuItemTime(cString text,
bool active = false,
int *callback = NULL,
2019-07-15 15:23:14 +02:00
eRecMenuState action = rmsNotConsumed);
2013-07-09 00:17:42 +02:00
virtual ~cRecMenuItemTime(void);
void SetPixmaps(void);
void Hide(void);
void Show(void);
eRecMenuState ProcessKey(eKeys Key);
void Draw(void);
int GetIntValue(void) { return value; };
};
// --- cRecMenuItemDay -------------------------------------------------------
class cRecMenuItemDay : public cRecMenuItem {
private:
cString text;
time_t currentVal;
time_t *callback;
2013-07-09 00:17:42 +02:00
cPixmap *pixmapVal;
void DrawValue(void);
public:
cRecMenuItemDay(cString text,
bool active = false,
time_t *callback = NULL,
eRecMenuState action = rmsNotConsumed);
2013-07-09 00:17:42 +02:00
virtual ~cRecMenuItemDay(void);
void SetPixmaps(void);
void Hide(void);
void Show(void);
eRecMenuState ProcessKey(eKeys Key);
void Draw(void);
time_t GetTimeValue(void) { return currentVal; };
};
// --- cRecMenuItemTimer -------------------------------------------------------
class cRecMenuItemTimer : public cRecMenuItem {
private:
const cTimer *timer;
eRecMenuState action2;
eRecMenuState action3;
eRecMenuState action4;
2013-07-09 00:17:42 +02:00
int iconActive;
cPixmap *pixmapIcons;
cPixmap *pixmapStatus;
time_t conflictStart;
time_t conflictStop;
time_t overlapStart;
time_t overlapStop;
int DrawIcons(void);
void DrawTimerConflict(void);
public:
cRecMenuItemTimer(const cTimer *timer,
eRecMenuState action1,
eRecMenuState action2,
eRecMenuState action3,
eRecMenuState action4,
2013-07-09 00:17:42 +02:00
time_t conflictStart,
time_t conflictStop,
time_t overlapStart,
time_t overlapStop,
bool active);
virtual ~cRecMenuItemTimer(void);
void SetPixmaps(void);
void Hide(void);
void Show(void);
eRecMenuState ProcessKey(eKeys Key);
void Draw(void);
};
// --- cRecMenuItemTimerConflictHeader -------------------------------------------------------
class cRecMenuItemTimerConflictHeader: public cRecMenuItem {
private:
cPixmap *pixmapStatus;
time_t conflictStart;
time_t conflictStop;
time_t overlapStart;
time_t overlapStop;
public:
cRecMenuItemTimerConflictHeader(time_t conflictStart,
time_t conflictStop,
time_t overlapStart,
time_t overlapStop);
virtual ~cRecMenuItemTimerConflictHeader(void);
void SetPixmaps(void);
void Hide(void);
void Show(void);
void setBackground(void);
void Draw(void);
};
// --- cRecMenuItemEvent -------------------------------------------------------
class cRecMenuItemEvent : public cRecMenuItem {
private:
const cEvent *event;
eRecMenuState action2;
int iconActive;
cPixmap *pixmapText;
cPixmap *pixmapIcons;
int DrawIcons(void);
public:
cRecMenuItemEvent(const cEvent *event,
eRecMenuState action1,
eRecMenuState action2,
bool active);
virtual ~cRecMenuItemEvent(void);
void SetPixmaps(void);
void Hide(void);
void Show(void);
2019-11-10 13:45:48 +01:00
const cEvent *GetEvent(void) { return event; };
2013-07-09 00:17:42 +02:00
eRecMenuState ProcessKey(eKeys Key);
void Draw(void);
};
// --- cRecMenuItemChannelChooser -------------------------------------------------------
class cRecMenuItemChannelChooser : public cRecMenuItem {
private:
cString text;
2019-07-18 16:41:04 +02:00
#if VDRVERSNUM >= 20301
const cChannels *channels;
const cChannel *chanNew;
#else
cChannels *channels;
cChannel *chanNew;
#endif
2018-03-08 13:02:38 +01:00
const cChannel *channel;
2013-07-09 00:17:42 +02:00
int channelNumber;
int *callback;
2013-07-09 00:17:42 +02:00
bool initialChannelSet;
bool fresh;
cPixmap *pixmapChannel;
void DrawValue(void);
public:
cRecMenuItemChannelChooser (cString text,
bool active = false,
int *callback = NULL,
2019-07-15 15:23:14 +02:00
eRecMenuState action = rmsNotConsumed);
2013-07-09 00:17:42 +02:00
virtual ~cRecMenuItemChannelChooser(void);
void SetPixmaps(void);
void Hide(void);
void Show(void);
eRecMenuState ProcessKey(eKeys Key);
void Draw(void);
int GetIntValue(void);
};
// --- cRecMenuItemDayChooser -------------------------------------------------------
class cRecMenuItemDayChooser : public cRecMenuItem {
private:
cString text;
int weekdays;
int *callback;
bool epgsearchMode;
2013-07-09 00:17:42 +02:00
std::string days;
int daysX;
int daysY;
int daysSize;
int selectedDay;
cPixmap *pixmapWeekdays;
cPixmap *pixmapWeekdaysSelect;
void SetSizes(void);
void DrawDays(void);
void DrawHighlight(int day);
void ToggleDay(void);
bool WeekDaySet(unsigned day);
public:
cRecMenuItemDayChooser (cString text,
bool active = false,
2019-07-15 15:23:14 +02:00
int *callback = NULL);
2013-07-09 00:17:42 +02:00
virtual ~cRecMenuItemDayChooser(void);
void SetPixmaps(void);
void Hide(void);
void Show(void);
void setBackground(void);
eRecMenuState ProcessKey(eKeys Key);
void Draw(void);
int GetIntValue(void) { return weekdays;} ;
};
// --- cRecMenuItemRecording -------------------------------------------------------
class cRecMenuItemRecording : public cRecMenuItem {
private:
2018-03-08 13:02:38 +01:00
const cRecording *recording;
2013-07-09 00:17:42 +02:00
cPixmap *pixmapText;
public:
2018-03-08 13:02:38 +01:00
cRecMenuItemRecording(const cRecording *recording, bool active);
2013-07-09 00:17:42 +02:00
virtual ~cRecMenuItemRecording(void);
void SetPixmaps(void);
void Hide(void);
void Show(void);
void Draw(void);
};
// --- cRecMenuItemTimelineHeader -------------------------------------------------------
class cRecMenuItemTimelineHeader : public cRecMenuItem {
private:
time_t day;
2018-03-08 13:02:38 +01:00
const cTimer *timer;
std::vector<cTVGuideTimerConflict*> conflicts;
cPixmap *pixmapTimeline;
cPixmap *pixmapTimerInfo;
cPixmap *pixmapTimerConflicts;
2020-03-05 14:46:52 +01:00
float width5Mins;
int x0;
2020-03-02 11:37:50 +01:00
int numTimersToday;
bool timelineDrawn;
void DrawTimeline(void);
void DrawTimerConflicts(void);
void DrawCurrentTimer(void);
public:
2020-03-02 11:37:50 +01:00
cRecMenuItemTimelineHeader(time_t day, int numTimersToday, std::vector<cTVGuideTimerConflict*> conflictsToday);
virtual ~cRecMenuItemTimelineHeader(void);
void SetDay(time_t day) { this->day = day; };
void SetPixmaps(void);
2018-03-08 13:02:38 +01:00
void SetCurrentTimer(const cTimer *timer) { this->timer = timer; };
void UnsetCurrentTimer(void) { timer = NULL; };
2020-03-02 11:37:50 +01:00
void SetNumTimersToday(int numTimersToday) { this->numTimersToday = numTimersToday; };
void RefreshTimerDisplay(void);
void Hide(void);
void Show(void);
void Draw(void);
};
// --- cRecMenuItemTimelineTimer -------------------------------------------------------
class cRecMenuItemTimelineTimer : public cRecMenuItem {
private:
2018-03-08 13:02:38 +01:00
const cTimer *timer;
std::vector<cTVGuideTimerConflict*> conflicts;
cPixmap *pixmapBack;
cPixmap *pixmapTimerConflicts;
cRecMenuItemTimelineHeader *header;
int x0;
2020-03-05 14:46:52 +01:00
float width5Mins;
time_t start;
time_t stop;
void DrawBackground(void);
void DrawTimerBar(void);
void DrawTimeScale(void);
void DrawTimerConflicts(void);
void DrawNoTimerInfo(void);
public:
2018-03-08 13:02:38 +01:00
cRecMenuItemTimelineTimer(const cTimer *timer, time_t start, time_t stop, std::vector<cTVGuideTimerConflict*> conflictsToday, cRecMenuItemTimelineHeader *header, bool active);
virtual ~cRecMenuItemTimelineTimer(void);
2019-11-10 13:54:35 +01:00
void SetActive(void);
void setInactive(void);
void SetPixmaps(void);
void Hide(void);
void Show(void);
void Draw(void);
2019-11-10 14:00:02 +01:00
const cTimer *GetTimer(void);
eRecMenuState ProcessKey(eKeys Key);
};
// --- cRecMenuItemSearchTimer -------------------------------------------------------
class cRecMenuItemSearchTimer : public cRecMenuItem {
private:
cTVGuideSearchTimer timer;
eRecMenuState action1;
eRecMenuState action2;
eRecMenuState action3;
int iconActive;
cPixmap *pixmapText;
cPixmap *pixmapIcons;
int DrawIcons(void);
public:
cRecMenuItemSearchTimer(cTVGuideSearchTimer timer,
eRecMenuState action1,
eRecMenuState action2,
eRecMenuState action3,
bool active);
virtual ~cRecMenuItemSearchTimer(void);
void SetPixmaps(void);
void Hide(void);
void Show(void);
void Draw(void);
cTVGuideSearchTimer GetTimer(void) { return timer; };
eRecMenuState ProcessKey(eKeys Key);
};
// --- cRecMenuItemFavorite -------------------------------------------------------
class cRecMenuItemFavorite : public cRecMenuItem {
private:
cTVGuideSearchTimer favorite;
eRecMenuState action1;
cPixmap *pixmapText;
cPixmap *pixmapIcons;
int DrawIcons(void);
public:
cRecMenuItemFavorite(cTVGuideSearchTimer favorite,
eRecMenuState action1,
bool active);
virtual ~cRecMenuItemFavorite(void);
void SetPixmaps(void);
void Hide(void);
void Show(void);
void Draw(void);
cTVGuideSearchTimer GetFavorite(void) { return favorite; };
eRecMenuState ProcessKey(eKeys Key);
};
// --- cRecMenuItemFavoriteStatic -------------------------------------------------------
class cRecMenuItemFavoriteStatic : public cRecMenuItem {
private:
std::string text;
cPixmap *pixmapText;
cPixmap *pixmapIcons;
int DrawIcons(void);
public:
cRecMenuItemFavoriteStatic(std::string text, eRecMenuState action, bool active);
virtual ~cRecMenuItemFavoriteStatic(void);
void SetPixmaps(void);
void Hide(void);
void Show(void);
void Draw(void);
eRecMenuState ProcessKey(eKeys Key);
};
2019-03-30 18:06:47 +01:00
#endif //__TVGUIDE_RECMENUITEM_H