UNIXworkcode

1 /* 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 3 * 4 * Copyright 2014 Olaf Wintermann. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <inttypes.h> 32 #include <QMenuBar> 33 #include <QAction> 34 35 #include "menu.h" 36 #include "toolkit.h" 37 #include "../common/context.h" 38 #include "../ui/properties.h" 39 #include "../ui/window.h" 40 #include "stock.h" 41 #include "container.h" 42 43 static UcxList *menus; 44 static UcxList *current; 45 46 /* -------------------------- UiMenu -------------------------- */ 47 48 UiMenu::UiMenu(char* label) { 49 this->items = NULL; 50 this->label = label; 51 } 52 53 void UiMenu::addMenuItem(UiMenuItemI* item) { 54 items = ucx_list_append(items, item); 55 } 56 57 void UiMenu::addTo(UiObject *obj, QMenuBar *menubar, QMenu *menu) { 58 QMenu *m = NULL; 59 if(menubar) { 60 m = menubar->addMenu(label); 61 } else { 62 m = menu->addMenu(label); 63 } 64 65 UCX_FOREACH(elm, items) { 66 UiMenuItemI *item = (UiMenuItemI*)elm->data; 67 item->addTo(obj, NULL, m); 68 } 69 } 70 71 72 /* -------------------------- UiMenuItem -------------------------- */ 73 74 UiMenuItem::UiMenuItem(char* label, ui_callback f, void* userdata) { 75 this->label = label; 76 this->callback = f; 77 this->userdata = userdata; 78 this->groups = NULL; 79 } 80 81 void UiMenuItem::addGroup(int group) { 82 groups = ucx_list_append(groups, (void*)(intptr_t)group); 83 } 84 85 void UiMenuItem::setCheckable(bool c) { 86 checkable = c; 87 } 88 89 void UiMenuItem::addTo(UiObject *obj, QMenuBar *menubar, QMenu *menu) { 90 QString str = QString::fromUtf8(label); 91 UiAction *action = new UiAction(obj, str, callback, userdata); 92 action->setCheckable(checkable); 93 if(checkable) { 94 action->setChecked(false); 95 } 96 menu->addAction(action); 97 QObject::connect(action, SIGNAL(triggered()), action, SLOT(trigger())); 98 } 99 100 101 /* -------------------------- UiStMenuItem -------------------------- */ 102 103 UiStMenuItem::UiStMenuItem(char* stockid, ui_callback f, void* userdata) { 104 this->stockid = stockid; 105 this->callback = f; 106 this->userdata = userdata; 107 this->groups = NULL; 108 } 109 110 void UiStMenuItem::addGroup(int group) { 111 groups = ucx_list_append(groups, (void*)(intptr_t)group); 112 } 113 114 void UiStMenuItem::addTo(UiObject *obj, QMenuBar *menubar, QMenu *menu) { 115 UiStockItem *stockItem = ui_get_stock_item(stockid); 116 117 QString str = QString::fromUtf8(stockItem->label); 118 UiAction *action = new UiAction(obj, str, callback, userdata); 119 action->setIcon(QIcon::fromTheme(stockItem->icon_name)); 120 action->setIconVisibleInMenu(true); 121 menu->addAction(action); 122 //UiEventWrapper *ev = new UiEventWrapper(callback, userdata); 123 QObject::connect(action, SIGNAL(triggered()), action, SLOT(trigger())); 124 } 125 126 127 /* -------------------------- UiMenuSeparator -------------------------- */ 128 129 void UiMenuSeparator::addTo(UiObject* obj, QMenuBar* menubar, QMenu* menu) { 130 menu->addSeparator(); 131 } 132 133 134 /* -------------------------- UiCheckItemNV -------------------------- */ 135 136 UiCheckItemNV::UiCheckItemNV(char* label, char* varname) { 137 this->label = label; 138 this->varname = varname; 139 } 140 141 void UiCheckItemNV::addTo(UiObject* obj, QMenuBar* menubar, QMenu* menu) { 142 QString str = QString::fromUtf8(label); 143 UiAction *action = new UiAction(obj, str, NULL, NULL); 144 action->setCheckable(true); 145 menu->addAction(action); 146 QObject::connect(action, SIGNAL(triggered()), action, SLOT(trigger())); 147 148 UiVar *var = uic_connect_var(obj->ctx, varname, UI_VAR_INTEGER); 149 if(var) { 150 UiInteger *value = (UiInteger*)var->value; 151 action->setChecked(value->value); 152 value->obj = action; 153 value->get = ui_checkitem_get; 154 value->set = ui_checkitem_set; 155 value = 0; 156 } else { 157 // TODO: error 158 } 159 } 160 161 162 /* -------------------------- UiAction -------------------------- */ 163 164 UiAction::UiAction(UiObject *obj, QString &label, ui_callback f, void* userdata) : QAction(label, NULL) { 165 //QAction(label, NULL); 166 this->obj = obj; 167 this->callback = f; 168 this->userdata = userdata; 169 } 170 171 void UiAction::trigger() { 172 if(!callback) { 173 return; 174 } 175 176 UiEvent e; 177 e.obj = obj; 178 e.window = obj->window; 179 e.document = obj->ctx->document; 180 e.eventdata = NULL; 181 182 if(isCheckable()) { 183 e.intval = isChecked(); 184 } else { 185 e.intval = 0; 186 } 187 188 callback(&e, userdata); 189 } 190 191 192 void ui_menu(char *label) { 193 // free current menu hierarchy 194 ucx_list_free(current); 195 196 // create menu 197 UiMenu *menu = new UiMenu(label); 198 199 current = ucx_list_prepend(NULL, menu); 200 menus = ucx_list_append(menus, menu); 201 } 202 203 void ui_submenu(char *label) { 204 UiMenu *menu = new UiMenu(label); 205 206 // add submenu to current menu 207 UiMenu *cm = (UiMenu*)current->data; 208 cm->addMenuItem(menu); 209 210 // set the submenu to current menu 211 current = ucx_list_prepend(current, menu); 212 } 213 214 void ui_submenu_end() { 215 if(ucx_list_size(current) < 2) { 216 return; 217 } 218 current = ucx_list_remove(current, current); 219 //UcxList *c = current; 220 } 221 222 223 void ui_menuitem(char *label, ui_callback f, void *userdata) { 224 ui_menuitem_gr(label, f, userdata, -1); 225 } 226 227 void ui_menuitem_st(char *stockid, ui_callback f, void *userdata) { 228 ui_menuitem_stgr(stockid, f, userdata, -1); 229 } 230 231 void ui_menuitem_gr(char *label, ui_callback f, void *userdata, ...) { 232 if(!current) { 233 return; 234 } 235 236 UiMenuItem *item = new UiMenuItem(label, f, userdata); 237 238 // add groups 239 va_list ap; 240 va_start(ap, userdata); 241 int group; 242 while((group = va_arg(ap, int)) != -1) { 243 item->addGroup(group); 244 } 245 va_end(ap); 246 247 UiMenu *cm = (UiMenu*)current->data; 248 cm->addMenuItem(item); 249 } 250 251 void ui_menuitem_stgr(char *stockid, ui_callback f, void *userdata, ...) { 252 if(!current) { 253 return; 254 } 255 256 UiStMenuItem *item = new UiStMenuItem(stockid, f, userdata); 257 258 // add groups 259 va_list ap; 260 va_start(ap, userdata); 261 int group; 262 while((group = va_arg(ap, int)) != -1) { 263 item->addGroup(group); 264 } 265 va_end(ap); 266 267 UiMenu *cm = (UiMenu*)current->data; 268 cm->addMenuItem(item); 269 } 270 271 void ui_menuseparator() { 272 if(!current) { 273 return; 274 } 275 276 UiMenuSeparator *item = new UiMenuSeparator(); 277 UiMenu *cm = (UiMenu*)current->data; 278 cm->addMenuItem(item); 279 } 280 281 void ui_checkitem(char *label, ui_callback f, void *userdata) { 282 if(!current) { 283 return; 284 } 285 286 UiMenuItem *item = new UiMenuItem(label, f, userdata); 287 item->setCheckable(true); 288 289 UiMenu *cm = (UiMenu*)current->data; 290 cm->addMenuItem(item); 291 } 292 293 void ui_checkitem_nv(char *label, char *vname) { 294 if(!current) { 295 return; 296 } 297 298 UiCheckItemNV *item = new UiCheckItemNV(label, vname); 299 300 UiMenu *cm = (UiMenu*)current->data; 301 cm->addMenuItem(item); 302 } 303 304 void ui_menuitem_list(UiList *items, ui_callback f, void *userdata) { 305 306 } 307 308 void ui_add_menus(UiObject *obj, QMainWindow *window) { 309 QMenuBar *mb = window->menuBar(); 310 311 UCX_FOREACH(elm, menus) { 312 UiMenu *menu = (UiMenu*)elm->data; 313 menu->addTo(obj, mb, NULL); 314 } 315 } 316 317 int ui_checkitem_get(UiInteger *i) { 318 QAction *action = (QAction*)i->obj; 319 i->value = action->isChecked(); 320 return i->value; 321 } 322 323 void ui_checkitem_set(UiInteger *i, int value) { 324 QAction *action = (QAction*)i->obj; 325 i->value = value; 326 action->setChecked(value); 327 } 328 329 330 /* 331 * widget menu functions 332 */ 333 334 UiContextMenuHandler::UiContextMenuHandler(QWidget *widget, QMenu* menu) { 335 this->widget = widget; 336 this->menu = menu; 337 } 338 339 void UiContextMenuHandler::contextMenuEvent(const QPoint & pos) { 340 menu->popup(widget->mapToGlobal(pos)); 341 } 342 UIMENU ui_contextmenu(UiObject *obj) { 343 UiContainer *ct = uic_get_current_container(obj); 344 return ui_contextmenu_w(obj, ct->current); 345 } 346 347 UIMENU ui_contextmenu_w(UiObject *obj, UIWIDGET widget) { 348 UiContainer *ct = uic_get_current_container(obj); 349 350 QMenu *menu = new QMenu(widget); 351 widget->setContextMenuPolicy(Qt::CustomContextMenu); 352 353 UiContextMenuHandler *handler = new UiContextMenuHandler(widget, menu); 354 QObject::connect( 355 widget, 356 SIGNAL(customContextMenuRequested(QPoint)), 357 handler, 358 SLOT(contextMenuEvent(QPoint))); 359 360 ct->menu = menu; 361 362 return menu; 363 } 364 365 void ui_contextmenu_popup(UIMENU menu) { 366 367 } 368 369 void ui_widget_menuitem(UiObject *obj, char *label, ui_callback f, void *userdata) { 370 ui_widget_menuitem_gr(obj, label, f, userdata, -1); 371 } 372 373 void ui_widget_menuitem_gr(UiObject *obj, char *label, ui_callback f, void *userdata, ...) { 374 UiContainer *ct = uic_get_current_container(obj); 375 if(!ct->menu) { 376 return; 377 } 378 379 // add groups 380 UcxList *groups = NULL; 381 va_list ap; 382 va_start(ap, userdata); 383 int group; 384 while((group = va_arg(ap, int)) != -1) { 385 ucx_list_append(groups, (void*)(intptr_t)group); 386 } 387 va_end(ap); 388 389 // create menuitem 390 QString str = QString::fromUtf8(label); 391 UiAction *action = new UiAction(obj, str, f, userdata); 392 ct->menu->addAction(action); 393 QObject::connect(action, SIGNAL(triggered()), action, SLOT(trigger())); 394 } 395 396 void ui_widget_menuitem_st(UiObject *obj, char *stockid, ui_callback f, void *userdata) { 397 ui_widget_menuitem_stgr(obj, stockid, f, userdata, -1); 398 } 399 400 void ui_widget_menuitem_stgr(UiObject *obj, char *stockid, ui_callback f, void *userdata, ...) { 401 UiContainer *ct = uic_get_current_container(obj); 402 if(!ct->menu) { 403 return; 404 } 405 406 // add groups 407 UcxList *groups = NULL; 408 va_list ap; 409 va_start(ap, userdata); 410 int group; 411 while((group = va_arg(ap, int)) != -1) { 412 ucx_list_append(groups, (void*)(intptr_t)group); 413 } 414 va_end(ap); 415 416 // create menuitem 417 UiStockItem *stockItem = ui_get_stock_item(stockid); 418 419 QString str = QString::fromUtf8(stockItem->label); 420 UiAction *action = new UiAction(obj, str, f, userdata); 421 action->setIcon(QIcon::fromTheme(stockItem->icon_name)); 422 action->setIconVisibleInMenu(true); 423 ct->menu->addAction(action); 424 QObject::connect(action, SIGNAL(triggered()), action, SLOT(trigger())); 425 } 426