1 /* This file is part of the KDE project
2    Copyright (C) 2006 Jarosław Staniek <staniek@kde.org>
3 
4    This program is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Library General Public
6    License as published by the Free Software Foundation; either
7    version 2 of the License, or (at your option) any later version.
8 
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Library General Public License for more details.
13 
14    You should have received a copy of the GNU Library General Public License
15    along with this program; see the file COPYING.  If not, write to
16    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18 */
19 
20 #include "utils.h"
21 #include "utils_p.h"
22 #include <KexiIcon.h>
23 
24 #include <KDb>
25 
26 #include <KStandardGuiItem>
27 
28 #include <QThread>
29 #include <QHeaderView>
30 #include <QPushButton>
31 #include <QTabWidget>
32 #include <QVBoxLayout>
33 #include <QDebug>
34 
35 static DebugWindow* debugWindow = 0;
36 static QTabWidget* debugWindowTab = 0;
37 static KexiDBDebugTreeWidget* kexiDBDebugPage = 0;
38 static QTreeWidget* kexiAlterTableActionDebugPage = 0;
39 
addKexiDBDebug(const QString & text)40 static void addKexiDBDebug(const QString& text)
41 {
42     // (this is internal code - do not use i18n() here)
43     if (!debugWindowTab)
44         return;
45     if (QThread::currentThread() != debugWindowTab->thread()) {
46 //! @todo send debug using async. signal
47         qWarning() << "Debugging from different thread not supported.";
48         return;
49     }
50     if (!kexiDBDebugPage) {
51         QWidget *page = new QWidget(debugWindowTab);
52         QVBoxLayout *vbox = new QVBoxLayout(page);
53         QHBoxLayout *hbox = new QHBoxLayout;
54         vbox->addLayout(hbox);
55         hbox->addStretch(1);
56         QPushButton *btn_copy = new QPushButton(page);
57         btn_copy->setIcon(koSmallIcon("edit-copy"));
58         hbox->addWidget(btn_copy);
59         QPushButton *btn_clear = new QPushButton(KStandardGuiItem::clear().icon(), KStandardGuiItem::clear().text(), page);
60         hbox->addWidget(btn_clear);
61 
62         kexiDBDebugPage = new KexiDBDebugTreeWidget(page);
63         kexiDBDebugPage->setObjectName("kexiDbDebugPage");
64         kexiDBDebugPage->setFont(KexiUtils::smallestReadableFont());
65         QObject::connect(btn_copy, SIGNAL(clicked()), kexiDBDebugPage, SLOT(copy()));
66         QObject::connect(btn_clear, SIGNAL(clicked()), kexiDBDebugPage, SLOT(clear()));
67         vbox->addWidget(kexiDBDebugPage);
68         kexiDBDebugPage->setHeaderLabel(QString());
69         kexiDBDebugPage->header()->hide();
70         kexiDBDebugPage->setSortingEnabled(false);
71         kexiDBDebugPage->setAllColumnsShowFocus(true);
72         kexiDBDebugPage->header()->setSectionResizeMode(0, QHeaderView::Stretch);
73         kexiDBDebugPage->header()->setStretchLastSection(true);
74         kexiDBDebugPage->setRootIsDecorated(true);
75         kexiDBDebugPage->setWordWrap(true);
76         kexiDBDebugPage->setAlternatingRowColors(true);
77         debugWindowTab->addTab(page, "KDb");
78         debugWindowTab->setCurrentWidget(page);
79         kexiDBDebugPage->show();
80     }
81     //add \n after (about) every 30 characters
82     QTreeWidgetItem * lastItem = kexiDBDebugPage->invisibleRootItem()->child(
83         kexiDBDebugPage->invisibleRootItem()->childCount()-1);
84     QTreeWidgetItem* li;
85     if (lastItem) {
86         li = new QTreeWidgetItem(kexiDBDebugPage, lastItem);
87     }
88     else {
89         li = new QTreeWidgetItem(kexiDBDebugPage->invisibleRootItem());
90     }
91     li->setText(0, text);
92     li->setToolTip(0, text);
93     li->setExpanded(true);
94 }
95 
addAlterTableActionDebug(const QString & text,int nestingLevel)96 static void addAlterTableActionDebug(const QString& text, int nestingLevel)
97 {
98     // (this is internal code - do not use i18n() here)
99     if (!debugWindowTab)
100         return;
101     if (!kexiAlterTableActionDebugPage) {
102         QWidget *page = new QWidget(debugWindowTab);
103         QVBoxLayout *vbox = new QVBoxLayout(page);
104         QHBoxLayout *hbox = new QHBoxLayout(page);
105         vbox->addLayout(hbox);
106         hbox->addStretch(1);
107         QPushButton *btn_exec = new QPushButton(KStandardGuiItem::save().icon(), "Real Alter Table", page);
108         btn_exec->setObjectName("executeRealAlterTable");
109         hbox->addWidget(btn_exec);
110         QPushButton *btn_clear = new QPushButton(KStandardGuiItem::clear().icon(), KStandardGuiItem::clear().text(), page);
111         hbox->addWidget(btn_clear);
112         QPushButton *btn_sim = new QPushButton(QIcon::fromTheme("system-run"), "Simulate Execution", page);
113         btn_sim->setObjectName("simulateAlterTableExecution");
114         hbox->addWidget(btn_sim);
115 
116         kexiAlterTableActionDebugPage = new QTreeWidget(page);
117         kexiAlterTableActionDebugPage->setFont(KexiUtils::smallestReadableFont());
118         kexiAlterTableActionDebugPage->setObjectName("kexiAlterTableActionDebugPage");
119         QObject::connect(btn_clear, SIGNAL(clicked()), kexiAlterTableActionDebugPage, SLOT(clear()));
120         vbox->addWidget(kexiAlterTableActionDebugPage);
121         kexiAlterTableActionDebugPage->setHeaderLabel(QString());
122         kexiAlterTableActionDebugPage->header()->hide();
123         kexiAlterTableActionDebugPage->setSortingEnabled(false);
124         kexiAlterTableActionDebugPage->setAllColumnsShowFocus(true);
125         kexiAlterTableActionDebugPage->header()->setSectionResizeMode(0, QHeaderView::Stretch);
126         kexiAlterTableActionDebugPage->setRootIsDecorated(true);
127         debugWindowTab->addTab(page, "AlterTable Actions");
128         debugWindowTab->setCurrentWidget(page);
129         page->show();
130     }
131     if (text.isEmpty()) //don't move up!
132         return;
133     QTreeWidgetItem * li;
134     int availableNestingLevels = 0;
135     // compute availableNestingLevels
136     QTreeWidgetItem * lastItem = kexiAlterTableActionDebugPage->invisibleRootItem()->child(
137         kexiAlterTableActionDebugPage->invisibleRootItem()->childCount()-1);
138     //qDebug() << "lastItem: " << (lastItem ? lastItem->text(0) : QString());
139     while (lastItem) {
140         lastItem = lastItem->parent();
141         availableNestingLevels++;
142     }
143     //qDebug() << "availableNestingLevels: " << availableNestingLevels;
144     //go up (availableNestingLevels-levelsToGoUp) levels
145     lastItem = kexiAlterTableActionDebugPage->invisibleRootItem()->child(
146         kexiAlterTableActionDebugPage->invisibleRootItem()->childCount()-1);
147     int levelsToGoUp = availableNestingLevels - nestingLevel;
148     while (levelsToGoUp > 0 && lastItem) {
149         lastItem = lastItem->parent();
150         levelsToGoUp--;
151     }
152     //qDebug() << "lastItem2: " << (lastItem ? lastItem->text(0) : QString());
153     if (lastItem) {
154         if (lastItem->childCount() > 0) {
155                li = new QTreeWidgetItem(lastItem, lastItem->child(lastItem->childCount()-1));   //child, after
156         }
157         else {
158                li = new QTreeWidgetItem(lastItem);   //1st child
159         }
160     } else {
161         lastItem = kexiAlterTableActionDebugPage->invisibleRootItem()->child(
162             kexiAlterTableActionDebugPage->invisibleRootItem()->childCount()-1);
163         while (lastItem && lastItem->parent()) {
164             lastItem = lastItem->parent();
165         }
166         //qDebug() << "lastItem2: " << (lastItem ? lastItem->text(0) : QString());
167         if (lastItem && lastItem->parent())
168              li = new QTreeWidgetItem(lastItem->parent(), lastItem);   //after
169         else if (!lastItem)
170              li = new QTreeWidgetItem(kexiAlterTableActionDebugPage->invisibleRootItem());
171         else if (!lastItem->parent())
172              li = new QTreeWidgetItem(kexiAlterTableActionDebugPage->invisibleRootItem(), lastItem);
173     }
174         li->setText(0, text);
175         li->setExpanded(true);
176 }
177 
createDebugWindow(QWidget * parent)178 QWidget *KexiUtils::createDebugWindow(QWidget *parent)
179 {
180     Q_UNUSED(parent);
181     KDb::setDebugGUIHandler(addKexiDBDebug);
182     KDb::setAlterTableActionDebugHandler(addAlterTableActionDebug);
183 
184     // (this is internal code - do not use i18n() here)
185     debugWindow = new DebugWindow(parent);
186     QBoxLayout *lyr = new QVBoxLayout(debugWindow);
187     debugWindowTab = new QTabWidget(debugWindow);
188     debugWindowTab->setObjectName("debugWindowTab");
189     lyr->addWidget(debugWindowTab);
190     debugWindow->resize(900, 600);
191     debugWindow->setWindowIcon(koIcon("document-properties"));
192     debugWindow->setWindowTitle("Kexi Internal Debugger");
193     debugWindow->show();
194     return debugWindow;
195 }
196 
connectPushButtonActionForDebugWindow(const char * actionName,const QObject * receiver,const char * slot)197 void KexiUtils::connectPushButtonActionForDebugWindow(const char* actionName,
198         const QObject *receiver, const char* slot)
199 {
200     if (debugWindow) {
201         QPushButton* btn = KexiUtils::findFirstChild<QPushButton*>(
202                                debugWindow, "QPushButton", actionName);
203         if (btn)
204             QObject::connect(btn, SIGNAL(clicked()), receiver, slot);
205     }
206 }
207