1/*
2 * Copyright 2011 Jon Ander PeƱalba <jonan88@gmail.com>
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "kdedemo.h"
27
28#include <QtCore/QProcess>
29#include <QtGui/QGraphicsGridLayout>
30#include <QtGui/QGraphicsLinearLayout>
31
32#include <KStandardDirs>
33#include <KMessageBox>
34
35#include <Plasma/Animator>
36#include <Plasma/Label>
37#include <Plasma/PushButton>
38
39#include "xmlhandler.h"
40
41// This is the command that links your applet to the .desktop file
42K_EXPORT_PLASMA_APPLET(kdedemo, KdeDemo)
43
44KdeDemo::KdeDemo(QObject *parent, const QVariantList &args)
45 : Plasma::Applet(parent, args)
46 , m_back_button(new Plasma::PushButton)
47 , m_quit_launch_button(new Plasma::PushButton)
48 , m_show_source_button(new Plasma::PushButton)
49 , m_text(new Plasma::Label)
50 , m_tittle(new Plasma::Label)
51 , m_layout(new QGraphicsGridLayout)
52 , m_current_category(new Category)
53 , m_current_example(new Example)
54{
55 setBackgroundHints(DefaultBackground);
56}
57
58KdeDemo::~KdeDemo()
59{
60}
61
62void KdeDemo::init()
63{
64 m_layout->setColumnFixedWidth(0, 200);
65 m_layout->setColumnFixedWidth(2, 0);
66 m_layout->setColumnMinimumWidth(1, 300);
67 m_layout->setRowMaximumHeight(1, 30);
68 m_layout->setHorizontalSpacing(35);
69 m_layout->setVerticalSpacing(30);
70
71 m_tittle->setAlignment(Qt::AlignCenter);
72
73 m_text->setAlignment(Qt::AlignJustify);
74 loadTextFromFile("KDE Examples and Demos", KStandardDirs::locate("data", "kdeexamples/README"));
75 m_layout->addItem(m_text, 0, 1, Qt::AlignCenter);
76
77 QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(Qt::Vertical);
78 m_back_button->setText("Back");
79 m_back_button->hide();
80 connect(m_back_button, SIGNAL(clicked()), this, SLOT(backToCategories()));
81 layout->addItem(m_back_button);
82 m_layout->addItem(layout, 1, 0);
83
84 layout = new QGraphicsLinearLayout(Qt::Horizontal);
85 layout->addStretch();
86 m_show_source_button->setText("Show Source Code");
87 m_show_source_button->hide();
88 connect(m_show_source_button, SIGNAL(clicked()), this, SLOT(openSourceCode()));
89 layout->addItem(m_show_source_button);
90 m_quit_launch_button->setText("Quit");
91 connect(m_quit_launch_button, SIGNAL(clicked()), this, SLOT(destroy()));
92 layout->addItem(m_quit_launch_button);
93 m_layout->addItem(layout, 1, 1);
94
95 setLayout(m_layout);
96
97 loadConfig();
98 if (hasFailedToLaunch())
99 return;
100
101 foreach (Category c, m_categories) {
102 Plasma::PushButton *button = new Plasma::PushButton;
103 button->setText(c.name);
104 connect(button, SIGNAL(clicked()), this, SLOT(loadExampleList()));
105 m_category_buttons.push_back(button);
106
107 QList<Plasma::PushButton*> x;
108 m_example_buttons.push_back(x);
109
110 foreach (Example e, c.examples) {
111 Plasma::PushButton *button = new Plasma::PushButton;
112 button->setText(e.name);
113 connect(button, SIGNAL(clicked()), this, SLOT(loadExample()));
114 m_example_buttons.back().push_back(button);
115 }
116 }
117 loadButtons(m_category_buttons, "Categories");
118}
119
120void KdeDemo::loadExampleList()
121{
122 Plasma::PushButton *button = qobject_cast<Plasma::PushButton*>(sender());
123 if (!button)
124 return;
125
126 foreach (Plasma::PushButton *b, m_category_buttons)
127 b->hide();
128 m_back_button->show();
129
130 int index = m_category_buttons.indexOf(button);
131 *m_current_category = m_categories.at(index);
132 QString file("kdeexamples/" + m_current_category->dirName + "/README");
133 loadTextFromFile(m_current_category->name, KStandardDirs::locate("data", file));
134 loadButtons(m_example_buttons.at(index), button->text());
135}
136
137void KdeDemo::loadExample()
138{
139 Plasma::PushButton *button = qobject_cast<Plasma::PushButton*>(sender());
140 if (!button)
141 return;
142
143 m_show_source_button->show();
144 m_quit_launch_button->disconnect();
145 m_quit_launch_button->setText("Launch");
146 connect(m_quit_launch_button, SIGNAL(clicked()), this, SLOT(launchExample()));
147
148 int i = m_categories.indexOf(*m_current_category);
149 int j = m_example_buttons.at(i).indexOf(button);
150
151 *m_current_example = m_current_category->examples.at(j);
152 QString file("kdeexamples/" + m_current_category->dirName + "/" + m_current_example->fileName + "/README");
153 loadTextFromFile(m_current_example->name, KStandardDirs::locate("data", file));
154}
155
156void KdeDemo::backToCategories()
157{
158 foreach (Plasma::PushButton *b, m_current_buttons)
159 b->hide();
160 m_back_button->hide();
161 m_show_source_button->hide();
162 loadButtons(m_category_buttons, "Categories");
163 loadTextFromFile("KDE Examples and Demos", KStandardDirs::locate("data", "kdeexamples/README"));
164 m_quit_launch_button->disconnect();
165 m_quit_launch_button->setText("Quit");
166 connect(m_quit_launch_button, SIGNAL(clicked()), this, SLOT(destroy()));
167}
168
169void KdeDemo::openSourceCode()
170{
171 QString dir(KStandardDirs::locate("data", "kdeexamples/" + m_current_category->dirName + "/" + m_current_example->fileName + "/"));
172 if (dir.isEmpty()) {
173 KMessageBox::information(0, "Sorry, no source code available for this example.");
174 return;
175 }
176
177 QProcess *process = new QProcess(this);
178 process->setWorkingDirectory(dir);
179 process->start("ls");
180 process->waitForFinished(-1);
181 QString files = process->readAll();
182 files.remove("README");
183
184 QStringList source_code = files.split("\n", QString::SkipEmptyParts);
185
186 if (source_code.empty())
187 return;
188
189 process = new QProcess(this);
190 process->setWorkingDirectory(dir);
191 process->start(KStandardDirs::locate("exe", "kate"), QStringList() << "-n" << source_code);
192}
193
194void KdeDemo::launchExample()
195{
196 QProcess *process = new QProcess(this);
197 QString f = m_current_example->fileName;
198 if (!m_current_example->plasmoid) {
199 process->start(KStandardDirs::locate("exe", f));
200 } else {
201 process->start(KStandardDirs::locate("exe", "plasmoidviewer"), QStringList() << f);
202 }
203}
204
205void KdeDemo::loadButtons(QList<Plasma::PushButton*> list, QString text)
206{
207 m_current_buttons = list;
208 foreach (Plasma::PushButton *b, m_current_buttons)
209 b->show();
210 QGraphicsLinearLayout *layout = new QGraphicsLinearLayout(Qt::Vertical);
211 m_tittle->setText("<h2>"+text+"</h2>");
212 layout->addItem(m_tittle);
213 foreach (Plasma::PushButton *b, list)
214 layout->addItem(b);
215 layout->addStretch();
216
217 m_layout->addItem(layout, 0, 0);
218}
219
220void KdeDemo::loadConfig()
221{
222 QString file_name = KStandardDirs::locate("data", "kdeexamples/kdedemo/");
223 if (file_name.isEmpty()) {
224 setFailedToLaunch(true, "No config file");
225 return;
226 }
227
228 QXmlSimpleReader xmlReader;
229 XmlHandler handler;
230 xmlReader.setContentHandler(&handler);
231 QXmlInputSource *source = new QXmlInputSource(new QFile(file_name + "examples.xml"));
232 if (xmlReader.parse(source))
233 m_categories = handler.getCategories();
234}
235
236void KdeDemo::loadTextFromFile(QString tittle, QString file_name)
237{
238 QString text_string("<h1>" + tittle + "</h1>");
239 QFile file(file_name);
240 if (file.open(QIODevice::ReadOnly)) {
241 QTextStream in(&file);
242 text_string += "<p>";
243 while (!in.atEnd()) {
244 QString line = in.readLine();
245 if (line.isEmpty()) {
246 text_string += "</p><p>";
247 } else {
248 text_string += line;
249 text_string += " ";
250 }
251 }
252 text_string += "</p>";
253 } else {
254 text_string += "<p>No description available</p>";
255 }
256 m_text->setText(text_string);
257}
258