root/scripts/kconfig/qconf.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. qgettext
  2. readSizes
  3. writeSizes
  4. okRename
  5. updateMenu
  6. testUpdateMenu
  7. init
  8. show
  9. keyPressEvent
  10. headerPopup
  11. menuSkip
  12. reinit
  13. saveSettings
  14. findConfigItem
  15. updateSelection
  16. updateList
  17. setValue
  18. changeValue
  19. setRootMenu
  20. setParentMenu
  21. updateMenuList
  22. updateMenuList
  23. keyPressEvent
  24. mousePressEvent
  25. mouseReleaseEvent
  26. mouseMoveEvent
  27. mouseDoubleClickEvent
  28. focusInEvent
  29. contextMenuEvent
  30. setOptionMode
  31. setShowName
  32. setShowRange
  33. setShowData
  34. setAllOpen
  35. updateList
  36. updateListAll
  37. _menu
  38. saveSettings
  39. setShowDebug
  40. setInfo
  41. symbolInfo
  42. menuInfo
  43. debug_info
  44. print_filter
  45. expr_print_help
  46. createStandardContextMenu
  47. contextMenuEvent
  48. result
  49. saveSettings
  50. search
  51. loadConfig
  52. saveConfig
  53. saveConfigAs
  54. searchConfig
  55. changeMenu
  56. setMenuLink
  57. listFocusChanged
  58. goBack
  59. showSingleView
  60. showSplitView
  61. showFullView
  62. closeEvent
  63. showIntro
  64. showAbout
  65. saveSettings
  66. conf_changed
  67. fixup_rootmenu
  68. usage
  69. main

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

/* [<][>][^][v][top][bottom][index][help] */