Warning, file /plasma/khotkeys/kcm_hotkeys/conditions/conditions_widget.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /* SPDX-FileCopyrightText: 2009 Michael Jansen <kde@michael-jansen.biz>
0002 
0003    SPDX-License-Identifier: LGPL-2.0-or-later
0004 */
0005 
0006 #include "conditions/conditions_widget.h"
0007 #include "conditions/active_window_condition.h"
0008 #include "conditions/condition.h"
0009 #include "conditions/conditions.h"
0010 #include "conditions/conditions_list.h"
0011 #include "conditions/conditions_list_base.h"
0012 #include "conditions/conditions_visitor.h"
0013 #include "conditions/existing_window_condition.h"
0014 
0015 #include "windows_helper/window_selection_list.h"
0016 
0017 #include "helper_widgets/window_definition_list_widget.h"
0018 
0019 #include "condition_type_menu.h"
0020 
0021 #include <QStack>
0022 
0023 #include <QDebug>
0024 
0025 class BuildTree : public KHotKeys::ConditionsVisitor
0026 {
0027 public:
0028     BuildTree(QTreeWidget *tree);
0029 
0030     void build();
0031 
0032     void visitConditionsListBase(KHotKeys::Condition_list_base *list) override;
0033     void visitConditionsList(KHotKeys::Condition_list *list) override;
0034     void visitCondition(KHotKeys::Condition *condition) override;
0035 
0036     QMap<QTreeWidgetItem *, KHotKeys::Condition *> _items;
0037 
0038 private:
0039     QTreeWidget *_tree;
0040     QStack<QTreeWidgetItem *> _stack;
0041 };
0042 
0043 BuildTree::BuildTree(QTreeWidget *tree)
0044     : _tree(tree)
0045 {
0046     _stack.push(_tree->invisibleRootItem());
0047 }
0048 
0049 void BuildTree::visitCondition(KHotKeys::Condition *cond)
0050 {
0051     QTreeWidgetItem *item = new QTreeWidgetItem(_stack.top());
0052     item->setText(0, cond->description());
0053     _items.insert(item, cond);
0054 }
0055 
0056 void BuildTree::visitConditionsList(KHotKeys::Condition_list *list)
0057 {
0058     Q_ASSERT(_stack.count() == 1);
0059 
0060     QTreeWidgetItem *parent = _stack.top();
0061 
0062     QTreeWidgetItem *item = new QTreeWidgetItem(parent);
0063     item->setText(0, i18nc("Add a new condition", "And"));
0064     _items.insert(item, list);
0065     _stack.push(item);
0066 
0067     for (KHotKeys::Condition_list_base::Iterator it = list->begin(); it != list->end(); ++it) {
0068         (*it)->visit(this);
0069     }
0070 
0071     _tree->expandAll();
0072 }
0073 
0074 void BuildTree::visitConditionsListBase(KHotKeys::Condition_list_base *list)
0075 {
0076     QTreeWidgetItem *parent = _stack.top();
0077 
0078     QTreeWidgetItem *item = new QTreeWidgetItem(parent);
0079     item->setText(0, list->description());
0080     _items.insert(item, list);
0081     _stack.push(item);
0082 
0083     for (KHotKeys::Condition_list_base::Iterator it = list->begin(); it != list->end(); ++it) {
0084         // QTreeWidgetItem *child = new QTreeWidgetItem(item);
0085         // child->setText(0, (*it)->description());
0086         // _items.insert(child, list);
0087         (*it)->visit(this);
0088     }
0089 
0090     _stack.pop();
0091 }
0092 
0093 ConditionsWidget::ConditionsWidget(QWidget *parent)
0094     : QWidget(parent)
0095     , _working(nullptr)
0096     , _changed(false)
0097 {
0098     ui.setupUi(this);
0099 
0100     connect(ui.edit_button, SIGNAL(clicked(bool)), SLOT(slotEdit()));
0101 
0102     connect(ui.delete_button, SIGNAL(clicked(bool)), SLOT(slotDelete()));
0103 
0104     ui.new_button->setMenu(new ConditionTypeMenu(this));
0105     // clang-format off
0106     connect(ui.new_button->menu(), SIGNAL(triggered(QAction*)), SLOT(slotNew(QAction*)));
0107     // clang-format on
0108 }
0109 
0110 ConditionsWidget::~ConditionsWidget()
0111 {
0112     delete _working;
0113     _working = nullptr;
0114 }
0115 
0116 void ConditionsWidget::copyFromObject()
0117 {
0118     Q_ASSERT(_conditions_list);
0119 
0120     // Clear the tree and delete our old working copy
0121     ui.tree->clear();
0122     if (_working)
0123         delete _working;
0124 
0125     // Create the working copy
0126     _working = _conditions_list->copy();
0127     Q_ASSERT(_working->count() == _conditions_list->count());
0128 
0129     qDebug() << _working->count();
0130     qDebug() << _conditions_list->count();
0131 
0132     // Build the tree
0133     BuildTree builder(ui.tree);
0134     _working->visit(&builder);
0135     _items = builder._items;
0136 
0137     _changed = false;
0138 }
0139 
0140 void ConditionsWidget::copyToObject()
0141 {
0142     qDebug();
0143 
0144     Q_ASSERT(_conditions_list);
0145     if (!_conditions_list)
0146         return;
0147 
0148     // Just copy the content from our working copy to the original
0149 
0150     // Remove the old content
0151     qDeleteAll(*_conditions_list);
0152     _conditions_list->clear();
0153 
0154     for (KHotKeys::Condition_list::Iterator it = _working->begin(); it != _working->end(); ++it) {
0155         qDebug();
0156         _conditions_list->append((*it)->copy());
0157     }
0158 
0159     Q_ASSERT(_working->count() == _conditions_list->count());
0160     _changed = false;
0161 }
0162 
0163 void ConditionsWidget::emitChanged(bool chgd)
0164 {
0165     if (_changed == (chgd || _changed))
0166         return;
0167 
0168     // Once changed always changed
0169     _changed = chgd || _changed;
0170 
0171     emit changed(_changed);
0172 }
0173 
0174 bool ConditionsWidget::hasChanges() const
0175 {
0176     return _changed;
0177 }
0178 
0179 void ConditionsWidget::setConditionsList(KHotKeys::Condition_list *list)
0180 {
0181     Q_ASSERT(list);
0182     _conditions_list = list;
0183 }
0184 
0185 void ConditionsWidget::slotDelete()
0186 {
0187     QTreeWidgetItem *citem = ui.tree->currentItem();
0188 
0189     // If no item is selected just return
0190     if (!citem)
0191         return;
0192 
0193     // TODO: Ask for confirmation before deleting
0194 
0195     // Get the currently select condition
0196     KHotKeys::Condition *cond = _items.value(citem);
0197 
0198     // Do not allow deleting the root item
0199     if (cond == _working)
0200         return;
0201 
0202     delete cond;
0203     delete citem;
0204     emitChanged(true);
0205 }
0206 
0207 void ConditionsWidget::slotEdit()
0208 {
0209     // Get the currently select condition
0210     QTreeWidgetItem *citem = ui.tree->currentItem();
0211 
0212     // If no item is selected just return
0213     if (!citem)
0214         return;
0215 
0216     KHotKeys::Condition *cond = _items.value(citem);
0217 
0218     // Currently we only allow editing existing and active window conditions.
0219     // TODO: Disable buttons according to active item
0220 
0221     KHotKeys::Existing_window_condition *ewcond = dynamic_cast<KHotKeys::Existing_window_condition *>(cond);
0222     if (ewcond) {
0223         WindowDefinitionListDialog dialog(ewcond->window());
0224         switch (dialog.exec()) {
0225         case QDialog::Accepted: {
0226             citem->setText(0, ewcond->description());
0227             emitChanged(true);
0228         } break;
0229 
0230         case QDialog::Rejected:
0231             // Nothing to do
0232             return;
0233 
0234         default:
0235             Q_ASSERT(false);
0236             return;
0237         }
0238     }
0239 
0240     KHotKeys::Active_window_condition *awcond = dynamic_cast<KHotKeys::Active_window_condition *>(cond);
0241     if (awcond) {
0242         WindowDefinitionListDialog dialog(awcond->window());
0243         switch (dialog.exec()) {
0244         case QDialog::Accepted: {
0245             citem->setText(0, awcond->description());
0246             emitChanged(true);
0247         } break;
0248 
0249         case QDialog::Rejected:
0250             // Nothing to do
0251             return;
0252 
0253         default:
0254             Q_ASSERT(false);
0255             return;
0256         }
0257     }
0258 
0259     return;
0260 }
0261 
0262 void ConditionsWidget::slotNew(QAction *action)
0263 {
0264     QTreeWidgetItem *citem = ui.tree->currentItem();
0265 
0266     KHotKeys::Condition *cond;
0267     if (!citem) {
0268         // If no item is selected create the new condition as a top level
0269         // condition
0270         cond = _working;
0271         citem = ui.tree->invisibleRootItem()->child(0);
0272         Q_ASSERT(citem);
0273     } else {
0274         // Get the currently select condition
0275         cond = _items.value(citem);
0276     }
0277 
0278     // get the nearest list
0279     KHotKeys::Condition_list_base *parent = dynamic_cast<KHotKeys::Condition_list_base *>(cond);
0280 
0281     if (!parent) {
0282         parent = cond->parent();
0283         citem = citem->parent();
0284     }
0285 
0286     Q_ASSERT(parent);
0287 
0288     switch (action->data().toInt()) {
0289     case ConditionTypeMenu::ACTIVE_WINDOW: {
0290         KHotKeys::Windowdef_list *list = new KHotKeys::Windowdef_list();
0291         WindowDefinitionListDialog dialog(list);
0292         switch (dialog.exec()) {
0293         case QDialog::Accepted: {
0294             KHotKeys::Active_window_condition *cond = new KHotKeys::Active_window_condition(list, parent);
0295             QTreeWidgetItem *item = new QTreeWidgetItem(citem);
0296             item->setText(0, cond->description());
0297             _items.insert(item, cond);
0298         } break;
0299 
0300         case QDialog::Rejected:
0301             delete list;
0302             return;
0303 
0304         default:
0305             Q_ASSERT(false);
0306             delete list;
0307             return;
0308         }
0309     } break;
0310 
0311     case ConditionTypeMenu::EXISTING_WINDOW: {
0312         KHotKeys::Windowdef_list *list = new KHotKeys::Windowdef_list();
0313         WindowDefinitionListDialog dialog(list);
0314         switch (dialog.exec()) {
0315         case QDialog::Accepted: {
0316             KHotKeys::Existing_window_condition *cond = new KHotKeys::Existing_window_condition(list, parent);
0317             QTreeWidgetItem *item = new QTreeWidgetItem(citem);
0318             item->setText(0, cond->description());
0319             _items.insert(item, cond);
0320         } break;
0321 
0322         case QDialog::Rejected:
0323             delete list;
0324             return;
0325 
0326         default:
0327             Q_ASSERT(false);
0328             delete list;
0329             return;
0330         }
0331     } break;
0332 
0333     case ConditionTypeMenu::AND: {
0334         KHotKeys::And_condition *cond = new KHotKeys::And_condition(parent);
0335         QTreeWidgetItem *item = new QTreeWidgetItem(citem);
0336         item->setText(0, cond->description());
0337         _items.insert(item, cond);
0338     } break;
0339 
0340     case ConditionTypeMenu::OR: {
0341         KHotKeys::Or_condition *cond = new KHotKeys::Or_condition(parent);
0342         QTreeWidgetItem *item = new QTreeWidgetItem(citem);
0343         item->setText(0, cond->description());
0344         _items.insert(item, cond);
0345     } break;
0346 
0347     case ConditionTypeMenu::NOT: {
0348         KHotKeys::Not_condition *cond = new KHotKeys::Not_condition(parent);
0349         QTreeWidgetItem *item = new QTreeWidgetItem(citem);
0350         item->setText(0, cond->description());
0351         _items.insert(item, cond);
0352     } break;
0353 
0354     default:
0355         Q_ASSERT(false);
0356         break;
0357     }
0358 
0359     emitChanged(true);
0360 }
0361 
0362 #include "moc_conditions_widget.cpp"