1 /***************************************************************************
2 rksaveobjectchooser - description
3 -------------------
4 begin : Mon Nov 27 2006
5 copyright : (C) 2006, 2007, 2009, 2010 by Thomas Friedrichsmeier
6 email : thomas.friedrichsmeier@kdemail.net
7 ***************************************************************************/
8
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18 #include "rksaveobjectchooser.h"
19
20 #include <qlineedit.h>
21 #include <qcheckbox.h>
22 #include <qlabel.h>
23 #include <QVBoxLayout>
24 #include <QPushButton>
25 #include <QTimer>
26 #include <QDialog>
27 #include <QDialogButtonBox>
28
29 #include <KLocalizedString>
30
31 #include "../core/robjectlist.h"
32 #include "../core/renvironmentobject.h"
33 #include "../misc/rkobjectlistview.h"
34
35 #include "../debug.h"
36
RKSaveObjectChooser(QWidget * parent,const QString & initial)37 RKSaveObjectChooser::RKSaveObjectChooser (QWidget *parent, const QString &initial) : QWidget (parent), RObjectListener (RObjectListener::Other) {
38 RK_TRACE (MISC);
39
40 object_exists = false;
41 addNotificationType (RObjectListener::ObjectRemoved);
42 addNotificationType (RObjectListener::ChildAdded);
43 root_object = 0;
44 current_object = 0;
45
46 QVBoxLayout *layout = new QVBoxLayout (this);
47 layout->setContentsMargins (0, 0, 0, 0);
48
49 QHBoxLayout *hlayout = new QHBoxLayout ();
50 root_label = new QLabel (this);
51 hlayout->addWidget (root_label);
52 hlayout->addStretch ();
53 root_button = new QPushButton (i18n ("Change"), this);
54 connect (root_button, &QPushButton::clicked, this, &RKSaveObjectChooser::selectRootObject);
55 hlayout->addWidget (root_button);
56 layout->addLayout (hlayout);
57
58 name_edit = new QLineEdit (this);
59 name_edit->setText (initial);
60 connect (name_edit, &QLineEdit::textChanged, this, &RKSaveObjectChooser::updateState);
61 layout->addWidget (name_edit);
62
63 overwrite_confirm = new QCheckBox (this);
64 connect (overwrite_confirm, &QCheckBox::stateChanged, this, &RKSaveObjectChooser::updateState);
65 layout->addWidget (overwrite_confirm);
66
67 // initialize
68 setRootObject (0);
69 }
70
~RKSaveObjectChooser()71 RKSaveObjectChooser::~RKSaveObjectChooser () {
72 RK_TRACE (MISC);
73
74 if (current_object) stopListenForObject (current_object);
75 stopListenForObject (root_object);
76 }
77
setRootObject(RObject * new_root)78 void RKSaveObjectChooser::setRootObject (RObject* new_root) {
79 RK_TRACE (MISC);
80
81 if (root_object && (new_root == root_object)) {
82 return;
83 }
84
85 if (root_object) stopListenForObject (root_object);
86 if (!new_root) new_root = RObjectList::getGlobalEnv ();
87 else if (!new_root->isInGlobalEnv ()) new_root = RObjectList::getGlobalEnv ();
88 else if (!new_root->isContainer ()) new_root = RObjectList::getGlobalEnv ();
89 root_object = new_root;
90 listenForObject (root_object);
91
92 root_label->setText (i18n ("Parent object: %1", root_object->getShortName ()));
93
94 updateState ();
95 }
96
selectRootObject()97 void RKSaveObjectChooser::selectRootObject () {
98 RK_TRACE (MISC);
99
100 // TODO: not very pretty, yet
101 QDialog *dialog = new QDialog (this);
102 dialog->setWindowTitle (i18n ("Select parent object"));
103 dialog->setModal (true);
104 QVBoxLayout *layout = new QVBoxLayout (dialog);
105
106 RKObjectListView* list_view = new RKObjectListView (false, dialog);
107 list_view->setSelectionMode (QAbstractItemView::SingleSelection);
108 list_view->initialize ();
109 list_view->setObjectCurrent (root_object);
110 connect (list_view, &QAbstractItemView::doubleClicked, dialog, &QDialog::accept);
111 layout->addWidget (list_view);
112
113 QDialogButtonBox *buttons = new QDialogButtonBox (QDialogButtonBox::Ok | QDialogButtonBox::Cancel, dialog);
114 connect (buttons->button (QDialogButtonBox::Ok), &QPushButton::clicked, dialog, &QDialog::accept);
115 connect (buttons->button (QDialogButtonBox::Cancel), &QPushButton::clicked, dialog, &QDialog::reject);
116 layout->addWidget (buttons);
117
118 dialog->exec ();
119
120 if (dialog->result () == QDialog::Accepted) {
121 RObject::ObjectList sel = list_view->selectedObjects ();
122 if (sel.isEmpty ()) setRootObject (0);
123 else {
124 RK_ASSERT (sel.size () == 1);
125 setRootObject (sel[0]);
126 }
127 }
128
129 delete dialog;
130 }
131
objectRemoved(RObject * removed)132 void RKSaveObjectChooser::objectRemoved (RObject* removed) {
133 RK_TRACE (MISC);
134
135 if (removed == root_object) {
136 setRootObject (0);
137 } else if (removed == current_object) {
138 stopListenForObject (removed);
139 current_full_name.clear (); // hack to achieve proper emit of change signal
140 QTimer::singleShot (0, this, SLOT (updateState()));
141 } else {
142 RK_ASSERT (false);
143 }
144 }
145
childAdded(int,RObject * parent)146 void RKSaveObjectChooser::childAdded (int, RObject* parent) {
147 RK_TRACE (MISC);
148
149 if (parent == root_object) {
150 updateState ();
151 } else {
152 // unusual, but ok
153 RK_ASSERT (parent == current_object);
154 }
155 }
156
setBaseName(const QString & name)157 void RKSaveObjectChooser::setBaseName (const QString &name) {
158 RK_TRACE (MISC);
159
160 name_edit->setText (name);
161 updateState ();
162 }
163
isOk() const164 bool RKSaveObjectChooser::isOk () const {
165 RK_TRACE (MISC);
166
167 if (name_edit->text ().isEmpty ()) return false;
168 return ((!object_exists) || overwrite_confirm->isChecked ());
169 }
170
updateState()171 void RKSaveObjectChooser::updateState () {
172 RK_TRACE (MISC);
173 RK_ASSERT (root_object && root_object->isContainer ());
174
175 QString new_name = static_cast<RContainerObject*> (root_object)->validizeName (name_edit->text (), false);
176 if (current_object) stopListenForObject (current_object);
177 current_object = root_object->findObject (new_name);
178 new_name = root_object->makeChildName (new_name); // make it the full name
179 if (current_object) {
180 object_exists = true;
181 overwrite_confirm->setText (i18n ("Overwrite? (The given object name already exists)"));
182 overwrite_confirm->setEnabled (true);
183 listenForObject (current_object);
184 } else {
185 object_exists = false;
186 overwrite_confirm->setText (i18n ("Overwrite?"));
187 overwrite_confirm->setEnabled (false);
188 overwrite_confirm->setChecked (false);
189 }
190
191 if ((new_name != current_full_name) || (sender () == overwrite_confirm)) {
192 current_full_name = new_name;
193 emit (changed (isOk ()));
194 }
195 }
196
setBackgroundColor(const QColor & color)197 void RKSaveObjectChooser::setBackgroundColor (const QColor &color) {
198 RK_TRACE (MISC);
199
200 QPalette palette = name_edit->palette ();
201 palette.setColor (name_edit->backgroundRole (), color);
202 name_edit->setPalette (palette);
203 }
204
currentBaseName() const205 QString RKSaveObjectChooser::currentBaseName () const {
206 return name_edit->text ();
207 }
208
209