1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org> 4 * Copyright (C) 2015 Boris Barbulovski <bbarbulovski@gmail.com> 5 */ 6 7 #include <qglobal.h> 8 9 #include <QMainWindow> 10 #include <QList> 11 #include <qtextbrowser.h> 12 #include <QAction> 13 #include <QFileDialog> 14 #include <QMenu> 15 16 #include <qapplication.h> 17 #include <qdesktopwidget.h> 18 #include <qtoolbar.h> 19 #include <qlayout.h> 20 #include <qsplitter.h> 21 #include <qlineedit.h> 22 #include <qlabel.h> 23 #include <qpushbutton.h> 24 #include <qmenubar.h> 25 #include <qmessagebox.h> 26 #include <qregexp.h> 27 #include <qevent.h> 28 29 #include <stdlib.h> 30 31 #include "lkc.h" 32 #include "qconf.h" 33 34 #include "qconf.moc" 35 #include "images.h" 36 37 38 static QApplication *configApp; 39 static ConfigSettings *configSettings; 40 41 QAction *ConfigMainWindow::saveAction; 42 43 static inline QString qgettext(const char* str) 44 { 45 return QString::fromLocal8Bit(str); 46 } 47 48 ConfigSettings::ConfigSettings() 49 : QSettings("kernel.org", "qconf") 50 { 51 } 52 53 /** 54 * Reads a list of integer values from the application settings. 55 */ 56 QList<int> ConfigSettings::readSizes(const QString& key, bool *ok) 57 { 58 QList<int> result; 59 60 if (contains(key)) 61 { 62 QStringList entryList = value(key).toStringList(); 63 QStringList::Iterator it; 64 65 for (it = entryList.begin(); it != entryList.end(); ++it) 66 result.push_back((*it).toInt()); 67 68 *ok = true; 69 } 70 else 71 *ok = false; 72 73 return result; 74 } 75 76 /** 77 * Writes a list of integer values to the application settings. 78 */ 79 bool ConfigSettings::writeSizes(const QString& key, const QList<int>& value) 80 { 81 QStringList stringList; 82 QList<int>::ConstIterator it; 83 84 for (it = value.begin(); it != value.end(); ++it) 85 stringList.push_back(QString::number(*it)); 86 setValue(key, stringList); 87 88 return true; 89 } 90 91 92 /* 93 * set the new data 94 * TODO check the value 95 */ 96 void ConfigItem::okRename(int col) 97 { 98 } 99 100 /* 101 * update the displayed of a menu entry 102 */ 103 void ConfigItem::updateMenu(void) 104 { 105 ConfigList* list; 106 struct symbol* sym; 107 struct property *prop; 108 QString prompt; 109 int type; 110 tristate expr; 111 112 list = listView(); 113 if (goParent) { 114 setPixmap(promptColIdx, list->menuBackPix); 115 prompt = ".."; 116 goto set_prompt; 117 } 118 119 sym = menu->sym; 120 prop = menu->prompt; 121 prompt = qgettext(menu_get_prompt(menu)); 122 123 if (prop) switch (prop->type) { 124 case P_MENU: 125 if (list->mode == singleMode || list->mode == symbolMode) { 126 /* a menuconfig entry is displayed differently 127 * depending whether it's at the view root or a child. 128 */ 129 if (sym && list->rootEntry == menu) 130 break; 131 setPixmap(promptColIdx, list->menuPix); 132 } else { 133 if (sym) 134 break; 135 setPixmap(promptColIdx, QIcon()); 136 } 137 goto set_prompt; 138 case P_COMMENT: 139 setPixmap(promptColIdx, QIcon()); 140 goto set_prompt; 141 default: 142 ; 143 } 144 if (!sym) 145 goto set_prompt; 146 147 setText(nameColIdx, QString::fromLocal8Bit(sym->name)); 148 149 type = sym_get_type(sym); 150 switch (type) { 151 case S_BOOLEAN: 152 case S_TRISTATE: 153 char ch; 154 155 if (!sym_is_changeable(sym) && list->optMode == normalOpt) { 156 setPixmap(promptColIdx, QIcon()); 157 setText(noColIdx, QString()); 158 setText(modColIdx, QString()); 159 setText(yesColIdx, QString()); 160 break; 161 } 162 expr = sym_get_tristate_value(sym); 163 switch (expr) { 164 case yes: 165 if (sym_is_choice_value(sym) && type == S_BOOLEAN) 166 setPixmap(promptColIdx, list->choiceYesPix); 167 else 168 setPixmap(promptColIdx, list->symbolYesPix); 169 setText(yesColIdx, "Y"); 170 ch = 'Y'; 171 break; 172 case mod: 173 setPixmap(promptColIdx, list->symbolModPix); 174 setText(modColIdx, "M"); 175 ch = 'M'; 176 break; 177 default: 178 if (sym_is_choice_value(sym) && type == S_BOOLEAN) 179 setPixmap(promptColIdx, list->choiceNoPix); 180 else 181 setPixmap(promptColIdx, list->symbolNoPix); 182 setText(noColIdx, "N"); 183 ch = 'N'; 184 break; 185 } 186 if (expr != no) 187 setText(noColIdx, sym_tristate_within_range(sym, no) ? "_" : 0); 188 if (expr != mod) 189 setText(modColIdx, sym_tristate_within_range(sym, mod) ? "_" : 0); 190 if (expr != yes) 191 setText(yesColIdx, sym_tristate_within_range(sym, yes) ? "_" : 0); 192 193 setText(dataColIdx, QChar(ch)); 194 break; 195 case S_INT: 196 case S_HEX: 197 case S_STRING: 198 const char* data; 199 200 data = sym_get_string_value(sym); 201 202 setText(dataColIdx, data); 203 if (type == S_STRING) 204 prompt = QString("%1: %2").arg(prompt).arg(data); 205 else 206 prompt = QString("(%2) %1").arg(prompt).arg(data); 207 break; 208 } 209 if (!sym_has_value(sym) && visible) 210 prompt += " (NEW)"; 211 set_prompt: 212 setText(promptColIdx, prompt); 213 } 214 215 void ConfigItem::testUpdateMenu(bool v) 216 { 217 ConfigItem* i; 218 219 visible = v; 220 if (!menu) 221 return; 222 223 sym_calc_value(menu->sym); 224 if (menu->flags & MENU_CHANGED) { 225 /* the menu entry changed, so update all list items */ 226 menu->flags &= ~MENU_CHANGED; 227 for (i = (ConfigItem*)menu->data; i; i = i->nextItem) 228 i->updateMenu(); 229 } else if (listView()->updateAll) 230 updateMenu(); 231 } 232 233 234 /* 235 * construct a menu entry 236 */ 237 void ConfigItem::init(void) 238 { 239 if (menu) { 240 ConfigList* list = listView(); 241 nextItem = (ConfigItem*)menu->data; 242 menu->data = this; 243 244 if (list->mode != fullMode) 245 setExpanded(true); 246 sym_calc_value(menu->sym); 247 } 248 updateMenu(); 249 } 250 251 /* 252 * destruct a menu entry 253 */ 254 ConfigItem::~ConfigItem(void) 255 { 256 if (menu) { 257 ConfigItem** ip = (ConfigItem**)&menu->data; 258 for (; *ip; ip = &(*ip)->nextItem) { 259 if (*ip == this) { 260 *ip = nextItem; 261 break; 262 } 263 } 264 } 265 } 266 267 ConfigLineEdit::ConfigLineEdit(ConfigView* parent) 268 : Parent(parent) 269 { 270 connect(this, SIGNAL(editingFinished()), SLOT(hide())); 271 } 272 273 void ConfigLineEdit::show(ConfigItem* i) 274 { 275 item = i; 276 if (sym_get_string_value(item->menu->sym)) 277 setText(QString::fromLocal8Bit(sym_get_string_value(item->menu->sym))); 278 else 279 setText(QString()); 280 Parent::show(); 281 setFocus(); 282 } 283 284 void ConfigLineEdit::keyPressEvent(QKeyEvent* e) 285 { 286 switch (e->key()) { 287 case Qt::Key_Escape: 288 break; 289 case Qt::Key_Return: 290 case Qt::Key_Enter: 291 sym_set_string_value(item->menu->sym, text().toLatin1()); 292 parent()->updateList(item); 293 break; 294 default: 295 Parent::keyPressEvent(e); 296 return; 297 } 298 e->accept(); 299 parent()->list->setFocus(); 300 hide(); 301 } 302 303 ConfigList::ConfigList(ConfigView* p, const char *name) 304 : Parent(p), 305 updateAll(false), 306 symbolYesPix(xpm_symbol_yes), symbolModPix(xpm_symbol_mod), symbolNoPix(xpm_symbol_no), 307 choiceYesPix(xpm_choice_yes), choiceNoPix(xpm_choice_no), 308 menuPix(xpm_menu), menuInvPix(xpm_menu_inv), menuBackPix(xpm_menuback), voidPix(xpm_void), 309 showName(false), showRange(false), showData(false), mode(singleMode), optMode(normalOpt), 310 rootEntry(0), headerPopup(0) 311 { 312 setObjectName(name); 313 setSortingEnabled(false); 314 setRootIsDecorated(true); 315 316 setVerticalScrollMode(ScrollPerPixel); 317 setHorizontalScrollMode(ScrollPerPixel); 318 319 if (mode == symbolMode) 320 setHeaderLabels(QStringList() << "Item" << "Name" << "N" << "M" << "Y" << "Value"); 321 else 322 setHeaderLabels(QStringList() << "Option" << "Name" << "N" << "M" << "Y" << "Value"); 323 324 connect(this, SIGNAL(itemSelectionChanged(void)), 325 SLOT(updateSelection(void))); 326 327 if (name) { 328 configSettings->beginGroup(name); 329 showName = configSettings->value("/showName", false).toBool(); 330 showRange = configSettings->value("/showRange", false).toBool(); 331 showData = configSettings->value("/showData", false).toBool(); 332 optMode = (enum optionMode)configSettings->value("/optionMode", 0).toInt(); 333 configSettings->endGroup(); 334 connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings())); 335 } 336 337 addColumn(promptColIdx); 338 339 reinit(); 340 } 341 342 bool ConfigList::menuSkip(struct menu *menu) 343 { 344 if (optMode == normalOpt && menu_is_visible(menu)) 345 return false; 346 if (optMode == promptOpt && menu_has_prompt(menu)) 347 return false; 348 if (optMode == allOpt) 349 return false; 350 return true; 351 } 352 353 void ConfigList::reinit(void) 354 { 355 removeColumn(dataColIdx); 356 removeColumn(yesColIdx); 357 removeColumn(modColIdx); 358 removeColumn(noColIdx); 359 removeColumn(nameColIdx); 360 361 if (showName) 362 addColumn(nameColIdx); 363 if (showRange) { 364 addColumn(noColIdx); 365 addColumn(modColIdx); 366 addColumn(yesColIdx); 367 } 368 if (showData) 369 addColumn(dataColIdx); 370 371 updateListAll(); 372 } 373 374 void ConfigList::saveSettings(void) 375 { 376 if (!objectName().isEmpty()) { 377 configSettings->beginGroup(objectName()); 378 configSettings->setValue("/showName", showName); 379 configSettings->setValue("/showRange", showRange); 380 configSettings->setValue("/showData", showData); 381 configSettings->setValue("/optionMode", (int)optMode); 382 configSettings->endGroup(); 383 } 384 } 385 386 ConfigItem* ConfigList::findConfigItem(struct menu *menu) 387 { 388 ConfigItem* item = (ConfigItem*)menu->data; 389 390 for (; item; item = item->nextItem) { 391 if (this == item->listView()) 392 break; 393 } 394 395 return item; 396 } 397 398 void ConfigList::updateSelection(void) 399 { 400 struct menu *menu; 401 enum prop_type type; 402 403 if (mode == symbolMode) 404 setHeaderLabels(QStringList() << "Item" << "Name" << "N" << "M" << "Y" << "Value"); 405 else 406 setHeaderLabels(QStringList() << "Option" << "Name" << "N" << "M" << "Y" << "Value"); 407 408 if (selectedItems().count() == 0) 409 return; 410 411 ConfigItem* item = (ConfigItem*)selectedItems().first(); 412 if (!item) 413 return; 414 415 menu = item->menu; 416 emit menuChanged(menu); 417 if (!menu) 418 return; 419 type = menu->prompt ? menu->prompt->type : P_UNKNOWN; 420 if (mode == menuMode && type == P_MENU) 421 emit menuSelected(menu); 422 } 423 424 void ConfigList::updateList(ConfigItem* item) 425 { 426 ConfigItem* last = 0; 427 428 if (!rootEntry) { 429 if (mode != listMode) 430 goto update; 431 QTreeWidgetItemIterator it(this); 432 ConfigItem* item; 433 434 while (*it) { 435 item = (ConfigItem*)(*it); 436 if (!item->menu) 437 continue; 438 item->testUpdateMenu(menu_is_visible(item->menu)); 439 440 ++it; 441 } 442 return; 443 } 444 445 if (rootEntry != &rootmenu && (mode == singleMode || 446 (mode == symbolMode && rootEntry->parent != &rootmenu))) { 447 item = (ConfigItem *)topLevelItem(0); 448 if (!item) 449 item = new ConfigItem(this, 0, true); 450 last = item; 451 } 452 if ((mode == singleMode || (mode == symbolMode && !(rootEntry->flags & MENU_ROOT))) && 453 rootEntry->sym && rootEntry->prompt) { 454 item = last ? last->nextSibling() : firstChild(); 455 if (!item) 456 item = new ConfigItem(this, last, rootEntry, true); 457 else 458 item->testUpdateMenu(true); 459 460 updateMenuList(item, rootEntry); 461 update(); 462 resizeColumnToContents(0); 463 return; 464 } 465 update: 466 updateMenuList(this, rootEntry); 467 update(); 468 resizeColumnToContents(0); 469 } 470 471 void ConfigList::setValue(ConfigItem* item, tristate val) 472 { 473 struct symbol* sym; 474 int type; 475 tristate oldval; 476 477 sym = item->menu ? item->menu->sym : 0; 478 if (!sym) 479 return; 480 481 type = sym_get_type(sym); 482 switch (type) { 483 case S_BOOLEAN: 484 case S_TRISTATE: 485 oldval = sym_get_tristate_value(sym); 486 487 if (!sym_set_tristate_value(sym, val)) 488 return; 489 if (oldval == no && item->menu->list) 490 item->setExpanded(true); 491 parent()->updateList(item); 492 break; 493 } 494 } 495 496 void ConfigList::changeValue(ConfigItem* item) 497 { 498 struct symbol* sym; 499 struct menu* menu; 500 int type, oldexpr, newexpr; 501 502 menu = item->menu; 503 if (!menu) 504 return; 505 sym = menu->sym; 506 if (!sym) { 507 if (item->menu->list) 508 item->setExpanded(!item->isExpanded()); 509 return; 510 } 511 512 type = sym_get_type(sym); 513 switch (type) { 514 case S_BOOLEAN: 515 case S_TRISTATE: 516 oldexpr = sym_get_tristate_value(sym); 517 newexpr = sym_toggle_tristate_value(sym); 518 if (item->menu->list) { 519 if (oldexpr == newexpr) 520 item->setExpanded(!item->isExpanded()); 521 else if (oldexpr == no) 522 item->setExpanded(true); 523 } 524 if (oldexpr != newexpr) 525 parent()->updateList(item); 526 break; 527 case S_INT: 528 case S_HEX: 529 case S_STRING: 530 parent()->lineEdit->show(item); 531 break; 532 } 533 } 534 535 void ConfigList::setRootMenu(struct menu *menu) 536 { 537 enum prop_type type; 538 539 if (rootEntry == menu) 540 return; 541 type = menu && menu->prompt ? menu->prompt->type : P_UNKNOWN; 542 if (type != P_MENU) 543 return; 544 updateMenuList(this, 0); 545 rootEntry = menu; 546 updateListAll(); 547 if (currentItem()) { 548 currentItem()->setSelected(hasFocus()); 549 scrollToItem(currentItem()); 550 } 551 } 552 553 void ConfigList::setParentMenu(void) 554 { 555 ConfigItem* item; 556 struct menu *oldroot; 557 558 oldroot = rootEntry; 559 if (rootEntry == &rootmenu) 560 return; 561 setRootMenu(menu_get_parent_menu(rootEntry->parent)); 562 563 QTreeWidgetItemIterator it(this); 564 while (*it) { 565 item = (ConfigItem *)(*it); 566 if (item->menu == oldroot) { 567 setCurrentItem(item); 568 scrollToItem(item); 569 break; 570 } 571 572 ++it; 573 } 574 } 575 576 /* 577 * update all the children of a menu entry 578 * removes/adds the entries from the parent widget as necessary 579 * 580 * parent: either the menu list widget or a menu entry widget 581 * menu: entry to be updated 582 */ 583 void ConfigList::updateMenuList(ConfigItem *parent, struct menu* menu) 584 { 585 struct menu* child; 586 ConfigItem* item; 587 ConfigItem* last; 588 bool visible; 589 enum prop_type type; 590 591 if (!menu) { 592 while (parent->childCount() > 0) 593 { 594 delete parent->takeChild(0); 595 } 596 597 return; 598 } 599 600 last = parent->firstChild(); 601 if (last && !last->goParent) 602 last = 0; 603 for (child = menu->list; child; child = child->next) { 604 item = last ? last->nextSibling() : parent->firstChild(); 605 type = child->prompt ? child->prompt->type : P_UNKNOWN; 606 607 switch (mode) { 608 case menuMode: 609 if (!(child->flags & MENU_ROOT)) 610 goto hide; 611 break; 612 case symbolMode: 613 if (child->flags & MENU_ROOT) 614 goto hide; 615 break; 616 default: 617 break; 618 } 619 620 visible = menu_is_visible(child); 621 if (!menuSkip(child)) { 622 if (!child->sym && !child->list && !child->prompt) 623 continue; 624 if (!item || item->menu != child) 625 item = new ConfigItem(parent, last, child, visible); 626 else 627 item->testUpdateMenu(visible); 628 629 if (mode == fullMode || mode == menuMode || type != P_MENU) 630 updateMenuList(item, child); 631 else 632 updateMenuList(item, 0); 633 last = item; 634 continue; 635 } 636 hide: 637 if (item && item->menu == child) { 638 last = parent->firstChild(); 639 if (last == item) 640 last = 0; 641 else while (last->nextSibling() != item) 642 last = last->nextSibling(); 643 delete item; 644 } 645 } 646 } 647 648 void ConfigList::updateMenuList(ConfigList *parent, struct menu* menu) 649 { 650 struct menu* child; 651 ConfigItem* item; 652 ConfigItem* last; 653 bool visible; 654 enum prop_type type; 655 656 if (!menu) { 657 while (parent->topLevelItemCount() > 0) 658 { 659 delete parent->takeTopLevelItem(0); 660 } 661 662 return; 663 } 664 665 last = (ConfigItem*)parent->topLevelItem(0); 666 if (last && !last->goParent) 667 last = 0; 668 for (child = menu->list; child; child = child->next) { 669 item = last ? last->nextSibling() : (ConfigItem*)parent->topLevelItem(0); 670 type = child->prompt ? child->prompt->type : P_UNKNOWN; 671 672 switch (mode) { 673 case menuMode: 674 if (!(child->flags & MENU_ROOT)) 675 goto hide; 676 break; 677 case symbolMode: 678 if (child->flags & MENU_ROOT) 679 goto hide; 680 break; 681 default: 682 break; 683 } 684 685 visible = menu_is_visible(child); 686 if (!menuSkip(child)) { 687 if (!child->sym && !child->list && !child->prompt) 688 continue; 689 if (!item || item->menu != child) 690 item = new ConfigItem(parent, last, child, visible); 691 else 692 item->testUpdateMenu(visible); 693 694 if (mode == fullMode || mode == menuMode || type != P_MENU) 695 updateMenuList(item, child); 696 else 697 updateMenuList(item, 0); 698 last = item; 699 continue; 700 } 701 hide: 702 if (item && item->menu == child) { 703 last = (ConfigItem*)parent->topLevelItem(0); 704 if (last == item) 705 last = 0; 706 else while (last->nextSibling() != item) 707 last = last->nextSibling(); 708 delete item; 709 } 710 } 711 } 712 713 void ConfigList::keyPressEvent(QKeyEvent* ev) 714 { 715 QTreeWidgetItem* i = currentItem(); 716 ConfigItem* item; 717 struct menu *menu; 718 enum prop_type type; 719 720 if (ev->key() == Qt::Key_Escape && mode != fullMode && mode != listMode) { 721 emit parentSelected(); 722 ev->accept(); 723 return; 724 } 725 726 if (!i) { 727 Parent::keyPressEvent(ev); 728 return; 729 } 730 item = (ConfigItem*)i; 731 732 switch (ev->key()) { 733 case Qt::Key_Return: 734 case Qt::Key_Enter: 735 if (item->goParent) { 736 emit parentSelected(); 737 break; 738 } 739 menu = item->menu; 740 if (!menu) 741 break; 742 type = menu->prompt ? menu->prompt->type : P_UNKNOWN; 743 if (type == P_MENU && rootEntry != menu && 744 mode != fullMode && mode != menuMode) { 745 if (mode == menuMode) 746 emit menuSelected(menu); 747 else 748 emit itemSelected(menu); 749 break; 750 } 751 case Qt::Key_Space: 752 changeValue(item); 753 break; 754 case Qt::Key_N: 755 setValue(item, no); 756 break; 757 case Qt::Key_M: 758 setValue(item, mod); 759 break; 760 case Qt::Key_Y: 761 setValue(item, yes); 762 break; 763 default: 764 Parent::keyPressEvent(ev); 765 return; 766 } 767 ev->accept(); 768 } 769 770 void ConfigList::mousePressEvent(QMouseEvent* e) 771 { 772 //QPoint p(contentsToViewport(e->pos())); 773 //printf("contentsMousePressEvent: %d,%d\n", p.x(), p.y()); 774 Parent::mousePressEvent(e); 775 } 776 777 void ConfigList::mouseReleaseEvent(QMouseEvent* e) 778 { 779 QPoint p = e->pos(); 780 ConfigItem* item = (ConfigItem*)itemAt(p); 781 struct menu *menu; 782 enum prop_type ptype; 783 QIcon icon; 784 int idx, x; 785 786 if (!item) 787 goto skip; 788 789 menu = item->menu; 790 x = header()->offset() + p.x(); 791 idx = header()->logicalIndexAt(x); 792 switch (idx) { 793 case promptColIdx: 794 icon = item->pixmap(promptColIdx); 795 if (!icon.isNull()) { 796 int off = header()->sectionPosition(0) + visualRect(indexAt(p)).x() + 4; // 4 is Hardcoded image offset. There might be a way to do it properly. 797 if (x >= off && x < off + icon.availableSizes().first().width()) { 798 if (item->goParent) { 799 emit parentSelected(); 800 break; 801 } else if (!menu) 802 break; 803 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; 804 if (ptype == P_MENU && rootEntry != menu && 805 mode != fullMode && mode != menuMode) 806 emit menuSelected(menu); 807 else 808 changeValue(item); 809 } 810 } 811 break; 812 case noColIdx: 813 setValue(item, no); 814 break; 815 case modColIdx: 816 setValue(item, mod); 817 break; 818 case yesColIdx: 819 setValue(item, yes); 820 break; 821 case dataColIdx: 822 changeValue(item); 823 break; 824 } 825 826 skip: 827 //printf("contentsMouseReleaseEvent: %d,%d\n", p.x(), p.y()); 828 Parent::mouseReleaseEvent(e); 829 } 830 831 void ConfigList::mouseMoveEvent(QMouseEvent* e) 832 { 833 //QPoint p(contentsToViewport(e->pos())); 834 //printf("contentsMouseMoveEvent: %d,%d\n", p.x(), p.y()); 835 Parent::mouseMoveEvent(e); 836 } 837 838 void ConfigList::mouseDoubleClickEvent(QMouseEvent* e) 839 { 840 QPoint p = e->pos(); 841 ConfigItem* item = (ConfigItem*)itemAt(p); 842 struct menu *menu; 843 enum prop_type ptype; 844 845 if (!item) 846 goto skip; 847 if (item->goParent) { 848 emit parentSelected(); 849 goto skip; 850 } 851 menu = item->menu; 852 if (!menu) 853 goto skip; 854 ptype = menu->prompt ? menu->prompt->type : P_UNKNOWN; 855 if (ptype == P_MENU) { 856 if (mode == singleMode) 857 emit itemSelected(menu); 858 else if (mode == symbolMode) 859 emit menuSelected(menu); 860 } else if (menu->sym) 861 changeValue(item); 862 863 skip: 864 //printf("contentsMouseDoubleClickEvent: %d,%d\n", p.x(), p.y()); 865 Parent::mouseDoubleClickEvent(e); 866 } 867 868 void ConfigList::focusInEvent(QFocusEvent *e) 869 { 870 struct menu *menu = NULL; 871 872 Parent::focusInEvent(e); 873 874 ConfigItem* item = (ConfigItem *)currentItem(); 875 if (item) { 876 item->setSelected(true); 877 menu = item->menu; 878 } 879 emit gotFocus(menu); 880 } 881 882 void ConfigList::contextMenuEvent(QContextMenuEvent *e) 883 { 884 if (e->y() <= header()->geometry().bottom()) { 885 if (!headerPopup) { 886 QAction *action; 887 888 headerPopup = new QMenu(this); 889 action = new QAction("Show Name", this); 890 action->setCheckable(true); 891 connect(action, SIGNAL(toggled(bool)), 892 parent(), SLOT(setShowName(bool))); 893 connect(parent(), SIGNAL(showNameChanged(bool)), 894 action, SLOT(setOn(bool))); 895 action->setChecked(showName); 896 headerPopup->addAction(action); 897 action = new QAction("Show Range", this); 898 action->setCheckable(true); 899 connect(action, SIGNAL(toggled(bool)), 900 parent(), SLOT(setShowRange(bool))); 901 connect(parent(), SIGNAL(showRangeChanged(bool)), 902 action, SLOT(setOn(bool))); 903 action->setChecked(showRange); 904 headerPopup->addAction(action); 905 action = new QAction("Show Data", this); 906 action->setCheckable(true); 907 connect(action, SIGNAL(toggled(bool)), 908 parent(), SLOT(setShowData(bool))); 909 connect(parent(), SIGNAL(showDataChanged(bool)), 910 action, SLOT(setOn(bool))); 911 action->setChecked(showData); 912 headerPopup->addAction(action); 913 } 914 headerPopup->exec(e->globalPos()); 915 e->accept(); 916 } else 917 e->ignore(); 918 } 919 920 ConfigView*ConfigView::viewList; 921 QAction *ConfigView::showNormalAction; 922 QAction *ConfigView::showAllAction; 923 QAction *ConfigView::showPromptAction; 924 925 ConfigView::ConfigView(QWidget* parent, const char *name) 926 : Parent(parent) 927 { 928 setObjectName(name); 929 QVBoxLayout *verticalLayout = new QVBoxLayout(this); 930 verticalLayout->setContentsMargins(0, 0, 0, 0); 931 932 list = new ConfigList(this); 933 verticalLayout->addWidget(list); 934 lineEdit = new ConfigLineEdit(this); 935 lineEdit->hide(); 936 verticalLayout->addWidget(lineEdit); 937 938 this->nextView = viewList; 939 viewList = this; 940 } 941 942 ConfigView::~ConfigView(void) 943 { 944 ConfigView** vp; 945 946 for (vp = &viewList; *vp; vp = &(*vp)->nextView) { 947 if (*vp == this) { 948 *vp = nextView; 949 break; 950 } 951 } 952 } 953 954 void ConfigView::setOptionMode(QAction *act) 955 { 956 if (act == showNormalAction) 957 list->optMode = normalOpt; 958 else if (act == showAllAction) 959 list->optMode = allOpt; 960 else 961 list->optMode = promptOpt; 962 963 list->updateListAll(); 964 } 965 966 void ConfigView::setShowName(bool b) 967 { 968 if (list->showName != b) { 969 list->showName = b; 970 list->reinit(); 971 emit showNameChanged(b); 972 } 973 } 974 975 void ConfigView::setShowRange(bool b) 976 { 977 if (list->showRange != b) { 978 list->showRange = b; 979 list->reinit(); 980 emit showRangeChanged(b); 981 } 982 } 983 984 void ConfigView::setShowData(bool b) 985 { 986 if (list->showData != b) { 987 list->showData = b; 988 list->reinit(); 989 emit showDataChanged(b); 990 } 991 } 992 993 void ConfigList::setAllOpen(bool open) 994 { 995 QTreeWidgetItemIterator it(this); 996 997 while (*it) { 998 (*it)->setExpanded(open); 999 1000 ++it; 1001 } 1002 } 1003 1004 void ConfigView::updateList(ConfigItem* item) 1005 { 1006 ConfigView* v; 1007 1008 for (v = viewList; v; v = v->nextView) 1009 v->list->updateList(item); 1010 } 1011 1012 void ConfigView::updateListAll(void) 1013 { 1014 ConfigView* v; 1015 1016 for (v = viewList; v; v = v->nextView) 1017 v->list->updateListAll(); 1018 } 1019 1020 ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name) 1021 : Parent(parent), sym(0), _menu(0) 1022 { 1023 setObjectName(name); 1024 1025 1026 if (!objectName().isEmpty()) { 1027 configSettings->beginGroup(objectName()); 1028 setShowDebug(configSettings->value("/showDebug", false).toBool()); 1029 configSettings->endGroup(); 1030 connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings())); 1031 } 1032 } 1033 1034 void ConfigInfoView::saveSettings(void) 1035 { 1036 if (!objectName().isEmpty()) { 1037 configSettings->beginGroup(objectName()); 1038 configSettings->setValue("/showDebug", showDebug()); 1039 configSettings->endGroup(); 1040 } 1041 } 1042 1043 void ConfigInfoView::setShowDebug(bool b) 1044 { 1045 if (_showDebug != b) { 1046 _showDebug = b; 1047 if (_menu) 1048 menuInfo(); 1049 else if (sym) 1050 symbolInfo(); 1051 emit showDebugChanged(b); 1052 } 1053 } 1054 1055 void ConfigInfoView::setInfo(struct menu *m) 1056 { 1057 if (_menu == m) 1058 return; 1059 _menu = m; 1060 sym = NULL; 1061 if (!_menu) 1062 clear(); 1063 else 1064 menuInfo(); 1065 } 1066 1067 void ConfigInfoView::symbolInfo(void) 1068 { 1069 QString str; 1070 1071 str += "<big>Symbol: <b>"; 1072 str += print_filter(sym->name); 1073 str += "</b></big><br><br>value: "; 1074 str += print_filter(sym_get_string_value(sym)); 1075 str += "<br>visibility: "; 1076 str += sym->visible == yes ? "y" : sym->visible == mod ? "m" : "n"; 1077 str += "<br>"; 1078 str += debug_info(sym); 1079 1080 setText(str); 1081 } 1082 1083 void ConfigInfoView::menuInfo(void) 1084 { 1085 struct symbol* sym; 1086 QString head, debug, help; 1087 1088 sym = _menu->sym; 1089 if (sym) { 1090 if (_menu->prompt) { 1091 head += "<big><b>"; 1092 head += print_filter(_menu->prompt->text); 1093 head += "</b></big>"; 1094 if (sym->name) { 1095 head += " ("; 1096 if (showDebug()) 1097 head += QString().sprintf("<a href=\"s%p\">", sym); 1098 head += print_filter(sym->name); 1099 if (showDebug()) 1100 head += "</a>"; 1101 head += ")"; 1102 } 1103 } else if (sym->name) { 1104 head += "<big><b>"; 1105 if (showDebug()) 1106 head += QString().sprintf("<a href=\"s%p\">", sym); 1107 head += print_filter(sym->name); 1108 if (showDebug()) 1109 head += "</a>"; 1110 head += "</b></big>"; 1111 } 1112 head += "<br><br>"; 1113 1114 if (showDebug()) 1115 debug = debug_info(sym); 1116 1117 struct gstr help_gstr = str_new(); 1118 menu_get_ext_help(_menu, &help_gstr); 1119 help = print_filter(str_get(&help_gstr)); 1120 str_free(&help_gstr); 1121 } else if (_menu->prompt) { 1122 head += "<big><b>"; 1123 head += print_filter(_menu->prompt->text); 1124 head += "</b></big><br><br>"; 1125 if (showDebug()) { 1126 if (_menu->prompt->visible.expr) { 1127 debug += " dep: "; 1128 expr_print(_menu->prompt->visible.expr, expr_print_help, &debug, E_NONE); 1129 debug += "<br><br>"; 1130 } 1131 } 1132 } 1133 if (showDebug()) 1134 debug += QString().sprintf("defined at %s:%d<br><br>", _menu->file->name, _menu->lineno); 1135 1136 setText(head + debug + help); 1137 } 1138 1139 QString ConfigInfoView::debug_info(struct symbol *sym) 1140 { 1141 QString debug; 1142 1143 debug += "type: "; 1144 debug += print_filter(sym_type_name(sym->type)); 1145 if (sym_is_choice(sym)) 1146 debug += " (choice)"; 1147 debug += "<br>"; 1148 if (sym->rev_dep.expr) { 1149 debug += "reverse dep: "; 1150 expr_print(sym->rev_dep.expr, expr_print_help, &debug, E_NONE); 1151 debug += "<br>"; 1152 } 1153 for (struct property *prop = sym->prop; prop; prop = prop->next) { 1154 switch (prop->type) { 1155 case P_PROMPT: 1156 case P_MENU: 1157 debug += QString().sprintf("prompt: <a href=\"m%p\">", prop->menu); 1158 debug += print_filter(prop->text); 1159 debug += "</a><br>"; 1160 break; 1161 case P_DEFAULT: 1162 case P_SELECT: 1163 case P_RANGE: 1164 debug += prop_get_type_name(prop->type); 1165 debug += ": "; 1166 expr_print(prop->expr, expr_print_help, &debug, E_NONE); 1167 debug += "<br>"; 1168 break; 1169 case P_CHOICE: 1170 if (sym_is_choice(sym)) { 1171 debug += "choice: "; 1172 expr_print(prop->expr, expr_print_help, &debug, E_NONE); 1173 debug += "<br>"; 1174 } 1175 break; 1176 default: 1177 debug += "unknown property: "; 1178 debug += prop_get_type_name(prop->type); 1179 debug += "<br>"; 1180 } 1181 if (prop->visible.expr) { 1182 debug += " dep: "; 1183 expr_print(prop->visible.expr, expr_print_help, &debug, E_NONE); 1184 debug += "<br>"; 1185 } 1186 } 1187 debug += "<br>"; 1188 1189 return debug; 1190 } 1191 1192 QString ConfigInfoView::print_filter(const QString &str) 1193 { 1194 QRegExp re("[<>&\"\\n]"); 1195 QString res = str; 1196 for (int i = 0; (i = res.indexOf(re, i)) >= 0;) { 1197 switch (res[i].toLatin1()) { 1198 case '<': 1199 res.replace(i, 1, "<"); 1200 i += 4; 1201 break; 1202 case '>': 1203 res.replace(i, 1, ">"); 1204 i += 4; 1205 break; 1206 case '&': 1207 res.replace(i, 1, "&"); 1208 i += 5; 1209 break; 1210 case '"': 1211 res.replace(i, 1, """); 1212 i += 6; 1213 break; 1214 case '\n': 1215 res.replace(i, 1, "<br>"); 1216 i += 4; 1217 break; 1218 } 1219 } 1220 return res; 1221 } 1222 1223 void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char *str) 1224 { 1225 QString* text = reinterpret_cast<QString*>(data); 1226 QString str2 = print_filter(str); 1227 1228 if (sym && sym->name && !(sym->flags & SYMBOL_CONST)) { 1229 *text += QString().sprintf("<a href=\"s%p\">", sym); 1230 *text += str2; 1231 *text += "</a>"; 1232 } else 1233 *text += str2; 1234 } 1235 1236 QMenu* ConfigInfoView::createStandardContextMenu(const QPoint & pos) 1237 { 1238 QMenu* popup = Parent::createStandardContextMenu(pos); 1239 QAction* action = new QAction("Show Debug Info", popup); 1240 1241 action->setCheckable(true); 1242 connect(action, SIGNAL(toggled(bool)), SLOT(setShowDebug(bool))); 1243 connect(this, SIGNAL(showDebugChanged(bool)), action, SLOT(setOn(bool))); 1244 action->setChecked(showDebug()); 1245 popup->addSeparator(); 1246 popup->addAction(action); 1247 return popup; 1248 } 1249 1250 void ConfigInfoView::contextMenuEvent(QContextMenuEvent *e) 1251 { 1252 Parent::contextMenuEvent(e); 1253 } 1254 1255 ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow* parent, const char *name) 1256 : Parent(parent), result(NULL) 1257 { 1258 setObjectName(name); 1259 setWindowTitle("Search Config"); 1260 1261 QVBoxLayout* layout1 = new QVBoxLayout(this); 1262 layout1->setContentsMargins(11, 11, 11, 11); 1263 layout1->setSpacing(6); 1264 QHBoxLayout* layout2 = new QHBoxLayout(0); 1265 layout2->setContentsMargins(0, 0, 0, 0); 1266 layout2->setSpacing(6); 1267 layout2->addWidget(new QLabel("Find:", this)); 1268 editField = new QLineEdit(this); 1269 connect(editField, SIGNAL(returnPressed()), SLOT(search())); 1270 layout2->addWidget(editField); 1271 searchButton = new QPushButton("Search", this); 1272 searchButton->setAutoDefault(false); 1273 connect(searchButton, SIGNAL(clicked()), SLOT(search())); 1274 layout2->addWidget(searchButton); 1275 layout1->addLayout(layout2); 1276 1277 split = new QSplitter(this); 1278 split->setOrientation(Qt::Vertical); 1279 list = new ConfigView(split, name); 1280 list->list->mode = listMode; 1281 info = new ConfigInfoView(split, name); 1282 connect(list->list, SIGNAL(menuChanged(struct menu *)), 1283 info, SLOT(setInfo(struct menu *))); 1284 connect(list->list, SIGNAL(menuChanged(struct menu *)), 1285 parent, SLOT(setMenuLink(struct menu *))); 1286 1287 layout1->addWidget(split); 1288 1289 if (name) { 1290 QVariant x, y; 1291 int width, height; 1292 bool ok; 1293 1294 configSettings->beginGroup(name); 1295 width = configSettings->value("/window width", parent->width() / 2).toInt(); 1296 height = configSettings->value("/window height", parent->height() / 2).toInt(); 1297 resize(width, height); 1298 x = configSettings->value("/window x"); 1299 y = configSettings->value("/window y"); 1300 if ((x.isValid())&&(y.isValid())) 1301 move(x.toInt(), y.toInt()); 1302 QList<int> sizes = configSettings->readSizes("/split", &ok); 1303 if (ok) 1304 split->setSizes(sizes); 1305 configSettings->endGroup(); 1306 connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings())); 1307 } 1308 } 1309 1310 void ConfigSearchWindow::saveSettings(void) 1311 { 1312 if (!objectName().isEmpty()) { 1313 configSettings->beginGroup(objectName()); 1314 configSettings->setValue("/window x", pos().x()); 1315 configSettings->setValue("/window y", pos().y()); 1316 configSettings->setValue("/window width", size().width()); 1317 configSettings->setValue("/window height", size().height()); 1318 configSettings->writeSizes("/split", split->sizes()); 1319 configSettings->endGroup(); 1320 } 1321 } 1322 1323 void ConfigSearchWindow::search(void) 1324 { 1325 struct symbol **p; 1326 struct property *prop; 1327 ConfigItem *lastItem = NULL; 1328 1329 free(result); 1330 list->list->clear(); 1331 info->clear(); 1332 1333 result = sym_re_search(editField->text().toLatin1()); 1334 if (!result) 1335 return; 1336 for (p = result; *p; p++) { 1337 for_all_prompts((*p), prop) 1338 lastItem = new ConfigItem(list->list, lastItem, prop->menu, 1339 menu_is_visible(prop->menu)); 1340 } 1341 } 1342 1343 /* 1344 * Construct the complete config widget 1345 */ 1346 ConfigMainWindow::ConfigMainWindow(void) 1347 : searchWindow(0) 1348 { 1349 QMenuBar* menu; 1350 bool ok = true; 1351 QVariant x, y; 1352 int width, height; 1353 char title[256]; 1354 1355 QDesktopWidget *d = configApp->desktop(); 1356 snprintf(title, sizeof(title), "%s%s", 1357 rootmenu.prompt->text, 1358 "" 1359 ); 1360 setWindowTitle(title); 1361 1362 width = configSettings->value("/window width", d->width() - 64).toInt(); 1363 height = configSettings->value("/window height", d->height() - 64).toInt(); 1364 resize(width, height); 1365 x = configSettings->value("/window x"); 1366 y = configSettings->value("/window y"); 1367 if ((x.isValid())&&(y.isValid())) 1368 move(x.toInt(), y.toInt()); 1369 1370 QWidget *widget = new QWidget(this); 1371 QVBoxLayout *layout = new QVBoxLayout(widget); 1372 setCentralWidget(widget); 1373 1374 split1 = new QSplitter(widget); 1375 split1->setOrientation(Qt::Horizontal); 1376 split1->setChildrenCollapsible(false); 1377 1378 menuView = new ConfigView(widget, "menu"); 1379 menuList = menuView->list; 1380 1381 split2 = new QSplitter(widget); 1382 split2->setChildrenCollapsible(false); 1383 split2->setOrientation(Qt::Vertical); 1384 1385 // create config tree 1386 configView = new ConfigView(widget, "config"); 1387 configList = configView->list; 1388 1389 helpText = new ConfigInfoView(widget, "help"); 1390 1391 layout->addWidget(split2); 1392 split2->addWidget(split1); 1393 split1->addWidget(configView); 1394 split1->addWidget(menuView); 1395 split2->addWidget(helpText); 1396 1397 setTabOrder(configList, helpText); 1398 configList->setFocus(); 1399 1400 menu = menuBar(); 1401 toolBar = new QToolBar("Tools", this); 1402 addToolBar(toolBar); 1403 1404 backAction = new QAction(QPixmap(xpm_back), "Back", this); 1405 connect(backAction, SIGNAL(triggered(bool)), SLOT(goBack())); 1406 backAction->setEnabled(false); 1407 QAction *quitAction = new QAction("&Quit", this); 1408 quitAction->setShortcut(Qt::CTRL + Qt::Key_Q); 1409 connect(quitAction, SIGNAL(triggered(bool)), SLOT(close())); 1410 QAction *loadAction = new QAction(QPixmap(xpm_load), "&Load", this); 1411 loadAction->setShortcut(Qt::CTRL + Qt::Key_L); 1412 connect(loadAction, SIGNAL(triggered(bool)), SLOT(loadConfig())); 1413 saveAction = new QAction(QPixmap(xpm_save), "&Save", this); 1414 saveAction->setShortcut(Qt::CTRL + Qt::Key_S); 1415 connect(saveAction, SIGNAL(triggered(bool)), SLOT(saveConfig())); 1416 conf_set_changed_callback(conf_changed); 1417 // Set saveAction's initial state 1418 conf_changed(); 1419 configname = xstrdup(conf_get_configname()); 1420 1421 QAction *saveAsAction = new QAction("Save &As...", this); 1422 connect(saveAsAction, SIGNAL(triggered(bool)), SLOT(saveConfigAs())); 1423 QAction *searchAction = new QAction("&Find", this); 1424 searchAction->setShortcut(Qt::CTRL + Qt::Key_F); 1425 connect(searchAction, SIGNAL(triggered(bool)), SLOT(searchConfig())); 1426 singleViewAction = new QAction(QPixmap(xpm_single_view), "Single View", this); 1427 singleViewAction->setCheckable(true); 1428 connect(singleViewAction, SIGNAL(triggered(bool)), SLOT(showSingleView())); 1429 splitViewAction = new QAction(QPixmap(xpm_split_view), "Split View", this); 1430 splitViewAction->setCheckable(true); 1431 connect(splitViewAction, SIGNAL(triggered(bool)), SLOT(showSplitView())); 1432 fullViewAction = new QAction(QPixmap(xpm_tree_view), "Full View", this); 1433 fullViewAction->setCheckable(true); 1434 connect(fullViewAction, SIGNAL(triggered(bool)), SLOT(showFullView())); 1435 1436 QAction *showNameAction = new QAction("Show Name", this); 1437 showNameAction->setCheckable(true); 1438 connect(showNameAction, SIGNAL(toggled(bool)), configView, SLOT(setShowName(bool))); 1439 showNameAction->setChecked(configView->showName()); 1440 QAction *showRangeAction = new QAction("Show Range", this); 1441 showRangeAction->setCheckable(true); 1442 connect(showRangeAction, SIGNAL(toggled(bool)), configView, SLOT(setShowRange(bool))); 1443 QAction *showDataAction = new QAction("Show Data", this); 1444 showDataAction->setCheckable(true); 1445 connect(showDataAction, SIGNAL(toggled(bool)), configView, SLOT(setShowData(bool))); 1446 1447 QActionGroup *optGroup = new QActionGroup(this); 1448 optGroup->setExclusive(true); 1449 connect(optGroup, SIGNAL(triggered(QAction*)), configView, 1450 SLOT(setOptionMode(QAction *))); 1451 connect(optGroup, SIGNAL(triggered(QAction *)), menuView, 1452 SLOT(setOptionMode(QAction *))); 1453 1454 configView->showNormalAction = new QAction("Show Normal Options", optGroup); 1455 configView->showAllAction = new QAction("Show All Options", optGroup); 1456 configView->showPromptAction = new QAction("Show Prompt Options", optGroup); 1457 configView->showNormalAction->setCheckable(true); 1458 configView->showAllAction->setCheckable(true); 1459 configView->showPromptAction->setCheckable(true); 1460 1461 QAction *showDebugAction = new QAction("Show Debug Info", this); 1462 showDebugAction->setCheckable(true); 1463 connect(showDebugAction, SIGNAL(toggled(bool)), helpText, SLOT(setShowDebug(bool))); 1464 showDebugAction->setChecked(helpText->showDebug()); 1465 1466 QAction *showIntroAction = new QAction("Introduction", this); 1467 connect(showIntroAction, SIGNAL(triggered(bool)), SLOT(showIntro())); 1468 QAction *showAboutAction = new QAction("About", this); 1469 connect(showAboutAction, SIGNAL(triggered(bool)), SLOT(showAbout())); 1470 1471 // init tool bar 1472 toolBar->addAction(backAction); 1473 toolBar->addSeparator(); 1474 toolBar->addAction(loadAction); 1475 toolBar->addAction(saveAction); 1476 toolBar->addSeparator(); 1477 toolBar->addAction(singleViewAction); 1478 toolBar->addAction(splitViewAction); 1479 toolBar->addAction(fullViewAction); 1480 1481 // create config menu 1482 QMenu* config = menu->addMenu("&File"); 1483 config->addAction(loadAction); 1484 config->addAction(saveAction); 1485 config->addAction(saveAsAction); 1486 config->addSeparator(); 1487 config->addAction(quitAction); 1488 1489 // create edit menu 1490 QMenu* editMenu = menu->addMenu("&Edit"); 1491 editMenu->addAction(searchAction); 1492 1493 // create options menu 1494 QMenu* optionMenu = menu->addMenu("&Option"); 1495 optionMenu->addAction(showNameAction); 1496 optionMenu->addAction(showRangeAction); 1497 optionMenu->addAction(showDataAction); 1498 optionMenu->addSeparator(); 1499 optionMenu->addActions(optGroup->actions()); 1500 optionMenu->addSeparator(); 1501 optionMenu->addAction(showDebugAction); 1502 1503 // create help menu 1504 menu->addSeparator(); 1505 QMenu* helpMenu = menu->addMenu("&Help"); 1506 helpMenu->addAction(showIntroAction); 1507 helpMenu->addAction(showAboutAction); 1508 1509 connect(configList, SIGNAL(menuChanged(struct menu *)), 1510 helpText, SLOT(setInfo(struct menu *))); 1511 connect(configList, SIGNAL(menuSelected(struct menu *)), 1512 SLOT(changeMenu(struct menu *))); 1513 connect(configList, SIGNAL(itemSelected(struct menu *)), 1514 SLOT(changeItens(struct menu *))); 1515 connect(configList, SIGNAL(parentSelected()), 1516 SLOT(goBack())); 1517 connect(menuList, SIGNAL(menuChanged(struct menu *)), 1518 helpText, SLOT(setInfo(struct menu *))); 1519 connect(menuList, SIGNAL(menuSelected(struct menu *)), 1520 SLOT(changeMenu(struct menu *))); 1521 1522 connect(configList, SIGNAL(gotFocus(struct menu *)), 1523 helpText, SLOT(setInfo(struct menu *))); 1524 connect(menuList, SIGNAL(gotFocus(struct menu *)), 1525 helpText, SLOT(setInfo(struct menu *))); 1526 connect(menuList, SIGNAL(gotFocus(struct menu *)), 1527 SLOT(listFocusChanged(void))); 1528 connect(helpText, SIGNAL(menuSelected(struct menu *)), 1529 SLOT(setMenuLink(struct menu *))); 1530 1531 QString listMode = configSettings->value("/listMode", "symbol").toString(); 1532 if (listMode == "single") 1533 showSingleView(); 1534 else if (listMode == "full") 1535 showFullView(); 1536 else /*if (listMode == "split")*/ 1537 showSplitView(); 1538 1539 // UI setup done, restore splitter positions 1540 QList<int> sizes = configSettings->readSizes("/split1", &ok); 1541 if (ok) 1542 split1->setSizes(sizes); 1543 1544 sizes = configSettings->readSizes("/split2", &ok); 1545 if (ok) 1546 split2->setSizes(sizes); 1547 } 1548 1549 void ConfigMainWindow::loadConfig(void) 1550 { 1551 QString str; 1552 QByteArray ba; 1553 const char *name; 1554 1555 str = QFileDialog::getOpenFileName(this, "", configname); 1556 if (str.isNull()) 1557 return; 1558 1559 ba = str.toLocal8Bit(); 1560 name = ba.data(); 1561 1562 if (conf_read(name)) 1563 QMessageBox::information(this, "qconf", "Unable to load configuration!"); 1564 1565 free(configname); 1566 configname = xstrdup(name); 1567 1568 ConfigView::updateListAll(); 1569 } 1570 1571 bool ConfigMainWindow::saveConfig(void) 1572 { 1573 if (conf_write(configname)) { 1574 QMessageBox::information(this, "qconf", "Unable to save configuration!"); 1575 return false; 1576 } 1577 conf_write_autoconf(0); 1578 1579 return true; 1580 } 1581 1582 void ConfigMainWindow::saveConfigAs(void) 1583 { 1584 QString str; 1585 QByteArray ba; 1586 const char *name; 1587 1588 str = QFileDialog::getSaveFileName(this, "", configname); 1589 if (str.isNull()) 1590 return; 1591 1592 ba = str.toLocal8Bit(); 1593 name = ba.data(); 1594 1595 if (conf_write(name)) { 1596 QMessageBox::information(this, "qconf", "Unable to save configuration!"); 1597 } 1598 conf_write_autoconf(0); 1599 1600 free(configname); 1601 configname = xstrdup(name); 1602 } 1603 1604 void ConfigMainWindow::searchConfig(void) 1605 { 1606 if (!searchWindow) 1607 searchWindow = new ConfigSearchWindow(this, "search"); 1608 searchWindow->show(); 1609 } 1610 1611 void ConfigMainWindow::changeItens(struct menu *menu) 1612 { 1613 configList->setRootMenu(menu); 1614 1615 if (configList->rootEntry->parent == &rootmenu) 1616 backAction->setEnabled(false); 1617 else 1618 backAction->setEnabled(true); 1619 } 1620 1621 void ConfigMainWindow::changeMenu(struct menu *menu) 1622 { 1623 menuList->setRootMenu(menu); 1624 1625 if (menuList->rootEntry->parent == &rootmenu) 1626 backAction->setEnabled(false); 1627 else 1628 backAction->setEnabled(true); 1629 } 1630 1631 void ConfigMainWindow::setMenuLink(struct menu *menu) 1632 { 1633 struct menu *parent; 1634 ConfigList* list = NULL; 1635 ConfigItem* item; 1636 1637 if (configList->menuSkip(menu)) 1638 return; 1639 1640 switch (configList->mode) { 1641 case singleMode: 1642 list = configList; 1643 parent = menu_get_parent_menu(menu); 1644 if (!parent) 1645 return; 1646 list->setRootMenu(parent); 1647 break; 1648 case symbolMode: 1649 if (menu->flags & MENU_ROOT) { 1650 configList->setRootMenu(menu); 1651 configList->clearSelection(); 1652 list = menuList; 1653 } else { 1654 list = configList; 1655 parent = menu_get_parent_menu(menu->parent); 1656 if (!parent) 1657 return; 1658 item = menuList->findConfigItem(parent); 1659 if (item) { 1660 item->setSelected(true); 1661 menuList->scrollToItem(item); 1662 } 1663 list->setRootMenu(parent); 1664 } 1665 break; 1666 case fullMode: 1667 list = configList; 1668 break; 1669 default: 1670 break; 1671 } 1672 1673 if (list) { 1674 item = list->findConfigItem(menu); 1675 if (item) { 1676 item->setSelected(true); 1677 list->scrollToItem(item); 1678 list->setFocus(); 1679 } 1680 } 1681 } 1682 1683 void ConfigMainWindow::listFocusChanged(void) 1684 { 1685 if (menuList->mode == menuMode) 1686 configList->clearSelection(); 1687 } 1688 1689 void ConfigMainWindow::goBack(void) 1690 { 1691 ConfigItem* item, *oldSelection; 1692 1693 configList->setParentMenu(); 1694 if (configList->rootEntry == &rootmenu) 1695 backAction->setEnabled(false); 1696 1697 if (menuList->selectedItems().count() == 0) 1698 return; 1699 1700 item = (ConfigItem*)menuList->selectedItems().first(); 1701 oldSelection = item; 1702 while (item) { 1703 if (item->menu == configList->rootEntry) { 1704 oldSelection->setSelected(false); 1705 item->setSelected(true); 1706 break; 1707 } 1708 item = (ConfigItem*)item->parent(); 1709 } 1710 } 1711 1712 void ConfigMainWindow::showSingleView(void) 1713 { 1714 singleViewAction->setEnabled(false); 1715 singleViewAction->setChecked(true); 1716 splitViewAction->setEnabled(true); 1717 splitViewAction->setChecked(false); 1718 fullViewAction->setEnabled(true); 1719 fullViewAction->setChecked(false); 1720 1721 menuView->hide(); 1722 menuList->setRootMenu(0); 1723 configList->mode = singleMode; 1724 if (configList->rootEntry == &rootmenu) 1725 configList->updateListAll(); 1726 else 1727 configList->setRootMenu(&rootmenu); 1728 configList->setFocus(); 1729 } 1730 1731 void ConfigMainWindow::showSplitView(void) 1732 { 1733 singleViewAction->setEnabled(true); 1734 singleViewAction->setChecked(false); 1735 splitViewAction->setEnabled(false); 1736 splitViewAction->setChecked(true); 1737 fullViewAction->setEnabled(true); 1738 fullViewAction->setChecked(false); 1739 1740 configList->mode = menuMode; 1741 if (configList->rootEntry == &rootmenu) 1742 configList->updateListAll(); 1743 else 1744 configList->setRootMenu(&rootmenu); 1745 configList->setAllOpen(true); 1746 configApp->processEvents(); 1747 menuList->mode = symbolMode; 1748 menuList->setRootMenu(&rootmenu); 1749 menuList->setAllOpen(true); 1750 menuView->show(); 1751 menuList->setFocus(); 1752 } 1753 1754 void ConfigMainWindow::showFullView(void) 1755 { 1756 singleViewAction->setEnabled(true); 1757 singleViewAction->setChecked(false); 1758 splitViewAction->setEnabled(true); 1759 splitViewAction->setChecked(false); 1760 fullViewAction->setEnabled(false); 1761 fullViewAction->setChecked(true); 1762 1763 menuView->hide(); 1764 menuList->setRootMenu(0); 1765 configList->mode = fullMode; 1766 if (configList->rootEntry == &rootmenu) 1767 configList->updateListAll(); 1768 else 1769 configList->setRootMenu(&rootmenu); 1770 configList->setFocus(); 1771 } 1772 1773 /* 1774 * ask for saving configuration before quitting 1775 */ 1776 void ConfigMainWindow::closeEvent(QCloseEvent* e) 1777 { 1778 if (!conf_get_changed()) { 1779 e->accept(); 1780 return; 1781 } 1782 QMessageBox mb("qconf", "Save configuration?", QMessageBox::Warning, 1783 QMessageBox::Yes | QMessageBox::Default, QMessageBox::No, QMessageBox::Cancel | QMessageBox::Escape); 1784 mb.setButtonText(QMessageBox::Yes, "&Save Changes"); 1785 mb.setButtonText(QMessageBox::No, "&Discard Changes"); 1786 mb.setButtonText(QMessageBox::Cancel, "Cancel Exit"); 1787 switch (mb.exec()) { 1788 case QMessageBox::Yes: 1789 if (saveConfig()) 1790 e->accept(); 1791 else 1792 e->ignore(); 1793 break; 1794 case QMessageBox::No: 1795 e->accept(); 1796 break; 1797 case QMessageBox::Cancel: 1798 e->ignore(); 1799 break; 1800 } 1801 } 1802 1803 void ConfigMainWindow::showIntro(void) 1804 { 1805 static const QString str = "Welcome to the qconf graphical configuration tool.\n\n" 1806 "For each option, a blank box indicates the feature is disabled, a check\n" 1807 "indicates it is enabled, and a dot indicates that it is to be compiled\n" 1808 "as a module. Clicking on the box will cycle through the three states.\n\n" 1809 "If you do not see an option (e.g., a device driver) that you believe\n" 1810 "should be present, try turning on Show All Options under the Options menu.\n" 1811 "Although there is no cross reference yet to help you figure out what other\n" 1812 "options must be enabled to support the option you are interested in, you can\n" 1813 "still view the help of a grayed-out option.\n\n" 1814 "Toggling Show Debug Info under the Options menu will show the dependencies,\n" 1815 "which you can then match by examining other options.\n\n"; 1816 1817 QMessageBox::information(this, "qconf", str); 1818 } 1819 1820 void ConfigMainWindow::showAbout(void) 1821 { 1822 static const QString str = "qconf is Copyright (C) 2002 Roman Zippel <zippel@linux-m68k.org>.\n" 1823 "Copyright (C) 2015 Boris Barbulovski <bbarbulovski@gmail.com>.\n\n" 1824 "Bug reports and feature request can also be entered at http://bugzilla.kernel.org/\n"; 1825 1826 QMessageBox::information(this, "qconf", str); 1827 } 1828 1829 void ConfigMainWindow::saveSettings(void) 1830 { 1831 configSettings->setValue("/window x", pos().x()); 1832 configSettings->setValue("/window y", pos().y()); 1833 configSettings->setValue("/window width", size().width()); 1834 configSettings->setValue("/window height", size().height()); 1835 1836 QString entry; 1837 switch(configList->mode) { 1838 case singleMode : 1839 entry = "single"; 1840 break; 1841 1842 case symbolMode : 1843 entry = "split"; 1844 break; 1845 1846 case fullMode : 1847 entry = "full"; 1848 break; 1849 1850 default: 1851 break; 1852 } 1853 configSettings->setValue("/listMode", entry); 1854 1855 configSettings->writeSizes("/split1", split1->sizes()); 1856 configSettings->writeSizes("/split2", split2->sizes()); 1857 } 1858 1859 void ConfigMainWindow::conf_changed(void) 1860 { 1861 if (saveAction) 1862 saveAction->setEnabled(conf_get_changed()); 1863 } 1864 1865 void fixup_rootmenu(struct menu *menu) 1866 { 1867 struct menu *child; 1868 static int menu_cnt = 0; 1869 1870 menu->flags |= MENU_ROOT; 1871 for (child = menu->list; child; child = child->next) { 1872 if (child->prompt && child->prompt->type == P_MENU) { 1873 menu_cnt++; 1874 fixup_rootmenu(child); 1875 menu_cnt--; 1876 } else if (!menu_cnt) 1877 fixup_rootmenu(child); 1878 } 1879 } 1880 1881 static const char *progname; 1882 1883 static void usage(void) 1884 { 1885 printf("%s [-s] <config>\n", progname); 1886 exit(0); 1887 } 1888 1889 int main(int ac, char** av) 1890 { 1891 ConfigMainWindow* v; 1892 const char *name; 1893 1894 progname = av[0]; 1895 configApp = new QApplication(ac, av); 1896 if (ac > 1 && av[1][0] == '-') { 1897 switch (av[1][1]) { 1898 case 's': 1899 conf_set_message_callback(NULL); 1900 break; 1901 case 'h': 1902 case '?': 1903 usage(); 1904 } 1905 name = av[2]; 1906 } else 1907 name = av[1]; 1908 if (!name) 1909 usage(); 1910 1911 conf_parse(name); 1912 fixup_rootmenu(&rootmenu); 1913 conf_read(NULL); 1914 //zconfdump(stdout); 1915 1916 configSettings = new ConfigSettings(); 1917 configSettings->beginGroup("/kconfig/qconf"); 1918 v = new ConfigMainWindow(); 1919 1920 //zconfdump(stdout); 1921 configApp->connect(configApp, SIGNAL(lastWindowClosed()), SLOT(quit())); 1922 configApp->connect(configApp, SIGNAL(aboutToQuit()), v, SLOT(saveSettings())); 1923 v->show(); 1924 configApp->exec(); 1925 1926 configSettings->endGroup(); 1927 delete configSettings; 1928 delete v; 1929 delete configApp; 1930 1931 return 0; 1932 } 1933