mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-08-28 21:50:43 +02:00
Update to v094r09 release.
byuu says: This will easily be the biggest diff in the history of higan. And not in a good way. * target-higan and target-loki have been blown away completely * nall and ruby massively updated * phoenix replaced with hiro (pretty near a total rewrite) * target-higan restarted using hiro (just a window for now) * all emulation cores updated to compile again * installation changed to not require root privileges (installs locally) For the foreseeable future (maybe even permanently?), the new higan UI will only build under Linux/BSD with GTK+ 2.20+. Probably the most likely route for Windows/OS X will be to try and figure out how to build hiro/GTK on those platforms, as awful as that would be. The other alternative would be to produce new UIs for those platforms ... which would actually be a good opportunity to make something much more user friendly. Being that I just started on this a few hours ago, that means that for at least a few weeks, don't expect to be able to actually play any games. Right now, you can pretty much just compile the binary and that's it. It's quite possible that some nall changes didn't produce compilation errors, but will produce runtime errors. So until the UI can actually load games, we won't know if anything is broken. But we should mostly be okay. It was mostly just trim<1> -> trim changes, moving to Hash::SHA256 (much cleaner), and patching some reckless memory copy functions enough to compile. Progress isn't going to be like it was before: I'm now dividing my time much thinner between studying and other hobbies. My aim this time is not to produce a binary for everyone to play games on. Rather, it's to keep the emulator alive. I want to be able to apply critical patches again. And I would also like the base of the emulator to live on, for use in other emulator frontends that utilize higan.
This commit is contained in:
53
hiro/qt/action/action.cpp
Normal file
53
hiro/qt/action/action.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
namespace phoenix {
|
||||
|
||||
void pAction::setEnabled(bool enabled) {
|
||||
if(dynamic_cast<Menu*>(&action)) {
|
||||
((Menu&)action).p.qtMenu->setEnabled(enabled);
|
||||
} else if(dynamic_cast<Separator*>(&action)) {
|
||||
((Separator&)action).p.qtAction->setEnabled(enabled);
|
||||
} else if(dynamic_cast<Item*>(&action)) {
|
||||
((Item&)action).p.qtAction->setEnabled(enabled);
|
||||
} else if(dynamic_cast<CheckItem*>(&action)) {
|
||||
((CheckItem&)action).p.qtAction->setEnabled(enabled);
|
||||
} else if(dynamic_cast<RadioItem*>(&action)) {
|
||||
((RadioItem&)action).p.qtAction->setEnabled(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
void pAction::setFont(string font) {
|
||||
QFont qtFont = pFont::create(font);
|
||||
|
||||
if(dynamic_cast<Menu*>(&action)) {
|
||||
((Menu&)action).p.setFont(font);
|
||||
} else if(dynamic_cast<Separator*>(&action)) {
|
||||
((Separator&)action).p.qtAction->setFont(qtFont);
|
||||
} else if(dynamic_cast<Item*>(&action)) {
|
||||
((Item&)action).p.qtAction->setFont(qtFont);
|
||||
} else if(dynamic_cast<CheckItem*>(&action)) {
|
||||
((CheckItem&)action).p.qtAction->setFont(qtFont);
|
||||
} else if(dynamic_cast<RadioItem*>(&action)) {
|
||||
((RadioItem&)action).p.qtAction->setFont(qtFont);
|
||||
}
|
||||
}
|
||||
|
||||
void pAction::setVisible(bool visible) {
|
||||
if(dynamic_cast<Menu*>(&action)) {
|
||||
((Menu&)action).p.qtMenu->menuAction()->setVisible(visible);
|
||||
} else if(dynamic_cast<Separator*>(&action)) {
|
||||
((Separator&)action).p.qtAction->setVisible(visible);
|
||||
} else if(dynamic_cast<Item*>(&action)) {
|
||||
((Item&)action).p.qtAction->setVisible(visible);
|
||||
} else if(dynamic_cast<CheckItem*>(&action)) {
|
||||
((CheckItem&)action).p.qtAction->setVisible(visible);
|
||||
} else if(dynamic_cast<RadioItem*>(&action)) {
|
||||
((RadioItem&)action).p.qtAction->setVisible(visible);
|
||||
}
|
||||
}
|
||||
|
||||
void pAction::constructor() {
|
||||
}
|
||||
|
||||
void pAction::destructor() {
|
||||
}
|
||||
|
||||
}
|
28
hiro/qt/action/check-item.cpp
Normal file
28
hiro/qt/action/check-item.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
namespace phoenix {
|
||||
|
||||
void pCheckItem::setChecked(bool checked) {
|
||||
qtAction->setChecked(checked);
|
||||
}
|
||||
|
||||
void pCheckItem::setText(string text) {
|
||||
qtAction->setText(QString::fromUtf8(text));
|
||||
}
|
||||
|
||||
void pCheckItem::constructor() {
|
||||
qtAction = new QAction(0);
|
||||
qtAction->setCheckable(true);
|
||||
connect(qtAction, SIGNAL(triggered()), SLOT(onToggle()));
|
||||
}
|
||||
|
||||
void pCheckItem::destructor() {
|
||||
if(action.state.menu) action.state.menu->remove(checkItem);
|
||||
delete qtAction;
|
||||
qtAction = nullptr;
|
||||
}
|
||||
|
||||
void pCheckItem::onToggle() {
|
||||
checkItem.state.checked = qtAction->isChecked();
|
||||
if(checkItem.onToggle) checkItem.onToggle();
|
||||
}
|
||||
|
||||
}
|
26
hiro/qt/action/item.cpp
Normal file
26
hiro/qt/action/item.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
namespace phoenix {
|
||||
|
||||
void pItem::setImage(const image& image) {
|
||||
qtAction->setIcon(CreateIcon(image));
|
||||
}
|
||||
|
||||
void pItem::setText(string text) {
|
||||
qtAction->setText(QString::fromUtf8(text));
|
||||
}
|
||||
|
||||
void pItem::constructor() {
|
||||
qtAction = new QAction(0);
|
||||
connect(qtAction, SIGNAL(triggered()), SLOT(onActivate()));
|
||||
}
|
||||
|
||||
void pItem::destructor() {
|
||||
if(action.state.menu) action.state.menu->remove(item);
|
||||
delete qtAction;
|
||||
qtAction = nullptr;
|
||||
}
|
||||
|
||||
void pItem::onActivate() {
|
||||
if(item.onActivate) item.onActivate();
|
||||
}
|
||||
|
||||
}
|
56
hiro/qt/action/menu.cpp
Normal file
56
hiro/qt/action/menu.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
namespace phoenix {
|
||||
|
||||
void pMenu::append(Action& action) {
|
||||
if(dynamic_cast<Menu*>(&action)) {
|
||||
qtMenu->addMenu(((Menu&)action).p.qtMenu);
|
||||
} else if(dynamic_cast<Separator*>(&action)) {
|
||||
qtMenu->addAction(((Separator&)action).p.qtAction);
|
||||
} else if(dynamic_cast<Item*>(&action)) {
|
||||
qtMenu->addAction(((Item&)action).p.qtAction);
|
||||
} else if(dynamic_cast<CheckItem*>(&action)) {
|
||||
qtMenu->addAction(((CheckItem&)action).p.qtAction);
|
||||
} else if(dynamic_cast<RadioItem*>(&action)) {
|
||||
qtMenu->addAction(((RadioItem&)action).p.qtAction);
|
||||
}
|
||||
}
|
||||
|
||||
void pMenu::remove(Action& action) {
|
||||
if(dynamic_cast<Menu*>(&action)) {
|
||||
//QMenu::removeMenu() does not exist
|
||||
qtMenu->clear();
|
||||
for(auto& action : menu.state.action) append(action);
|
||||
} else if(dynamic_cast<Separator*>(&action)) {
|
||||
qtMenu->removeAction(((Separator&)action).p.qtAction);
|
||||
} else if(dynamic_cast<Item*>(&action)) {
|
||||
qtMenu->removeAction(((Item&)action).p.qtAction);
|
||||
} else if(dynamic_cast<CheckItem*>(&action)) {
|
||||
qtMenu->removeAction(((CheckItem&)action).p.qtAction);
|
||||
} else if(dynamic_cast<RadioItem*>(&action)) {
|
||||
qtMenu->removeAction(((CheckItem&)action).p.qtAction);
|
||||
}
|
||||
}
|
||||
|
||||
void pMenu::setFont(string font) {
|
||||
qtMenu->setFont(pFont::create(font));
|
||||
for(auto &item : menu.state.action) item.p.setFont(font);
|
||||
}
|
||||
|
||||
void pMenu::setImage(const image& image) {
|
||||
qtMenu->setIcon(CreateIcon(image));
|
||||
}
|
||||
|
||||
void pMenu::setText(string text) {
|
||||
qtMenu->setTitle(QString::fromUtf8(text));
|
||||
}
|
||||
|
||||
void pMenu::constructor() {
|
||||
qtMenu = new QMenu;
|
||||
}
|
||||
|
||||
void pMenu::destructor() {
|
||||
if(action.state.menu) action.state.menu->remove(menu);
|
||||
delete qtMenu;
|
||||
qtMenu = nullptr;
|
||||
}
|
||||
|
||||
}
|
42
hiro/qt/action/radio-item.cpp
Normal file
42
hiro/qt/action/radio-item.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
namespace phoenix {
|
||||
|
||||
void pRadioItem::setChecked() {
|
||||
lock();
|
||||
for(auto& item : radioItem.state.group) {
|
||||
bool checkState = item.p.qtAction == qtAction;
|
||||
item.state.checked = checkState;
|
||||
item.p.qtAction->setChecked(checkState);
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
|
||||
void pRadioItem::setGroup(const group<RadioItem>& group) {
|
||||
}
|
||||
|
||||
void pRadioItem::setText(string text) {
|
||||
qtAction->setText(QString::fromUtf8(text));
|
||||
}
|
||||
|
||||
void pRadioItem::constructor() {
|
||||
qtAction = new QAction(0);
|
||||
qtGroup = new QActionGroup(0);
|
||||
qtAction->setCheckable(true);
|
||||
qtAction->setActionGroup(qtGroup);
|
||||
qtAction->setChecked(true);
|
||||
connect(qtAction, SIGNAL(triggered()), SLOT(onActivate()));
|
||||
}
|
||||
|
||||
void pRadioItem::destructor() {
|
||||
if(action.state.menu) action.state.menu->remove(radioItem);
|
||||
delete qtAction;
|
||||
qtAction = nullptr;
|
||||
}
|
||||
|
||||
void pRadioItem::onActivate() {
|
||||
if(!radioItem.state.checked) {
|
||||
setChecked();
|
||||
if(!locked() && radioItem.onActivate) radioItem.onActivate();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
14
hiro/qt/action/separator.cpp
Normal file
14
hiro/qt/action/separator.cpp
Normal file
@@ -0,0 +1,14 @@
|
||||
namespace phoenix {
|
||||
|
||||
void pSeparator::constructor() {
|
||||
qtAction = new QAction(0);
|
||||
qtAction->setSeparator(true);
|
||||
}
|
||||
|
||||
void pSeparator::destructor() {
|
||||
if(action.state.menu) action.state.menu->remove(separator);
|
||||
delete qtAction;
|
||||
qtAction = nullptr;
|
||||
}
|
||||
|
||||
}
|
54
hiro/qt/application.cpp
Normal file
54
hiro/qt/application.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
namespace phoenix {
|
||||
|
||||
XlibDisplay* pApplication::display = nullptr;
|
||||
|
||||
void pApplication::run() {
|
||||
if(Application::main) {
|
||||
while(applicationState.quit == false) {
|
||||
processEvents();
|
||||
Application::main();
|
||||
}
|
||||
} else {
|
||||
QApplication::exec();
|
||||
}
|
||||
}
|
||||
|
||||
bool pApplication::pendingEvents() {
|
||||
return QApplication::hasPendingEvents();
|
||||
}
|
||||
|
||||
void pApplication::processEvents() {
|
||||
while(pendingEvents()) QApplication::processEvents();
|
||||
}
|
||||
|
||||
void pApplication::quit() {
|
||||
QApplication::quit();
|
||||
//note: QApplication cannot be deleted; or libQtGui will crash
|
||||
qtApplication = nullptr;
|
||||
}
|
||||
|
||||
void pApplication::syncX() {
|
||||
for(unsigned n = 0; n < 8; n++) {
|
||||
QApplication::syncX();
|
||||
Application::processEvents();
|
||||
usleep(2000);
|
||||
}
|
||||
}
|
||||
|
||||
void pApplication::initialize() {
|
||||
display = XOpenDisplay(0);
|
||||
|
||||
settings = new Settings;
|
||||
settings->load();
|
||||
|
||||
static int argc = 1;
|
||||
static char* argv[] = {new char[8], nullptr};
|
||||
strcpy(argv[0], "phoenix");
|
||||
char** argvp = argv;
|
||||
|
||||
qtApplication = new QApplication(argc, argvp);
|
||||
|
||||
pKeyboard::initialize();
|
||||
}
|
||||
|
||||
}
|
54
hiro/qt/browser-window.cpp
Normal file
54
hiro/qt/browser-window.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
namespace phoenix {
|
||||
|
||||
string pBrowserWindow::directory(BrowserWindow::State& state) {
|
||||
QString directory = QFileDialog::getExistingDirectory(
|
||||
state.parent ? state.parent->p.qtWindow : nullptr,
|
||||
state.title ? state.title : "Select Directory",
|
||||
QString::fromUtf8(state.path), QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks
|
||||
);
|
||||
string name = directory.toUtf8().constData();
|
||||
if(name && name.endsWith("/") == false) name.append("/");
|
||||
return name;
|
||||
}
|
||||
|
||||
string pBrowserWindow::open(BrowserWindow::State& state) {
|
||||
string filters = state.filters.merge(";;");
|
||||
|
||||
//convert filter list from phoenix to Qt format, example:
|
||||
//"Text, XML files (*.txt,*.xml)" -> "Text, XML files (*.txt *.xml)"
|
||||
signed parentheses = 0;
|
||||
for(auto& n : filters) {
|
||||
if(n == '(') parentheses++;
|
||||
if(n == ')') parentheses--;
|
||||
if(n == ',' && parentheses) n = ' ';
|
||||
}
|
||||
|
||||
QString filename = QFileDialog::getOpenFileName(
|
||||
state.parent ? state.parent->p.qtWindow : nullptr,
|
||||
state.title ? state.title : "Open File",
|
||||
QString::fromUtf8(state.path), QString::fromUtf8(filters)
|
||||
);
|
||||
return filename.toUtf8().constData();
|
||||
}
|
||||
|
||||
string pBrowserWindow::save(BrowserWindow::State& state) {
|
||||
string filters = state.filters.merge(";;");
|
||||
|
||||
//convert filter list from phoenix to Qt format, example:
|
||||
//"Text, XML files (*.txt,*.xml)" -> "Text, XML files (*.txt *.xml)"
|
||||
signed parentheses = 0;
|
||||
for(auto& n : filters) {
|
||||
if(n == '(') parentheses++;
|
||||
if(n == ')') parentheses--;
|
||||
if(n == ',' && parentheses) n = ' ';
|
||||
}
|
||||
|
||||
QString filename = QFileDialog::getSaveFileName(
|
||||
state.parent ? state.parent->p.qtWindow : nullptr,
|
||||
state.title ? state.title : "Save File",
|
||||
QString::fromUtf8(state.path), QString::fromUtf8(filters)
|
||||
);
|
||||
return filename.toUtf8().constData();
|
||||
}
|
||||
|
||||
}
|
13
hiro/qt/desktop.cpp
Normal file
13
hiro/qt/desktop.cpp
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace phoenix {
|
||||
|
||||
Size pDesktop::size() {
|
||||
QRect rect = QApplication::desktop()->screenGeometry();
|
||||
return {rect.width(), rect.height()};
|
||||
}
|
||||
|
||||
Geometry pDesktop::workspace() {
|
||||
QRect rect = QApplication::desktop()->availableGeometry();
|
||||
return {rect.x(), rect.y(), rect.width(), rect.height()};
|
||||
}
|
||||
|
||||
}
|
60
hiro/qt/font.cpp
Normal file
60
hiro/qt/font.cpp
Normal file
@@ -0,0 +1,60 @@
|
||||
namespace phoenix {
|
||||
|
||||
string pFont::serif(unsigned size, string style) {
|
||||
if(size == 0) size = 8;
|
||||
if(style == "") style = "Normal";
|
||||
return {"Serif, ", size, ", ", style};
|
||||
}
|
||||
|
||||
string pFont::sans(unsigned size, string style) {
|
||||
if(size == 0) size = 8;
|
||||
if(style == "") style = "Normal";
|
||||
return {"Sans, ", size, ", ", style};
|
||||
}
|
||||
|
||||
string pFont::monospace(unsigned size, string style) {
|
||||
if(size == 0) size = 8;
|
||||
if(style == "") style = "Normal";
|
||||
return {"Liberation Mono, ", size, ", ", style};
|
||||
}
|
||||
|
||||
Size pFont::size(string font, string text) {
|
||||
return pFont::size(pFont::create(font), text);
|
||||
}
|
||||
|
||||
QFont pFont::create(string description) {
|
||||
lstring part = description.split<2>(",").strip();
|
||||
|
||||
string family = "Sans";
|
||||
unsigned size = 8u;
|
||||
bool bold = false;
|
||||
bool italic = false;
|
||||
|
||||
if(part[0] != "") family = part[0];
|
||||
if(part.size() >= 2) size = decimal(part[1]);
|
||||
if(part.size() >= 3) bold = (bool)part[2].find("Bold");
|
||||
if(part.size() >= 3) italic = (bool)part[2].find("Italic");
|
||||
|
||||
QFont qtFont;
|
||||
qtFont.setFamily(family);
|
||||
qtFont.setPointSize(size);
|
||||
if(bold) qtFont.setBold(true);
|
||||
if(italic) qtFont.setItalic(true);
|
||||
return qtFont;
|
||||
}
|
||||
|
||||
Size pFont::size(const QFont& qtFont, string text) {
|
||||
QFontMetrics metrics(qtFont);
|
||||
|
||||
lstring lines;
|
||||
lines.split("\n", text);
|
||||
|
||||
unsigned maxWidth = 0;
|
||||
for(auto& line : lines) {
|
||||
maxWidth = max(maxWidth, metrics.width(line));
|
||||
}
|
||||
|
||||
return {maxWidth, metrics.height() * lines.size()};
|
||||
}
|
||||
|
||||
}
|
16
hiro/qt/header.hpp
Normal file
16
hiro/qt/header.hpp
Normal file
@@ -0,0 +1,16 @@
|
||||
#include <QApplication>
|
||||
#include <QtGui>
|
||||
#include <nall/xorg/guard.hpp>
|
||||
#define XK_MISCELLANY
|
||||
#define XK_LATIN1
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/keysymdef.h>
|
||||
#undef XK_MISCELLANY
|
||||
#undef XK_LATIN1
|
||||
#include <nall/xorg/guard.hpp>
|
||||
|
||||
//Qt 4.8.0 and earlier improperly define the QLOCATION macro
|
||||
//in C++11, it is detected as a malformed user-defined literal
|
||||
//below is a workaround to fix compilation errors caused by this
|
||||
#undef QLOCATION
|
||||
#define QLOCATION "\0" __FILE__ ":" QTOSTRING(__LINE__)
|
149
hiro/qt/keyboard.cpp
Normal file
149
hiro/qt/keyboard.cpp
Normal file
@@ -0,0 +1,149 @@
|
||||
namespace phoenix {
|
||||
|
||||
void pKeyboard::initialize() {
|
||||
auto append = [](Keyboard::Scancode scancode, unsigned keysym) {
|
||||
settings->keymap.insert(scancode, XKeysymToKeycode(pApplication::display, keysym));
|
||||
};
|
||||
|
||||
append(Keyboard::Scancode::Escape, XK_Escape);
|
||||
append(Keyboard::Scancode::F1, XK_F1);
|
||||
append(Keyboard::Scancode::F2, XK_F2);
|
||||
append(Keyboard::Scancode::F3, XK_F3);
|
||||
append(Keyboard::Scancode::F4, XK_F4);
|
||||
append(Keyboard::Scancode::F5, XK_F5);
|
||||
append(Keyboard::Scancode::F6, XK_F6);
|
||||
append(Keyboard::Scancode::F7, XK_F7);
|
||||
append(Keyboard::Scancode::F8, XK_F8);
|
||||
append(Keyboard::Scancode::F9, XK_F9);
|
||||
append(Keyboard::Scancode::F10, XK_F10);
|
||||
append(Keyboard::Scancode::F11, XK_F11);
|
||||
append(Keyboard::Scancode::F12, XK_F12);
|
||||
|
||||
append(Keyboard::Scancode::PrintScreen, XK_Print);
|
||||
append(Keyboard::Scancode::ScrollLock, XK_Scroll_Lock);
|
||||
append(Keyboard::Scancode::Pause, XK_Pause);
|
||||
|
||||
append(Keyboard::Scancode::Insert, XK_Insert);
|
||||
append(Keyboard::Scancode::Delete, XK_Delete);
|
||||
append(Keyboard::Scancode::Home, XK_Home);
|
||||
append(Keyboard::Scancode::End, XK_End);
|
||||
append(Keyboard::Scancode::PageUp, XK_Prior);
|
||||
append(Keyboard::Scancode::PageDown, XK_Next);
|
||||
|
||||
append(Keyboard::Scancode::Up, XK_Up);
|
||||
append(Keyboard::Scancode::Down, XK_Down);
|
||||
append(Keyboard::Scancode::Left, XK_Left);
|
||||
append(Keyboard::Scancode::Right, XK_Right);
|
||||
|
||||
append(Keyboard::Scancode::Grave, XK_asciitilde);
|
||||
append(Keyboard::Scancode::Number1, XK_1);
|
||||
append(Keyboard::Scancode::Number2, XK_2);
|
||||
append(Keyboard::Scancode::Number3, XK_3);
|
||||
append(Keyboard::Scancode::Number4, XK_4);
|
||||
append(Keyboard::Scancode::Number5, XK_5);
|
||||
append(Keyboard::Scancode::Number6, XK_6);
|
||||
append(Keyboard::Scancode::Number7, XK_7);
|
||||
append(Keyboard::Scancode::Number8, XK_8);
|
||||
append(Keyboard::Scancode::Number9, XK_9);
|
||||
append(Keyboard::Scancode::Number0, XK_0);
|
||||
append(Keyboard::Scancode::Minus, XK_minus);
|
||||
append(Keyboard::Scancode::Equal, XK_equal);
|
||||
append(Keyboard::Scancode::Backspace, XK_BackSpace);
|
||||
|
||||
append(Keyboard::Scancode::BracketLeft, XK_bracketleft);
|
||||
append(Keyboard::Scancode::BracketRight, XK_bracketright);
|
||||
append(Keyboard::Scancode::Backslash, XK_backslash);
|
||||
append(Keyboard::Scancode::Semicolon, XK_semicolon);
|
||||
append(Keyboard::Scancode::Apostrophe, XK_apostrophe);
|
||||
append(Keyboard::Scancode::Comma, XK_comma);
|
||||
append(Keyboard::Scancode::Period, XK_period);
|
||||
append(Keyboard::Scancode::Slash, XK_slash);
|
||||
|
||||
append(Keyboard::Scancode::Tab, XK_Tab);
|
||||
append(Keyboard::Scancode::CapsLock, XK_Caps_Lock);
|
||||
append(Keyboard::Scancode::Return, XK_Return);
|
||||
append(Keyboard::Scancode::ShiftLeft, XK_Shift_L);
|
||||
append(Keyboard::Scancode::ShiftRight, XK_Shift_R);
|
||||
append(Keyboard::Scancode::ControlLeft, XK_Control_L);
|
||||
append(Keyboard::Scancode::ControlRight, XK_Control_R);
|
||||
append(Keyboard::Scancode::SuperLeft, XK_Super_L);
|
||||
append(Keyboard::Scancode::SuperRight, XK_Super_R);
|
||||
append(Keyboard::Scancode::AltLeft, XK_Alt_L);
|
||||
append(Keyboard::Scancode::AltRight, XK_Alt_R);
|
||||
append(Keyboard::Scancode::Space, XK_space);
|
||||
append(Keyboard::Scancode::Menu, XK_Menu);
|
||||
|
||||
append(Keyboard::Scancode::A, XK_A);
|
||||
append(Keyboard::Scancode::B, XK_B);
|
||||
append(Keyboard::Scancode::C, XK_C);
|
||||
append(Keyboard::Scancode::D, XK_D);
|
||||
append(Keyboard::Scancode::E, XK_E);
|
||||
append(Keyboard::Scancode::F, XK_F);
|
||||
append(Keyboard::Scancode::G, XK_G);
|
||||
append(Keyboard::Scancode::H, XK_H);
|
||||
append(Keyboard::Scancode::I, XK_I);
|
||||
append(Keyboard::Scancode::J, XK_J);
|
||||
append(Keyboard::Scancode::K, XK_K);
|
||||
append(Keyboard::Scancode::L, XK_L);
|
||||
append(Keyboard::Scancode::M, XK_M);
|
||||
append(Keyboard::Scancode::N, XK_N);
|
||||
append(Keyboard::Scancode::O, XK_O);
|
||||
append(Keyboard::Scancode::P, XK_P);
|
||||
append(Keyboard::Scancode::Q, XK_Q);
|
||||
append(Keyboard::Scancode::R, XK_R);
|
||||
append(Keyboard::Scancode::S, XK_S);
|
||||
append(Keyboard::Scancode::T, XK_T);
|
||||
append(Keyboard::Scancode::U, XK_U);
|
||||
append(Keyboard::Scancode::V, XK_V);
|
||||
append(Keyboard::Scancode::W, XK_W);
|
||||
append(Keyboard::Scancode::X, XK_X);
|
||||
append(Keyboard::Scancode::Y, XK_Y);
|
||||
append(Keyboard::Scancode::Z, XK_Z);
|
||||
|
||||
append(Keyboard::Scancode::NumLock, XK_Num_Lock);
|
||||
append(Keyboard::Scancode::Divide, XK_KP_Divide);
|
||||
append(Keyboard::Scancode::Multiply, XK_KP_Multiply);
|
||||
append(Keyboard::Scancode::Subtract, XK_KP_Subtract);
|
||||
append(Keyboard::Scancode::Add, XK_KP_Add);
|
||||
append(Keyboard::Scancode::Enter, XK_KP_Enter);
|
||||
append(Keyboard::Scancode::Point, XK_KP_Decimal);
|
||||
|
||||
append(Keyboard::Scancode::Keypad1, XK_KP_1);
|
||||
append(Keyboard::Scancode::Keypad2, XK_KP_2);
|
||||
append(Keyboard::Scancode::Keypad3, XK_KP_3);
|
||||
append(Keyboard::Scancode::Keypad4, XK_KP_4);
|
||||
append(Keyboard::Scancode::Keypad5, XK_KP_5);
|
||||
append(Keyboard::Scancode::Keypad6, XK_KP_6);
|
||||
append(Keyboard::Scancode::Keypad7, XK_KP_7);
|
||||
append(Keyboard::Scancode::Keypad8, XK_KP_8);
|
||||
append(Keyboard::Scancode::Keypad9, XK_KP_9);
|
||||
append(Keyboard::Scancode::Keypad0, XK_KP_0);
|
||||
}
|
||||
|
||||
bool pKeyboard::pressed(Keyboard::Scancode scancode) {
|
||||
char state[256];
|
||||
XQueryKeymap(pApplication::display, state);
|
||||
if(auto result = settings->keymap.find(scancode)) {
|
||||
unsigned id = result();
|
||||
return state[id >> 3] & (1 << (id & 7));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
vector<bool> pKeyboard::state() {
|
||||
vector<bool> output;
|
||||
output.resize((unsigned)Keyboard::Scancode::Limit);
|
||||
for(auto& n : output) n = false;
|
||||
|
||||
char state[256];
|
||||
XQueryKeymap(pApplication::display, state);
|
||||
for(auto node : settings->keymap) {
|
||||
if(state[node.value >> 3] & (1 << (node.value & 7))) {
|
||||
output[(unsigned)node.key] = true;
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
}
|
55
hiro/qt/message-window.cpp
Normal file
55
hiro/qt/message-window.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
namespace phoenix {
|
||||
|
||||
static QMessageBox::StandardButtons MessageWindow_buttons(MessageWindow::Buttons buttons) {
|
||||
QMessageBox::StandardButtons standardButtons = QMessageBox::NoButton;
|
||||
if(buttons == MessageWindow::Buttons::Ok) standardButtons = QMessageBox::Ok;
|
||||
if(buttons == MessageWindow::Buttons::OkCancel) standardButtons = QMessageBox::Ok | QMessageBox::Cancel;
|
||||
if(buttons == MessageWindow::Buttons::YesNo) standardButtons = QMessageBox::Yes | QMessageBox::No;
|
||||
if(buttons == MessageWindow::Buttons::YesNoCancel) standardButtons = QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel;
|
||||
return standardButtons;
|
||||
}
|
||||
|
||||
static MessageWindow::Response MessageWindow_response(MessageWindow::Buttons buttons, QMessageBox::StandardButton response) {
|
||||
if(response == QMessageBox::Ok) return MessageWindow::Response::Ok;
|
||||
if(response == QMessageBox::Cancel) return MessageWindow::Response::Cancel;
|
||||
if(response == QMessageBox::Yes) return MessageWindow::Response::Yes;
|
||||
if(response == QMessageBox::No) return MessageWindow::Response::No;
|
||||
|
||||
//MessageWindow was closed via window manager, rather than by a button; assume a cancel/no response
|
||||
if(buttons == MessageWindow::Buttons::Ok) return MessageWindow::Response::Ok;
|
||||
if(buttons == MessageWindow::Buttons::OkCancel) return MessageWindow::Response::Cancel;
|
||||
if(buttons == MessageWindow::Buttons::YesNo) return MessageWindow::Response::No;
|
||||
if(buttons == MessageWindow::Buttons::YesNoCancel) return MessageWindow::Response::Cancel;
|
||||
|
||||
throw;
|
||||
}
|
||||
|
||||
MessageWindow::Response pMessageWindow::error(MessageWindow::State& state) {
|
||||
return MessageWindow_response(
|
||||
state.buttons, QMessageBox::critical(state.parent ? state.parent->p.qtWindow : nullptr, state.title ? state.title : " ",
|
||||
QString::fromUtf8(state.text), MessageWindow_buttons(state.buttons))
|
||||
);
|
||||
}
|
||||
|
||||
MessageWindow::Response pMessageWindow::information(MessageWindow::State& state) {
|
||||
return MessageWindow_response(
|
||||
state.buttons, QMessageBox::information(state.parent ? state.parent->p.qtWindow : nullptr, state.title ? state.title : " ",
|
||||
QString::fromUtf8(state.text), MessageWindow_buttons(state.buttons))
|
||||
);
|
||||
}
|
||||
|
||||
MessageWindow::Response pMessageWindow::question(MessageWindow::State& state) {
|
||||
return MessageWindow_response(
|
||||
state.buttons, QMessageBox::question(state.parent ? state.parent->p.qtWindow : nullptr, state.title ? state.title : " ",
|
||||
QString::fromUtf8(state.text), MessageWindow_buttons(state.buttons))
|
||||
);
|
||||
}
|
||||
|
||||
MessageWindow::Response pMessageWindow::warning(MessageWindow::State& state) {
|
||||
return MessageWindow_response(
|
||||
state.buttons, QMessageBox::warning(state.parent ? state.parent->p.qtWindow : nullptr, state.title ? state.title : " ",
|
||||
QString::fromUtf8(state.text), MessageWindow_buttons(state.buttons))
|
||||
);
|
||||
}
|
||||
|
||||
}
|
16
hiro/qt/monitor.cpp
Normal file
16
hiro/qt/monitor.cpp
Normal file
@@ -0,0 +1,16 @@
|
||||
namespace phoenix {
|
||||
|
||||
unsigned pMonitor::count() {
|
||||
return QApplication::desktop()->screenCount();
|
||||
}
|
||||
|
||||
Geometry pMonitor::geometry(unsigned monitor) {
|
||||
QRect rectangle = QApplication::desktop()->screenGeometry(monitor);
|
||||
return {rectangle.x(), rectangle.y(), rectangle.width(), rectangle.height()};
|
||||
}
|
||||
|
||||
unsigned pMonitor::primary() {
|
||||
return QApplication::desktop()->primaryScreen();
|
||||
}
|
||||
|
||||
}
|
18
hiro/qt/mouse.cpp
Normal file
18
hiro/qt/mouse.cpp
Normal file
@@ -0,0 +1,18 @@
|
||||
namespace phoenix {
|
||||
|
||||
Position pMouse::position() {
|
||||
QPoint point = QCursor::pos();
|
||||
return {point.x(), point.y()};
|
||||
}
|
||||
|
||||
bool pMouse::pressed(Mouse::Button button) {
|
||||
Qt::MouseButtons buttons = QApplication::mouseButtons();
|
||||
switch(button) {
|
||||
case Mouse::Button::Left: return buttons & Qt::LeftButton;
|
||||
case Mouse::Button::Middle: return buttons & Qt::MidButton;
|
||||
case Mouse::Button::Right: return buttons & Qt::RightButton;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
49
hiro/qt/platform.cpp
Normal file
49
hiro/qt/platform.cpp
Normal file
@@ -0,0 +1,49 @@
|
||||
#include "platform.moc.hpp"
|
||||
#include "platform.moc"
|
||||
|
||||
#include "utility.cpp"
|
||||
#include "settings.cpp"
|
||||
|
||||
#include "desktop.cpp"
|
||||
#include "monitor.cpp"
|
||||
#include "keyboard.cpp"
|
||||
#include "mouse.cpp"
|
||||
#include "browser-window.cpp"
|
||||
#include "message-window.cpp"
|
||||
#include "font.cpp"
|
||||
#include "timer.cpp"
|
||||
#include "window.cpp"
|
||||
#include "popup-menu.cpp"
|
||||
|
||||
#include "action/action.cpp"
|
||||
#include "action/menu.cpp"
|
||||
#include "action/separator.cpp"
|
||||
#include "action/item.cpp"
|
||||
#include "action/check-item.cpp"
|
||||
#include "action/radio-item.cpp"
|
||||
|
||||
#include "widget/widget.cpp"
|
||||
#include "widget/button.cpp"
|
||||
#include "widget/canvas.cpp"
|
||||
#include "widget/check-button.cpp"
|
||||
#include "widget/check-label.cpp"
|
||||
#include "widget/combo-button.cpp"
|
||||
#include "widget/console.cpp"
|
||||
#include "widget/frame.cpp"
|
||||
#include "widget/hex-edit.cpp"
|
||||
#include "widget/horizontal-scroller.cpp"
|
||||
#include "widget/horizontal-slider.cpp"
|
||||
#include "widget/icon-view.cpp"
|
||||
#include "widget/label.cpp"
|
||||
#include "widget/line-edit.cpp"
|
||||
#include "widget/list-view.cpp"
|
||||
#include "widget/progress-bar.cpp"
|
||||
#include "widget/radio-button.cpp"
|
||||
#include "widget/radio-label.cpp"
|
||||
#include "widget/tab-frame.cpp"
|
||||
#include "widget/text-edit.cpp"
|
||||
#include "widget/vertical-scroller.cpp"
|
||||
#include "widget/vertical-slider.cpp"
|
||||
#include "widget/viewport.cpp"
|
||||
|
||||
#include "application.cpp"
|
1816
hiro/qt/platform.moc
Normal file
1816
hiro/qt/platform.moc
Normal file
File diff suppressed because it is too large
Load Diff
876
hiro/qt/platform.moc.hpp
Normal file
876
hiro/qt/platform.moc.hpp
Normal file
@@ -0,0 +1,876 @@
|
||||
namespace phoenix {
|
||||
|
||||
struct pApplication {
|
||||
static XlibDisplay* display;
|
||||
|
||||
static void run();
|
||||
static bool pendingEvents();
|
||||
static void processEvents();
|
||||
static void quit();
|
||||
|
||||
static void initialize();
|
||||
static void syncX();
|
||||
};
|
||||
|
||||
static QApplication* qtApplication = nullptr;
|
||||
|
||||
struct Settings : Configuration::Document {
|
||||
bimap<Keyboard::Scancode, unsigned> keymap;
|
||||
|
||||
struct Geometry : Configuration::Node {
|
||||
unsigned frameX;
|
||||
unsigned frameY;
|
||||
unsigned frameWidth;
|
||||
unsigned frameHeight;
|
||||
unsigned menuHeight;
|
||||
unsigned statusHeight;
|
||||
} geometry;
|
||||
|
||||
void load();
|
||||
void save();
|
||||
Settings();
|
||||
};
|
||||
|
||||
struct pWindow;
|
||||
struct pMenu;
|
||||
struct pLayout;
|
||||
struct pWidget;
|
||||
|
||||
struct pFont {
|
||||
static string serif(unsigned size, string style);
|
||||
static string sans(unsigned size, string style);
|
||||
static string monospace(unsigned size, string style);
|
||||
static Size size(string font, string text);
|
||||
|
||||
static QFont create(string description);
|
||||
static Size size(const QFont& qtFont, string text);
|
||||
};
|
||||
|
||||
struct pDesktop {
|
||||
static Size size();
|
||||
static Geometry workspace();
|
||||
};
|
||||
|
||||
struct pMonitor {
|
||||
static unsigned count();
|
||||
static Geometry geometry(unsigned monitor);
|
||||
static unsigned primary();
|
||||
};
|
||||
|
||||
struct pKeyboard {
|
||||
static bool pressed(Keyboard::Scancode scancode);
|
||||
static vector<bool> state();
|
||||
|
||||
static void initialize();
|
||||
};
|
||||
|
||||
struct pMouse {
|
||||
static Position position();
|
||||
static bool pressed(Mouse::Button button);
|
||||
};
|
||||
|
||||
struct pBrowserWindow {
|
||||
static string directory(BrowserWindow::State& state);
|
||||
static string open(BrowserWindow::State& state);
|
||||
static string save(BrowserWindow::State& state);
|
||||
};
|
||||
|
||||
struct pMessageWindow {
|
||||
static MessageWindow::Response error(MessageWindow::State& state);
|
||||
static MessageWindow::Response information(MessageWindow::State& state);
|
||||
static MessageWindow::Response question(MessageWindow::State& state);
|
||||
static MessageWindow::Response warning(MessageWindow::State& state);
|
||||
};
|
||||
|
||||
struct pObject {
|
||||
Object& object;
|
||||
signed locks = 0;
|
||||
|
||||
bool locked() const { return locks != 0; }
|
||||
void lock() { locks++; }
|
||||
void unlock() { locks--; }
|
||||
|
||||
pObject(Object& object) : object(object) {}
|
||||
virtual ~pObject() {}
|
||||
void constructor() {}
|
||||
void destructor() {}
|
||||
};
|
||||
|
||||
struct pTimer : public QObject, public pObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Timer& timer;
|
||||
QTimer* qtTimer;
|
||||
|
||||
void setEnabled(bool enabled);
|
||||
void setInterval(unsigned interval);
|
||||
|
||||
pTimer(Timer& timer) : pObject(timer), timer(timer) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
|
||||
public slots:
|
||||
void onActivate();
|
||||
};
|
||||
|
||||
struct pWindow : public QObject, public pObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Window& window;
|
||||
struct QtWindow : public QWidget {
|
||||
pWindow& self;
|
||||
void closeEvent(QCloseEvent*);
|
||||
void dragEnterEvent(QDragEnterEvent*);
|
||||
void dropEvent(QDropEvent*);
|
||||
void keyPressEvent(QKeyEvent*);
|
||||
void keyReleaseEvent(QKeyEvent*);
|
||||
void moveEvent(QMoveEvent*);
|
||||
void resizeEvent(QResizeEvent*);
|
||||
QSize sizeHint() const;
|
||||
QtWindow(pWindow& self) : self(self) {}
|
||||
};
|
||||
QtWindow* qtWindow;
|
||||
QVBoxLayout* qtLayout;
|
||||
QMenuBar* qtMenu;
|
||||
QStatusBar* qtStatus;
|
||||
QWidget* qtContainer;
|
||||
|
||||
void append(Layout& layout);
|
||||
void append(Menu& menu);
|
||||
void append(Widget& widget);
|
||||
Geometry frameMargin();
|
||||
bool focused();
|
||||
void remove(Layout& layout);
|
||||
void remove(Menu& menu);
|
||||
void remove(Widget& widget);
|
||||
void setBackgroundColor(Color color);
|
||||
void setDroppable(bool droppable);
|
||||
void setFocused();
|
||||
void setFullScreen(bool fullScreen);
|
||||
void setGeometry(Geometry geometry);
|
||||
void setMenuFont(string font);
|
||||
void setMenuVisible(bool visible);
|
||||
void setModal(bool modal);
|
||||
void setResizable(bool resizable);
|
||||
void setStatusFont(string font);
|
||||
void setStatusText(string text);
|
||||
void setStatusVisible(bool visible);
|
||||
void setTitle(string text);
|
||||
void setVisible(bool visible);
|
||||
void setWidgetFont(string font);
|
||||
|
||||
pWindow(Window& window) : pObject(window), window(window) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
void updateFrameGeometry();
|
||||
};
|
||||
|
||||
struct pPopupMenu : public pObject {
|
||||
PopupMenu& popupMenu;
|
||||
QMenu* qtMenu;
|
||||
|
||||
void append(Action& action);
|
||||
void remove(Action& action);
|
||||
void setVisible();
|
||||
|
||||
pPopupMenu(PopupMenu& popupMenu) : pObject(popupMenu), popupMenu(popupMenu) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
};
|
||||
|
||||
struct pAction : public pObject {
|
||||
Action& action;
|
||||
|
||||
void setEnabled(bool enabled);
|
||||
void setFont(string font);
|
||||
void setVisible(bool visible);
|
||||
|
||||
pAction(Action& action) : pObject(action), action(action) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
};
|
||||
|
||||
struct pMenu : public pAction {
|
||||
Menu& menu;
|
||||
QMenu* qtMenu;
|
||||
|
||||
void append(Action& action);
|
||||
void remove(Action& action);
|
||||
void setFont(string font);
|
||||
void setImage(const image& image);
|
||||
void setText(string text);
|
||||
|
||||
pMenu(Menu& menu) : pAction(menu), menu(menu) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
};
|
||||
|
||||
struct pSeparator : public pAction {
|
||||
Separator& separator;
|
||||
QAction* qtAction;
|
||||
|
||||
pSeparator(Separator& separator) : pAction(separator), separator(separator) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
};
|
||||
|
||||
struct pItem : public QObject, public pAction {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Item& item;
|
||||
QAction* qtAction;
|
||||
|
||||
void setImage(const image& image);
|
||||
void setText(string text);
|
||||
|
||||
pItem(Item& item) : pAction(item), item(item) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
|
||||
public slots:
|
||||
void onActivate();
|
||||
};
|
||||
|
||||
struct pCheckItem : public QObject, public pAction {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CheckItem& checkItem;
|
||||
QAction* qtAction;
|
||||
|
||||
void setChecked(bool checked);
|
||||
void setText(string text);
|
||||
|
||||
pCheckItem(CheckItem& checkItem) : pAction(checkItem), checkItem(checkItem) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
|
||||
public slots:
|
||||
void onToggle();
|
||||
};
|
||||
|
||||
struct pRadioItem : public QObject, public pAction {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
RadioItem& radioItem;
|
||||
QAction* qtAction;
|
||||
QActionGroup* qtGroup;
|
||||
|
||||
void setChecked();
|
||||
void setGroup(const group<RadioItem>& group);
|
||||
void setText(string text);
|
||||
|
||||
pRadioItem(RadioItem& radioItem) : pAction(radioItem), radioItem(radioItem) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
|
||||
public slots:
|
||||
void onActivate();
|
||||
};
|
||||
|
||||
struct pSizable : public pObject {
|
||||
Sizable& sizable;
|
||||
|
||||
virtual Position displacement() { return {0, 0}; }
|
||||
|
||||
pSizable(Sizable& sizable) : pObject(sizable), sizable(sizable) {}
|
||||
|
||||
void constructor() {}
|
||||
void destructor() {}
|
||||
};
|
||||
|
||||
struct pLayout : public pSizable {
|
||||
Layout& layout;
|
||||
|
||||
pLayout(Layout& layout) : pSizable(layout), layout(layout) {}
|
||||
|
||||
void constructor() {}
|
||||
void destructor() {}
|
||||
};
|
||||
|
||||
struct pWidget : public pSizable {
|
||||
Widget& widget;
|
||||
QWidget* qtWidget;
|
||||
|
||||
virtual QWidget* container(Widget& widget);
|
||||
bool focused();
|
||||
virtual Size minimumSize();
|
||||
virtual void setEnabled(bool enabled);
|
||||
void setFocused();
|
||||
void setFont(string font);
|
||||
virtual void setGeometry(Geometry geometry);
|
||||
virtual void setVisible(bool visible);
|
||||
|
||||
pWidget(Widget& widget) : pSizable(widget), widget(widget) {}
|
||||
void constructor();
|
||||
void synchronizeState();
|
||||
void destructor();
|
||||
virtual void orphan();
|
||||
};
|
||||
|
||||
struct pButton : public QObject, public pWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Button& button;
|
||||
QToolButton* qtButton;
|
||||
|
||||
Size minimumSize();
|
||||
void setBordered(bool bordered);
|
||||
void setImage(const image& image, Orientation orientation);
|
||||
void setText(string text);
|
||||
|
||||
pButton(Button& button) : pWidget(button), button(button) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
void orphan();
|
||||
|
||||
public slots:
|
||||
void onActivate();
|
||||
};
|
||||
|
||||
struct pCanvas : public QObject, public pWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Canvas& canvas;
|
||||
QImage* surface = nullptr;
|
||||
unsigned surfaceWidth = 0;
|
||||
unsigned surfaceHeight = 0;
|
||||
struct QtCanvas : public QWidget {
|
||||
pCanvas& self;
|
||||
void dragEnterEvent(QDragEnterEvent*);
|
||||
void dropEvent(QDropEvent*);
|
||||
void leaveEvent(QEvent*);
|
||||
void mouseMoveEvent(QMouseEvent*);
|
||||
void mousePressEvent(QMouseEvent*);
|
||||
void mouseReleaseEvent(QMouseEvent*);
|
||||
void paintEvent(QPaintEvent*);
|
||||
QtCanvas(pCanvas& self);
|
||||
};
|
||||
QtCanvas* qtCanvas;
|
||||
|
||||
void setDroppable(bool droppable);
|
||||
void setGeometry(Geometry geometry);
|
||||
void setMode(Canvas::Mode mode);
|
||||
void setSize(Size size);
|
||||
|
||||
pCanvas(Canvas& canvas) : pWidget(canvas), canvas(canvas) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
void orphan();
|
||||
void rasterize();
|
||||
void release();
|
||||
|
||||
public slots:
|
||||
};
|
||||
|
||||
struct pCheckButton : public QObject, public pWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CheckButton& checkButton;
|
||||
QToolButton* qtCheckButton;
|
||||
|
||||
Size minimumSize();
|
||||
void setChecked(bool checked);
|
||||
void setImage(const image& image, Orientation orientation);
|
||||
void setText(string text);
|
||||
|
||||
pCheckButton(CheckButton& checkButton) : pWidget(checkButton), checkButton(checkButton) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
void orphan();
|
||||
|
||||
public slots:
|
||||
void onToggle(bool checked);
|
||||
};
|
||||
|
||||
struct pCheckLabel : public QObject, public pWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
CheckLabel& checkLabel;
|
||||
QCheckBox* qtCheckLabel;
|
||||
|
||||
Size minimumSize();
|
||||
void setChecked(bool checked);
|
||||
void setText(string text);
|
||||
|
||||
pCheckLabel(CheckLabel& checkLabel) : pWidget(checkLabel), checkLabel(checkLabel) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
void orphan();
|
||||
|
||||
public slots:
|
||||
void onToggle();
|
||||
};
|
||||
|
||||
struct pComboButton : public QObject, public pWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ComboButton& comboButton;
|
||||
QComboBox* qtComboButton;
|
||||
|
||||
void append();
|
||||
Size minimumSize();
|
||||
void remove(unsigned selection);
|
||||
void reset();
|
||||
void setSelected(unsigned selection);
|
||||
void setText(unsigned selection, string text);
|
||||
|
||||
pComboButton(ComboButton& comboButton) : pWidget(comboButton), comboButton(comboButton) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
void orphan();
|
||||
|
||||
public slots:
|
||||
void onChange();
|
||||
};
|
||||
|
||||
struct pConsole : public QObject, public pWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Console& console;
|
||||
struct QtConsole : public QTextEdit {
|
||||
pConsole& self;
|
||||
void keyPressEvent(QKeyEvent*);
|
||||
void keyPressEventAcknowledge(QKeyEvent*);
|
||||
QtConsole(pConsole& self) : self(self) {}
|
||||
};
|
||||
QtConsole* qtConsole;
|
||||
|
||||
void print(string text);
|
||||
void reset();
|
||||
void setBackgroundColor(Color color);
|
||||
void setForegroundColor(Color color);
|
||||
void setPrompt(string prompt);
|
||||
|
||||
pConsole(Console& console) : pWidget(console), console(console) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
void orphan();
|
||||
void keyPressEvent(QKeyEvent*);
|
||||
};
|
||||
|
||||
struct pFrame : public QObject, public pWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Frame& frame;
|
||||
QGroupBox* qtFrame;
|
||||
|
||||
void setEnabled(bool enabled);
|
||||
void setGeometry(Geometry geometry);
|
||||
void setText(string text);
|
||||
void setVisible(bool visible);
|
||||
|
||||
pFrame(Frame& frame) : pWidget(frame), frame(frame) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
void orphan();
|
||||
};
|
||||
|
||||
struct pHexEdit : public QObject, public pWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
HexEdit& hexEdit;
|
||||
struct QtHexEdit : public QTextEdit {
|
||||
pHexEdit& self;
|
||||
void keyPressEvent(QKeyEvent*);
|
||||
void keyPressEventAcknowledge(QKeyEvent*);
|
||||
void wheelEvent(QWheelEvent*);
|
||||
QtHexEdit(pHexEdit& self) : self(self) {}
|
||||
};
|
||||
struct QtHexEditScrollBar : public QScrollBar {
|
||||
pHexEdit& self;
|
||||
bool event(QEvent*);
|
||||
QtHexEditScrollBar(pHexEdit& self) : QScrollBar(Qt::Vertical), self(self) {}
|
||||
};
|
||||
QtHexEdit* qtHexEdit;
|
||||
QHBoxLayout* qtLayout;
|
||||
QtHexEditScrollBar* qtScroll;
|
||||
|
||||
void setBackgroundColor(Color color);
|
||||
void setColumns(unsigned columns);
|
||||
void setForegroundColor(Color color);
|
||||
void setLength(unsigned length);
|
||||
void setOffset(unsigned offset);
|
||||
void setRows(unsigned rows);
|
||||
void update();
|
||||
|
||||
pHexEdit(HexEdit& hexEdit) : pWidget(hexEdit), hexEdit(hexEdit) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
void orphan();
|
||||
void keyPressEvent(QKeyEvent*);
|
||||
signed rows();
|
||||
signed rowsScrollable();
|
||||
void scrollTo(signed position);
|
||||
|
||||
public slots:
|
||||
void onScroll();
|
||||
};
|
||||
|
||||
struct pHorizontalScroller : public QObject, public pWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
HorizontalScroller& horizontalScroller;
|
||||
QScrollBar* qtScroller;
|
||||
|
||||
Size minimumSize();
|
||||
void setLength(unsigned length);
|
||||
void setPosition(unsigned position);
|
||||
|
||||
pHorizontalScroller(HorizontalScroller& horizontalScroller) : pWidget(horizontalScroller), horizontalScroller(horizontalScroller) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
void orphan();
|
||||
|
||||
public slots:
|
||||
void onChange();
|
||||
};
|
||||
|
||||
struct pHorizontalSlider : public QObject, public pWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
HorizontalSlider& horizontalSlider;
|
||||
QSlider* qtSlider;
|
||||
|
||||
Size minimumSize();
|
||||
void setLength(unsigned length);
|
||||
void setPosition(unsigned position);
|
||||
|
||||
pHorizontalSlider(HorizontalSlider& horizontalSlider) : pWidget(horizontalSlider), horizontalSlider(horizontalSlider) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
void orphan();
|
||||
|
||||
public slots:
|
||||
void onChange();
|
||||
};
|
||||
|
||||
struct pIconView : public QObject, public pWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
IconView& iconView;
|
||||
struct QtListWidget : public QListWidget {
|
||||
void resizeEvent(QResizeEvent*);
|
||||
};
|
||||
QtListWidget* qtIconView;
|
||||
|
||||
void append();
|
||||
void remove(unsigned selection);
|
||||
void reset();
|
||||
void setBackgroundColor(Color color);
|
||||
void setFlow(Orientation flow);
|
||||
void setForegroundColor(Color color);
|
||||
void setImage(unsigned selection, const image& image);
|
||||
void setOrientation(Orientation orientation);
|
||||
void setSelected(unsigned selection, bool selected);
|
||||
void setSelected(const vector<unsigned>& selections);
|
||||
void setSelectedAll();
|
||||
void setSelectedNone();
|
||||
void setSingleSelection(bool singleSelection);
|
||||
void setText(unsigned selection, const string& text);
|
||||
|
||||
pIconView(IconView& iconView) : pWidget(iconView), iconView(iconView) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
void orphan();
|
||||
|
||||
public slots:
|
||||
void onActivate();
|
||||
void onChange();
|
||||
void onContext();
|
||||
};
|
||||
|
||||
struct pLabel : public pWidget {
|
||||
Label& label;
|
||||
QLabel* qtLabel;
|
||||
|
||||
Size minimumSize();
|
||||
void setText(string text);
|
||||
|
||||
pLabel(Label& label) : pWidget(label), label(label) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
void orphan();
|
||||
};
|
||||
|
||||
struct pLineEdit : public QObject, public pWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
LineEdit& lineEdit;
|
||||
QLineEdit* qtLineEdit;
|
||||
|
||||
Size minimumSize();
|
||||
void setBackgroundColor(Color color);
|
||||
void setEditable(bool editable);
|
||||
void setForegroundColor(Color color);
|
||||
void setText(string text);
|
||||
string text();
|
||||
|
||||
pLineEdit(LineEdit& lineEdit) : pWidget(lineEdit), lineEdit(lineEdit) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
void orphan();
|
||||
|
||||
public slots:
|
||||
void onActivate();
|
||||
void onChange();
|
||||
};
|
||||
|
||||
struct pListView : public QObject, public pWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ListView& listView;
|
||||
struct QtTreeWidget : public QTreeWidget {
|
||||
pListView& self;
|
||||
void mousePressEvent(QMouseEvent*);
|
||||
QtTreeWidget(pListView& self);
|
||||
};
|
||||
struct QtTreeWidgetDelegate : public QStyledItemDelegate {
|
||||
pListView& self;
|
||||
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
|
||||
QtTreeWidgetDelegate(pListView& self);
|
||||
};
|
||||
QtTreeWidget* qtListView;
|
||||
QtTreeWidgetDelegate* qtListViewDelegate;
|
||||
|
||||
void appendColumn();
|
||||
void appendItem();
|
||||
void removeColumn(unsigned position);
|
||||
void removeItem(unsigned position);
|
||||
void reset();
|
||||
void resizeColumns();
|
||||
void setActiveColumn(unsigned column);
|
||||
void setBackgroundColor(Color color);
|
||||
void setCheckable(bool checkable);
|
||||
void setChecked(unsigned position, bool checked);
|
||||
void setChecked(const vector<unsigned>& selections);
|
||||
void setCheckedAll();
|
||||
void setCheckedNone();
|
||||
void setColumnBackgroundColor(unsigned position, maybe<Color> color);
|
||||
void setColumnEditable(unsigned position, bool editable);
|
||||
void setColumnFont(unsigned position, maybe<string> font);
|
||||
void setColumnForegroundColor(unsigned position, maybe<Color> color);
|
||||
void setColumnHorizontalAlignment(unsigned position, double alignment);
|
||||
void setColumnResizable(unsigned position, bool resizable);
|
||||
void setColumnSortable(unsigned position, bool sortable);
|
||||
void setColumnText(unsigned position, const string& text);
|
||||
void setColumnVerticalAlignment(unsigned position, double alignment);
|
||||
void setColumnVisible(unsigned position, bool visible);
|
||||
void setColumnWidth(unsigned position, signed width);
|
||||
void setForegroundColor(Color color);
|
||||
void setGridVisible(bool visible);
|
||||
void setHeaderVisible(bool visible);
|
||||
void setImage(unsigned row, unsigned column, const image& image);
|
||||
void setSelected(unsigned position, bool selected);
|
||||
void setSelected(const vector<unsigned>& selections);
|
||||
void setSelectedAll();
|
||||
void setSelectedNone();
|
||||
void setSingleSelection(bool singleSelection);
|
||||
void setText(unsigned row, unsigned column, string text);
|
||||
|
||||
pListView(ListView& listView) : pWidget(listView), listView(listView) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
void orphan();
|
||||
|
||||
public slots:
|
||||
void onActivate();
|
||||
void onChange();
|
||||
void onContext();
|
||||
void onSort(int column);
|
||||
void onToggle(QTreeWidgetItem* item);
|
||||
int calculateAlignment(double horizontal, double vertical);
|
||||
};
|
||||
|
||||
struct pProgressBar : public pWidget {
|
||||
ProgressBar& progressBar;
|
||||
QProgressBar* qtProgressBar;
|
||||
|
||||
Size minimumSize();
|
||||
void setPosition(unsigned position);
|
||||
|
||||
pProgressBar(ProgressBar& progressBar) : pWidget(progressBar), progressBar(progressBar) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
void orphan();
|
||||
};
|
||||
|
||||
struct pRadioLabel : public QObject, public pWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
RadioLabel& radioLabel;
|
||||
QRadioButton* qtRadioLabel;
|
||||
|
||||
bool checked();
|
||||
Size minimumSize();
|
||||
void setChecked();
|
||||
void setGroup(const group<RadioLabel>& group);
|
||||
void setText(string text);
|
||||
|
||||
pRadioLabel(RadioLabel& radioLabel) : pWidget(radioLabel), radioLabel(radioLabel) {}
|
||||
pRadioLabel& parent();
|
||||
void constructor();
|
||||
void destructor();
|
||||
void orphan();
|
||||
|
||||
public slots:
|
||||
void onActivate();
|
||||
};
|
||||
|
||||
struct pRadioButton : public QObject, public pWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
RadioButton& radioButton;
|
||||
QToolButton* qtRadioButton;
|
||||
|
||||
Size minimumSize();
|
||||
void setChecked();
|
||||
void setGroup(const group<RadioButton>& group);
|
||||
void setImage(const image& image, Orientation orientation);
|
||||
void setText(string text);
|
||||
|
||||
pRadioButton(RadioButton& radioButton) : pWidget(radioButton), radioButton(radioButton) {}
|
||||
pRadioButton& parent();
|
||||
void constructor();
|
||||
void destructor();
|
||||
void orphan();
|
||||
|
||||
public slots:
|
||||
void onActivate();
|
||||
};
|
||||
|
||||
struct pTabFrame : public QObject, public pWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TabFrame& tabFrame;
|
||||
QTabWidget* qtTabFrame;
|
||||
|
||||
void append();
|
||||
QWidget* container(Widget& widget);
|
||||
Position displacement();
|
||||
void remove(unsigned selection);
|
||||
void setEnabled(bool enabled);
|
||||
void setGeometry(Geometry geometry);
|
||||
void setImage(unsigned selection, const image& image);
|
||||
void setSelected(unsigned selection);
|
||||
void setText(unsigned selection, string text);
|
||||
void setVisible(bool visible);
|
||||
|
||||
pTabFrame(TabFrame& tabFrame) : pWidget(tabFrame), tabFrame(tabFrame) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
void orphan();
|
||||
void synchronizeLayout();
|
||||
|
||||
public slots:
|
||||
void onChange(int selection);
|
||||
};
|
||||
|
||||
struct pTextEdit : public QObject, public pWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TextEdit& textEdit;
|
||||
QTextEdit* qtTextEdit;
|
||||
|
||||
void setBackgroundColor(Color color);
|
||||
void setCursorPosition(unsigned position);
|
||||
void setEditable(bool editable);
|
||||
void setForegroundColor(Color color);
|
||||
void setText(string text);
|
||||
void setWordWrap(bool wordWrap);
|
||||
string text();
|
||||
|
||||
pTextEdit(TextEdit& textEdit) : pWidget(textEdit), textEdit(textEdit) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
void orphan();
|
||||
|
||||
public slots:
|
||||
void onChange();
|
||||
};
|
||||
|
||||
struct pVerticalScroller : public QObject, public pWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
VerticalScroller& verticalScroller;
|
||||
QScrollBar* qtScroller;
|
||||
|
||||
Size minimumSize();
|
||||
void setLength(unsigned length);
|
||||
void setPosition(unsigned position);
|
||||
|
||||
pVerticalScroller(VerticalScroller& verticalScroller) : pWidget(verticalScroller), verticalScroller(verticalScroller) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
void orphan();
|
||||
|
||||
public slots:
|
||||
void onChange();
|
||||
};
|
||||
|
||||
struct pVerticalSlider : public QObject, public pWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
VerticalSlider& verticalSlider;
|
||||
QSlider* qtSlider;
|
||||
|
||||
Size minimumSize();
|
||||
void setLength(unsigned length);
|
||||
void setPosition(unsigned position);
|
||||
|
||||
pVerticalSlider(VerticalSlider& verticalSlider) : pWidget(verticalSlider), verticalSlider(verticalSlider) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
void orphan();
|
||||
|
||||
public slots:
|
||||
void onChange();
|
||||
};
|
||||
|
||||
struct pViewport : public pWidget {
|
||||
Viewport& viewport;
|
||||
struct QtViewport : public QWidget {
|
||||
pViewport& self;
|
||||
void dragEnterEvent(QDragEnterEvent*);
|
||||
void dropEvent(QDropEvent*);
|
||||
void leaveEvent(QEvent*);
|
||||
void mouseMoveEvent(QMouseEvent*);
|
||||
void mousePressEvent(QMouseEvent*);
|
||||
void mouseReleaseEvent(QMouseEvent*);
|
||||
QtViewport(pViewport& self);
|
||||
};
|
||||
QtViewport* qtViewport;
|
||||
|
||||
uintptr_t handle();
|
||||
void setDroppable(bool droppable);
|
||||
|
||||
pViewport(Viewport& viewport) : pWidget(viewport), viewport(viewport) {}
|
||||
void constructor();
|
||||
void destructor();
|
||||
void orphan();
|
||||
};
|
||||
|
||||
}
|
46
hiro/qt/popup-menu.cpp
Normal file
46
hiro/qt/popup-menu.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
namespace phoenix {
|
||||
|
||||
void pPopupMenu::append(Action& action) {
|
||||
if(dynamic_cast<Menu*>(&action)) {
|
||||
qtMenu->addMenu(((Menu&)action).p.qtMenu);
|
||||
} else if(dynamic_cast<Separator*>(&action)) {
|
||||
qtMenu->addAction(((Separator&)action).p.qtAction);
|
||||
} else if(dynamic_cast<Item*>(&action)) {
|
||||
qtMenu->addAction(((Item&)action).p.qtAction);
|
||||
} else if(dynamic_cast<CheckItem*>(&action)) {
|
||||
qtMenu->addAction(((CheckItem&)action).p.qtAction);
|
||||
} else if(dynamic_cast<RadioItem*>(&action)) {
|
||||
qtMenu->addAction(((RadioItem&)action).p.qtAction);
|
||||
}
|
||||
}
|
||||
|
||||
void pPopupMenu::remove(Action& action) {
|
||||
if(dynamic_cast<Menu*>(&action)) {
|
||||
//QMenu::removeMenu() does not exist
|
||||
qtMenu->clear();
|
||||
for(auto& action : popupMenu.state.action) append(action);
|
||||
} else if(dynamic_cast<Separator*>(&action)) {
|
||||
qtMenu->removeAction(((Separator&)action).p.qtAction);
|
||||
} else if(dynamic_cast<Item*>(&action)) {
|
||||
qtMenu->removeAction(((Item&)action).p.qtAction);
|
||||
} else if(dynamic_cast<CheckItem*>(&action)) {
|
||||
qtMenu->removeAction(((CheckItem&)action).p.qtAction);
|
||||
} else if(dynamic_cast<RadioItem*>(&action)) {
|
||||
qtMenu->removeAction(((RadioItem&)action).p.qtAction);
|
||||
}
|
||||
}
|
||||
|
||||
void pPopupMenu::setVisible() {
|
||||
qtMenu->popup(QCursor::pos());
|
||||
}
|
||||
|
||||
void pPopupMenu::constructor() {
|
||||
qtMenu = new QMenu;
|
||||
}
|
||||
|
||||
void pPopupMenu::destructor() {
|
||||
delete qtMenu;
|
||||
qtMenu = nullptr;
|
||||
}
|
||||
|
||||
}
|
26
hiro/qt/settings.cpp
Normal file
26
hiro/qt/settings.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
namespace phoenix {
|
||||
|
||||
static Settings *settings = nullptr;
|
||||
|
||||
void Settings::load() {
|
||||
string path = {userpath(), ".config/phoenix/"};
|
||||
Configuration::Document::load({path, "qt.bml"});
|
||||
}
|
||||
|
||||
void Settings::save() {
|
||||
string path = {userpath(), ".config/phoenix/"};
|
||||
directory::create(path, 0755);
|
||||
Configuration::Document::save({path, "qt.bml"});
|
||||
}
|
||||
|
||||
Settings::Settings() {
|
||||
geometry.append(geometry.frameX = 4, "FrameX");
|
||||
geometry.append(geometry.frameY = 24, "FrameY");
|
||||
geometry.append(geometry.frameWidth = 8, "FrameWidth");
|
||||
geometry.append(geometry.frameHeight = 28, "FrameHeight");
|
||||
geometry.append(geometry.menuHeight = 20, "MenuHeight");
|
||||
geometry.append(geometry.statusHeight = 20, "StatusHeight");
|
||||
append(geometry, "Geometry");
|
||||
}
|
||||
|
||||
}
|
29
hiro/qt/timer.cpp
Normal file
29
hiro/qt/timer.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
namespace phoenix {
|
||||
|
||||
void pTimer::setEnabled(bool enabled) {
|
||||
if(enabled) {
|
||||
qtTimer->start();
|
||||
} else {
|
||||
qtTimer->stop();
|
||||
}
|
||||
}
|
||||
|
||||
void pTimer::setInterval(unsigned interval) {
|
||||
qtTimer->setInterval(interval);
|
||||
}
|
||||
|
||||
void pTimer::constructor() {
|
||||
qtTimer = new QTimer;
|
||||
qtTimer->setInterval(0);
|
||||
connect(qtTimer, SIGNAL(timeout()), SLOT(onActivate()));
|
||||
}
|
||||
|
||||
void pTimer::destructor() {
|
||||
delete qtTimer;
|
||||
}
|
||||
|
||||
void pTimer::onActivate() {
|
||||
if(timer.onActivate) timer.onActivate();
|
||||
}
|
||||
|
||||
}
|
237
hiro/qt/utility.cpp
Normal file
237
hiro/qt/utility.cpp
Normal file
@@ -0,0 +1,237 @@
|
||||
namespace phoenix {
|
||||
|
||||
static QIcon CreateIcon(const nall::image& image, bool scale = false) {
|
||||
if(image.empty()) return QIcon();
|
||||
nall::image qtBuffer = image;
|
||||
qtBuffer.transform(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0);
|
||||
if(scale) qtBuffer.scale(16, 16, Interpolation::Linear);
|
||||
QImage qtImage(qtBuffer.data, qtBuffer.width, qtBuffer.height, QImage::Format_ARGB32);
|
||||
return QIcon(QPixmap::fromImage(qtImage));
|
||||
}
|
||||
|
||||
static lstring DropPaths(QDropEvent* event) {
|
||||
QList<QUrl> urls = event->mimeData()->urls();
|
||||
if(urls.size() == 0) return {};
|
||||
|
||||
lstring paths;
|
||||
for(unsigned n = 0; n < urls.size(); n++) {
|
||||
string path = urls[n].path().toUtf8().constData();
|
||||
if(path.empty()) continue;
|
||||
if(directory::exists(path) && !path.endsWith("/")) path.append("/");
|
||||
paths.append(path);
|
||||
}
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
static Position GetDisplacement(Sizable* sizable) {
|
||||
Position position;
|
||||
while(sizable->state.parent) {
|
||||
Position displacement = sizable->state.parent->p.displacement();
|
||||
position.x += displacement.x;
|
||||
position.y += displacement.y;
|
||||
sizable = sizable->state.parent;
|
||||
}
|
||||
return position;
|
||||
}
|
||||
|
||||
static Layout* GetParentWidgetLayout(Sizable* sizable) {
|
||||
while(sizable) {
|
||||
if(sizable->state.parent && dynamic_cast<TabFrame*>(sizable->state.parent)) return (Layout*)sizable;
|
||||
sizable = sizable->state.parent;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static Widget* GetParentWidget(Sizable* sizable) {
|
||||
while(sizable) {
|
||||
if(sizable->state.parent && dynamic_cast<TabFrame*>(sizable->state.parent)) return (Widget*)sizable->state.parent;
|
||||
sizable = sizable->state.parent;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static Keyboard::Keycode Keysym(int keysym) {
|
||||
switch(keysym) {
|
||||
case XK_Escape: return Keyboard::Keycode::Escape;
|
||||
case XK_F1: return Keyboard::Keycode::F1;
|
||||
case XK_F2: return Keyboard::Keycode::F2;
|
||||
case XK_F3: return Keyboard::Keycode::F3;
|
||||
case XK_F4: return Keyboard::Keycode::F4;
|
||||
case XK_F5: return Keyboard::Keycode::F5;
|
||||
case XK_F6: return Keyboard::Keycode::F6;
|
||||
case XK_F7: return Keyboard::Keycode::F7;
|
||||
case XK_F8: return Keyboard::Keycode::F8;
|
||||
case XK_F9: return Keyboard::Keycode::F9;
|
||||
case XK_F10: return Keyboard::Keycode::F10;
|
||||
case XK_F11: return Keyboard::Keycode::F11;
|
||||
case XK_F12: return Keyboard::Keycode::F12;
|
||||
|
||||
case XK_Print: return Keyboard::Keycode::PrintScreen;
|
||||
//Keyboard::Keycode::SysRq
|
||||
case XK_Scroll_Lock: return Keyboard::Keycode::ScrollLock;
|
||||
case XK_Pause: return Keyboard::Keycode::Pause;
|
||||
//Keyboard::Keycode::Break
|
||||
|
||||
case XK_Insert: return Keyboard::Keycode::Insert;
|
||||
case XK_Delete: return Keyboard::Keycode::Delete;
|
||||
case XK_Home: return Keyboard::Keycode::Home;
|
||||
case XK_End: return Keyboard::Keycode::End;
|
||||
case XK_Prior: return Keyboard::Keycode::PageUp;
|
||||
case XK_Next: return Keyboard::Keycode::PageDown;
|
||||
|
||||
case XK_Up: return Keyboard::Keycode::Up;
|
||||
case XK_Down: return Keyboard::Keycode::Down;
|
||||
case XK_Left: return Keyboard::Keycode::Left;
|
||||
case XK_Right: return Keyboard::Keycode::Right;
|
||||
|
||||
case XK_grave: return Keyboard::Keycode::Grave;
|
||||
case XK_1: return Keyboard::Keycode::Number1;
|
||||
case XK_2: return Keyboard::Keycode::Number2;
|
||||
case XK_3: return Keyboard::Keycode::Number3;
|
||||
case XK_4: return Keyboard::Keycode::Number4;
|
||||
case XK_5: return Keyboard::Keycode::Number5;
|
||||
case XK_6: return Keyboard::Keycode::Number6;
|
||||
case XK_7: return Keyboard::Keycode::Number7;
|
||||
case XK_8: return Keyboard::Keycode::Number8;
|
||||
case XK_9: return Keyboard::Keycode::Number9;
|
||||
case XK_0: return Keyboard::Keycode::Number0;
|
||||
case XK_minus: return Keyboard::Keycode::Minus;
|
||||
case XK_equal: return Keyboard::Keycode::Equal;
|
||||
case XK_BackSpace: return Keyboard::Keycode::Backspace;
|
||||
|
||||
case XK_asciitilde: return Keyboard::Keycode::Tilde;
|
||||
case XK_exclam: return Keyboard::Keycode::Exclamation;
|
||||
case XK_at: return Keyboard::Keycode::At;
|
||||
case XK_numbersign: return Keyboard::Keycode::Pound;
|
||||
case XK_dollar: return Keyboard::Keycode::Dollar;
|
||||
case XK_percent: return Keyboard::Keycode::Percent;
|
||||
case XK_asciicircum: return Keyboard::Keycode::Power;
|
||||
case XK_ampersand: return Keyboard::Keycode::Ampersand;
|
||||
case XK_asterisk: return Keyboard::Keycode::Asterisk;
|
||||
case XK_parenleft: return Keyboard::Keycode::ParenthesisLeft;
|
||||
case XK_parenright: return Keyboard::Keycode::ParenthesisRight;
|
||||
case XK_underscore: return Keyboard::Keycode::Underscore;
|
||||
case XK_plus: return Keyboard::Keycode::Plus;
|
||||
|
||||
case XK_bracketleft: return Keyboard::Keycode::BracketLeft;
|
||||
case XK_bracketright: return Keyboard::Keycode::BracketRight;
|
||||
case XK_backslash: return Keyboard::Keycode::Backslash;
|
||||
case XK_semicolon: return Keyboard::Keycode::Semicolon;
|
||||
case XK_apostrophe: return Keyboard::Keycode::Apostrophe;
|
||||
case XK_comma: return Keyboard::Keycode::Comma;
|
||||
case XK_period: return Keyboard::Keycode::Period;
|
||||
case XK_slash: return Keyboard::Keycode::Slash;
|
||||
|
||||
case XK_braceleft: return Keyboard::Keycode::BraceLeft;
|
||||
case XK_braceright: return Keyboard::Keycode::BraceRight;
|
||||
case XK_bar: return Keyboard::Keycode::Pipe;
|
||||
case XK_colon: return Keyboard::Keycode::Colon;
|
||||
case XK_quotedbl: return Keyboard::Keycode::Quote;
|
||||
case XK_less: return Keyboard::Keycode::CaretLeft;
|
||||
case XK_greater: return Keyboard::Keycode::CaretRight;
|
||||
case XK_question: return Keyboard::Keycode::Question;
|
||||
|
||||
case XK_Tab: return Keyboard::Keycode::Tab;
|
||||
case XK_Caps_Lock: return Keyboard::Keycode::CapsLock;
|
||||
case XK_Return: return Keyboard::Keycode::Return;
|
||||
case XK_Shift_L: return Keyboard::Keycode::ShiftLeft;
|
||||
case XK_Shift_R: return Keyboard::Keycode::ShiftRight;
|
||||
case XK_Control_L: return Keyboard::Keycode::ControlLeft;
|
||||
case XK_Control_R: return Keyboard::Keycode::ControlRight;
|
||||
case XK_Super_L: return Keyboard::Keycode::SuperLeft;
|
||||
case XK_Super_R: return Keyboard::Keycode::SuperRight;
|
||||
case XK_Alt_L: return Keyboard::Keycode::AltLeft;
|
||||
case XK_Alt_R: return Keyboard::Keycode::AltRight;
|
||||
case XK_space: return Keyboard::Keycode::Space;
|
||||
case XK_Menu: return Keyboard::Keycode::Menu;
|
||||
|
||||
case XK_A: return Keyboard::Keycode::A;
|
||||
case XK_B: return Keyboard::Keycode::B;
|
||||
case XK_C: return Keyboard::Keycode::C;
|
||||
case XK_D: return Keyboard::Keycode::D;
|
||||
case XK_E: return Keyboard::Keycode::E;
|
||||
case XK_F: return Keyboard::Keycode::F;
|
||||
case XK_G: return Keyboard::Keycode::G;
|
||||
case XK_H: return Keyboard::Keycode::H;
|
||||
case XK_I: return Keyboard::Keycode::I;
|
||||
case XK_J: return Keyboard::Keycode::J;
|
||||
case XK_K: return Keyboard::Keycode::K;
|
||||
case XK_L: return Keyboard::Keycode::L;
|
||||
case XK_M: return Keyboard::Keycode::M;
|
||||
case XK_N: return Keyboard::Keycode::N;
|
||||
case XK_O: return Keyboard::Keycode::O;
|
||||
case XK_P: return Keyboard::Keycode::P;
|
||||
case XK_Q: return Keyboard::Keycode::Q;
|
||||
case XK_R: return Keyboard::Keycode::R;
|
||||
case XK_S: return Keyboard::Keycode::S;
|
||||
case XK_T: return Keyboard::Keycode::T;
|
||||
case XK_U: return Keyboard::Keycode::U;
|
||||
case XK_V: return Keyboard::Keycode::V;
|
||||
case XK_W: return Keyboard::Keycode::W;
|
||||
case XK_X: return Keyboard::Keycode::X;
|
||||
case XK_Y: return Keyboard::Keycode::Y;
|
||||
case XK_Z: return Keyboard::Keycode::Z;
|
||||
|
||||
case XK_a: return Keyboard::Keycode::a;
|
||||
case XK_b: return Keyboard::Keycode::b;
|
||||
case XK_c: return Keyboard::Keycode::c;
|
||||
case XK_d: return Keyboard::Keycode::d;
|
||||
case XK_e: return Keyboard::Keycode::e;
|
||||
case XK_f: return Keyboard::Keycode::f;
|
||||
case XK_g: return Keyboard::Keycode::g;
|
||||
case XK_h: return Keyboard::Keycode::h;
|
||||
case XK_i: return Keyboard::Keycode::i;
|
||||
case XK_j: return Keyboard::Keycode::j;
|
||||
case XK_k: return Keyboard::Keycode::k;
|
||||
case XK_l: return Keyboard::Keycode::l;
|
||||
case XK_m: return Keyboard::Keycode::m;
|
||||
case XK_n: return Keyboard::Keycode::n;
|
||||
case XK_o: return Keyboard::Keycode::o;
|
||||
case XK_p: return Keyboard::Keycode::p;
|
||||
case XK_q: return Keyboard::Keycode::q;
|
||||
case XK_r: return Keyboard::Keycode::r;
|
||||
case XK_s: return Keyboard::Keycode::s;
|
||||
case XK_t: return Keyboard::Keycode::t;
|
||||
case XK_u: return Keyboard::Keycode::u;
|
||||
case XK_v: return Keyboard::Keycode::v;
|
||||
case XK_w: return Keyboard::Keycode::w;
|
||||
case XK_x: return Keyboard::Keycode::x;
|
||||
case XK_y: return Keyboard::Keycode::y;
|
||||
case XK_z: return Keyboard::Keycode::z;
|
||||
|
||||
case XK_Num_Lock: return Keyboard::Keycode::NumLock;
|
||||
case XK_KP_Divide: return Keyboard::Keycode::Divide;
|
||||
case XK_KP_Multiply: return Keyboard::Keycode::Multiply;
|
||||
case XK_KP_Subtract: return Keyboard::Keycode::Subtract;
|
||||
case XK_KP_Add: return Keyboard::Keycode::Add;
|
||||
case XK_KP_Enter: return Keyboard::Keycode::Enter;
|
||||
case XK_KP_Decimal: return Keyboard::Keycode::Point;
|
||||
|
||||
case XK_KP_1: return Keyboard::Keycode::Keypad1;
|
||||
case XK_KP_2: return Keyboard::Keycode::Keypad2;
|
||||
case XK_KP_3: return Keyboard::Keycode::Keypad3;
|
||||
case XK_KP_4: return Keyboard::Keycode::Keypad4;
|
||||
case XK_KP_5: return Keyboard::Keycode::Keypad5;
|
||||
case XK_KP_6: return Keyboard::Keycode::Keypad6;
|
||||
case XK_KP_7: return Keyboard::Keycode::Keypad7;
|
||||
case XK_KP_8: return Keyboard::Keycode::Keypad8;
|
||||
case XK_KP_9: return Keyboard::Keycode::Keypad9;
|
||||
case XK_KP_0: return Keyboard::Keycode::Keypad0;
|
||||
|
||||
case XK_KP_Home: return Keyboard::Keycode::KeypadHome;
|
||||
case XK_KP_End: return Keyboard::Keycode::KeypadEnd;
|
||||
case XK_KP_Page_Up: return Keyboard::Keycode::KeypadPageUp;
|
||||
case XK_KP_Page_Down: return Keyboard::Keycode::KeypadPageDown;
|
||||
case XK_KP_Up: return Keyboard::Keycode::KeypadUp;
|
||||
case XK_KP_Down: return Keyboard::Keycode::KeypadDown;
|
||||
case XK_KP_Left: return Keyboard::Keycode::KeypadLeft;
|
||||
case XK_KP_Right: return Keyboard::Keycode::KeypadRight;
|
||||
case XK_KP_Begin: return Keyboard::Keycode::KeypadCenter;
|
||||
case XK_KP_Insert: return Keyboard::Keycode::KeypadInsert;
|
||||
case XK_KP_Delete: return Keyboard::Keycode::KeypadDelete;
|
||||
}
|
||||
return Keyboard::Keycode::None;
|
||||
}
|
||||
|
||||
}
|
62
hiro/qt/widget/button.cpp
Normal file
62
hiro/qt/widget/button.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
namespace phoenix {
|
||||
|
||||
Size pButton::minimumSize() {
|
||||
Size size = pFont::size(qtWidget->font(), button.state.text);
|
||||
|
||||
if(button.state.orientation == Orientation::Horizontal) {
|
||||
size.width += button.state.image.width;
|
||||
size.height = max(button.state.image.height, size.height);
|
||||
}
|
||||
|
||||
if(button.state.orientation == Orientation::Vertical) {
|
||||
size.width = max(button.state.image.width, size.width);
|
||||
size.height += button.state.image.height;
|
||||
}
|
||||
|
||||
return {size.width + (button.state.text ? 20 : 12), size.height + 12};
|
||||
}
|
||||
|
||||
void pButton::setBordered(bool bordered) {
|
||||
qtButton->setAutoRaise(bordered == false);
|
||||
}
|
||||
|
||||
void pButton::setImage(const image& image, Orientation orientation) {
|
||||
qtButton->setIconSize(QSize(image.width, image.height));
|
||||
qtButton->setIcon(CreateIcon(image));
|
||||
qtButton->setStyleSheet("text-align: top;");
|
||||
switch(orientation) {
|
||||
case Orientation::Horizontal: qtButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); break;
|
||||
case Orientation::Vertical: qtButton->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); break;
|
||||
}
|
||||
}
|
||||
|
||||
void pButton::setText(string text) {
|
||||
qtButton->setText(QString::fromUtf8(text));
|
||||
}
|
||||
|
||||
void pButton::constructor() {
|
||||
qtWidget = qtButton = new QToolButton;
|
||||
qtButton->setToolButtonStyle(Qt::ToolButtonTextOnly);
|
||||
connect(qtButton, SIGNAL(released()), SLOT(onActivate()));
|
||||
|
||||
pWidget::synchronizeState();
|
||||
setBordered(button.state.bordered);
|
||||
setImage(button.state.image, button.state.orientation);
|
||||
setText(button.state.text);
|
||||
}
|
||||
|
||||
void pButton::destructor() {
|
||||
delete qtButton;
|
||||
qtWidget = qtButton = nullptr;
|
||||
}
|
||||
|
||||
void pButton::orphan() {
|
||||
destructor();
|
||||
constructor();
|
||||
}
|
||||
|
||||
void pButton::onActivate() {
|
||||
if(button.onActivate) button.onActivate();
|
||||
}
|
||||
|
||||
}
|
155
hiro/qt/widget/canvas.cpp
Normal file
155
hiro/qt/widget/canvas.cpp
Normal file
@@ -0,0 +1,155 @@
|
||||
namespace phoenix {
|
||||
|
||||
void pCanvas::setDroppable(bool droppable) {
|
||||
qtCanvas->setAcceptDrops(droppable);
|
||||
}
|
||||
|
||||
void pCanvas::setGeometry(Geometry geometry) {
|
||||
if(canvas.state.width == 0 || canvas.state.height == 0) rasterize();
|
||||
unsigned width = canvas.state.width;
|
||||
unsigned height = canvas.state.height;
|
||||
if(width == 0) width = widget.state.geometry.width;
|
||||
if(height == 0) height = widget.state.geometry.height;
|
||||
|
||||
if(width < geometry.width) {
|
||||
geometry.x += (geometry.width - width) / 2;
|
||||
geometry.width = width;
|
||||
}
|
||||
|
||||
if(height < geometry.height) {
|
||||
geometry.y += (geometry.height - height) / 2;
|
||||
geometry.height = height;
|
||||
}
|
||||
|
||||
pWidget::setGeometry(geometry);
|
||||
}
|
||||
|
||||
void pCanvas::setMode(Canvas::Mode mode) {
|
||||
rasterize();
|
||||
qtCanvas->update();
|
||||
}
|
||||
|
||||
void pCanvas::setSize(Size size) {
|
||||
rasterize();
|
||||
qtCanvas->update();
|
||||
}
|
||||
|
||||
void pCanvas::constructor() {
|
||||
qtWidget = qtCanvas = new QtCanvas(*this);
|
||||
qtCanvas->setMouseTracking(true);
|
||||
|
||||
pWidget::synchronizeState();
|
||||
rasterize(), qtCanvas->update();
|
||||
}
|
||||
|
||||
void pCanvas::destructor() {
|
||||
release();
|
||||
delete qtCanvas;
|
||||
qtWidget = qtCanvas = nullptr;
|
||||
}
|
||||
|
||||
void pCanvas::orphan() {
|
||||
destructor();
|
||||
constructor();
|
||||
}
|
||||
|
||||
void pCanvas::rasterize() {
|
||||
unsigned width = canvas.state.width;
|
||||
unsigned height = canvas.state.height;
|
||||
if(width == 0) width = widget.state.geometry.width;
|
||||
if(height == 0) height = widget.state.geometry.height;
|
||||
|
||||
if(canvas.state.mode != Canvas::Mode::Color) {
|
||||
if(width != surfaceWidth || height != surfaceHeight) release();
|
||||
if(!surface) surface = new QImage(width, height, QImage::Format_ARGB32);
|
||||
}
|
||||
|
||||
if(canvas.state.mode == Canvas::Mode::Gradient) {
|
||||
nall::image image;
|
||||
image.allocate(width, height);
|
||||
image.gradient(
|
||||
canvas.state.gradient[0].argb(), canvas.state.gradient[1].argb(), canvas.state.gradient[2].argb(), canvas.state.gradient[3].argb()
|
||||
);
|
||||
memcpy(surface->bits(), image.data, image.size);
|
||||
}
|
||||
|
||||
if(canvas.state.mode == Canvas::Mode::Image) {
|
||||
nall::image image = canvas.state.image;
|
||||
image.scale(width, height);
|
||||
image.transform(0, 32, 255u << 24, 255u << 16, 255u << 8, 255u << 0);
|
||||
memcpy(surface->bits(), image.data, image.size);
|
||||
}
|
||||
|
||||
if(canvas.state.mode == Canvas::Mode::Data) {
|
||||
if(width == canvas.state.width && height == canvas.state.height) {
|
||||
memcpy(surface->bits(), canvas.state.data, width * height * sizeof(uint32_t));
|
||||
} else {
|
||||
memset(surface->bits(), 0x00, width * height * sizeof(uint32_t));
|
||||
}
|
||||
}
|
||||
|
||||
surfaceWidth = width;
|
||||
surfaceHeight = height;
|
||||
}
|
||||
|
||||
void pCanvas::release() {
|
||||
if(surface == nullptr) return;
|
||||
delete surface;
|
||||
surface = nullptr;
|
||||
surfaceWidth = 0;
|
||||
surfaceHeight = 0;
|
||||
}
|
||||
|
||||
void pCanvas::QtCanvas::dragEnterEvent(QDragEnterEvent* event) {
|
||||
if(event->mimeData()->hasUrls()) {
|
||||
event->acceptProposedAction();
|
||||
}
|
||||
}
|
||||
|
||||
void pCanvas::QtCanvas::dropEvent(QDropEvent* event) {
|
||||
lstring paths = DropPaths(event);
|
||||
if(paths.empty()) return;
|
||||
if(self.canvas.onDrop) self.canvas.onDrop(paths);
|
||||
}
|
||||
|
||||
void pCanvas::QtCanvas::leaveEvent(QEvent* event) {
|
||||
if(self.canvas.onMouseLeave) self.canvas.onMouseLeave();
|
||||
}
|
||||
|
||||
void pCanvas::QtCanvas::mouseMoveEvent(QMouseEvent* event) {
|
||||
if(self.canvas.onMouseMove) self.canvas.onMouseMove({event->pos().x(), event->pos().y()});
|
||||
}
|
||||
|
||||
void pCanvas::QtCanvas::mousePressEvent(QMouseEvent* event) {
|
||||
if(!self.canvas.onMousePress) return;
|
||||
switch(event->button()) {
|
||||
case Qt::LeftButton: self.canvas.onMousePress(Mouse::Button::Left); break;
|
||||
case Qt::MidButton: self.canvas.onMousePress(Mouse::Button::Middle); break;
|
||||
case Qt::RightButton: self.canvas.onMousePress(Mouse::Button::Right); break;
|
||||
}
|
||||
}
|
||||
|
||||
void pCanvas::QtCanvas::mouseReleaseEvent(QMouseEvent* event) {
|
||||
if(!self.canvas.onMouseRelease) return;
|
||||
switch(event->button()) {
|
||||
case Qt::LeftButton: self.canvas.onMouseRelease(Mouse::Button::Left); break;
|
||||
case Qt::MidButton: self.canvas.onMouseRelease(Mouse::Button::Middle); break;
|
||||
case Qt::RightButton: self.canvas.onMouseRelease(Mouse::Button::Right); break;
|
||||
}
|
||||
}
|
||||
|
||||
void pCanvas::QtCanvas::paintEvent(QPaintEvent* event) {
|
||||
Canvas& canvas = self.canvas;
|
||||
QPainter painter(self.qtCanvas);
|
||||
|
||||
if(canvas.state.mode == Canvas::Mode::Color) {
|
||||
painter.fillRect(event->rect(), QBrush(QColor(canvas.state.color.red, canvas.state.color.green, canvas.state.color.blue, canvas.state.color.alpha)));
|
||||
} else {
|
||||
painter.drawImage(0, 0, *self.surface);
|
||||
}
|
||||
}
|
||||
|
||||
pCanvas::QtCanvas::QtCanvas(pCanvas& self) : self(self) {
|
||||
}
|
||||
|
||||
}
|
63
hiro/qt/widget/check-button.cpp
Normal file
63
hiro/qt/widget/check-button.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
namespace phoenix {
|
||||
|
||||
Size pCheckButton::minimumSize() {
|
||||
Size size = pFont::size(qtWidget->font(), checkButton.state.text);
|
||||
|
||||
if(checkButton.state.orientation == Orientation::Horizontal) {
|
||||
size.width += checkButton.state.image.width;
|
||||
size.height = max(checkButton.state.image.height, size.height);
|
||||
}
|
||||
|
||||
if(checkButton.state.orientation == Orientation::Vertical) {
|
||||
size.width = max(checkButton.state.image.width, size.width);
|
||||
size.height += checkButton.state.image.height;
|
||||
}
|
||||
|
||||
return {size.width + 20, size.height + 12};
|
||||
}
|
||||
|
||||
void pCheckButton::setChecked(bool checked) {
|
||||
lock();
|
||||
qtCheckButton->setChecked(checked);
|
||||
unlock();
|
||||
}
|
||||
|
||||
void pCheckButton::setImage(const image& image, Orientation orientation) {
|
||||
qtCheckButton->setIconSize(QSize(image.width, image.height));
|
||||
qtCheckButton->setIcon(CreateIcon(image));
|
||||
qtCheckButton->setStyleSheet("text-align: top;");
|
||||
switch(orientation) {
|
||||
case Orientation::Horizontal: qtCheckButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); break;
|
||||
case Orientation::Vertical: qtCheckButton->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); break;
|
||||
}
|
||||
}
|
||||
|
||||
void pCheckButton::setText(string text) {
|
||||
qtCheckButton->setText(QString::fromUtf8(text));
|
||||
}
|
||||
|
||||
void pCheckButton::constructor() {
|
||||
qtWidget = qtCheckButton = new QToolButton;
|
||||
qtCheckButton->setCheckable(true);
|
||||
qtCheckButton->setToolButtonStyle(Qt::ToolButtonTextOnly);
|
||||
connect(qtCheckButton, SIGNAL(toggled(bool)), SLOT(onToggle(bool)));
|
||||
|
||||
pWidget::synchronizeState();
|
||||
setChecked(checkButton.state.checked);
|
||||
setText(checkButton.state.text);
|
||||
}
|
||||
|
||||
void pCheckButton::destructor() {
|
||||
}
|
||||
|
||||
void pCheckButton::orphan() {
|
||||
destructor();
|
||||
constructor();
|
||||
}
|
||||
|
||||
void pCheckButton::onToggle(bool checked) {
|
||||
checkButton.state.checked = checked;
|
||||
if(!locked() && checkButton.onToggle) checkButton.onToggle();
|
||||
}
|
||||
|
||||
}
|
42
hiro/qt/widget/check-label.cpp
Normal file
42
hiro/qt/widget/check-label.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
namespace phoenix {
|
||||
|
||||
Size pCheckLabel::minimumSize() {
|
||||
Size size = pFont::size(qtWidget->font(), checkLabel.state.text);
|
||||
return {size.width + 26, size.height + 6};
|
||||
}
|
||||
|
||||
void pCheckLabel::setChecked(bool checked) {
|
||||
lock();
|
||||
qtCheckLabel->setChecked(checked);
|
||||
unlock();
|
||||
}
|
||||
|
||||
void pCheckLabel::setText(string text) {
|
||||
qtCheckLabel->setText(QString::fromUtf8(text));
|
||||
}
|
||||
|
||||
void pCheckLabel::constructor() {
|
||||
qtWidget = qtCheckLabel = new QCheckBox;
|
||||
connect(qtCheckLabel, SIGNAL(stateChanged(int)), SLOT(onToggle()));
|
||||
|
||||
pWidget::synchronizeState();
|
||||
setChecked(checkLabel.state.checked);
|
||||
setText(checkLabel.state.text);
|
||||
}
|
||||
|
||||
void pCheckLabel::destructor() {
|
||||
delete qtCheckLabel;
|
||||
qtWidget = qtCheckLabel = nullptr;
|
||||
}
|
||||
|
||||
void pCheckLabel::orphan() {
|
||||
destructor();
|
||||
constructor();
|
||||
}
|
||||
|
||||
void pCheckLabel::onToggle() {
|
||||
checkLabel.state.checked = qtCheckLabel->isChecked();
|
||||
if(!locked() && checkLabel.onToggle) checkLabel.onToggle();
|
||||
}
|
||||
|
||||
}
|
67
hiro/qt/widget/combo-button.cpp
Normal file
67
hiro/qt/widget/combo-button.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
namespace phoenix {
|
||||
|
||||
void pComboButton::append() {
|
||||
lock();
|
||||
qtComboButton->addItem("");
|
||||
unlock();
|
||||
}
|
||||
|
||||
Size pComboButton::minimumSize() {
|
||||
unsigned maximumWidth = 0;
|
||||
for(auto& text : comboButton.state.text) maximumWidth = max(maximumWidth, pFont::size(qtWidget->font(), text).width);
|
||||
Size size = pFont::size(qtWidget->font(), " ");
|
||||
return {maximumWidth + 32, size.height + 12};
|
||||
}
|
||||
|
||||
void pComboButton::remove(unsigned selection) {
|
||||
lock();
|
||||
qtComboButton->removeItem(selection);
|
||||
if(selection == comboButton.state.selection) comboButton[0].setSelected();
|
||||
unlock();
|
||||
}
|
||||
|
||||
void pComboButton::reset() {
|
||||
lock();
|
||||
while(qtComboButton->count()) qtComboButton->removeItem(0);
|
||||
unlock();
|
||||
}
|
||||
|
||||
void pComboButton::setSelected(unsigned selection) {
|
||||
lock();
|
||||
qtComboButton->setCurrentIndex(selection);
|
||||
unlock();
|
||||
}
|
||||
|
||||
void pComboButton::setText(unsigned selection, string text) {
|
||||
qtComboButton->setItemText(selection, text);
|
||||
}
|
||||
|
||||
void pComboButton::constructor() {
|
||||
qtWidget = qtComboButton = new QComboBox;
|
||||
connect(qtComboButton, SIGNAL(currentIndexChanged(int)), SLOT(onChange()));
|
||||
|
||||
pWidget::synchronizeState();
|
||||
unsigned selection = comboButton.state.selection;
|
||||
for(unsigned n = 0; n < comboButton.count(); n++) {
|
||||
append();
|
||||
setText(n, comboButton.state.text[n]);
|
||||
}
|
||||
comboButton[selection].setSelected();
|
||||
}
|
||||
|
||||
void pComboButton::destructor() {
|
||||
delete qtComboButton;
|
||||
qtWidget = qtComboButton = nullptr;
|
||||
}
|
||||
|
||||
void pComboButton::orphan() {
|
||||
destructor();
|
||||
constructor();
|
||||
}
|
||||
|
||||
void pComboButton::onChange() {
|
||||
comboButton.state.selection = qtComboButton->currentIndex();
|
||||
if(!locked() && comboButton.onChange) comboButton.onChange();
|
||||
}
|
||||
|
||||
}
|
52
hiro/qt/widget/console.cpp
Normal file
52
hiro/qt/widget/console.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
namespace phoenix {
|
||||
|
||||
void pConsole::print(string text) {
|
||||
}
|
||||
|
||||
void pConsole::reset() {
|
||||
}
|
||||
|
||||
void pConsole::setBackgroundColor(Color color) {
|
||||
QPalette palette = qtConsole->palette();
|
||||
palette.setColor(QPalette::Base, QColor(color.red, color.green, color.blue));
|
||||
qtConsole->setPalette(palette);
|
||||
qtConsole->setAutoFillBackground(true);
|
||||
}
|
||||
|
||||
void pConsole::setForegroundColor(Color color) {
|
||||
QPalette palette = qtConsole->palette();
|
||||
palette.setColor(QPalette::Text, QColor(color.red, color.green, color.blue));
|
||||
qtConsole->setPalette(palette);
|
||||
}
|
||||
|
||||
void pConsole::setPrompt(string prompt) {
|
||||
}
|
||||
|
||||
void pConsole::constructor() {
|
||||
qtWidget = qtConsole = new QtConsole(*this);
|
||||
|
||||
pWidget::synchronizeState();
|
||||
}
|
||||
|
||||
void pConsole::destructor() {
|
||||
delete qtConsole;
|
||||
qtWidget = qtConsole = nullptr;
|
||||
}
|
||||
|
||||
void pConsole::orphan() {
|
||||
destructor();
|
||||
constructor();
|
||||
}
|
||||
|
||||
void pConsole::keyPressEvent(QKeyEvent* event) {
|
||||
}
|
||||
|
||||
void pConsole::QtConsole::keyPressEvent(QKeyEvent* event) {
|
||||
self.keyPressEvent(event);
|
||||
}
|
||||
|
||||
void pConsole::QtConsole::keyPressEventAcknowledge(QKeyEvent* event) {
|
||||
QTextEdit::keyPressEvent(event);
|
||||
}
|
||||
|
||||
}
|
52
hiro/qt/widget/frame.cpp
Normal file
52
hiro/qt/widget/frame.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
namespace phoenix {
|
||||
|
||||
void pFrame::setEnabled(bool enabled) {
|
||||
if(frame.state.layout) frame.state.layout->setEnabled(frame.state.layout->enabled());
|
||||
pWidget::setEnabled(enabled);
|
||||
}
|
||||
|
||||
void pFrame::setGeometry(Geometry geometry) {
|
||||
pWidget::setGeometry(geometry);
|
||||
if(frame.state.layout == nullptr) return;
|
||||
Size size = pFont::size(widget.state.font, frame.state.text);
|
||||
if(frame.state.text.empty()) size.height = 8;
|
||||
geometry.x += 1, geometry.width -= 2;
|
||||
geometry.y += size.height, geometry.height -= size.height + 1;
|
||||
frame.state.layout->setGeometry(geometry);
|
||||
}
|
||||
|
||||
void pFrame::setText(string text) {
|
||||
qtFrame->setTitle(QString::fromUtf8(text));
|
||||
}
|
||||
|
||||
void pFrame::setVisible(bool visible) {
|
||||
if(frame.state.layout) frame.state.layout->setVisible(frame.state.layout->visible());
|
||||
pWidget::setVisible(visible);
|
||||
}
|
||||
|
||||
void pFrame::constructor() {
|
||||
qtWidget = qtFrame = new QGroupBox;
|
||||
if(QApplication::style()->objectName() == "gtk+") {
|
||||
//QGtkStyle (gtk+) theme disrespects font weight and omits the border, even if native GTK+ theme does not
|
||||
//bold Label controls already exist; so this style sheet forces QGtkStyle to look like a Frame instead
|
||||
qtFrame->setStyleSheet(
|
||||
"QGroupBox { border: 1px solid #aaa; border-radius: 5px; margin-top: 0.5em; }\n"
|
||||
"QGroupBox::title { left: 5px; subcontrol-origin: margin; }\n"
|
||||
);
|
||||
}
|
||||
|
||||
pWidget::synchronizeState();
|
||||
setText(frame.state.text);
|
||||
}
|
||||
|
||||
void pFrame::destructor() {
|
||||
delete qtFrame;
|
||||
qtWidget = qtFrame = nullptr;
|
||||
}
|
||||
|
||||
void pFrame::orphan() {
|
||||
destructor();
|
||||
constructor();
|
||||
}
|
||||
|
||||
}
|
298
hiro/qt/widget/hex-edit.cpp
Normal file
298
hiro/qt/widget/hex-edit.cpp
Normal file
@@ -0,0 +1,298 @@
|
||||
namespace phoenix {
|
||||
|
||||
void pHexEdit::setBackgroundColor(Color color) {
|
||||
QPalette palette = qtHexEdit->palette();
|
||||
palette.setColor(QPalette::Base, QColor(color.red, color.green, color.blue));
|
||||
qtHexEdit->setPalette(palette);
|
||||
qtHexEdit->setAutoFillBackground(true);
|
||||
}
|
||||
|
||||
void pHexEdit::setColumns(unsigned columns) {
|
||||
update();
|
||||
}
|
||||
|
||||
void pHexEdit::setForegroundColor(Color color) {
|
||||
QPalette palette = qtHexEdit->palette();
|
||||
palette.setColor(QPalette::Text, QColor(color.red, color.green, color.blue));
|
||||
qtHexEdit->setPalette(palette);
|
||||
}
|
||||
|
||||
void pHexEdit::setLength(unsigned length) {
|
||||
//add one if last row is not equal to column length (eg only part of the row is present)
|
||||
bool indivisible = hexEdit.state.columns == 0 || (hexEdit.state.length % hexEdit.state.columns) != 0;
|
||||
qtScroll->setRange(0, hexEdit.state.length / hexEdit.state.columns + indivisible - hexEdit.state.rows);
|
||||
update();
|
||||
}
|
||||
|
||||
void pHexEdit::setOffset(unsigned offset) {
|
||||
lock();
|
||||
qtScroll->setSliderPosition(hexEdit.state.offset / hexEdit.state.columns);
|
||||
unlock();
|
||||
update();
|
||||
}
|
||||
|
||||
void pHexEdit::setRows(unsigned rows) {
|
||||
qtScroll->setPageStep(hexEdit.state.rows);
|
||||
update();
|
||||
}
|
||||
|
||||
void pHexEdit::update() {
|
||||
if(!hexEdit.onRead) {
|
||||
qtHexEdit->setPlainText("");
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned cursorPosition = qtHexEdit->textCursor().position();
|
||||
|
||||
string output;
|
||||
unsigned offset = hexEdit.state.offset;
|
||||
for(unsigned row = 0; row < hexEdit.state.rows; row++) {
|
||||
output.append(hex<8>(offset));
|
||||
output.append(" ");
|
||||
|
||||
string hexdata;
|
||||
string ansidata = " ";
|
||||
|
||||
for(unsigned column = 0; column < hexEdit.state.columns; column++) {
|
||||
if(offset < hexEdit.state.length) {
|
||||
uint8_t data = hexEdit.onRead(offset++);
|
||||
hexdata.append(hex<2>(data));
|
||||
hexdata.append(" ");
|
||||
ansidata.append(data >= 0x20 && data <= 0x7e ? (char)data : '.');
|
||||
} else {
|
||||
hexdata.append(" ");
|
||||
ansidata.append(" ");
|
||||
}
|
||||
}
|
||||
|
||||
output.append(hexdata);
|
||||
output.append(ansidata);
|
||||
if(offset >= hexEdit.state.length) break;
|
||||
if(row != hexEdit.state.rows - 1) output.append("\n");
|
||||
}
|
||||
|
||||
qtHexEdit->setPlainText(QString::fromUtf8(output));
|
||||
QTextCursor cursor = qtHexEdit->textCursor();
|
||||
cursor.setPosition(cursorPosition);
|
||||
qtHexEdit->setTextCursor(cursor);
|
||||
}
|
||||
|
||||
void pHexEdit::constructor() {
|
||||
qtWidget = qtHexEdit = new QtHexEdit(*this);
|
||||
|
||||
qtHexEdit->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
qtHexEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
qtHexEdit->setTextInteractionFlags(Qt::TextSelectableByKeyboard | Qt::TextSelectableByMouse);
|
||||
|
||||
qtLayout = new QHBoxLayout;
|
||||
qtLayout->setAlignment(Qt::AlignRight);
|
||||
qtLayout->setMargin(0);
|
||||
qtLayout->setSpacing(0);
|
||||
qtHexEdit->setLayout(qtLayout);
|
||||
|
||||
qtScroll = new QtHexEditScrollBar(*this);
|
||||
qtScroll->setSingleStep(1);
|
||||
qtLayout->addWidget(qtScroll);
|
||||
|
||||
connect(qtScroll, SIGNAL(actionTriggered(int)), SLOT(onScroll()));
|
||||
|
||||
pWidget::synchronizeState();
|
||||
setColumns(hexEdit.state.columns);
|
||||
setRows(hexEdit.state.rows);
|
||||
setLength(hexEdit.state.length);
|
||||
setOffset(hexEdit.state.offset);
|
||||
update();
|
||||
}
|
||||
|
||||
void pHexEdit::destructor() {
|
||||
delete qtScroll;
|
||||
delete qtLayout;
|
||||
delete qtHexEdit;
|
||||
qtWidget = qtHexEdit = nullptr;
|
||||
qtLayout = nullptr;
|
||||
qtScroll = nullptr;
|
||||
}
|
||||
|
||||
void pHexEdit::orphan() {
|
||||
destructor();
|
||||
constructor();
|
||||
}
|
||||
|
||||
void pHexEdit::keyPressEvent(QKeyEvent* event) {
|
||||
if(!hexEdit.onRead) return;
|
||||
|
||||
//allow Ctrl+C (copy)
|
||||
if(event->key() == Qt::Key_C && event->modifiers() == Qt::ControlModifier) {
|
||||
qtHexEdit->keyPressEventAcknowledge(event);
|
||||
return;
|
||||
}
|
||||
|
||||
//disallow other text operations (cut, paste, etc)
|
||||
if(event->modifiers() & (Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier)) return;
|
||||
|
||||
QTextCursor cursor = qtHexEdit->textCursor();
|
||||
signed lineWidth = 10 + (hexEdit.state.columns * 3) + 1 + hexEdit.state.columns + 1;
|
||||
signed cursorY = cursor.position() / lineWidth;
|
||||
signed cursorX = cursor.position() % lineWidth;
|
||||
|
||||
unsigned nibble = 0;
|
||||
switch(event->key()) {
|
||||
default: return;
|
||||
|
||||
case Qt::Key_Left:
|
||||
if(cursorX > 0) {
|
||||
cursor.setPosition(cursor.position() - 1);
|
||||
qtHexEdit->setTextCursor(cursor);
|
||||
}
|
||||
return;
|
||||
|
||||
case Qt::Key_Right:
|
||||
if(cursorX < lineWidth - 1) {
|
||||
cursor.setPosition(cursor.position() + 1);
|
||||
qtHexEdit->setTextCursor(cursor);
|
||||
}
|
||||
return;
|
||||
|
||||
case Qt::Key_Home:
|
||||
cursor.setPosition(cursorY * lineWidth + 10);
|
||||
qtHexEdit->setTextCursor(cursor);
|
||||
return;
|
||||
|
||||
case Qt::Key_End:
|
||||
cursor.setPosition(cursorY * lineWidth + 57);
|
||||
qtHexEdit->setTextCursor(cursor);
|
||||
return;
|
||||
|
||||
case Qt::Key_Up:
|
||||
if(cursorY > 0) {
|
||||
cursor.setPosition(cursor.position() - lineWidth);
|
||||
qtHexEdit->setTextCursor(cursor);
|
||||
} else {
|
||||
scrollTo(qtScroll->sliderPosition() - 1);
|
||||
}
|
||||
return;
|
||||
|
||||
case Qt::Key_Down:
|
||||
if(cursorY >= rows() - 1) {
|
||||
//cannot scroll down further
|
||||
} else if(cursorY < hexEdit.state.rows - 1) {
|
||||
cursor.setPosition(cursor.position() + lineWidth);
|
||||
qtHexEdit->setTextCursor(cursor);
|
||||
} else {
|
||||
scrollTo(qtScroll->sliderPosition() + 1);
|
||||
}
|
||||
return;
|
||||
|
||||
case Qt::Key_PageUp:
|
||||
scrollTo(qtScroll->sliderPosition() - hexEdit.state.rows);
|
||||
return;
|
||||
|
||||
case Qt::Key_PageDown:
|
||||
scrollTo(qtScroll->sliderPosition() + hexEdit.state.rows);
|
||||
return;
|
||||
|
||||
case Qt::Key_0: nibble = 0; break;
|
||||
case Qt::Key_1: nibble = 1; break;
|
||||
case Qt::Key_2: nibble = 2; break;
|
||||
case Qt::Key_3: nibble = 3; break;
|
||||
case Qt::Key_4: nibble = 4; break;
|
||||
case Qt::Key_5: nibble = 5; break;
|
||||
case Qt::Key_6: nibble = 6; break;
|
||||
case Qt::Key_7: nibble = 7; break;
|
||||
case Qt::Key_8: nibble = 8; break;
|
||||
case Qt::Key_9: nibble = 9; break;
|
||||
case Qt::Key_A: nibble = 10; break;
|
||||
case Qt::Key_B: nibble = 11; break;
|
||||
case Qt::Key_C: nibble = 12; break;
|
||||
case Qt::Key_D: nibble = 13; break;
|
||||
case Qt::Key_E: nibble = 14; break;
|
||||
case Qt::Key_F: nibble = 15; break;
|
||||
}
|
||||
|
||||
if(cursorX >= 10) {
|
||||
//not on an offset
|
||||
cursorX -= 10;
|
||||
if((cursorX % 3) != 2) {
|
||||
//not on a space
|
||||
bool cursorNibble = (cursorX % 3) == 1; //0 = high, 1 = low
|
||||
cursorX /= 3;
|
||||
if(cursorX < hexEdit.state.columns) {
|
||||
//not in ANSI region
|
||||
unsigned offset = hexEdit.state.offset + (cursorY * hexEdit.state.columns + cursorX);
|
||||
|
||||
if(offset >= hexEdit.state.length) return; //do not edit past end of file
|
||||
uint8_t data = hexEdit.onRead(offset);
|
||||
|
||||
//write modified value
|
||||
if(cursorNibble == 1) {
|
||||
data = (data & 0xf0) | (nibble << 0);
|
||||
} else {
|
||||
data = (data & 0x0f) | (nibble << 4);
|
||||
}
|
||||
if(hexEdit.onWrite) hexEdit.onWrite(offset, data);
|
||||
|
||||
//auto-advance cursor to next nibble/byte
|
||||
unsigned step = 1;
|
||||
if(cursorNibble && cursorX != hexEdit.state.columns - 1) step = 2;
|
||||
cursor.setPosition(cursor.position() + step);
|
||||
qtHexEdit->setTextCursor(cursor);
|
||||
|
||||
//refresh output to reflect modified data
|
||||
update();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//number of actual rows
|
||||
signed pHexEdit::rows() {
|
||||
return (max(1u, hexEdit.state.length) + hexEdit.state.columns - 1) / hexEdit.state.columns;
|
||||
}
|
||||
|
||||
//number of scrollable row positions
|
||||
signed pHexEdit::rowsScrollable() {
|
||||
return max(0u, rows() - hexEdit.state.rows);
|
||||
}
|
||||
|
||||
void pHexEdit::scrollTo(signed position) {
|
||||
if(position > rowsScrollable()) position = rowsScrollable();
|
||||
if(position < 0) position = 0;
|
||||
qtScroll->setSliderPosition(position);
|
||||
}
|
||||
|
||||
void pHexEdit::onScroll() {
|
||||
if(locked()) return;
|
||||
unsigned offset = qtScroll->sliderPosition();
|
||||
hexEdit.state.offset = offset * hexEdit.state.columns;
|
||||
update();
|
||||
}
|
||||
|
||||
void pHexEdit::QtHexEdit::keyPressEvent(QKeyEvent* event) {
|
||||
self.keyPressEvent(event);
|
||||
}
|
||||
|
||||
void pHexEdit::QtHexEdit::keyPressEventAcknowledge(QKeyEvent* event) {
|
||||
QTextEdit::keyPressEvent(event);
|
||||
}
|
||||
|
||||
void pHexEdit::QtHexEdit::wheelEvent(QWheelEvent* event) {
|
||||
if(event->orientation() == Qt::Vertical) {
|
||||
signed offset = event->delta() < 0 ? +1 : -1;
|
||||
self.scrollTo(self.qtScroll->sliderPosition() + offset);
|
||||
event->accept();
|
||||
}
|
||||
}
|
||||
|
||||
bool pHexEdit::QtHexEditScrollBar::event(QEvent* event) {
|
||||
if(event->type() == QEvent::Wheel) {
|
||||
QWheelEvent* wheelEvent = (QWheelEvent*)event;
|
||||
if(wheelEvent->orientation() == Qt::Vertical) {
|
||||
signed offset = wheelEvent->delta() < 0 ? +1 : -1;
|
||||
self.scrollTo(sliderPosition() + offset);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return QScrollBar::event(event);
|
||||
}
|
||||
|
||||
}
|
43
hiro/qt/widget/horizontal-scroller.cpp
Normal file
43
hiro/qt/widget/horizontal-scroller.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
namespace phoenix {
|
||||
|
||||
Size pHorizontalScroller::minimumSize() {
|
||||
return {0, 15};
|
||||
}
|
||||
|
||||
void pHorizontalScroller::setLength(unsigned length) {
|
||||
length += length == 0;
|
||||
qtScroller->setRange(0, length - 1);
|
||||
qtScroller->setPageStep(length >> 3);
|
||||
}
|
||||
|
||||
void pHorizontalScroller::setPosition(unsigned position) {
|
||||
qtScroller->setValue(position);
|
||||
}
|
||||
|
||||
void pHorizontalScroller::constructor() {
|
||||
qtWidget = qtScroller = new QScrollBar(Qt::Horizontal);
|
||||
qtScroller->setRange(0, 100);
|
||||
qtScroller->setPageStep(101 >> 3);
|
||||
connect(qtScroller, SIGNAL(valueChanged(int)), SLOT(onChange()));
|
||||
|
||||
pWidget::synchronizeState();
|
||||
setLength(horizontalScroller.state.length);
|
||||
setPosition(horizontalScroller.state.position);
|
||||
}
|
||||
|
||||
void pHorizontalScroller::destructor() {
|
||||
delete qtScroller;
|
||||
qtWidget = qtScroller = nullptr;
|
||||
}
|
||||
|
||||
void pHorizontalScroller::orphan() {
|
||||
destructor();
|
||||
constructor();
|
||||
}
|
||||
|
||||
void pHorizontalScroller::onChange() {
|
||||
horizontalScroller.state.position = qtScroller->value();
|
||||
if(horizontalScroller.onChange) horizontalScroller.onChange();
|
||||
}
|
||||
|
||||
}
|
43
hiro/qt/widget/horizontal-slider.cpp
Normal file
43
hiro/qt/widget/horizontal-slider.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
namespace phoenix {
|
||||
|
||||
Size pHorizontalSlider::minimumSize() {
|
||||
return {0, 20};
|
||||
}
|
||||
|
||||
void pHorizontalSlider::setLength(unsigned length) {
|
||||
length += length == 0;
|
||||
qtSlider->setRange(0, length - 1);
|
||||
qtSlider->setPageStep(length >> 3);
|
||||
}
|
||||
|
||||
void pHorizontalSlider::setPosition(unsigned position) {
|
||||
qtSlider->setValue(position);
|
||||
}
|
||||
|
||||
void pHorizontalSlider::constructor() {
|
||||
qtWidget = qtSlider = new QSlider(Qt::Horizontal);
|
||||
qtSlider->setRange(0, 100);
|
||||
qtSlider->setPageStep(101 >> 3);
|
||||
connect(qtSlider, SIGNAL(valueChanged(int)), SLOT(onChange()));
|
||||
|
||||
pWidget::synchronizeState();
|
||||
setLength(horizontalSlider.state.length);
|
||||
setPosition(horizontalSlider.state.position);
|
||||
}
|
||||
|
||||
void pHorizontalSlider::destructor() {
|
||||
delete qtSlider;
|
||||
qtWidget = qtSlider = nullptr;
|
||||
}
|
||||
|
||||
void pHorizontalSlider::orphan() {
|
||||
destructor();
|
||||
constructor();
|
||||
}
|
||||
|
||||
void pHorizontalSlider::onChange() {
|
||||
horizontalSlider.state.position = qtSlider->value();
|
||||
if(horizontalSlider.onChange) horizontalSlider.onChange();
|
||||
}
|
||||
|
||||
}
|
148
hiro/qt/widget/icon-view.cpp
Normal file
148
hiro/qt/widget/icon-view.cpp
Normal file
@@ -0,0 +1,148 @@
|
||||
namespace phoenix {
|
||||
|
||||
void pIconView::append() {
|
||||
lock();
|
||||
auto item = new QListWidgetItem(qtIconView);
|
||||
unlock();
|
||||
}
|
||||
|
||||
void pIconView::remove(unsigned selection) {
|
||||
lock();
|
||||
if(auto item = qtIconView->item(selection)) {
|
||||
delete item;
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
|
||||
void pIconView::reset() {
|
||||
lock();
|
||||
qtIconView->clear();
|
||||
unlock();
|
||||
}
|
||||
|
||||
void pIconView::setBackgroundColor(Color color) {
|
||||
QPalette palette = qtIconView->palette();
|
||||
palette.setColor(QPalette::Base, QColor(color.red, color.green, color.blue));
|
||||
qtIconView->setPalette(palette);
|
||||
qtIconView->setAutoFillBackground(true);
|
||||
}
|
||||
|
||||
void pIconView::setFlow(Orientation flow) {
|
||||
qtIconView->setFlow(flow == Orientation::Horizontal ? QListView::LeftToRight : QListView::TopToBottom);
|
||||
qtIconView->resize(qtIconView->size()); //adjust visibility of scroll bars
|
||||
}
|
||||
|
||||
void pIconView::setForegroundColor(Color color) {
|
||||
QPalette palette = qtIconView->palette();
|
||||
palette.setColor(QPalette::Text, QColor(color.red, color.green, color.blue));
|
||||
qtIconView->setPalette(palette);
|
||||
}
|
||||
|
||||
void pIconView::setImage(unsigned selection, const image& image) {
|
||||
if(auto item = qtIconView->item(selection)) {
|
||||
item->setIcon(CreateIcon(image));
|
||||
}
|
||||
}
|
||||
|
||||
void pIconView::setOrientation(Orientation orientation) {
|
||||
qtIconView->setViewMode(orientation == Orientation::Horizontal ? QListView::ListMode : QListView::IconMode);
|
||||
qtIconView->setWrapping(true);
|
||||
}
|
||||
|
||||
void pIconView::setSelected(unsigned selection, bool selected) {
|
||||
lock();
|
||||
if(auto item = qtIconView->item(selection)) {
|
||||
item->setSelected(selected);
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
|
||||
void pIconView::setSelected(const vector<unsigned>& selections) {
|
||||
lock();
|
||||
qtIconView->clearSelection();
|
||||
for(auto& selection : selections) {
|
||||
if(auto item = qtIconView->item(selection)) {
|
||||
item->setSelected(true);
|
||||
}
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
|
||||
void pIconView::setSelectedAll() {
|
||||
lock();
|
||||
qtIconView->selectAll();
|
||||
unlock();
|
||||
}
|
||||
|
||||
void pIconView::setSelectedNone() {
|
||||
lock();
|
||||
qtIconView->clearSelection();
|
||||
unlock();
|
||||
}
|
||||
|
||||
void pIconView::setSingleSelection(bool singleSelection) {
|
||||
qtIconView->setSelectionMode(singleSelection ? QAbstractItemView::SingleSelection : QAbstractItemView::ExtendedSelection);
|
||||
}
|
||||
|
||||
void pIconView::setText(unsigned selection, const string& text) {
|
||||
if(auto item = qtIconView->item(selection)) {
|
||||
item->setText(QString::fromUtf8(text));
|
||||
}
|
||||
}
|
||||
|
||||
void pIconView::constructor() {
|
||||
qtWidget = qtIconView = new QtListWidget;
|
||||
qtIconView->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
qtIconView->setMovement(QListView::Static);
|
||||
qtIconView->setResizeMode(QListView::Adjust);
|
||||
qtIconView->setSelectionRectVisible(true);
|
||||
qtIconView->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
|
||||
qtIconView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
|
||||
|
||||
connect(qtIconView, SIGNAL(itemActivated(QListWidgetItem*)), SLOT(onActivate()));
|
||||
connect(qtIconView, SIGNAL(itemSelectionChanged()), SLOT(onChange()));
|
||||
connect(qtIconView, SIGNAL(customContextMenuRequested(const QPoint&)), SLOT(onContext()));
|
||||
|
||||
setFlow(iconView.state.flow);
|
||||
setOrientation(iconView.state.orientation);
|
||||
setSingleSelection(iconView.state.singleSelection);
|
||||
}
|
||||
|
||||
void pIconView::destructor() {
|
||||
delete qtIconView;
|
||||
qtWidget = qtIconView = nullptr;
|
||||
}
|
||||
|
||||
void pIconView::orphan() {
|
||||
destructor();
|
||||
constructor();
|
||||
}
|
||||
|
||||
void pIconView::onActivate() {
|
||||
if(!locked() && iconView.onActivate) iconView.onActivate();
|
||||
}
|
||||
|
||||
void pIconView::onChange() {
|
||||
for(auto& selected : iconView.state.selected) selected = false;
|
||||
for(unsigned n = 0; n < qtIconView->count(); n++) {
|
||||
if(auto item = qtIconView->item(n)) {
|
||||
if(item->isSelected()) iconView.state.selected[n] = true;
|
||||
}
|
||||
}
|
||||
if(!locked() && iconView.onChange) iconView.onChange();
|
||||
}
|
||||
|
||||
void pIconView::onContext() {
|
||||
if(!locked() && iconView.onContext) iconView.onContext();
|
||||
}
|
||||
|
||||
void pIconView::QtListWidget::resizeEvent(QResizeEvent* event) {
|
||||
//Qt::ScrollBarAsNeeded results in the scroll bar area being reserved from the icon viewport even when scroll bar is hidden
|
||||
//this creates the appearance of an invisible gap that wastes precious screen space
|
||||
//below code simulates a Qt::ScrollBarAsNeeded which uses the extra space when the scroll bar is hidden
|
||||
setHorizontalScrollBarPolicy(horizontalScrollBar()->maximum() > horizontalScrollBar()->minimum() ? Qt::ScrollBarAlwaysOn : Qt::ScrollBarAlwaysOff);
|
||||
setVerticalScrollBarPolicy(verticalScrollBar()->maximum() > verticalScrollBar()->minimum() ? Qt::ScrollBarAlwaysOn : Qt::ScrollBarAlwaysOff);
|
||||
return QListWidget::resizeEvent(event);
|
||||
}
|
||||
|
||||
}
|
29
hiro/qt/widget/label.cpp
Normal file
29
hiro/qt/widget/label.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
namespace phoenix {
|
||||
|
||||
Size pLabel::minimumSize() {
|
||||
Size size = pFont::size(qtWidget->font(), label.state.text);
|
||||
return {size.width, size.height};
|
||||
}
|
||||
|
||||
void pLabel::setText(string text) {
|
||||
qtLabel->setText(QString::fromUtf8(text));
|
||||
}
|
||||
|
||||
void pLabel::constructor() {
|
||||
qtWidget = qtLabel = new QLabel;
|
||||
|
||||
pWidget::synchronizeState();
|
||||
setText(label.state.text);
|
||||
}
|
||||
|
||||
void pLabel::destructor() {
|
||||
delete qtLabel;
|
||||
qtWidget = qtLabel = nullptr;
|
||||
}
|
||||
|
||||
void pLabel::orphan() {
|
||||
destructor();
|
||||
constructor();
|
||||
}
|
||||
|
||||
}
|
62
hiro/qt/widget/line-edit.cpp
Normal file
62
hiro/qt/widget/line-edit.cpp
Normal file
@@ -0,0 +1,62 @@
|
||||
namespace phoenix {
|
||||
|
||||
Size pLineEdit::minimumSize() {
|
||||
Size size = pFont::size(qtWidget->font(), lineEdit.state.text);
|
||||
return {size.width + 12, size.height + 12};
|
||||
}
|
||||
|
||||
void pLineEdit::setBackgroundColor(Color color) {
|
||||
QPalette palette = qtLineEdit->palette();
|
||||
palette.setColor(QPalette::Base, QColor(color.red, color.green, color.blue));
|
||||
qtLineEdit->setPalette(palette);
|
||||
qtLineEdit->setAutoFillBackground(true);
|
||||
}
|
||||
|
||||
void pLineEdit::setEditable(bool editable) {
|
||||
qtLineEdit->setReadOnly(!editable);
|
||||
}
|
||||
|
||||
void pLineEdit::setForegroundColor(Color color) {
|
||||
QPalette palette = qtLineEdit->palette();
|
||||
palette.setColor(QPalette::Text, QColor(color.red, color.green, color.blue));
|
||||
qtLineEdit->setPalette(palette);
|
||||
}
|
||||
|
||||
void pLineEdit::setText(string text) {
|
||||
qtLineEdit->setText(QString::fromUtf8(text));
|
||||
}
|
||||
|
||||
string pLineEdit::text() {
|
||||
return qtLineEdit->text().toUtf8().constData();
|
||||
}
|
||||
|
||||
void pLineEdit::constructor() {
|
||||
qtWidget = qtLineEdit = new QLineEdit;
|
||||
connect(qtLineEdit, SIGNAL(returnPressed()), SLOT(onActivate()));
|
||||
connect(qtLineEdit, SIGNAL(textEdited(const QString&)), SLOT(onChange()));
|
||||
|
||||
pWidget::synchronizeState();
|
||||
setEditable(lineEdit.state.editable);
|
||||
setText(lineEdit.state.text);
|
||||
}
|
||||
|
||||
void pLineEdit::destructor() {
|
||||
delete qtLineEdit;
|
||||
qtWidget = qtLineEdit = nullptr;
|
||||
}
|
||||
|
||||
void pLineEdit::orphan() {
|
||||
destructor();
|
||||
constructor();
|
||||
}
|
||||
|
||||
void pLineEdit::onActivate() {
|
||||
if(lineEdit.onActivate) lineEdit.onActivate();
|
||||
}
|
||||
|
||||
void pLineEdit::onChange() {
|
||||
lineEdit.state.text = text();
|
||||
if(lineEdit.onChange) lineEdit.onChange();
|
||||
}
|
||||
|
||||
}
|
395
hiro/qt/widget/list-view.cpp
Normal file
395
hiro/qt/widget/list-view.cpp
Normal file
@@ -0,0 +1,395 @@
|
||||
namespace phoenix {
|
||||
|
||||
void pListView::appendColumn() {
|
||||
orphan();
|
||||
}
|
||||
|
||||
void pListView::appendItem() {
|
||||
lock();
|
||||
auto item = new QTreeWidgetItem(qtListView);
|
||||
for(unsigned column = 0; column < listView.columns(); column++) {
|
||||
auto& state = listView.state.columns[column];
|
||||
if(state.backgroundColor) {
|
||||
item->setBackground(column, QColor(
|
||||
state.backgroundColor->red, state.backgroundColor->green, state.backgroundColor->blue
|
||||
));
|
||||
}
|
||||
if(state.font) {
|
||||
item->setFont(column, pFont::create(*state.font));
|
||||
}
|
||||
if(state.foregroundColor) {
|
||||
item->setForeground(column, QColor(
|
||||
state.foregroundColor->red, state.foregroundColor->green, state.foregroundColor->blue
|
||||
));
|
||||
}
|
||||
item->setTextAlignment(column, calculateAlignment(
|
||||
state.horizontalAlignment, state.verticalAlignment
|
||||
));
|
||||
}
|
||||
if(listView.state.checkable) item->setCheckState(0, Qt::Unchecked);
|
||||
unlock();
|
||||
}
|
||||
|
||||
void pListView::removeColumn(unsigned position) {
|
||||
orphan();
|
||||
}
|
||||
|
||||
void pListView::removeItem(unsigned position) {
|
||||
lock();
|
||||
if(auto item = qtListView->topLevelItem(position)) {
|
||||
delete item;
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
|
||||
void pListView::reset() {
|
||||
lock();
|
||||
qtListView->clear();
|
||||
unlock();
|
||||
}
|
||||
|
||||
void pListView::resizeColumns() {
|
||||
}
|
||||
|
||||
//todo: this doesn't work ...
|
||||
void pListView::setActiveColumn(unsigned column) {
|
||||
if(column >= listView.columns()) return;
|
||||
qtListView->header()->setSortIndicator(column, Qt::DescendingOrder);
|
||||
}
|
||||
|
||||
void pListView::setBackgroundColor(Color color) {
|
||||
QPalette palette = qtListView->palette();
|
||||
palette.setColor(QPalette::Base, QColor(color.red, color.green, color.blue));
|
||||
palette.setColor(QPalette::AlternateBase, QColor(max(0, (signed)color.red - 17), max(0, (signed)color.green - 17), max(0, (signed)color.blue - 17)));
|
||||
qtListView->setPalette(palette);
|
||||
qtListView->setAutoFillBackground(true);
|
||||
}
|
||||
|
||||
void pListView::setCheckable(bool checkable) {
|
||||
lock();
|
||||
if(checkable) {
|
||||
for(unsigned n = 0; n < qtListView->topLevelItemCount(); n++) {
|
||||
if(auto item = qtListView->topLevelItem(n)) {
|
||||
item->setCheckState(0, Qt::Unchecked);
|
||||
}
|
||||
}
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
|
||||
void pListView::setChecked(unsigned position, bool checked) {
|
||||
lock();
|
||||
if(auto item = qtListView->topLevelItem(position)) {
|
||||
item->setCheckState(0, checked ? Qt::Checked : Qt::Unchecked);
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
|
||||
void pListView::setChecked(const vector<unsigned>& selections) {
|
||||
lock();
|
||||
setCheckedNone();
|
||||
for(auto& position : selections) setChecked(position, true);
|
||||
unlock();
|
||||
}
|
||||
|
||||
void pListView::setCheckedAll() {
|
||||
lock();
|
||||
for(unsigned n = 0; n < qtListView->topLevelItemCount(); n++) {
|
||||
if(auto item = qtListView->topLevelItem(n)) {
|
||||
item->setCheckState(0, Qt::Checked);
|
||||
}
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
|
||||
void pListView::setCheckedNone() {
|
||||
lock();
|
||||
for(unsigned n = 0; n < qtListView->topLevelItemCount(); n++) {
|
||||
if(auto item = qtListView->topLevelItem(n)) {
|
||||
item->setCheckState(0, Qt::Unchecked);
|
||||
}
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
|
||||
void pListView::setColumnBackgroundColor(unsigned column, maybe<Color> color) {
|
||||
for(unsigned row = 0; row < listView.items(); row++) {
|
||||
if(auto item = qtListView->topLevelItem(row)) {
|
||||
item->setBackground(column, color ? QColor(color->red, color->green, color->blue) : QBrush());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pListView::setColumnEditable(unsigned column, bool editable) {
|
||||
}
|
||||
|
||||
void pListView::setColumnFont(unsigned column, maybe<string> font) {
|
||||
auto qtFont = pFont::create(font ? *font : widget.state.font);
|
||||
for(unsigned row = 0; row < listView.items(); row++) {
|
||||
if(auto item = qtListView->topLevelItem(row)) {
|
||||
item->setFont(column, qtFont);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pListView::setColumnForegroundColor(unsigned column, maybe<Color> color) {
|
||||
for(unsigned row = 0; row < listView.items(); row++) {
|
||||
if(auto item = qtListView->topLevelItem(row)) {
|
||||
item->setForeground(column, color ? QColor(color->red, color->green, color->blue) : QBrush());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pListView::setColumnHorizontalAlignment(unsigned column, double alignment) {
|
||||
qtListView->headerItem()->setTextAlignment(column, calculateAlignment(alignment, 0.5));
|
||||
for(unsigned row = 0; row < listView.items(); row++) {
|
||||
if(auto item = qtListView->topLevelItem(row)) {
|
||||
auto& state = listView.state.columns[column];
|
||||
item->setTextAlignment(column, calculateAlignment(state.horizontalAlignment, state.verticalAlignment));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pListView::setColumnResizable(unsigned column, bool resizable) {
|
||||
qtListView->header()->setResizeMode(column, resizable ? QHeaderView::Interactive : QHeaderView::Fixed);
|
||||
}
|
||||
|
||||
void pListView::setColumnSortable(unsigned column, bool sortable) {
|
||||
bool clickable = false;
|
||||
for(auto& column : listView.state.columns) clickable |= column.sortable;
|
||||
qtListView->header()->setClickable(clickable);
|
||||
}
|
||||
|
||||
void pListView::setColumnText(unsigned column, const string& text) {
|
||||
qtListView->headerItem()->setText(column, QString::fromUtf8(text));
|
||||
}
|
||||
|
||||
void pListView::setColumnVerticalAlignment(unsigned column, double alignment) {
|
||||
for(unsigned row = 0; row < listView.items(); row++) {
|
||||
if(auto item = qtListView->topLevelItem(row)) {
|
||||
auto& state = listView.state.columns[column];
|
||||
item->setTextAlignment(column, calculateAlignment(state.horizontalAlignment, state.verticalAlignment));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void pListView::setColumnVisible(unsigned column, bool visible) {
|
||||
if(column >= listView.columns()) return;
|
||||
qtListView->setColumnHidden(column, !visible);
|
||||
}
|
||||
|
||||
void pListView::setColumnWidth(unsigned column, signed width) {
|
||||
if(column >= listView.columns()) return;
|
||||
resizeColumns();
|
||||
}
|
||||
|
||||
void pListView::setForegroundColor(Color color) {
|
||||
QPalette palette = qtListView->palette();
|
||||
palette.setColor(QPalette::Text, QColor(color.red, color.green, color.blue));
|
||||
qtListView->setPalette(palette);
|
||||
}
|
||||
|
||||
void pListView::setGridVisible(bool visible) {
|
||||
qtListView->repaint();
|
||||
}
|
||||
|
||||
void pListView::setHeaderVisible(bool visible) {
|
||||
qtListView->setHeaderHidden(!visible);
|
||||
resizeColumns();
|
||||
}
|
||||
|
||||
void pListView::setImage(unsigned row, unsigned column, const nall::image& image) {
|
||||
if(auto item = qtListView->topLevelItem(row)) {
|
||||
item->setIcon(column, CreateIcon(image));
|
||||
}
|
||||
}
|
||||
|
||||
void pListView::setSelected(unsigned position, bool selected) {
|
||||
lock();
|
||||
if(auto item = qtListView->topLevelItem(position)) {
|
||||
item->setSelected(selected);
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
|
||||
void pListView::setSelected(const vector<unsigned>& selections) {
|
||||
lock();
|
||||
setSelectedNone();
|
||||
if(selections.size()) {
|
||||
if(auto item = qtListView->topLevelItem(selections[0])) {
|
||||
qtListView->setCurrentItem(item);
|
||||
}
|
||||
for(auto& position : selections) setSelected(position, true);
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
|
||||
void pListView::setSelectedAll() {
|
||||
lock();
|
||||
qtListView->selectAll();
|
||||
unlock();
|
||||
}
|
||||
|
||||
void pListView::setSelectedNone() {
|
||||
lock();
|
||||
qtListView->clearSelection();
|
||||
unlock();
|
||||
}
|
||||
|
||||
void pListView::setSingleSelection(bool singleSelection) {
|
||||
lock();
|
||||
qtListView->setSelectionMode(singleSelection ? QAbstractItemView::SingleSelection : QAbstractItemView::ExtendedSelection);
|
||||
unlock();
|
||||
}
|
||||
|
||||
void pListView::setText(unsigned row, unsigned column, string text) {
|
||||
lock();
|
||||
if(auto item = qtListView->topLevelItem(row)) {
|
||||
item->setText(column, QString::fromUtf8(text));
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
|
||||
void pListView::constructor() {
|
||||
qtWidget = qtListView = new QtTreeWidget(*this);
|
||||
qtListView->setAllColumnsShowFocus(true);
|
||||
qtListView->setAlternatingRowColors(listView.columns() >= 2);
|
||||
qtListView->setColumnCount(max(1u, listView.columns()));
|
||||
qtListView->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
qtListView->setRootIsDecorated(false);
|
||||
qtListView->header()->setMovable(false);
|
||||
|
||||
qtListViewDelegate = new QtTreeWidgetDelegate(*this);
|
||||
qtListView->setItemDelegate(qtListViewDelegate);
|
||||
|
||||
connect(qtListView, SIGNAL(itemActivated(QTreeWidgetItem*, int)), SLOT(onActivate()));
|
||||
connect(qtListView, SIGNAL(itemSelectionChanged()), SLOT(onChange()));
|
||||
connect(qtListView, SIGNAL(customContextMenuRequested(const QPoint&)), SLOT(onContext()));
|
||||
connect(qtListView->header(), SIGNAL(sectionClicked(int)), SLOT(onSort(int)));
|
||||
connect(qtListView, SIGNAL(itemChanged(QTreeWidgetItem*, int)), SLOT(onToggle(QTreeWidgetItem*)));
|
||||
|
||||
pWidget::synchronizeState();
|
||||
for(unsigned column = 0; column < listView.columns(); column++) {
|
||||
auto& state = listView.state.columns[column];
|
||||
setColumnBackgroundColor(column, state.backgroundColor);
|
||||
setColumnEditable(column, state.editable);
|
||||
setColumnFont(column, state.font);
|
||||
setColumnForegroundColor(column, state.foregroundColor);
|
||||
//setColumnHorizontalAlignment(column, state.horizontalAlignment);
|
||||
setColumnResizable(column, state.resizable);
|
||||
setColumnSortable(column, state.sortable);
|
||||
setColumnText(column, state.text);
|
||||
//setColumnVerticalAlignment(column, state.verticalAlignment);
|
||||
setColumnVisible(column, state.visible);
|
||||
//setColumnWidth(column, state.width);
|
||||
qtListView->headerItem()->setTextAlignment(column, calculateAlignment(state.horizontalAlignment, 0.5));
|
||||
}
|
||||
setActiveColumn(listView.state.activeColumn);
|
||||
setCheckable(listView.state.checkable);
|
||||
//setGridVisible(listView.state.gridVisible);
|
||||
setHeaderVisible(listView.state.headerVisible);
|
||||
setSingleSelection(listView.state.singleSelection);
|
||||
for(unsigned row = 0; row < listView.items(); row++) {
|
||||
appendItem();
|
||||
setSelected(row, listView.state.items[row].selected);
|
||||
if(listView.state.checkable) {
|
||||
setChecked(row, listView.state.items[row].checked);
|
||||
}
|
||||
for(unsigned column = 0; column < listView.columns(); column++) {
|
||||
setImage(row, column, listView.state.items[row].image(column, {}));
|
||||
setText(row, column, listView.state.items[row].text(column, ""));
|
||||
}
|
||||
}
|
||||
resizeColumns();
|
||||
}
|
||||
|
||||
void pListView::destructor() {
|
||||
delete qtListViewDelegate;
|
||||
delete qtListView;
|
||||
qtWidget = qtListView = nullptr;
|
||||
qtListViewDelegate = nullptr;
|
||||
}
|
||||
|
||||
void pListView::orphan() {
|
||||
destructor();
|
||||
constructor();
|
||||
}
|
||||
|
||||
void pListView::onActivate() {
|
||||
if(!locked() && listView.onActivate) listView.onActivate();
|
||||
}
|
||||
|
||||
void pListView::onChange() {
|
||||
for(auto& item : listView.state.items) item.selected = false;
|
||||
for(unsigned position = 0; position < qtListView->topLevelItemCount(); position++) {
|
||||
if(auto item = qtListView->topLevelItem(position)) {
|
||||
if(item->isSelected()) listView.state.items[position].selected = true;
|
||||
}
|
||||
}
|
||||
if(!locked() && listView.onChange) listView.onChange();
|
||||
}
|
||||
|
||||
void pListView::onContext() {
|
||||
if(!locked() && listView.onContext) listView.onContext();
|
||||
}
|
||||
|
||||
void pListView::onSort(int column) {
|
||||
if(column >= listView.columns()) return;
|
||||
if(listView.state.columns[column].sortable) {
|
||||
if(!locked() && listView.onSort) listView.onSort(column);
|
||||
}
|
||||
}
|
||||
|
||||
void pListView::onToggle(QTreeWidgetItem* item) {
|
||||
maybe<unsigned> row;
|
||||
for(unsigned position = 0; position < qtListView->topLevelItemCount(); position++) {
|
||||
if(auto topLevelItem = qtListView->topLevelItem(position)) {
|
||||
if(topLevelItem == item) {
|
||||
row = position;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(row) {
|
||||
listView.state.items[*row].checked = (item->checkState(0) == Qt::Checked);
|
||||
if(!locked() && listView.onToggle) listView.onToggle(*row);
|
||||
}
|
||||
}
|
||||
|
||||
int pListView::calculateAlignment(double horizontal, double vertical) {
|
||||
int alignment = 0;
|
||||
if(horizontal < 0.333) alignment |= Qt::AlignLeft;
|
||||
else if(horizontal > 0.666) alignment |= Qt::AlignRight;
|
||||
else alignment |= Qt::AlignCenter;
|
||||
if(vertical < 0.333) alignment |= Qt::AlignTop;
|
||||
else if(vertical > 0.666) alignment |= Qt::AlignBottom;
|
||||
else alignment |= Qt::AlignVCenter;
|
||||
return alignment;
|
||||
}
|
||||
|
||||
void pListView::QtTreeWidget::mousePressEvent(QMouseEvent* event) {
|
||||
QTreeWidget::mousePressEvent(event);
|
||||
|
||||
if(event->button() == Qt::RightButton) {
|
||||
self.onContext();
|
||||
}
|
||||
}
|
||||
|
||||
pListView::QtTreeWidget::QtTreeWidget(pListView& self) : self(self) {
|
||||
}
|
||||
|
||||
void pListView::QtTreeWidgetDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const {
|
||||
QStyledItemDelegate::paint(painter, option, index);
|
||||
if(self.listView.state.gridVisible) {
|
||||
QPen pen;
|
||||
pen.setColor(QColor(192, 192, 192));
|
||||
pen.setWidth(1);
|
||||
painter->setPen(pen);
|
||||
painter->drawRect(option.rect);
|
||||
}
|
||||
}
|
||||
|
||||
pListView::QtTreeWidgetDelegate::QtTreeWidgetDelegate(pListView& self) : QStyledItemDelegate(self.qtListView), self(self) {
|
||||
}
|
||||
|
||||
}
|
30
hiro/qt/widget/progress-bar.cpp
Normal file
30
hiro/qt/widget/progress-bar.cpp
Normal file
@@ -0,0 +1,30 @@
|
||||
namespace phoenix {
|
||||
|
||||
Size pProgressBar::minimumSize() {
|
||||
return {0, 25};
|
||||
}
|
||||
|
||||
void pProgressBar::setPosition(unsigned position) {
|
||||
qtProgressBar->setValue(position);
|
||||
}
|
||||
|
||||
void pProgressBar::constructor() {
|
||||
qtWidget = qtProgressBar = new QProgressBar;
|
||||
qtProgressBar->setRange(0, 100);
|
||||
qtProgressBar->setTextVisible(false);
|
||||
|
||||
pWidget::synchronizeState();
|
||||
setPosition(progressBar.state.position);
|
||||
}
|
||||
|
||||
void pProgressBar::destructor() {
|
||||
delete qtProgressBar;
|
||||
qtWidget = qtProgressBar = nullptr;
|
||||
}
|
||||
|
||||
void pProgressBar::orphan() {
|
||||
destructor();
|
||||
constructor();
|
||||
}
|
||||
|
||||
}
|
85
hiro/qt/widget/radio-button.cpp
Normal file
85
hiro/qt/widget/radio-button.cpp
Normal file
@@ -0,0 +1,85 @@
|
||||
namespace phoenix {
|
||||
|
||||
Size pRadioButton::minimumSize() {
|
||||
Size size = pFont::size(qtWidget->font(), radioButton.state.text);
|
||||
|
||||
if(radioButton.state.orientation == Orientation::Horizontal) {
|
||||
size.width += radioButton.state.image.width;
|
||||
size.height = max(radioButton.state.image.height, size.height);
|
||||
}
|
||||
|
||||
if(radioButton.state.orientation == Orientation::Vertical) {
|
||||
size.width = max(radioButton.state.image.width, size.width);
|
||||
size.height += radioButton.state.image.height;
|
||||
}
|
||||
|
||||
return {size.width + 20, size.height + 12};
|
||||
}
|
||||
|
||||
void pRadioButton::setChecked() {
|
||||
parent().lock();
|
||||
for(auto& item : radioButton.state.group) {
|
||||
bool checked = &item.p == this;
|
||||
item.p.qtRadioButton->setChecked(item.state.checked = checked);
|
||||
}
|
||||
parent().unlock();
|
||||
}
|
||||
|
||||
void pRadioButton::setGroup(const group<RadioButton>& group) {
|
||||
parent().lock();
|
||||
for(auto& item : radioButton.state.group) {
|
||||
item.p.qtRadioButton->setChecked(item.state.checked);
|
||||
}
|
||||
parent().unlock();
|
||||
}
|
||||
|
||||
void pRadioButton::setImage(const image& image, Orientation orientation) {
|
||||
qtRadioButton->setIconSize(QSize(image.width, image.height));
|
||||
qtRadioButton->setIcon(CreateIcon(image));
|
||||
qtRadioButton->setStyleSheet("text-align: top;");
|
||||
switch(orientation) {
|
||||
case Orientation::Horizontal: qtRadioButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); break;
|
||||
case Orientation::Vertical: qtRadioButton->setToolButtonStyle(Qt::ToolButtonTextUnderIcon); break;
|
||||
}
|
||||
}
|
||||
|
||||
void pRadioButton::setText(string text) {
|
||||
qtRadioButton->setText(QString::fromUtf8(text));
|
||||
}
|
||||
|
||||
pRadioButton& pRadioButton::parent() {
|
||||
if(radioButton.state.group.size()) return radioButton.state.group.first().p;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void pRadioButton::constructor() {
|
||||
qtWidget = qtRadioButton = new QToolButton;
|
||||
qtRadioButton->setCheckable(true);
|
||||
qtRadioButton->setToolButtonStyle(Qt::ToolButtonTextOnly);
|
||||
connect(qtRadioButton, SIGNAL(toggled(bool)), SLOT(onActivate()));
|
||||
|
||||
pWidget::synchronizeState();
|
||||
setGroup(radioButton.state.group);
|
||||
setText(radioButton.state.text);
|
||||
}
|
||||
|
||||
void pRadioButton::destructor() {
|
||||
if(qtRadioButton) delete qtRadioButton;
|
||||
qtWidget = qtRadioButton = nullptr;
|
||||
}
|
||||
|
||||
void pRadioButton::orphan() {
|
||||
destructor();
|
||||
constructor();
|
||||
}
|
||||
|
||||
void pRadioButton::onActivate() {
|
||||
if(parent().locked()) return;
|
||||
bool wasChecked = radioButton.state.checked;
|
||||
setChecked();
|
||||
if(!wasChecked) {
|
||||
if(radioButton.onActivate) radioButton.onActivate();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
63
hiro/qt/widget/radio-label.cpp
Normal file
63
hiro/qt/widget/radio-label.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
namespace phoenix {
|
||||
|
||||
Size pRadioLabel::minimumSize() {
|
||||
Size size = pFont::size(qtWidget->font(), radioLabel.state.text);
|
||||
return {size.width + 26, size.height + 6};
|
||||
}
|
||||
|
||||
void pRadioLabel::setChecked() {
|
||||
parent().lock();
|
||||
for(auto& item : radioLabel.state.group) {
|
||||
bool checked = &item == &radioLabel;
|
||||
item.p.qtRadioLabel->setChecked(item.state.checked = checked);
|
||||
}
|
||||
parent().unlock();
|
||||
}
|
||||
|
||||
void pRadioLabel::setGroup(const group<RadioLabel>& group) {
|
||||
parent().lock();
|
||||
for(auto& item : radioLabel.state.group) {
|
||||
item.p.qtRadioLabel->setChecked(item.state.checked);
|
||||
}
|
||||
parent().unlock();
|
||||
}
|
||||
|
||||
void pRadioLabel::setText(string text) {
|
||||
qtRadioLabel->setText(QString::fromUtf8(text));
|
||||
}
|
||||
|
||||
pRadioLabel& pRadioLabel::parent() {
|
||||
if(radioLabel.state.group.size()) return radioLabel.state.group.first().p;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void pRadioLabel::constructor() {
|
||||
qtWidget = qtRadioLabel = new QRadioButton;
|
||||
qtRadioLabel->setAutoExclusive(false);
|
||||
connect(qtRadioLabel, SIGNAL(toggled(bool)), SLOT(onActivate()));
|
||||
|
||||
pWidget::synchronizeState();
|
||||
setGroup(radioLabel.state.group);
|
||||
setText(radioLabel.state.text);
|
||||
}
|
||||
|
||||
void pRadioLabel::destructor() {
|
||||
if(qtRadioLabel) delete qtRadioLabel;
|
||||
qtWidget = qtRadioLabel = nullptr;
|
||||
}
|
||||
|
||||
void pRadioLabel::orphan() {
|
||||
destructor();
|
||||
constructor();
|
||||
}
|
||||
|
||||
void pRadioLabel::onActivate() {
|
||||
if(parent().locked()) return;
|
||||
bool wasChecked = radioLabel.state.checked;
|
||||
setChecked();
|
||||
if(!wasChecked) {
|
||||
if(radioLabel.onActivate) radioLabel.onActivate();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
95
hiro/qt/widget/tab-frame.cpp
Normal file
95
hiro/qt/widget/tab-frame.cpp
Normal file
@@ -0,0 +1,95 @@
|
||||
namespace phoenix {
|
||||
|
||||
void pTabFrame::append() {
|
||||
qtTabFrame->addTab(new QWidget, "");
|
||||
}
|
||||
|
||||
QWidget* pTabFrame::container(Widget& widget) {
|
||||
Layout* widgetLayout = GetParentWidgetLayout(&widget);
|
||||
unsigned selection = 0;
|
||||
for(auto& layout : tabFrame.state.layout) {
|
||||
if(layout == widgetLayout) return qtTabFrame->widget(selection);
|
||||
selection++;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Position pTabFrame::displacement() {
|
||||
return {5, 33};
|
||||
}
|
||||
|
||||
void pTabFrame::remove(unsigned selection) {
|
||||
qtTabFrame->removeTab(selection);
|
||||
}
|
||||
|
||||
void pTabFrame::setEnabled(bool enabled) {
|
||||
for(auto& layout : tabFrame.state.layout) {
|
||||
if(layout) layout->setEnabled(layout->enabled());
|
||||
}
|
||||
pWidget::setEnabled(enabled);
|
||||
}
|
||||
|
||||
void pTabFrame::setGeometry(Geometry geometry) {
|
||||
pWidget::setGeometry(geometry);
|
||||
geometry.x += 0, geometry.width -= 5;
|
||||
geometry.y += 29, geometry.height -= 33;
|
||||
for(auto& layout : tabFrame.state.layout) {
|
||||
if(layout) layout->setGeometry(geometry);
|
||||
}
|
||||
synchronizeLayout();
|
||||
}
|
||||
|
||||
void pTabFrame::setImage(unsigned selection, const image& image) {
|
||||
qtTabFrame->setTabIcon(selection, CreateIcon(image));
|
||||
}
|
||||
|
||||
void pTabFrame::setSelected(unsigned selection) {
|
||||
lock();
|
||||
qtTabFrame->setCurrentIndex(selection);
|
||||
synchronizeLayout();
|
||||
unlock();
|
||||
}
|
||||
|
||||
void pTabFrame::setText(unsigned selection, string text) {
|
||||
qtTabFrame->setTabText(selection, QString::fromUtf8(text));
|
||||
}
|
||||
|
||||
void pTabFrame::setVisible(bool visible) {
|
||||
for(auto& layout : tabFrame.state.layout) {
|
||||
if(layout) layout->setVisible(layout->visible());
|
||||
}
|
||||
pWidget::setVisible(visible);
|
||||
}
|
||||
|
||||
void pTabFrame::constructor() {
|
||||
qtWidget = qtTabFrame = new QTabWidget;
|
||||
connect(qtTabFrame, SIGNAL(currentChanged(int)), SLOT(onChange(int)));
|
||||
|
||||
setSelected(tabFrame.state.selection);
|
||||
}
|
||||
|
||||
void pTabFrame::destructor() {
|
||||
delete qtTabFrame;
|
||||
qtWidget = qtTabFrame = nullptr;
|
||||
}
|
||||
|
||||
void pTabFrame::orphan() {
|
||||
destructor();
|
||||
constructor();
|
||||
}
|
||||
|
||||
void pTabFrame::synchronizeLayout() {
|
||||
unsigned selection = 0;
|
||||
for(auto& layout : tabFrame.state.layout) {
|
||||
if(layout) layout->setVisible(selection == tabFrame.state.selection);
|
||||
selection++;
|
||||
}
|
||||
}
|
||||
|
||||
void pTabFrame::onChange(int selection) {
|
||||
tabFrame.state.selection = selection;
|
||||
synchronizeLayout();
|
||||
if(!locked() && tabFrame.onChange) tabFrame.onChange();
|
||||
}
|
||||
|
||||
}
|
66
hiro/qt/widget/text-edit.cpp
Normal file
66
hiro/qt/widget/text-edit.cpp
Normal file
@@ -0,0 +1,66 @@
|
||||
namespace phoenix {
|
||||
|
||||
void pTextEdit::setBackgroundColor(Color color) {
|
||||
QPalette palette = qtTextEdit->palette();
|
||||
palette.setColor(QPalette::Base, QColor(color.red, color.green, color.blue));
|
||||
qtTextEdit->setPalette(palette);
|
||||
qtTextEdit->setAutoFillBackground(true);
|
||||
}
|
||||
|
||||
void pTextEdit::setCursorPosition(unsigned position) {
|
||||
QTextCursor cursor = qtTextEdit->textCursor();
|
||||
unsigned lastCharacter = strlen(qtTextEdit->toPlainText().toUtf8().constData());
|
||||
cursor.setPosition(min(position, lastCharacter));
|
||||
qtTextEdit->setTextCursor(cursor);
|
||||
}
|
||||
|
||||
void pTextEdit::setEditable(bool editable) {
|
||||
qtTextEdit->setTextInteractionFlags(editable ? Qt::TextEditorInteraction : Qt::TextSelectableByKeyboard | Qt::TextSelectableByMouse);
|
||||
}
|
||||
|
||||
void pTextEdit::setForegroundColor(Color color) {
|
||||
QPalette palette = qtTextEdit->palette();
|
||||
palette.setColor(QPalette::Text, QColor(color.red, color.green, color.blue));
|
||||
qtTextEdit->setPalette(palette);
|
||||
}
|
||||
|
||||
void pTextEdit::setText(string text) {
|
||||
qtTextEdit->setPlainText(QString::fromUtf8(text));
|
||||
}
|
||||
|
||||
void pTextEdit::setWordWrap(bool wordWrap) {
|
||||
qtTextEdit->setWordWrapMode(wordWrap ? QTextOption::WordWrap : QTextOption::NoWrap);
|
||||
qtTextEdit->setHorizontalScrollBarPolicy(wordWrap ? Qt::ScrollBarAlwaysOff : Qt::ScrollBarAlwaysOn);
|
||||
qtTextEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
|
||||
}
|
||||
|
||||
string pTextEdit::text() {
|
||||
return qtTextEdit->toPlainText().toUtf8().constData();
|
||||
}
|
||||
|
||||
void pTextEdit::constructor() {
|
||||
qtWidget = qtTextEdit = new QTextEdit;
|
||||
connect(qtTextEdit, SIGNAL(textChanged()), SLOT(onChange()));
|
||||
|
||||
pWidget::synchronizeState();
|
||||
setEditable(textEdit.state.editable);
|
||||
setText(textEdit.state.text);
|
||||
setWordWrap(textEdit.state.wordWrap);
|
||||
}
|
||||
|
||||
void pTextEdit::destructor() {
|
||||
delete qtTextEdit;
|
||||
qtWidget = qtTextEdit = nullptr;
|
||||
}
|
||||
|
||||
void pTextEdit::orphan() {
|
||||
destructor();
|
||||
constructor();
|
||||
}
|
||||
|
||||
void pTextEdit::onChange() {
|
||||
textEdit.state.text = text();
|
||||
if(textEdit.onChange) textEdit.onChange();
|
||||
}
|
||||
|
||||
}
|
43
hiro/qt/widget/vertical-scroller.cpp
Normal file
43
hiro/qt/widget/vertical-scroller.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
namespace phoenix {
|
||||
|
||||
Size pVerticalScroller::minimumSize() {
|
||||
return {15, 0};
|
||||
}
|
||||
|
||||
void pVerticalScroller::setLength(unsigned length) {
|
||||
length += length == 0;
|
||||
qtScroller->setRange(0, length - 1);
|
||||
qtScroller->setPageStep(length >> 3);
|
||||
}
|
||||
|
||||
void pVerticalScroller::setPosition(unsigned position) {
|
||||
qtScroller->setValue(position);
|
||||
}
|
||||
|
||||
void pVerticalScroller::constructor() {
|
||||
qtWidget = qtScroller = new QScrollBar(Qt::Vertical);
|
||||
qtScroller->setRange(0, 100);
|
||||
qtScroller->setPageStep(101 >> 3);
|
||||
connect(qtScroller, SIGNAL(valueChanged(int)), SLOT(onChange()));
|
||||
|
||||
pWidget::synchronizeState();
|
||||
setLength(verticalScroller.state.length);
|
||||
setPosition(verticalScroller.state.position);
|
||||
}
|
||||
|
||||
void pVerticalScroller::destructor() {
|
||||
delete qtScroller;
|
||||
qtWidget = qtScroller = nullptr;
|
||||
}
|
||||
|
||||
void pVerticalScroller::orphan() {
|
||||
destructor();
|
||||
constructor();
|
||||
}
|
||||
|
||||
void pVerticalScroller::onChange() {
|
||||
verticalScroller.state.position = qtScroller->value();
|
||||
if(verticalScroller.onChange) verticalScroller.onChange();
|
||||
}
|
||||
|
||||
}
|
43
hiro/qt/widget/vertical-slider.cpp
Normal file
43
hiro/qt/widget/vertical-slider.cpp
Normal file
@@ -0,0 +1,43 @@
|
||||
namespace phoenix {
|
||||
|
||||
Size pVerticalSlider::minimumSize() {
|
||||
return {20, 0};
|
||||
}
|
||||
|
||||
void pVerticalSlider::setLength(unsigned length) {
|
||||
length += length == 0;
|
||||
qtSlider->setRange(0, length - 1);
|
||||
qtSlider->setPageStep(length >> 3);
|
||||
}
|
||||
|
||||
void pVerticalSlider::setPosition(unsigned position) {
|
||||
qtSlider->setValue(position);
|
||||
}
|
||||
|
||||
void pVerticalSlider::constructor() {
|
||||
qtWidget = qtSlider = new QSlider(Qt::Vertical);
|
||||
qtSlider->setRange(0, 100);
|
||||
qtSlider->setPageStep(101 >> 3);
|
||||
connect(qtSlider, SIGNAL(valueChanged(int)), SLOT(onChange()));
|
||||
|
||||
pWidget::synchronizeState();
|
||||
setLength(verticalSlider.state.length);
|
||||
setPosition(verticalSlider.state.position);
|
||||
}
|
||||
|
||||
void pVerticalSlider::destructor() {
|
||||
delete qtSlider;
|
||||
qtWidget = qtSlider = nullptr;
|
||||
}
|
||||
|
||||
void pVerticalSlider::orphan() {
|
||||
destructor();
|
||||
constructor();
|
||||
}
|
||||
|
||||
void pVerticalSlider::onChange() {
|
||||
verticalSlider.state.position = qtSlider->value();
|
||||
if(verticalSlider.onChange) verticalSlider.onChange();
|
||||
}
|
||||
|
||||
}
|
71
hiro/qt/widget/viewport.cpp
Normal file
71
hiro/qt/widget/viewport.cpp
Normal file
@@ -0,0 +1,71 @@
|
||||
namespace phoenix {
|
||||
|
||||
uintptr_t pViewport::handle() {
|
||||
return (uintptr_t)qtViewport->winId();
|
||||
}
|
||||
|
||||
void pViewport::setDroppable(bool droppable) {
|
||||
qtViewport->setAcceptDrops(droppable);
|
||||
}
|
||||
|
||||
void pViewport::constructor() {
|
||||
qtWidget = qtViewport = new QtViewport(*this);
|
||||
qtViewport->setMouseTracking(true);
|
||||
qtViewport->setAttribute(Qt::WA_PaintOnScreen, true);
|
||||
qtViewport->setStyleSheet("background: #000000");
|
||||
|
||||
pWidget::synchronizeState();
|
||||
}
|
||||
|
||||
void pViewport::destructor() {
|
||||
delete qtViewport;
|
||||
qtWidget = qtViewport = nullptr;
|
||||
}
|
||||
|
||||
void pViewport::orphan() {
|
||||
destructor();
|
||||
constructor();
|
||||
}
|
||||
|
||||
void pViewport::QtViewport::dragEnterEvent(QDragEnterEvent* event) {
|
||||
if(event->mimeData()->hasUrls()) {
|
||||
event->acceptProposedAction();
|
||||
}
|
||||
}
|
||||
|
||||
void pViewport::QtViewport::dropEvent(QDropEvent* event) {
|
||||
lstring paths = DropPaths(event);
|
||||
if(paths.empty()) return;
|
||||
if(self.viewport.onDrop) self.viewport.onDrop(paths);
|
||||
}
|
||||
|
||||
void pViewport::QtViewport::leaveEvent(QEvent* event) {
|
||||
if(self.viewport.onMouseLeave) self.viewport.onMouseLeave();
|
||||
}
|
||||
|
||||
void pViewport::QtViewport::mouseMoveEvent(QMouseEvent* event) {
|
||||
if(self.viewport.onMouseMove) self.viewport.onMouseMove({event->pos().x(), event->pos().y()});
|
||||
}
|
||||
|
||||
void pViewport::QtViewport::mousePressEvent(QMouseEvent* event) {
|
||||
if(!self.viewport.onMousePress) return;
|
||||
switch(event->button()) {
|
||||
case Qt::LeftButton: self.viewport.onMousePress(Mouse::Button::Left); break;
|
||||
case Qt::MidButton: self.viewport.onMousePress(Mouse::Button::Middle); break;
|
||||
case Qt::RightButton: self.viewport.onMousePress(Mouse::Button::Right); break;
|
||||
}
|
||||
}
|
||||
|
||||
void pViewport::QtViewport::mouseReleaseEvent(QMouseEvent* event) {
|
||||
if(!self.viewport.onMouseRelease) return;
|
||||
switch(event->button()) {
|
||||
case Qt::LeftButton: self.viewport.onMouseRelease(Mouse::Button::Left); break;
|
||||
case Qt::MidButton: self.viewport.onMouseRelease(Mouse::Button::Middle); break;
|
||||
case Qt::RightButton: self.viewport.onMouseRelease(Mouse::Button::Right); break;
|
||||
}
|
||||
}
|
||||
|
||||
pViewport::QtViewport::QtViewport(pViewport& self) : self(self) {
|
||||
}
|
||||
|
||||
}
|
68
hiro/qt/widget/widget.cpp
Normal file
68
hiro/qt/widget/widget.cpp
Normal file
@@ -0,0 +1,68 @@
|
||||
namespace phoenix {
|
||||
|
||||
QWidget* pWidget::container(Widget& widget) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool pWidget::focused() {
|
||||
return qtWidget->hasFocus();
|
||||
}
|
||||
|
||||
Size pWidget::minimumSize() {
|
||||
return {0, 0};
|
||||
}
|
||||
|
||||
void pWidget::setEnabled(bool enabled) {
|
||||
if(!widget.parent()) enabled = false;
|
||||
if(widget.state.abstract) enabled = false;
|
||||
if(!widget.enabledToAll()) enabled = false;
|
||||
qtWidget->setEnabled(enabled);
|
||||
}
|
||||
|
||||
void pWidget::setFocused() {
|
||||
qtWidget->setFocus(Qt::OtherFocusReason);
|
||||
}
|
||||
|
||||
void pWidget::setFont(string font) {
|
||||
qtWidget->setFont(pFont::create(font));
|
||||
}
|
||||
|
||||
void pWidget::setGeometry(Geometry geometry) {
|
||||
Position displacement = GetDisplacement(&widget);
|
||||
geometry.x -= displacement.x;
|
||||
geometry.y -= displacement.y;
|
||||
|
||||
qtWidget->setGeometry(geometry.x, geometry.y, geometry.width, geometry.height);
|
||||
if(widget.onSize) widget.onSize();
|
||||
}
|
||||
|
||||
void pWidget::setVisible(bool visible) {
|
||||
if(!widget.parent()) visible = false;
|
||||
if(widget.state.abstract) visible = false;
|
||||
if(!widget.visibleToAll()) visible = false;
|
||||
qtWidget->setVisible(visible);
|
||||
}
|
||||
|
||||
void pWidget::constructor() {
|
||||
if(widget.state.abstract) qtWidget = new QWidget;
|
||||
}
|
||||
|
||||
//pWidget::constructor() called before p{Derived}::constructor(); ergo qtWidget is not yet valid
|
||||
//pWidget::synchronizeState() is called to finish construction of p{Derived}::constructor()
|
||||
void pWidget::synchronizeState() {
|
||||
setFont(widget.font());
|
||||
}
|
||||
|
||||
void pWidget::destructor() {
|
||||
if(widget.state.abstract) {
|
||||
delete qtWidget;
|
||||
qtWidget = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void pWidget::orphan() {
|
||||
destructor();
|
||||
constructor();
|
||||
}
|
||||
|
||||
}
|
314
hiro/qt/window.cpp
Normal file
314
hiro/qt/window.cpp
Normal file
@@ -0,0 +1,314 @@
|
||||
namespace phoenix {
|
||||
|
||||
void pWindow::append(Layout& layout) {
|
||||
Geometry geometry = window.state.geometry;
|
||||
geometry.x = geometry.y = 0;
|
||||
layout.setGeometry(geometry);
|
||||
}
|
||||
|
||||
void pWindow::append(Menu& menu) {
|
||||
if(window.state.menuFont != "") menu.p.setFont(window.state.menuFont);
|
||||
else menu.p.setFont(Font::sans(8));
|
||||
qtMenu->addMenu(menu.p.qtMenu);
|
||||
}
|
||||
|
||||
void pWindow::append(Widget& widget) {
|
||||
if(widget.font().empty() && !window.state.widgetFont.empty()) {
|
||||
widget.setFont(window.state.widgetFont);
|
||||
}
|
||||
if(widget.font().empty()) widget.p.setFont(Font::sans(8));
|
||||
if(GetParentWidget(&widget)) {
|
||||
widget.p.qtWidget->setParent(GetParentWidget(&widget)->p.container(widget));
|
||||
} else {
|
||||
widget.p.qtWidget->setParent(qtContainer);
|
||||
}
|
||||
widget.setVisible(widget.visible());
|
||||
}
|
||||
|
||||
Geometry pWindow::frameMargin() {
|
||||
unsigned menuHeight = window.state.menuVisible ? settings->geometry.menuHeight : 0;
|
||||
unsigned statusHeight = window.state.statusVisible ? settings->geometry.statusHeight : 0;
|
||||
if(window.state.fullScreen) return {0, menuHeight, 0, menuHeight + statusHeight};
|
||||
return {
|
||||
settings->geometry.frameX,
|
||||
settings->geometry.frameY + menuHeight,
|
||||
settings->geometry.frameWidth,
|
||||
settings->geometry.frameHeight + menuHeight + statusHeight
|
||||
};
|
||||
}
|
||||
|
||||
bool pWindow::focused() {
|
||||
return qtWindow->isActiveWindow() && !qtWindow->isMinimized();
|
||||
}
|
||||
|
||||
void pWindow::remove(Layout& layout) {
|
||||
}
|
||||
|
||||
void pWindow::remove(Menu& menu) {
|
||||
//QMenuBar::removeMenu() does not exist
|
||||
qtMenu->clear();
|
||||
for(auto& menu : window.state.menu) append(menu);
|
||||
}
|
||||
|
||||
void pWindow::remove(Widget& widget) {
|
||||
//orphan() destroys and recreates widgets (to disassociate them from their parent);
|
||||
//attempting to create widget again after QApplication::quit() crashes libQtGui
|
||||
if(qtApplication) widget.p.orphan();
|
||||
}
|
||||
|
||||
void pWindow::setBackgroundColor(Color color) {
|
||||
QPalette palette;
|
||||
palette.setColor(QPalette::Background, QColor(color.red, color.green, color.blue /*, color.alpha */));
|
||||
qtContainer->setPalette(palette);
|
||||
qtContainer->setAutoFillBackground(true);
|
||||
//translucency results are very unpleasant without a compositor; so disable for now
|
||||
//qtWindow->setAttribute(Qt::WA_TranslucentBackground, color.alpha != 255);
|
||||
}
|
||||
|
||||
void pWindow::setDroppable(bool droppable) {
|
||||
qtWindow->setAcceptDrops(droppable);
|
||||
}
|
||||
|
||||
void pWindow::setFocused() {
|
||||
qtWindow->raise();
|
||||
qtWindow->activateWindow();
|
||||
}
|
||||
|
||||
void pWindow::setFullScreen(bool fullScreen) {
|
||||
if(fullScreen == false) {
|
||||
setResizable(window.state.resizable);
|
||||
qtWindow->showNormal();
|
||||
qtWindow->adjustSize();
|
||||
} else {
|
||||
qtLayout->setSizeConstraint(QLayout::SetDefaultConstraint);
|
||||
qtContainer->setFixedSize(Desktop::size().width - frameMargin().width, Desktop::size().height - frameMargin().height);
|
||||
qtWindow->showFullScreen();
|
||||
}
|
||||
}
|
||||
|
||||
void pWindow::setGeometry(Geometry geometry) {
|
||||
lock();
|
||||
Application::processEvents();
|
||||
QApplication::syncX();
|
||||
|
||||
setResizable(window.state.resizable);
|
||||
qtWindow->move(geometry.x - frameMargin().x, geometry.y - frameMargin().y);
|
||||
//qtWindow->adjustSize() fails if larger than 2/3rds screen size
|
||||
qtWindow->resize(qtWindow->sizeHint());
|
||||
if(window.state.resizable) {
|
||||
//required to allow shrinking window from default size
|
||||
qtWindow->setMinimumSize(1, 1);
|
||||
qtContainer->setMinimumSize(1, 1);
|
||||
}
|
||||
|
||||
for(auto& layout : window.state.layout) {
|
||||
geometry.x = geometry.y = 0;
|
||||
layout.setGeometry(geometry);
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
|
||||
void pWindow::setMenuFont(string font) {
|
||||
qtMenu->setFont(pFont::create(font));
|
||||
for(auto& item : window.state.menu) item.p.setFont(font);
|
||||
}
|
||||
|
||||
void pWindow::setMenuVisible(bool visible) {
|
||||
qtMenu->setVisible(visible);
|
||||
setGeometry(window.state.geometry);
|
||||
}
|
||||
|
||||
void pWindow::setModal(bool modal) {
|
||||
if(modal == true) {
|
||||
//windowModality can only be enabled while window is invisible
|
||||
setVisible(false);
|
||||
qtWindow->setWindowModality(Qt::ApplicationModal);
|
||||
setVisible(true);
|
||||
while(window.state.modal) {
|
||||
Application::processEvents();
|
||||
if(Application::main) {
|
||||
Application::main();
|
||||
} else {
|
||||
usleep(20 * 1000);
|
||||
}
|
||||
}
|
||||
qtWindow->setWindowModality(Qt::NonModal);
|
||||
}
|
||||
}
|
||||
|
||||
void pWindow::setResizable(bool resizable) {
|
||||
if(resizable) {
|
||||
qtLayout->setSizeConstraint(QLayout::SetDefaultConstraint);
|
||||
qtContainer->setMinimumSize(window.state.geometry.width, window.state.geometry.height);
|
||||
} else {
|
||||
qtLayout->setSizeConstraint(QLayout::SetFixedSize);
|
||||
qtContainer->setFixedSize(window.state.geometry.width, window.state.geometry.height);
|
||||
}
|
||||
qtStatus->setSizeGripEnabled(resizable);
|
||||
}
|
||||
|
||||
void pWindow::setStatusFont(string font) {
|
||||
qtStatus->setFont(pFont::create(font));
|
||||
}
|
||||
|
||||
void pWindow::setStatusText(string text) {
|
||||
qtStatus->showMessage(QString::fromUtf8(text), 0);
|
||||
}
|
||||
|
||||
void pWindow::setStatusVisible(bool visible) {
|
||||
qtStatus->setVisible(visible);
|
||||
setGeometry(window.state.geometry);
|
||||
}
|
||||
|
||||
void pWindow::setTitle(string text) {
|
||||
qtWindow->setWindowTitle(QString::fromUtf8(text));
|
||||
}
|
||||
|
||||
void pWindow::setVisible(bool visible) {
|
||||
lock();
|
||||
qtWindow->setVisible(visible);
|
||||
if(visible) {
|
||||
updateFrameGeometry();
|
||||
setGeometry(window.state.geometry);
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
|
||||
void pWindow::setWidgetFont(string font) {
|
||||
}
|
||||
|
||||
void pWindow::constructor() {
|
||||
qtWindow = new QtWindow(*this);
|
||||
qtWindow->setWindowTitle(" ");
|
||||
|
||||
//if program was given a name, try and set the window taskbar icon to a matching pixmap image
|
||||
if(applicationState.name.empty() == false) {
|
||||
if(file::exists({"/usr/share/pixmaps/", applicationState.name, ".png"})) {
|
||||
qtWindow->setWindowIcon(QIcon(string{"/usr/share/pixmaps/", applicationState.name, ".png"}));
|
||||
} else if(file::exists({"/usr/local/share/pixmaps/", applicationState.name, ".png"})) {
|
||||
qtWindow->setWindowIcon(QIcon(string{"/usr/local/share/pixmaps/", applicationState.name, ".png"}));
|
||||
} else if(file::exists({userpath(), ".local/share/icons/", applicationState.name, ".png"})) {
|
||||
qtWindow->setWindowIcon(QIcon(string{userpath(), ".local/share/icons/", applicationState.name, ".png"}));
|
||||
}
|
||||
}
|
||||
|
||||
qtLayout = new QVBoxLayout(qtWindow);
|
||||
qtLayout->setMargin(0);
|
||||
qtLayout->setSpacing(0);
|
||||
qtWindow->setLayout(qtLayout);
|
||||
|
||||
qtMenu = new QMenuBar(qtWindow);
|
||||
qtMenu->setVisible(false);
|
||||
qtLayout->addWidget(qtMenu);
|
||||
|
||||
qtContainer = new QWidget(qtWindow);
|
||||
qtContainer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
qtContainer->setVisible(true);
|
||||
qtLayout->addWidget(qtContainer);
|
||||
|
||||
qtStatus = new QStatusBar(qtWindow);
|
||||
qtStatus->setSizeGripEnabled(true);
|
||||
qtStatus->setVisible(false);
|
||||
qtLayout->addWidget(qtStatus);
|
||||
|
||||
setGeometry(window.state.geometry);
|
||||
setMenuFont(Font::sans(8));
|
||||
setStatusFont(Font::sans(8));
|
||||
|
||||
QColor color = qtWindow->palette().color(QPalette::ColorRole::Window);
|
||||
window.state.backgroundColor = Color((uint8_t)color.red(), (uint8_t)color.green(), (uint8_t)color.blue(), (uint8_t)color.alpha());
|
||||
}
|
||||
|
||||
void pWindow::destructor() {
|
||||
delete qtStatus;
|
||||
delete qtContainer;
|
||||
delete qtMenu;
|
||||
delete qtLayout;
|
||||
delete qtWindow;
|
||||
}
|
||||
|
||||
void pWindow::updateFrameGeometry() {
|
||||
pApplication::syncX();
|
||||
QRect border = qtWindow->frameGeometry();
|
||||
QRect client = qtWindow->geometry();
|
||||
|
||||
settings->geometry.frameX = client.x() - border.x();
|
||||
settings->geometry.frameY = client.y() - border.y();
|
||||
settings->geometry.frameWidth = border.width() - client.width();
|
||||
settings->geometry.frameHeight = border.height() - client.height();
|
||||
|
||||
if(window.state.menuVisible) {
|
||||
pApplication::syncX();
|
||||
settings->geometry.menuHeight = qtMenu->height();
|
||||
}
|
||||
|
||||
if(window.state.statusVisible) {
|
||||
pApplication::syncX();
|
||||
settings->geometry.statusHeight = qtStatus->height();
|
||||
}
|
||||
|
||||
settings->save();
|
||||
}
|
||||
|
||||
void pWindow::QtWindow::closeEvent(QCloseEvent* event) {
|
||||
event->ignore();
|
||||
if(self.window.onClose) self.window.onClose();
|
||||
else self.window.setVisible(false);
|
||||
if(self.window.state.modal && !self.window.visible()) self.window.setModal(false);
|
||||
}
|
||||
|
||||
void pWindow::QtWindow::moveEvent(QMoveEvent* event) {
|
||||
if(!self.locked() && self.window.state.fullScreen == false && self.qtWindow->isVisible() == true) {
|
||||
self.window.state.geometry.x += event->pos().x() - event->oldPos().x();
|
||||
self.window.state.geometry.y += event->pos().y() - event->oldPos().y();
|
||||
}
|
||||
|
||||
if(!self.locked() && self.window.onMove) self.window.onMove();
|
||||
}
|
||||
|
||||
void pWindow::QtWindow::dragEnterEvent(QDragEnterEvent* event) {
|
||||
if(event->mimeData()->hasUrls()) {
|
||||
event->acceptProposedAction();
|
||||
}
|
||||
}
|
||||
|
||||
void pWindow::QtWindow::dropEvent(QDropEvent* event) {
|
||||
lstring paths = DropPaths(event);
|
||||
if(paths.empty()) return;
|
||||
if(self.window.onDrop) self.window.onDrop(paths);
|
||||
}
|
||||
|
||||
void pWindow::QtWindow::keyPressEvent(QKeyEvent* event) {
|
||||
Keyboard::Keycode sym = Keysym(event->nativeVirtualKey());
|
||||
if(sym != Keyboard::Keycode::None && self.window.onKeyPress) self.window.onKeyPress(sym);
|
||||
}
|
||||
|
||||
void pWindow::QtWindow::keyReleaseEvent(QKeyEvent* event) {
|
||||
Keyboard::Keycode sym = Keysym(event->nativeVirtualKey());
|
||||
if(sym != Keyboard::Keycode::None && self.window.onKeyRelease) self.window.onKeyRelease(sym);
|
||||
}
|
||||
|
||||
void pWindow::QtWindow::resizeEvent(QResizeEvent*) {
|
||||
if(!self.locked() && self.window.state.fullScreen == false && self.qtWindow->isVisible() == true) {
|
||||
self.window.state.geometry.width = self.qtContainer->geometry().width();
|
||||
self.window.state.geometry.height = self.qtContainer->geometry().height();
|
||||
}
|
||||
|
||||
for(auto& layout : self.window.state.layout) {
|
||||
Geometry geometry = self.window.state.geometry;
|
||||
geometry.x = geometry.y = 0;
|
||||
layout.setGeometry(geometry);
|
||||
}
|
||||
|
||||
if(!self.locked() && self.window.onSize) self.window.onSize();
|
||||
}
|
||||
|
||||
QSize pWindow::QtWindow::sizeHint() const {
|
||||
unsigned width = self.window.state.geometry.width;
|
||||
unsigned height = self.window.state.geometry.height;
|
||||
if(self.window.state.menuVisible) height += settings->geometry.menuHeight;
|
||||
if(self.window.state.statusVisible) height += settings->geometry.statusHeight;
|
||||
return QSize(width, height);
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user