1 /*
2 * Kexi Report Plugin
3 * Copyright (C) 2007-2009 by Adam Pigg <adam@piggz.co.uk>
4 * Copyright (C) 2011-2017 Jarosław Staniek <staniek@kde.org>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #include "kexireportdesignview.h"
21 #include <core/KexiMainWindowIface.h>
22 #include <core/KexiWindow.h>
23 #include "kexisourceselector.h"
24 #include <KexiIcon.h>
25 #include <kexiutils/utils.h>
26 
27 #include <KDbConnection>
28 
29 #include <QShortcut>
30 #include <QDebug>
31 #include <QScrollArea>
32 #include <QLayout>
33 
34 #include <KStandardGuiItem>
35 
KexiReportDesignView(QWidget * parent,KexiSourceSelector * s)36 KexiReportDesignView::KexiReportDesignView(QWidget *parent, KexiSourceSelector *s)
37         : KexiView(parent)
38 {
39     m_scrollArea = new QScrollArea(this);
40     layout()->addWidget(m_scrollArea);
41     m_sourceSelector = s;
42 
43     m_reportDesigner = 0;
44 
45     m_editCutAction = KStandardAction::cut(this);
46     m_editCutAction->setProperty("iconOnly", true);
47     m_editCopyAction = KStandardAction::copy(this);
48     m_editCopyAction->setProperty("iconOnly", true);
49     m_editPasteAction = KStandardAction::paste(this);
50     m_editPasteAction->setProperty("iconOnly", true);
51     const KGuiItem del = KStandardGuiItem::del();
52     m_editDeleteAction = new QAction(del.icon(), del.text(), this);
53     m_editDeleteAction->setObjectName("editdelete");
54     m_editDeleteAction->setToolTip(del.toolTip());
55     m_editDeleteAction->setWhatsThis(del.whatsThis());
56     m_editDeleteAction->setProperty("iconOnly", true);
57 
58     m_editSectionAction = new QAction(xi18n("Edit Sections"), this);
59     m_editSectionAction->setObjectName("sectionedit");
60 
61     m_itemRaiseAction = new QAction(koIcon("object-order-front"), xi18n("Raise"), this);
62     m_itemRaiseAction->setObjectName("itemraise");
63     m_itemLowerAction = new QAction(koIcon("object-order-back"), xi18n("Lower"), this);
64     m_itemLowerAction->setObjectName("itemlower");
65     QList<QAction*> al;
66     QAction *sep = new QAction(QString(), this);
67     sep->setSeparator(true);
68 
69     al << m_editCutAction << m_editCopyAction << m_editPasteAction << m_editDeleteAction << sep << m_editSectionAction << sep << m_itemLowerAction << m_itemRaiseAction;
70     setViewActions(al);
71 
72 }
73 
~KexiReportDesignView()74 KexiReportDesignView::~KexiReportDesignView()
75 {
76 }
77 
propertySet()78 KPropertySet *KexiReportDesignView::propertySet()
79 {
80     return m_reportDesigner->selectedItemPropertySet();
81 }
82 
slotDesignerPropertySetChanged()83 void KexiReportDesignView::slotDesignerPropertySetChanged()
84 {
85     propertySetReloaded(true);
86     propertySetSwitched();
87 }
88 
storeNewData(const KDbObject & object,KexiView::StoreNewDataOptions options,bool * cancel)89 KDbObject* KexiReportDesignView::storeNewData(const KDbObject& object,
90                                                        KexiView::StoreNewDataOptions options,
91                                                        bool *cancel)
92 {
93     KDbObject *s = KexiView::storeNewData(object, options, cancel);
94     if (!s || *cancel) {
95         delete s;
96         return 0;
97     }
98     qDebug() << "new id:" << s->id();
99 
100     if (!storeData()) {
101         //failure: remove object's object data to avoid garbage
102         KDbConnection *conn = KexiMainWindowIface::global()->project()->dbConnection();
103         conn->removeObject(s->id());
104         delete s;
105         return 0;
106     }
107     return s;
108 
109 }
110 
storeData(bool dontAsk)111 tristate KexiReportDesignView::storeData(bool dontAsk)
112 {
113     Q_UNUSED(dontAsk);
114 
115     QDomDocument doc("kexireport");
116     QDomElement root = doc.createElement("kexireport");
117     QDomElement conndata = connectionData();
118 
119     if (conndata.isNull())
120         qDebug() << "Null conn data!";
121 
122     root.appendChild(m_reportDesigner->document());
123     root.appendChild(conndata);
124     doc.appendChild(root);
125 
126     QString src  = doc.toString();
127     qDebug() << src;
128 
129     if (storeDataBlock(src, "layout")) {
130         qDebug() << "Saved OK";
131         setDirty(false);
132         return true;
133     }
134 
135     qDebug() << "NOT Saved OK";
136     return false;
137 }
138 
beforeSwitchTo(Kexi::ViewMode mode,bool * dontStore)139 tristate KexiReportDesignView::beforeSwitchTo(Kexi::ViewMode mode, bool *dontStore)
140 {
141     //qDebug() << mode;
142     *dontStore = true;
143     if (m_reportDesigner && mode == Kexi::DataViewMode) {
144         //qDebug() << "Saving temp data";
145         tempData()->reportDefinition = m_reportDesigner->document();
146         //qDebug() << m_reportDesigner->document().toDocument().toString();
147         tempData()->reportSchemaChangedInPreviousView = true;
148     }
149     return true;
150 }
151 
afterSwitchFrom(Kexi::ViewMode mode)152 tristate KexiReportDesignView::afterSwitchFrom(Kexi::ViewMode mode)
153 {
154     Q_UNUSED(mode);
155 
156     if (tempData()->reportDefinition.isNull()) {
157         m_reportDesigner = new KReportDesigner(this);
158     } else {
159         if (m_reportDesigner) {
160             m_scrollArea->takeWidget();
161             delete m_reportDesigner;
162             m_reportDesigner = 0;
163         }
164 
165         m_reportDesigner = new KReportDesigner(this, tempData()->reportDefinition);
166         setConnectionData(tempData()->connectionDefinition);
167         m_reportDesigner->setScriptSource(qobject_cast<KexiReportPart*>(part()));
168     }
169     connect(m_reportDesigner, SIGNAL(itemInserted(QString)), this, SIGNAL(itemInserted(QString)));
170 
171     m_scrollArea->setWidget(m_reportDesigner);
172 
173     connect(m_reportDesigner, SIGNAL(propertySetChanged()), this, SLOT(slotDesignerPropertySetChanged()));
174     connect(m_reportDesigner, SIGNAL(dirty()), this, SLOT(setDirty()));
175 
176      //Added default keyboard shortcuts for the actions
177      QShortcut *cutShortcut = new QShortcut(QKeySequence(QKeySequence::Cut), m_reportDesigner);
178      QShortcut *copyShortcut = new QShortcut(QKeySequence(QKeySequence::Copy), m_reportDesigner);
179      QShortcut *pasteShortcut = new QShortcut(QKeySequence(QKeySequence::Paste), m_reportDesigner);
180      QShortcut *deleteShortcut = new QShortcut(QKeySequence(QKeySequence::Delete), m_reportDesigner);
181 
182      connect(cutShortcut, SIGNAL(activated()), m_reportDesigner, SLOT(slotEditCut()));
183      connect(copyShortcut, SIGNAL(activated()), m_reportDesigner, SLOT(slotEditCopy()));
184      connect(pasteShortcut, SIGNAL(activated()), m_reportDesigner, SLOT(slotEditPaste()));
185      connect(deleteShortcut, SIGNAL(activated()), m_reportDesigner, SLOT(slotEditDelete()));
186 
187     //Edit Actions
188     connect(m_editCutAction, SIGNAL(triggered()), m_reportDesigner, SLOT(slotEditCut()));
189     connect(m_editCopyAction, SIGNAL(triggered()), m_reportDesigner, SLOT(slotEditCopy()));
190     connect(m_editPasteAction, SIGNAL(triggered()), m_reportDesigner, SLOT(slotEditPaste()));
191     connect(m_editDeleteAction, SIGNAL(triggered()), m_reportDesigner, SLOT(slotEditDelete()));
192 
193     connect(m_editSectionAction, SIGNAL(triggered()), m_reportDesigner, SLOT(slotSectionEditor()));
194 
195     //Raise/Lower
196     connect(m_itemRaiseAction, SIGNAL(triggered()), m_reportDesigner, SLOT(slotRaiseSelected()));
197     connect(m_itemLowerAction, SIGNAL(triggered()), m_reportDesigner, SLOT(slotLowerSelected()));
198     return true;
199 }
200 
tempData() const201 KexiReportPartTempData* KexiReportDesignView::tempData() const
202 {
203     return static_cast<KexiReportPartTempData*>(window()->data());
204 }
205 
slotDataSourceChanged()206 void KexiReportDesignView::slotDataSourceChanged()
207 {
208     if (m_sourceSelector->isSelectionValid()) {
209         m_reportDesigner->setDataSource(new KexiDBReportDataSource(
210             m_sourceSelector->selectedName(), m_sourceSelector->selectedPluginId(), tempData()));
211         tempData()->connectionDefinition = connectionData();
212     } else {
213         m_reportDesigner->setDataSource(nullptr);
214         tempData()->connectionDefinition = QDomElement();
215     }
216     setDirty(true);
217 }
218 
triggerAction(const QString & action)219 void KexiReportDesignView::triggerAction(const QString &action)
220 {
221     m_reportDesigner->slotItem(action);
222 }
223 
connectionData() const224 QDomElement KexiReportDesignView::connectionData() const
225 {
226     QDomDocument dd;
227     QDomElement conndata = dd.createElement("connection");
228     conndata.setAttribute("type", "internal"); // for backward compatibility, currently always
229                                                // internal, we used to have "external" in old Kexi
230     conndata.setAttribute("source", m_sourceSelector->selectedName());
231     conndata.setAttribute("class", m_sourceSelector->selectedPluginId());
232     return conndata;
233 }
234 
setConnectionData(const QDomElement & c)235 void KexiReportDesignView::setConnectionData(const QDomElement &c)
236 {
237     //qDebug() << c;
238     if (c.attribute("type") == "internal") {
239         QString sourceClass(c.attribute("class"));
240         if (sourceClass != "org.kexi-project.table" && sourceClass != "org.kexi-project.query") {
241             sourceClass.clear(); // KexiDataSourceComboBox will try to find table, then query
242         }
243         m_sourceSelector->setDataSource(sourceClass, c.attribute("source"));
244         slotDataSourceChanged();
245     }
246 }
247