1 /***************************************************************************
2 editlabelsdialog - description
3 -------------------
4 begin : Tue Sep 21 2004
5 copyright : (C) 2004, 2006, 2007 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 #include "editlabelsdialog.h"
18
19 #include <KLocalizedString>
20 #include <kactioncollection.h>
21
22 #include <qlabel.h>
23 #include <QHeaderView>
24 #include <QTimer>
25 #include <QHBoxLayout>
26 #include <QVBoxLayout>
27 #include <QAction>
28 #include <QDialogButtonBox>
29 #include <QPushButton>
30
31 #include "../core/rkvariable.h"
32 #include "../dataeditor/rktextmatrix.h"
33 #include "../misc/rkdialogbuttonbox.h"
34 #include "celleditor.h"
35
36 #include "../debug.h"
37
RKVarLevelsTable(QWidget * parent,const RObject::ValueLabels & labels)38 RKVarLevelsTable::RKVarLevelsTable (QWidget *parent, const RObject::ValueLabels& labels) : RKTableView (parent) {
39 RK_TRACE (EDITOR);
40
41 setHorizontalScrollBarPolicy (Qt::ScrollBarAlwaysOff);
42 setSelectionMode (QAbstractItemView::ContiguousSelection);
43 horizontalHeader ()->setStretchLastSection (true);
44 verticalHeader ()->setFixedWidth (40);
45 setMinimumWidth (80);
46
47 addAction (KStandardAction::cut (this, SLOT (cut()), this));
48 addAction (KStandardAction::copy (this, SLOT (copy()), this));
49 addAction (KStandardAction::paste (this, SLOT (paste()), this));
50 setContextMenuPolicy (Qt::ActionsContextMenu);
51
52 setModel (lmodel = new RKVarLevelsTableModel (labels, this));
53 connect (this, &RKVarLevelsTable::blankSelectionRequest, this, &RKVarLevelsTable::blankSelected);
54 setRKItemDelegate (new RKItemDelegate (this, lmodel, true));
55 trailing_rows = 1;
56 }
57
~RKVarLevelsTable()58 RKVarLevelsTable::~RKVarLevelsTable () {
59 RK_TRACE (EDITOR);
60 }
61
blankSelected()62 void RKVarLevelsTable::blankSelected () {
63 RK_TRACE (EDITOR);
64
65 QItemSelectionRange range = getSelectionBoundaries ();
66 if (!range.isValid ()) return;
67
68 for (int row = range.top (); row <= range.bottom (); ++row) {
69 lmodel->setData (lmodel->index (row, 0), QString ());
70 }
71 }
72
cut()73 void RKVarLevelsTable::cut () {
74 RK_TRACE (EDITOR);
75
76 QItemSelectionRange range = getSelectionBoundaries ();
77 if (!range.isValid ()) return;
78
79 copy ();
80 blankSelected ();
81 }
82
copy()83 void RKVarLevelsTable::copy () {
84 RK_TRACE (EDITOR);
85
86 QItemSelectionRange range = getSelectionBoundaries ();
87 if (!range.isValid ()) return;
88
89 RKTextMatrix mat;
90 int trow = 0;
91 for (int i = range.top (); i <= range.bottom (); ++i) {
92 mat.setText (trow++, 0, lmodel->data (lmodel->index (i, 0)).toString ());
93 }
94 mat.copyToClipboard ();
95 }
96
paste()97 void RKVarLevelsTable::paste () {
98 RK_TRACE (EDITOR);
99
100 // Unfortunately, we need to duplicate some of TwinTable::paste () and RKEditorDataFramPart::doPaste. Those are not easy to reconcile.
101 QModelIndex current = currentIndex ();
102 if (!current.isValid ()) return;
103 int row = current.row ();
104 RK_ASSERT (current.column () == 0);
105
106 RKTextMatrix pasted = RKTextMatrix::matrixFromClipboard ();
107 if (pasted.isEmpty ()) return;
108
109 if (pasted.numColumns () > 1) { // there were tabs in the pasted text. Let's transpose the first row
110 for (int i = 0; i < pasted.numColumns (); ++i) {
111 lmodel->setData (lmodel->index (row++, 0), pasted.getText (0, i));
112 }
113 } else { // else paste the first column
114 for (int i = 0; i < pasted.numRows (); ++i) {
115 lmodel->setData (lmodel->index (row++, 0), pasted.getText (i, 0));
116 }
117 }
118 }
119
120 /////////////// RKVarLevelsTableModel /////////////////
121
RKVarLevelsTableModel(const RObject::ValueLabels & labels,QObject * parent)122 RKVarLevelsTableModel::RKVarLevelsTableModel (const RObject::ValueLabels& labels, QObject* parent) : QAbstractTableModel (parent) {
123 RK_TRACE (EDITOR);
124
125 RKVarLevelsTableModel::labels = labels;
126 }
127
~RKVarLevelsTableModel()128 RKVarLevelsTableModel::~RKVarLevelsTableModel () {
129 RK_TRACE (EDITOR);
130 }
131
rowCount(const QModelIndex & parent) const132 int RKVarLevelsTableModel::rowCount (const QModelIndex& parent) const {
133 RK_TRACE (EDITOR);
134
135 if (parent.isValid ()) return 0;
136 return labels.count () + 1;
137 }
138
columnCount(const QModelIndex & parent) const139 int RKVarLevelsTableModel::columnCount (const QModelIndex& parent) const {
140 RK_TRACE (EDITOR);
141
142 if (parent.isValid ()) return 0;
143 return 1;
144 }
145
data(const QModelIndex & index,int role) const146 QVariant RKVarLevelsTableModel::data (const QModelIndex& index, int role) const {
147 RK_TRACE (EDITOR);
148
149 if (!index.isValid ()) return QVariant ();
150 if (index.column () != 0) return QVariant ();
151 if ((role == Qt::BackgroundRole) && (index.row () == labels.count ())) return QBrush (Qt::gray);
152 if (index.row () >= labels.count ()) return QVariant ();
153
154 if ((role == Qt::DisplayRole) || (role == Qt::EditRole)) return labels.value (QString::number (index.row ()+1));
155
156 return QVariant ();
157 }
158
flags(const QModelIndex & index) const159 Qt::ItemFlags RKVarLevelsTableModel::flags (const QModelIndex& index) const {
160 RK_TRACE (EDITOR);
161
162 if (!index.isValid ()) return 0;
163 if (index.column () != 0) return 0;
164 if (index.row () >= labels.count ()) return (Qt::ItemIsEditable | Qt::ItemIsEnabled);
165 return (Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
166 }
167
setData(const QModelIndex & index,const QVariant & value,int role)168 bool RKVarLevelsTableModel::setData (const QModelIndex& index, const QVariant& value, int role) {
169 RK_TRACE (EDITOR);
170
171 if (role != Qt::EditRole) return false;
172 if (!index.isValid ()) return false;
173 if (index.column () != 0) return false;
174 if (!value.isValid ()) return false;
175 if (index.row () > labels.count ()) return false;
176
177 QString text = value.toString ();
178 if (index.row () == labels.count ()) {
179 beginInsertRows (QModelIndex (), index.row (), index.row ());
180 labels.insert (QString::number (index.row () + 1), text);
181 endInsertRows ();
182 } else {
183 labels.insert (QString::number (index.row () + 1), text);
184 emit (dataChanged (index, index));
185 }
186
187 if (text.isEmpty ()) { // remove trailing empty rows
188 while ((!labels.isEmpty ()) && labels.value (QString::number (labels.count ())).isEmpty ()) {
189 int row = labels.count () - 1;
190 beginRemoveRows (QModelIndex (), row, row);
191 labels.remove (QString::number (row + 1));
192 endRemoveRows ();
193 }
194 }
195
196 return true;
197 }
198
headerData(int section,Qt::Orientation orientation,int role) const199 QVariant RKVarLevelsTableModel::headerData (int section, Qt::Orientation orientation, int role) const {
200 RK_TRACE (EDITOR);
201
202 if (role != Qt::DisplayRole) return QVariant ();
203 if (orientation == Qt::Vertical) return QString::number (section + 1);
204 if (section != 0) return QVariant ();
205 return i18n ("Label");
206 }
207
208 //////////////// EditLabelsDialog ///////////////////////
209
EditLabelsDialog(QWidget * parent,const RObject::ValueLabels & labels,const QString & varname)210 EditLabelsDialog::EditLabelsDialog (QWidget *parent, const RObject::ValueLabels& labels, const QString& varname) : QDialog (parent) {
211 RK_TRACE (EDITOR);
212
213 setWindowTitle (i18n ("Levels / Value labels for '%1'", varname));
214
215 QVBoxLayout *layout = new QVBoxLayout (this);
216 QLabel *label = new QLabel (i18n ("Levels can be assigned only to consecutive integers starting with 1 (the index column is read only). To remove levels at the end of the list, just set them to empty."), this);
217 label->setWordWrap (true);
218 layout->addWidget (label);
219
220 table = new RKVarLevelsTable (this, labels);
221 layout->addWidget (table);
222
223 RKDialogButtonBox *buttons = new RKDialogButtonBox (QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
224 layout->addWidget (buttons);
225 }
226
~EditLabelsDialog()227 EditLabelsDialog::~EditLabelsDialog () {
228 RK_TRACE (EDITOR);
229 }
230
accept()231 void EditLabelsDialog::accept () {
232 RK_TRACE (EDITOR);
233
234 table->setCurrentIndex (QModelIndex ()); // should flush editing
235 QDialog::accept ();
236 }
237
238 ////////////////// EditLabelsDialogProxy /////////////////////////
239
EditLabelsDialogProxy(QWidget * parent)240 EditLabelsDialogProxy::EditLabelsDialogProxy (QWidget* parent) : QWidget (parent) {
241 RK_TRACE (EDITOR);
242 dialog = 0;
243 }
244
~EditLabelsDialogProxy()245 EditLabelsDialogProxy::~EditLabelsDialogProxy () {
246 RK_TRACE (EDITOR);
247 }
248
initialize(const RObject::ValueLabels & labels,const QString & varname)249 void EditLabelsDialogProxy::initialize (const RObject::ValueLabels& labels, const QString& varname) {
250 RK_TRACE (EDITOR);
251
252 if (dialog) return; // one dialog at a time, please!
253
254 EditLabelsDialogProxy::labels = labels; // we need to take a copy in case the dialog is rejected
255
256 dialog = new EditLabelsDialog (this, labels, varname);
257 connect (dialog, &QDialog::finished, this, &EditLabelsDialogProxy::dialogDone);
258 QTimer::singleShot (0, dialog, SLOT (exec()));
259 }
260
dialogDone(int result)261 void EditLabelsDialogProxy::dialogDone (int result) {
262 RK_TRACE (EDITOR);
263 RK_ASSERT (dialog);
264
265 if (result == QDialog::Accepted) {
266 labels = dialog->table->lmodel->labels;
267 emit (done (this, RKItemDelegate::EditorExit));
268 } else {
269 emit (done (this, RKItemDelegate::EditorReject));
270 }
271 dialog->deleteLater ();
272 dialog = 0;
273 }
274
275
276