Right click fixed, again
[on:on.git] / shell / on.cpp
1 #include "on.h"
2
3 On::On(QWidget *parent)
4     : QWebView(parent)
5 {
6     setWindow();
7     setWebSettings();
8     setWallpaper();
9     setNative();
10     loadByLanguage();
11     //setUrl(QUrl("/usr/share/on/shell/index.html"));
12     connect(page()->mainFrame(), SIGNAL(javaScriptWindowObjectCleared()), this, SLOT(setNative()));
13     //setWatchers();
14     QFuture<void> future = QtConcurrent::run(this, &On::setWatchers);
15 }
16
17 On::~On()
18 {
19
20 }
21
22 QString On::username() { return QDir::homePath().remove("/home/"); }
23
24 QString On::userDir(int dir) { return QDesktopServices::storageLocation(QDesktopServices::StandardLocation(dir)); }
25
26 QString On::userDirName(int dir) { return QDesktopServices::displayName(QDesktopServices::StandardLocation(dir)); }
27
28 QString On::lang()
29 {
30     QString lang = QLocale::system().name().split("_").first();
31     if (lang == "C") {
32         lang = "en";
33     }
34     return lang;
35 }
36
37 // Set the window that is going to be the whole desktop
38 void On::setWindow()
39 {
40     /*if(getenv("QT_GRAPHICSSYSTEM") == 0) {
41         QApplication::setGraphicsSystem("raster");
42     }*/
43
44     QDesktopWidget* desktop = QApplication::desktop();
45     const QRect screen = desktop->screenGeometry(this);
46
47     static Atom atom = XInternAtom(QX11Info::display(), "_NET_WM_DESKTOP", False);
48     ulong data[1];
49     data[0] = 0xFFFFFFFF;
50     XChangeProperty(QX11Info::display(), winId(), atom, atom, 32, PropModeReplace, (unsigned char *) data, 1);
51
52     setWindowFlags(Qt::WindowStaysOnBottomHint);
53     setAttribute(Qt::WA_X11NetWmWindowTypeDesktop);
54     //showMaximized();
55
56     setGeometry(0, 24, desktop->width(), desktop->height());
57
58     /*if (QX11Info::isCompositingManagerRunning()) {
59         setAttribute(Qt::WA_TranslucentBackground);
60     } else {
61         setAutoFillBackground(true);
62     }*/
63     setContextMenuPolicy(Qt::NoContextMenu);
64     setFocus();
65 }
66
67 // Set some things of WebKit
68 void On::setWebSettings()
69 {
70     QSettings cfg(QSettings::IniFormat, QSettings::UserScope, "asturix", "on");
71     QString cfgDir = QFileInfo(cfg.fileName()).absolutePath() + "/";
72     settings()->setLocalStoragePath(cfgDir);
73     settings()->setIconDatabasePath(cfgDir);
74     settings()->setOfflineStoragePath(cfgDir);
75     settings()->setAttribute(QWebSettings::AcceleratedCompositingEnabled, true);
76     settings()->setAttribute(QWebSettings::JavascriptCanAccessClipboard, true);
77     settings()->setAttribute(QWebSettings::LocalContentCanAccessFileUrls, true);
78     settings()->setAttribute(QWebSettings::LocalContentCanAccessRemoteUrls, true);
79     settings()->setAttribute(QWebSettings::LocalStorageEnabled, true);
80     settings()->setAttribute(QWebSettings::LocalStorageDatabaseEnabled, true);
81     settings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true);
82 }
83
84 // Add this to the Javascript window object so this can be accessed from web code
85 void On::setNative() {
86     page()->mainFrame()->addToJavaScriptWindowObject("native", this);
87 }
88
89 // Set the background
90 // NOTE: The background is controlled by Qt because setting it as a CSS background is too slow
91 void On::setWallpaper()
92 {
93     GSettings *backgroundSettings = g_settings_new("org.gnome.desktop.background");
94     QString bg = QUrl::fromEncoded(g_variant_get_string(g_settings_get_value(backgroundSettings, "picture-uri"), 0)).toString();
95     QPalette p = palette();
96     QRect rect = this->rect();
97     if (!bg.isEmpty()) {
98         bg = bg.remove("file://");
99         QPixmap background(QFileInfo(bg).canonicalFilePath());
100         if (background.isNull()) {
101             background = QPixmap("/usr/share/themes/Asturix/backgrounds/asturix4.jpg");
102         }
103         QSize size(rect.width(), rect.height());
104         QPixmap pixmap(background.scaledToWidth(size.width(), Qt::SmoothTransformation));
105         //QPixmap pixmap(background.scaled(size, Qt::KeepAspectRatio));
106         //QPixmap pixmap(background.scaled(size));
107         p.setBrush(QPalette::Background, pixmap);
108         // TODO: Modes. picture-options: zoom, fill, span, scale, center, tile
109     } else {
110         QColor primColor(g_variant_get_string(g_settings_get_value(backgroundSettings, "primary-color"), 0));
111         qDebug(g_variant_get_string(g_settings_get_value(backgroundSettings, "primary-color"), 0));
112         QColor secColor(g_variant_get_string(g_settings_get_value(backgroundSettings, "secondary-color"), 0));
113         QString mode = QString(g_variant_get_string(g_settings_get_value(backgroundSettings, "color-shading-type"), 0));
114         QBrush brush;
115         if (mode == "solid") {
116             brush = QBrush(primColor);
117         } else if (mode == "vertical") {
118             QLinearGradient grad(QPointF(0, 0), QPointF(0, rect.height()));
119             grad.setColorAt(0, primColor);
120             grad.setColorAt(1, secColor);
121             brush = QBrush(grad);
122         } else {
123             QLinearGradient grad(QPointF(0, 0), QPointF(rect.width(), 0));
124             grad.setColorAt(0, primColor);
125             grad.setColorAt(1, secColor);
126             brush = QBrush(grad);
127         }
128         p.setBrush(QPalette::Background, brush);
129     }
130     setPalette(p);
131     p.setBrush(QPalette::Base, Qt::transparent);
132     page()->setPalette(p);
133     setAttribute(Qt::WA_OpaquePaintEvent, false);
134     g_object_unref(backgroundSettings);
135 }
136
137 void On::loadByLanguage() {
138     QFile file("/usr/share/on/shell/index.html");
139     if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
140         QString contents;
141         while (!file.atEnd()) {
142             QByteArray line = file.readLine();
143             contents.append(line);
144         }
145         setHtml(contents.replace("LANGUAGE", lang()), QUrl("file:///usr/share/on/shell/index.html"));
146     }
147 }
148
149 QString On::appsJSON() {
150     QFile file("/var/local/asturix/launcherjsonview.json");
151     if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
152         QString contents;
153         while (!file.atEnd()) {
154             QByteArray line = file.readLine();
155             contents.append(line);
156         }
157         return contents;
158     }
159     return QString();
160 }
161
162 // Get the base64 of the theme icon
163 QString On::getThemeIcon(QString icon) {
164
165     if (icon.contains("/") && !QFile::exists(icon)) {
166         GtkIconInfo *iconInfo = gtk_icon_theme_lookup_icon(gtk_icon_theme_get_default(), "application-default-icon", 48, (GtkIconLookupFlags)0);
167         icon = gtk_icon_info_get_filename(iconInfo);
168         gtk_icon_info_free(iconInfo);
169     } else if (!icon.contains("/")) {
170         GtkIconInfo *iconInfo = gtk_icon_theme_lookup_icon(gtk_icon_theme_get_default(), icon.toAscii(), 48, (GtkIconLookupFlags)0);
171         if (iconInfo == NULL) {
172             iconInfo = gtk_icon_theme_lookup_icon(gtk_icon_theme_get_default(), "application-default-icon", 48, (GtkIconLookupFlags)0);
173         }
174         icon = gtk_icon_info_get_filename(iconInfo);
175         gtk_icon_info_free(iconInfo);
176     }
177     QPixmap pixmap = QIcon(icon).pixmap(48, 48);
178     QByteArray byteArray;
179     QBuffer buffer(&byteArray);
180     pixmap.save(&buffer, "PNG");
181     QString iconBase64 = QString::fromLatin1(byteArray.toBase64().data());
182     return iconBase64;
183 }
184
185 #define EVENT_SIZE  ( sizeof (struct inotify_event) )
186 #define BUF_LEN     ( 1024 * ( EVENT_SIZE + 16 ) )
187
188 // Set some watchers so we can monitorize dirs, files etc.
189 void On::setWatchers() {
190
191     Inotify notify;
192
193     InotifyWatch watch("/var/local/asturix/launcherjsonview.json", IN_CLOSE_WRITE);
194     notify.Add(watch);
195
196     for (;;) {
197         notify.WaitForEvents();
198
199         size_t count = notify.GetEventCount();
200         while (count > 0) {
201             InotifyEvent event;
202             bool got_event = notify.GetEvent(&event);
203
204             if (got_event) {
205                 QMetaObject::invokeMethod(this,"appsChanged",Qt::QueuedConnection);
206             }
207
208             count--;
209         }
210     }
211
212 }
213
214 // Execute code when /var/local/asturix/launcherjsonview.json file is modified
215 void On::appsChanged() {
216     page()->mainFrame()->evaluateJavaScript("refreshAppsList();");
217 }
218
219 // Execute a command
220 // NOTE: The buffer of the process is being read and shown
221 void On::exec(QString exec) {
222     /*QProcess proc;
223     proc.start("/bin/sh -c \""+exec+"\"");*/
224     QProcess::startDetached("/bin/sh -c \""+exec+"\"");
225 }
226
227 /*void On::showNotification(QString title, QString content, QString themeIcon, int time) {
228     //QProcess::startDetached("notify-send "+title+" "+content+" -i "+themeIcon);
229
230     NotifyNotification *notif = notify_notification_new(title.toUtf8(), content.toUtf8(), themeIcon.toUtf8());
231     notify_notification_set_timeout(notif, time);
232     notify_notification_show(notif, NULL);
233     g_object_unref(notif);
234 }*/
235
236 QString On::gdkPixbufToBase64(GdkPixbuf *pixbuf) {
237     if (pixbuf == NULL) {
238         GtkIconInfo *iconInfo = gtk_icon_theme_lookup_icon(gtk_icon_theme_get_default(), "application-default-icon", 48, (GtkIconLookupFlags)0);
239         pixbuf = gtk_icon_info_load_icon(iconInfo, NULL);
240         gtk_icon_info_free(iconInfo);
241     }
242     QImage image(gdk_pixbuf_get_pixels(pixbuf),
243         gdk_pixbuf_get_width(pixbuf),
244         gdk_pixbuf_get_height(pixbuf),
245         gdk_pixbuf_get_rowstride(pixbuf),
246         QImage::Format_ARGB32);
247     QImage swappedImage = image.rgbSwapped();
248     QByteArray byteArray;
249     QBuffer buffer(&byteArray);
250     swappedImage.save(&buffer, "PNG");
251     QString iconBase64 = QString::fromLatin1(byteArray.toBase64().data());
252     g_object_unref(pixbuf);
253     return iconBase64;
254 }
255
256 #define GFOREACH(item, list) for(GList *__glist = list; __glist && (item = __glist->data, true); __glist = __glist->next)
257
258 QStringList On::placesBookmarks() {
259
260     QFile file(QDir::homePath()+"/.gtk-bookmarks");
261     if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
262         QStringList bookmarks;
263         while (!file.atEnd()) {
264             QByteArray line = file.readLine();
265             line = line.replace("\n", "");
266             GFile *file = g_file_new_for_uri(line);
267             GFileInfo *fileInfo = g_file_query_info(file, "standard::*", 0, NULL, NULL);
268             QString icon = g_icon_to_string(g_file_info_get_icon(fileInfo));
269             if (icon != NULL) {
270                 icon = icon.split(" ")[2];
271                 bookmarks.append(line);
272                 bookmarks.append(QFileInfo(line).fileName());
273                 bookmarks.append(getThemeIcon(icon));
274             }
275         }
276         return bookmarks;
277     }
278     return QStringList();
279 }
280
281 QStringList On::recentFiles() {
282
283     QStringList recent;
284
285     GtkRecentManager *manager = gtk_recent_manager_get_default();
286     GList *list = gtk_recent_manager_get_items(manager);
287     GtkRecentInfo *item;
288
289     int i = 0;
290
291     GFOREACH(item, list) {
292         recent.append(QUrl::fromEncoded(gtk_recent_info_get_uri(item)).toString());
293         recent.append(QUrl::fromEncoded(gtk_recent_info_get_display_name(item)).toString());
294         recent.append(gdkPixbufToBase64(gtk_recent_info_get_icon(item, 48)));
295         if (i == 50) {
296             gtk_recent_info_unref(item);
297             g_list_free(list);
298             return recent;
299         }
300         i++;
301     }
302     gtk_recent_info_unref(item);
303     g_list_free(list);
304     //g_object_unref(manager);
305     return recent;
306 }