$search
00001 /* 00002 Aseba - an event-based framework for distributed robot control 00003 Copyright (C) 2007--2012: 00004 Stephane Magnenat <stephane at magnenat dot net> 00005 (http://stephane.magnenat.net) 00006 and other contributors, see authors.txt for details 00007 00008 This program is free software: you can redistribute it and/or modify 00009 it under the terms of the GNU Lesser General Public License as published 00010 by the Free Software Foundation, version 3 of the License. 00011 00012 This program is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU Lesser General Public License for more details. 00016 00017 You should have received a copy of the GNU Lesser General Public License 00018 along with this program. If not, see <http://www.gnu.org/licenses/>. 00019 */ 00020 00021 #include "ConfigDialog.h" 00022 00023 #include <QSettings> 00024 00025 #include <ConfigDialog.moc> 00026 00027 00028 #define BOOL_TO_CHECKED(value) (value == true ? Qt::Checked : Qt::Unchecked) 00029 #define CHECKED_TO_BOOL(value) (value == Qt::Checked ? true : false) 00030 00031 #define CONFIG_PROPERTY_CHECKBOX_HANDLER(name, page, keyword) \ 00032 const bool ConfigDialog::get##name() { \ 00033 if (me) \ 00034 return me->page->checkboxCache[#keyword].value; \ 00035 else \ 00036 return false; \ 00037 } \ 00038 \ 00039 void ConfigDialog::set##name(bool value) { \ 00040 if (me && !me->isVisible()) \ 00041 me->page->checkboxCache[#keyword].value = value; \ 00042 } 00043 00044 00045 #define TITLE_SPACING 10 00046 #define HORIZONTAL_STRUT 700 00047 00048 namespace Aseba 00049 { 00050 CONFIG_PROPERTY_CHECKBOX_HANDLER(ShowLineNumbers, generalpage, showlinenumbers ) 00051 CONFIG_PROPERTY_CHECKBOX_HANDLER(ShowHidden, generalpage, showhidden ) 00052 CONFIG_PROPERTY_CHECKBOX_HANDLER(ShowKeywordToolbar, generalpage, keywordToolbar ) 00053 CONFIG_PROPERTY_CHECKBOX_HANDLER(ShowMemoryUsage, generalpage, memoryusage ) 00054 CONFIG_PROPERTY_CHECKBOX_HANDLER(AutoCompletion, editorpage, autoKeyword ) 00055 00056 /*** ConfigPage ***/ 00057 ConfigPage::ConfigPage(QString title, QWidget *parent): 00058 QWidget(parent) 00059 { 00060 QLabel* myTitle = new QLabel(title); 00061 // bold & align center 00062 myTitle->setAlignment(Qt::AlignCenter); 00063 QFont current = myTitle->font(); 00064 current.setBold(true); 00065 myTitle->setFont(current); 00066 00067 mainLayout = new QVBoxLayout(); 00068 mainLayout->addWidget(myTitle); 00069 mainLayout->addSpacing(TITLE_SPACING); 00070 mainLayout->addStrut(HORIZONTAL_STRUT); 00071 setLayout(mainLayout); 00072 } 00073 00074 QCheckBox* ConfigPage::newCheckbox(QString label, QString ID, bool checked) 00075 { 00076 QCheckBox* widget = new QCheckBox(label); 00077 widget->setCheckState(BOOL_TO_CHECKED(checked)); 00078 WidgetCache<bool> cache(widget, checked); 00079 checkboxCache.insert(std::pair<QString, WidgetCache<bool> >(ID, cache)); 00080 connect(widget, SIGNAL(released()), ConfigDialog::getInstance(), SLOT(flushCache())); 00081 connect(widget, SIGNAL(released()), ConfigDialog::getInstance(), SIGNAL(settingsChanged())); 00082 return widget; 00083 } 00084 00085 void ConfigPage::readSettings() 00086 { 00087 // update cache and widgets from disk 00088 QSettings settings; 00089 // iterate on checkboxes 00090 for (std::map<QString, WidgetCache<bool> >::iterator it = checkboxCache.begin(); it != checkboxCache.end(); it++) 00091 { 00092 QString name = it->first; 00093 QCheckBox* checkbox = dynamic_cast<QCheckBox*>((it->second).widget); 00094 Q_ASSERT(checkbox); 00095 if (settings.contains(name)) 00096 { 00097 bool value = settings.value(name, false).toBool(); 00098 checkbox->setCheckState(BOOL_TO_CHECKED(value)); // update widget 00099 (it->second).value = value; // update cache 00100 } 00101 } 00102 } 00103 00104 void ConfigPage::writeSettings() 00105 { 00106 // write the cache on disk 00107 QSettings settings; 00108 // iterate on checkboxes 00109 for (std::map<QString, WidgetCache<bool> >::iterator it = checkboxCache.begin(); it != checkboxCache.end(); it++) 00110 { 00111 QString name = it->first; 00112 QCheckBox* checkbox = dynamic_cast<QCheckBox*>((it->second).widget); 00113 Q_ASSERT(checkbox); 00114 Q_UNUSED(checkbox); 00115 settings.setValue(name, (it->second).value); 00116 } 00117 } 00118 00119 void ConfigPage::saveState() 00120 { 00121 // create a temporary cache 00122 checkboxCacheSave = checkboxCache; 00123 } 00124 00125 void ConfigPage::flushCache() 00126 { 00127 // sync the cache with the widgets' state 00128 // iterate on checkboxes 00129 for (std::map<QString, WidgetCache<bool> >::iterator it = checkboxCache.begin(); it != checkboxCache.end(); it++) 00130 { 00131 QCheckBox* checkbox = dynamic_cast<QCheckBox*>((it->second).widget); 00132 Q_ASSERT(checkbox); 00133 (it->second).value = CHECKED_TO_BOOL(checkbox->checkState()); 00134 } 00135 } 00136 00137 void ConfigPage::discardChanges() 00138 { 00139 // reload values from the temporary cache 00140 checkboxCache = checkboxCacheSave; 00141 // update widgets accordingly 00142 reloadFromCache(); 00143 } 00144 00145 void ConfigPage::reloadFromCache() 00146 { 00147 // update widgets based on the cache 00148 for (std::map<QString, WidgetCache<bool> >::iterator it = checkboxCache.begin(); it != checkboxCache.end(); it++) 00149 { 00150 QCheckBox* checkbox = dynamic_cast<QCheckBox*>((it->second).widget); 00151 Q_ASSERT(checkbox); 00152 checkbox->setCheckState(BOOL_TO_CHECKED((it->second).value)); 00153 } 00154 } 00155 00156 00157 /*** GeneralPage ***/ 00158 GeneralPage::GeneralPage(QWidget *parent): 00159 ConfigPage(tr("General Setup"), parent) 00160 { 00161 QGroupBox* gb1 = new QGroupBox(tr("Layout")); 00162 QVBoxLayout* gb1layout = new QVBoxLayout(); 00163 gb1->setLayout(gb1layout); 00164 mainLayout->addWidget(gb1); 00165 // Show the keyword toolbar 00166 gb1layout->addWidget(newCheckbox(tr("Show keyword toolbar"), "keywordToolbar", true)); 00167 // Show the memory usage gauge 00168 gb1layout->addWidget(newCheckbox(tr("Show memory usage"), "memoryusage", false)); 00169 // Show hidden variables & functions 00170 gb1layout->addWidget(newCheckbox(tr("Show hidden variables"), "showhidden", false)); 00171 // Show line numbers 00172 gb1layout->addWidget(newCheckbox(tr("Show line numbers"), "showlinenumbers", true)); 00173 00174 mainLayout->addStretch(); 00175 } 00176 00177 void GeneralPage::readSettings() 00178 { 00179 QSettings settings; 00180 settings.beginGroup("general-config"); 00181 ConfigPage::readSettings(); 00182 settings.endGroup(); 00183 } 00184 00185 void GeneralPage::writeSettings() 00186 { 00187 QSettings settings; 00188 settings.beginGroup("general-config"); 00189 ConfigPage::writeSettings(); 00190 settings.endGroup(); 00191 } 00192 00193 00194 /*** EditorPage ***/ 00195 EditorPage::EditorPage(QWidget *parent): 00196 ConfigPage(tr("Editor Setup"), parent) 00197 { 00198 // 00199 QGroupBox* gb1 = new QGroupBox(tr("Autocompletion")); 00200 QVBoxLayout* gb1layout = new QVBoxLayout(); 00201 gb1->setLayout(gb1layout); 00202 mainLayout->addWidget(gb1); 00203 // 00204 gb1layout->addWidget(newCheckbox(tr("Keywords"), "autoKeyword", true)); 00205 00206 mainLayout->addStretch(); 00207 } 00208 00209 void EditorPage::readSettings() 00210 { 00211 QSettings settings; 00212 settings.beginGroup("editor-config"); 00213 ConfigPage::readSettings(); 00214 settings.endGroup(); 00215 } 00216 00217 void EditorPage::writeSettings() 00218 { 00219 QSettings settings; 00220 settings.beginGroup("editor-config"); 00221 ConfigPage::writeSettings(); 00222 settings.endGroup(); 00223 } 00224 00225 00226 /*** ConfigDialog ***/ 00227 void ConfigDialog::init(QWidget* parent) 00228 { 00229 if (!me) 00230 { 00231 me = new ConfigDialog(parent); 00232 me->setupWidgets(); 00233 } 00234 } 00235 00236 void ConfigDialog::bye() 00237 { 00238 if (me) 00239 { 00240 delete me; 00241 me = NULL; 00242 } 00243 } 00244 00245 void ConfigDialog::showConfig() 00246 { 00247 me->setModal(true); 00248 me->reloadFromCache(); 00249 me->saveState(); 00250 me->show(); 00251 00252 } 00253 00254 ConfigDialog* ConfigDialog::me = NULL; 00255 00256 ConfigDialog::ConfigDialog(QWidget* parent): 00257 QDialog(parent) 00258 { 00259 } 00260 00261 ConfigDialog::~ConfigDialog() 00262 { 00263 writeSettings(); 00264 } 00265 00266 void ConfigDialog::setupWidgets() 00267 { 00268 // list of topics 00269 topicList = new QListWidget(); 00270 topicList->setViewMode(QListView::IconMode); 00271 topicList->setIconSize(QSize(64, 64)); 00272 topicList->setMovement(QListView::Static); 00273 topicList->setMaximumWidth(128); 00274 topicList->setGridSize(QSize(100, 100)); 00275 topicList->setMinimumHeight(300); 00276 // add topics 00277 QListWidgetItem* general = new QListWidgetItem(QIcon(":/images/exec.png"), tr("General")); 00278 general->setTextAlignment(Qt::AlignHCenter); 00279 topicList->addItem(general); 00280 QListWidgetItem* editor = new QListWidgetItem(QIcon(":/images/kedit.png"), tr("Editor")); 00281 editor->setTextAlignment(Qt::AlignHCenter); 00282 topicList->addItem(editor); 00283 00284 // create pages 00285 configStack = new QStackedWidget(); 00286 generalpage = new GeneralPage(); 00287 configStack->addWidget(generalpage); 00288 editorpage = new EditorPage(); 00289 configStack->addWidget(editorpage); 00290 00291 connect(topicList, SIGNAL(currentRowChanged(int)), configStack, SLOT(setCurrentIndex(int))); 00292 topicList->setCurrentRow(0); 00293 00294 // buttons 00295 okButton = new QPushButton(tr("Ok")); 00296 cancelButton = new QPushButton(tr("Cancel")); 00297 connect(okButton, SIGNAL(clicked()), SLOT(accept())); 00298 connect(cancelButton, SIGNAL(clicked()), SLOT(reject())); 00299 00300 // main layout 00301 QHBoxLayout* contentLayout = new QHBoxLayout(); 00302 contentLayout->addWidget(topicList); 00303 contentLayout->addWidget(configStack); 00304 00305 QHBoxLayout* buttonLayout = new QHBoxLayout(); 00306 buttonLayout->addStretch(); 00307 buttonLayout->addWidget(okButton); 00308 buttonLayout->addWidget(cancelButton); 00309 00310 QVBoxLayout* mainLayout = new QVBoxLayout(); 00311 mainLayout->addLayout(contentLayout); 00312 mainLayout->addLayout(buttonLayout); 00313 00314 setLayout(mainLayout); 00315 setWindowTitle(tr("Aseba Studio - Settings")); 00316 00317 readSettings(); 00318 } 00319 00320 void ConfigDialog::saveState() 00321 { 00322 // save the state of pages, prior to editing 00323 for (int i = 0; i < configStack->count(); i++) 00324 { 00325 ConfigPage* config = dynamic_cast<ConfigPage*>(configStack->widget(i)); 00326 if (config) 00327 config->saveState(); 00328 } 00329 } 00330 00331 void ConfigDialog::reloadFromCache() 00332 { 00333 // reload values from the cache 00334 for (int i = 0; i < configStack->count(); i++) 00335 { 00336 ConfigPage* config = dynamic_cast<ConfigPage*>(configStack->widget(i)); 00337 if (config) 00338 config->reloadFromCache(); 00339 } 00340 } 00341 00342 void ConfigDialog::accept() 00343 { 00344 // update the cache with new values 00345 flushCache(); 00346 QDialog::accept(); 00347 } 00348 00349 void ConfigDialog::reject() 00350 { 00351 // discard the cache and reload widgets with old values 00352 for (int i = 0; i < configStack->count(); i++) 00353 { 00354 ConfigPage* config = dynamic_cast<ConfigPage*>(configStack->widget(i)); 00355 if (config) 00356 config->discardChanges(); 00357 } 00358 // GUI should adopt changes 00359 emit settingsChanged(); 00360 QDialog::reject(); 00361 } 00362 00363 void ConfigDialog::flushCache() 00364 { 00365 // update the cache with new values 00366 for (int i = 0; i < configStack->count(); i++) 00367 { 00368 ConfigPage* config = dynamic_cast<ConfigPage*>(configStack->widget(i)); 00369 if (config) 00370 config->flushCache(); 00371 } 00372 } 00373 00374 void ConfigDialog::readSettings() 00375 { 00376 for (int i = 0; i < configStack->count(); i++) 00377 { 00378 ConfigPage* config = dynamic_cast<ConfigPage*>(configStack->widget(i)); 00379 if (config) 00380 config->readSettings(); 00381 } 00382 } 00383 00384 void ConfigDialog::writeSettings() 00385 { 00386 for (int i = 0; i < configStack->count(); i++) 00387 { 00388 ConfigPage* config = dynamic_cast<ConfigPage*>(configStack->widget(i)); 00389 if (config) 00390 config->writeSettings(); 00391 } 00392 } 00393 00394 } 00395