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