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:
Tim Allen
2015-02-26 21:10:46 +11:00
parent 1a7bc6bb87
commit a512d14628
793 changed files with 20182 additions and 19416 deletions

53
hiro/qt/action/action.cpp Normal file
View 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() {
}
}

View 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
View 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
View 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;
}
}

View 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();
}
}
}

View 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
View 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();
}
}

View 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
View 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
View 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
View 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
View 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;
}
}

View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

876
hiro/qt/platform.moc.hpp Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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) {
}
}

View 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();
}
}

View 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();
}
}

View 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();
}
}

View 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
View 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
View 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);
}
}

View 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();
}
}

View 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();
}
}

View 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
View 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();
}
}

View 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();
}
}

View 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) {
}
}

View 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();
}
}

View 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();
}
}
}

View 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();
}
}
}

View 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();
}
}

View 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();
}
}

View 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();
}
}

View 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();
}
}

View 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
View 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
View 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);
}
}