trabucco1.1/ 0000755 0001750 0001750 00000000000 13110635066 012133 5 ustar salvo salvo trabucco1.1/desktopaction.cpp 0000644 0001750 0001750 00000013445 13110635066 015515 0 ustar salvo salvo /*
This file is part of Trabucco.
Trabucco is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Trabucco is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Trabucco. If not, see .
Copyright (C) 2016 Salvo "LtWorf" Tomaselli
Copyright (C) 2016 Giuseppe Bilotta
*/
#include
#include
#include
#include
#include
#include
#include "desktopaction.h"
#include "iconfinder.h"
/**
* @brief DesktopAction::clear_action
*
* Removes the placeholders for the command line parameters.
*/
void DesktopAction::clear_action() {
static const char * substitutions[] = {
"%f",
"%F",
"%u",
"%U",
"%d",
"%D",
"%n",
"%N",
"%i",
"%k",
"%v",
"%m",
};
this->action = this->action.replace("%c", this->name);
for (unsigned int i=0; i< sizeof(substitutions)/sizeof(int*); i++) {
this->action = this->action.replace(substitutions[i],"");
}
}
DesktopAction::DesktopAction(QString file, QObject *parent): Action(parent) {
QSettings settings(file, QSettings::IniFormat);
settings.setIniCodec("UTF-8");
this->name = settings.value("Desktop Entry/Name","").toString();
this->icon = settings.value("Desktop Entry/Icon","").toString();
this->action = settings.value("Desktop Entry/Exec","").toString();
this->terminal = settings.value("Desktop Entry/Terminal","false").toBool();
this->clear_action();
this->show = true;
//Determine wheter to show it
if (settings.value("Desktop Entry/NoDisplay","false").toBool()) {
this->show = false;
}
//Show/hide depending on the DE being used
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
QSet desktop_environments = QSet::fromList(
env.value("XDG_CURRENT_DESKTOP","").split(":")
);
QSet not_show = QSet::fromList(
settings.value("Desktop Entry/NotShowIn","").toString().split(":")
);
QSet show_in = QSet::fromList(
settings.value("Desktop Entry/OnlyShowIn","").toString().split(":")
);
desktop_environments.remove("");
not_show.remove("");
show_in.remove("");
int show_in_c = show_in.size();
if (not_show.size()) {
not_show.intersect(desktop_environments);
if (not_show.size() != 0) {
this->show = false;
}
}
if (show_in_c) {
show_in.subtract(desktop_environments);
if (show_in_c == show_in.size()) {
this->show = false;
}
}
if (settings.value("Desktop Entry/Hidden", "false").toBool()) {
this->show = false;
}
}
bool DesktopAction::mustShow() {
return this->show;
}
void DesktopAction::runAction() {
printf("%s\n", this->action.toStdString().c_str());
if (!this->terminal) {
QProcess::startDetached(this->action);
} else {
QProcess::startDetached("x-terminal-emulator -e " + this->action);
}
}
QString DesktopAction::getIcon() {
if (!this->cached_icon) {
this->cached_icon_path = IconFinder::FindIcon(this->icon);
this->cached_icon = true;
}
return this->cached_icon_path;
}
static void iterate_dir(BTree* tree, QString dir, QObject* parent) {
// Include subdirectories and follow links
QDirIterator i(dir, QDirIterator::Subdirectories | QDirIterator::FollowSymlinks);
while (i.hasNext()) {
QString path = i.next();
if (!path.endsWith(".desktop")) {
continue;
}
QFileInfo info(path);
if (info.isFile() && info.isReadable()) {
DesktopAction * action = new DesktopAction(path, parent);
if (!action->mustShow() || !tree->add(action))
delete action;
}
}
}
// Following the freedesktop.org specification, we look for applications in the
// `applications` subdirectory of:
// $XDG_DATA_HOME (which defaults to `$HOME/.local/share`),
// and all components of $XDG_DATA_DIRS (a colon-separated list of paths
// that defaults to `/usr/local/share/:/usr/share/`)
static const QString xdg_data_dirs_default = "/usr/local/share/:/usr/share/";
/**
* @brief DesktopAction::GetPaths
* @return the list of paths containing .desktop files
*/
QStringList* DesktopAction::GetPaths() {
static QStringList* result = NULL;
if (result)
return result;
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
QStringList xdg_data_dirs =
env.value("XDG_DATA_DIRS", xdg_data_dirs_default).split(":");
// put user's data dir before the system ones
xdg_data_dirs.prepend(env.value("XDG_DATA_HOME", QDir::homePath() + "/.local/share/"));
result = new QStringList();
QStringListIterator i(xdg_data_dirs);
while (i.hasNext()) {
result->append(i.next() + "/applications");
}
result->removeDuplicates();
return result;
}
/**
* @brief DesktopAction::LoadDesktopActions
* @return a stack containing Action for all the .desktop files
*/
void DesktopAction::LoadDesktopActions(BTree* tree, QObject *parent) {
QStringListIterator i(*DesktopAction::GetPaths());
while (i.hasNext()) {
iterate_dir(tree, i.next(), parent);
}
}
trabucco1.1/bookmarkaction.cpp 0000644 0001750 0001750 00000024361 13110635066 015650 0 ustar salvo salvo /*
This file is part of Trabucco.
Trabucco is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Trabucco is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Trabucco. If not, see .
Copyright (C) 2016 Salvo "LtWorf" Tomaselli
Copyright (C) 2016 Giuseppe Bilotta
*/
#include "bookmarkaction.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "cache.h"
#include "downloader.h"
#include "iconfinder.h"
/**
* @brief load_from_chromium
* @param tree: add the Actions to this tree
* @param value
*
* Recursively load bookmarks from chromium json file.
*
* The json has many levels, some can be done with objects
* and some can be done with arrays.
*
* This function iterates the entire document until it finds
* actual bookmarks and adds them.
*/
static void load_from_chromium(BTree *tree, QJsonValue *value, QObject* parent) {
if (value->isUndefined())
return;
QJsonObject obj;
if (value->isObject()) {
obj = value->toObject();
QJsonValue type = obj.value("type");
if (type.toString() == "url") {
//Found a URL.
QString name = obj.value("name").toString();
QString url = obj.value("url").toString();
if (name.length()!=0 && url.length() != 0) {
BookmarkAction* bookmark = new BookmarkAction(name,url,"", parent);
if (!tree->add(bookmark))
delete bookmark;
}
} else {
QStringList keys = obj.keys();
for (int i = 0; i < keys.length(); i++) {
QJsonValue tmp = obj.value(keys[i]);
load_from_chromium(tree, &tmp, parent);
}
}
} else if (value->isArray()) {
QJsonArray array = value->toArray();
for (int i=0; i< array.size(); i++) {
QJsonValue tmp = array.at(i);
load_from_chromium(tree, &tmp, parent);
}
}
}
/**
* @brief load_from_chromium
* @param tree
* @param chromium_bookmarks
*
* Load bookmarks actions from a chromium-like json file into the tree.
*/
static void load_from_chromium(BTree* tree, QFileInfo chromium_bookmarks, QObject* parent) {
if (chromium_bookmarks.exists() && chromium_bookmarks.isReadable()) {
QFile bookmarks(chromium_bookmarks.absoluteFilePath());
bookmarks.open(QIODevice::ReadOnly);
QByteArray content = bookmarks.readAll();
QJsonDocument document = QJsonDocument::fromJson(content);
if (document.isObject()) {
QJsonValue obj = document.object();
load_from_chromium(tree, &obj, parent);
}
}
}
/**
* @brief load_from_firefox_places
*
* Load bookmark actions from a Firefox-like `places` SQLite database
*/
static void load_from_firefox_places(
BTree *tree, //< [out] action tree to add actions to
QString dbfile, //< path to a Firefox places database
QObject* parent
) {
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName(dbfile);
if (!db.open()) {
qDebug() << "Failed to open Firefox bookmarks @ " << dbfile << "\n";
}
qDebug() << "Loading Firefox bookmarks @ " << dbfile << "\n";
QSqlQuery query(
"select moz_bookmarks.title, moz_places.url, moz_favicons.url "
"from moz_bookmarks, moz_places left join moz_favicons "
"on moz_places.favicon_id = moz_favicons.id "
"where moz_bookmarks.fk = moz_places.id;",
db);
while (query.next()) {
QString title = query.value(0).toString();
QString url = query.value(1).toString();
// skip entry if it has no title or it's a special place or a bookmarklet
if (title.isEmpty() || url.startsWith("place:") || url.startsWith("javascript:"))
continue;
QString icon_url = query.value(2).toString();
BookmarkAction* bookmark = new BookmarkAction(title, url, icon_url, parent);
if (!tree->add(bookmark))
delete bookmark;
}
db.close();
}
/**
* @brief load_from_firefox
*
* Load bookmark actions from the default Firefox profile found in a given directory
*/
static void load_from_firefox(
BTree *tree, //< [out] action tree to add actions to
QString path,//< path to a Firefox configuration directory
QObject* parent
) {
QSettings profiles(path + "profiles.ini", QSettings::IniFormat);
QStringList groups(profiles.childGroups());
groups.removeAll("General");
QStringListIterator group(groups);
QString section;
// If there are multiple profiles defined, then we want the one with
// Default=1; otherwise, we just want the first one. We could do conditionals
// based on the number of elements in groups, but it's simpler to just
// over the whole list, break if we meet one with Default=1, and
// just leave the last one selected.
while (group.hasNext()) {
section = group.next();
if (profiles.value(section + "/Default").toInt() == 1)
break;
}
if (section.isEmpty()) {
qDebug() << "No Firefox profile found\n";
return;
}
profiles.beginGroup(section);
qDebug() << "Loading from profile " << profiles.value("Name").toString() << "\n";
// TODO FIXME handle IsRelative
QString places_path = path + profiles.value("Path").toString() + "/places.sqlite";
load_from_firefox_places(tree, places_path, parent);
profiles.endGroup();
}
/**
* Load bookmarks from an Opera bookmark list (pre-Blink versions)
*/
static void load_from_opera12(
BTree* tree, //< [out] action tree to add actions to
QString path, //< path to the old Opera bookmark file
QObject* parent
) {
QFile bookmarks(path);
if (!bookmarks.exists())
return;
bookmarks.open(QIODevice::ReadOnly);
// file is UTF-8 encoded, and QString reads a QByteArray assuming
// that encoding, so we're good
QString content(bookmarks.readAll());
int section_begin = 0;
int section_end = 0;
// delete the Trash folder from the content
section_begin = content.indexOf("TRASH FOLDER=YES");
section_end = content.indexOf("\n\n-\n\n", section_begin);
content.remove(section_begin, section_end - section_begin);
// bookmarks are stored in sections that begin with #URL and end with double-newlines
while ((section_begin = content.indexOf("#URL\n", section_end)) >= 0) {
section_end = content.indexOf("\n\n", section_begin);
if (section_end < 0)
section_end = content.length();
QStringRef section(&content, section_begin, section_end - section_begin);
// skip 'partner' bookmarks
if (section.contains("\tPARTNERID="))
continue;
int name_idx = section.indexOf("\tNAME=");
int url_idx = section.indexOf("\tURL=");
if (name_idx < 0 || url_idx < 0)
continue;
name_idx += 6;
url_idx += 5;
int name_end = section.indexOf("\n", name_idx);
int url_end = section.indexOf("\n", url_idx);
QString name(section.mid(name_idx, name_end - name_idx).toString());
QString url(section.mid(url_idx, url_end - url_idx).toString());
BookmarkAction* bookmark = new BookmarkAction(name, url, QString(), parent);
if (!tree->add(bookmark))
delete bookmark;
}
}
/**
* @brief BookmarkAction::LoadBookmarkActions
* @param tree
*
* Loads bookmarks actions inside the tree
*/
void BookmarkAction::LoadBookmarkActions(BTree* tree, QObject *parent) {
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
QString config_root = env.value("XDG_CONFIG_HOME",
env.value("HOME") + "/.config");
QFileInfo chromium_bookmarks(config_root + "/chromium/Default/Bookmarks");
load_from_chromium(tree, chromium_bookmarks, parent);
QFileInfo opera_bookmarks(config_root + "/opera/Bookmarks");
load_from_chromium(tree, opera_bookmarks, parent);
QFileInfo google_chrome(config_root + "/google-chrome/Default/Bookmarks");
load_from_chromium(tree, google_chrome, parent);
QString ff_config_root = env.value("HOME") + "/.mozilla/firefox/";
load_from_firefox(tree, ff_config_root, parent);
load_from_opera12(tree, env.value("HOME") + "/.opera/bookmarks.adr", parent);
}
QStringList* BookmarkAction::GetPaths() {
static QStringList* result = NULL;
if (result)
return result;
result = new QStringList();
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
QString config_root = env.value("XDG_CONFIG_HOME",
env.value("HOME") + "/.config");
result->append(config_root + "/chromium/Default/Bookmarks");
result->append(config_root + "/opera/Bookmarks");
result->append(config_root + "/google-chrome/Default/Bookmarks");
result->append(env.value("HOME") + "/.opera/bookmarks.adr");
//TODO firefox path for bookmarks
return result;
}
bool BookmarkAction::hasCornerIcon() {
return true;
}
BookmarkAction::BookmarkAction(QString name, QUrl url, QString icon, QObject* parent): Action(parent) {
this->name = name;
this->url = url;
this->icon = Cache::cached_icon(url);
QFileInfo cached_icon(this->icon);
if (!cached_icon.exists())
Cache::download_favicon(url, this->icon, this, icon);
}
void BookmarkAction::runAction() {
QDesktopServices::openUrl(url);
}
QString BookmarkAction::getIcon() {
static QString browser = IconFinder::FindIcon("internet-web-browser");
return browser;
}
QString BookmarkAction::getCornerIcon() {
QFileInfo cached_icon(this->icon);
//If the downloader managed to get an icon return it
if (cached_icon.size() != 0)
return this->icon;
//Return the default icon
return "";
}
trabucco1.1/cache.cpp 0000644 0001750 0001750 00000004440 13110635066 013704 0 ustar salvo salvo /*
This file is part of Trabucco.
Trabucco is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Trabucco is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Trabucco. If not, see .
Copyright (C) 2016 Salvo "LtWorf" Tomaselli
*/
#include
#include
#include
#include
#include
#include "cache.h"
#include "downloader.h"
/**
* @brief Cache::create_cache_dir
*
* Make sure that the cache directory exists.
*/
void Cache::create_cache_dir() {
QString cache_path = QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
QDir dir;
if (!dir.exists(cache_path)) {
dir.mkdir(cache_path);
}
}
/**
* @brief Create an hash path to store the favicon of a website
* @param favicon
* @return
*/
QString Cache::cached_icon(QUrl url) {
url.setPath("/favicon.ico");
url.setQuery("");
QByteArray hash = QCryptographicHash::hash(
url.toString().toLatin1(),
QCryptographicHash::Md5
);
QString cache_dir = QStandardPaths::writableLocation(QStandardPaths::CacheLocation);
return cache_dir + "/" + hash.toHex();
}
void Cache::download_favicon(QUrl url, QString destination, QObject* parent, QString default_icon) {
url.setQuery("");
//Create empty destination file
QFile cache(destination);
cache.open(QIODevice::WriteOnly);
cache.close();
QStringList icons;
//The icon indicated in the bookmark
if (default_icon.size() != 0 && ! default_icon.startsWith("blob:")) {
icons.append(default_icon);
}
url.setPath("//apple-touch-icon.png");
icons.append(url.toString());
url.setPath("/favicon.ico");
icons.append(url.toString());
//Setting this as parent to free the memory of it
new Downloader(icons, destination, parent);
}
trabucco1.1/node.h 0000644 0001750 0001750 00000002114 13110635066 013227 0 ustar salvo salvo /*
This file is part of Trabucco.
Trabucco is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Trabucco is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Trabucco. If not, see .
Copyright (C) 2016 Salvo "LtWorf" Tomaselli
*/
#ifndef NODE_H
#define NODE_H
#include
#include
#include
#include "action.h"
class Node {
public:
Node();
Node(Action* action);
~Node();
void add(Action* action);
Action * search(QString prefix);
private:
QHash hash;
Action * action=NULL;
void add(Action* action, QString name);
Action * _search(QString prefix);
};
#endif // NODE_H
trabucco1.1/clipboard.h 0000644 0001750 0001750 00000001562 13110635066 014247 0 ustar salvo salvo /*
This file is part of Trabucco.
Trabucco is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Trabucco is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Trabucco. If not, see .
Copyright (C) 2016 Salvo "LtWorf" Tomaselli
*/
#ifndef CLIPBOARD_H
#define CLIPBOARD_H
#include
#include
class Clipboard : public QObject
{
Q_OBJECT
public slots:
QString getSelection();
};
#endif // CLIPBOARD_H
trabucco1.1/singleinstance.h 0000644 0001750 0001750 00000000331 13110635066 015307 0 ustar salvo salvo #ifndef SINGLEINSTANCE_H
#define SINGLEINSTANCE_H
typedef enum {
SYSTEM,
SESSION,
} scope_t;
class SingleInstance
{
public:
static bool unique(QString key, scope_t scope);
};
#endif // SINGLEINSTANCE_H
trabucco1.1/downloader.cpp 0000644 0001750 0001750 00000003340 13110635066 014775 0 ustar salvo salvo /*
This file is part of Trabucco.
Trabucco is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Trabucco is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Trabucco. If not, see .
Copyright (C) 2016 Salvo "LtWorf" Tomaselli
*/
#include "downloader.h"
#include
#include
Downloader::Downloader(QStringList sources, QString destination, QObject *parent) : QObject(parent) {
this->sources = sources;
this->destination = destination;
//this->dest_file = QFile(destination);
connect(
&this->nam,
&QNetworkAccessManager::finished,
this,
&Downloader::finished
);
this->download();
//TODO place a lock on the destination file
}
void Downloader::finished(QNetworkReply* reply) {
if (reply->error() != QNetworkReply::NoError) {
this->download();
return;
}
QString tmp = destination + "_temp";
QFile dest(tmp);
dest.open(QIODevice::WriteOnly);
dest.write(reply->readAll());
dest.close();
QDir d;
d.remove(destination);
d.rename(tmp, destination);
}
void Downloader::download() {
if (this->sources.isEmpty())
return;
QUrl url(this->sources.at(0));
this->sources.removeFirst();
QNetworkRequest request(url);
this->nam.get(request);
}
trabucco1.1/searchaction.cpp 0000644 0001750 0001750 00000011244 13110635066 015304 0 ustar salvo salvo /*
This file is part of Trabucco.
Trabucco is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Trabucco is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Trabucco. If not, see .
Copyright (C) 2016 Salvo "LtWorf" Tomaselli
*/
#include "searchaction.h"
#include
#include
#include
#include
#include
#include
#include "cache.h"
#include "iconfinder.h"
static QString get_url(QString action, QString query) {
action.replace("\\{@}", QUrl::toPercentEncoding(query));
return action;
}
SearchAction::SearchAction(QString name, QString query, bool hidden, QObject *parent): Action(parent) {
this->name = name + ":";
this->action = query;
this->show = ! hidden;
//Hide invalid entries
if (!name.size() || !query.size())
this->show = false;
if (this->show == false)
return;
QUrl url = get_url(this->action, "");
this->icon = Cache::cached_icon(url);
QFileInfo cached_icon(this->icon);
if (!cached_icon.exists())
Cache::download_favicon(url, this->icon, this);
}
QList SearchAction::LoadFile(QString file, QObject* parent) {
QList r;
QSettings settings(file, QSettings::IniFormat);
QString charset = settings.value("Desktop Entry/Charset", "").toString();
if (charset == "")
charset = "UTF-8";
settings.setIniCodec(charset.toStdString().c_str());
//Some validation
{
QString type = settings.value("Desktop Entry/Type","").toString();
if (type != "Service")
return r;
}
QString query = settings.value("Desktop Entry/Query","").toString();
bool hidden = settings.value("Desktop Entry/Hidden","").toBool();
QStringList keys = settings.value("Desktop Entry/Keys","").toStringList();
for (int i = 0; i < keys.size(); i++) {
SearchAction* action = new SearchAction(keys.at(i), query, hidden, parent);
r.append(action);
}
return r;
}
QStringList* SearchAction::GetPaths() {
static QStringList* result = NULL;
if (result)
return result;
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
result = new QStringList();
result->append("/usr/share/kservices5/searchproviders/");
if (env.contains("HOME")) {
QString home = env.value("HOME");
QString xdg_data_home = env.value("XDG_DATA_HOME", home + "/.local/share/");
result->append(home + "/.kde/share/kde4/services/searchproviders");
result->append(xdg_data_home + "/kservices5/searchproviders");
}
return result;
}
//TODO de-duplicate this code with the one in desktopaction.cpp
static void iterate_dir(BTree* tree, QString dir, QObject* parent) {
// Include subdirectories and follow links
QDirIterator i(dir, QDirIterator::Subdirectories | QDirIterator::FollowSymlinks);
while (i.hasNext()) {
QString path = i.next();
if (!path.endsWith(".desktop")) {
continue;
}
QFileInfo info(path);
if (info.isFile() && info.isReadable()) {
QList actions = SearchAction::LoadFile(path, parent);
for (int i=0; i < actions.size(); i++) {
SearchAction* action = actions.at(i);
if (!action->mustShow() || !tree->add(action))
delete action;
}
}
}
}
bool SearchAction::mustShow() {
return this->show;
}
void SearchAction::LoadSearchActions(BTree* tree, QObject *parent) {
QStringListIterator i(*SearchAction::GetPaths());
while (i.hasNext()) {
iterate_dir(tree, i.next(), parent);
}
}
bool SearchAction::isPrefix() {
return true;
}
bool SearchAction::hasCornerIcon() {
return true;
}
QString SearchAction::getCornerIcon() {
QFileInfo cached_icon(this->icon);
//If the downloader managed to get an icon return it
if (cached_icon.size() != 0)
return this->icon;
//Return the default icon
return "";
}
QString SearchAction::getIcon() {
static QString browser = IconFinder::FindIcon("internet-web-browser");
return browser;
}
void SearchAction::runAction(QString query) {
QDesktopServices::openUrl(get_url(this->action, query));
}
trabucco1.1/tree.h 0000644 0001750 0001750 00000002462 13110635066 013247 0 ustar salvo salvo /*
This file is part of Trabucco.
Trabucco is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Trabucco is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Trabucco. If not, see .
Copyright (C) 2016 Salvo "LtWorf" Tomaselli
Copyright (C) 2016 Giuseppe Bilotta
*/
#ifndef TREE_H
#define TREE_H
#include
#include
#include
#include "desktopaction.h"
#include "action.h"
#include "node.h"
class Tree : public QObject {
Q_OBJECT
public:
explicit Tree(QObject *parent = 0);
public slots:
Action * search(QString prefix);
void runAction();
void rescan();
private:
bool ready = false;
bool bookmarks;
bool desktop;
bool searchprovider;
QObject* action_parent = NULL;
Action * last = NULL;
QString last_prefix;
Node * node = NULL;
QFileSystemWatcher watcher;
};
#endif // TREE_H
trabucco1.1/settings.h 0000644 0001750 0001750 00000002011 13110635066 014136 0 ustar salvo salvo /*
This file is part of Trabucco.
Trabucco is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Trabucco is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Trabucco. If not, see .
Copyright (C) 2016 Salvo "LtWorf" Tomaselli
*/
#ifndef SETTINGS_H
#define SETTINGS_H
#include
#define CONFIG_RELOAD 23
namespace Ui {
class Settings;
}
class Settings : public QDialog {
Q_OBJECT
public:
explicit Settings(QWidget *parent = 0);
~Settings();
public slots:
void accept();
void grab_error();
private:
Ui::Settings *ui;
};
#endif // SETTINGS_H
trabucco1.1/CHANGELOG 0000644 0001750 0001750 00000000222 13110635066 013341 0 ustar salvo salvo 1.1
* Find more icons
* Show UI to select a different shortcut, if the default one is taken
* Able to reload configuration
1.0
* Initial release
trabucco1.1/desktopaction.h 0000644 0001750 0001750 00000002440 13110635066 015153 0 ustar salvo salvo /*
This file is part of Trabucco.
Trabucco is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Trabucco is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Trabucco. If not, see .
Copyright (C) 2016 Salvo "LtWorf" Tomaselli
Copyright (C) 2016 Giuseppe Bilotta
*/
#ifndef DESKTOPACTION_H
#define DESKTOPACTION_H
#include
#include
#include "action.h"
#include "btree.h"
class DesktopAction: public Action {
public:
DesktopAction(QString file,QObject * parent=NULL);
static void LoadDesktopActions(BTree*, QObject* parent=NULL);
static QStringList* GetPaths();
public slots:
virtual void runAction();
virtual QString getIcon();
bool mustShow();
private:
bool show;
bool terminal;
bool cached_icon = false;
QString cached_icon_path;
void clear_action();
};
#endif // DESKTOPACTION_H
trabucco1.1/action.cpp 0000644 0001750 0001750 00000003032 13110635066 014112 0 ustar salvo salvo /*
This file is part of Trabucco.
Trabucco is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Trabucco is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Trabucco. If not, see .
Copyright (C) 2016 Salvo "LtWorf" Tomaselli
Copyright (C) 2016 Giuseppe Bilotta
*/
#include "action.h"
#include
Action::Action(QObject *parent) : QObject(parent) {
QQmlEngine::setObjectOwnership(
this,
QQmlEngine::CppOwnership
);
}
Action::Action(QString name, QString action, QString icon, QObject *parent): QObject(parent) {
QQmlEngine::setObjectOwnership(
this,
QQmlEngine::CppOwnership
);
this->name = name;
this->action = action;
this->icon = icon;
}
QString Action::getName() {
return this->name;
}
QString Action::getAction() {
return this->action;
}
QString Action::getIcon() {
return this->icon;
}
QString Action::getCornerIcon() {
return "";
}
bool Action::hasCornerIcon() {
return false;
}
bool Action::isPrefix() {
return false;
}
void Action::runAction() {}
void Action::runAction(QString /* unused */) {}
trabucco1.1/shortcutactivator.cpp 0000644 0001750 0001750 00000006166 13110635066 016440 0 ustar salvo salvo /*
This file is part of Trabucco.
Trabucco is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Trabucco is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Trabucco. If not, see .
Copyright (C) 2016 Salvo "LtWorf" Tomaselli
Copyright (C) 2016 Giuseppe Bilotta
*/
#include "shortcutactivator.h"
#include
#include
#include
#include
#include
bool grab_error = False;
int xerrorhandler(Display *, XErrorEvent * ev) {
if (ev->error_code == BadAccess) {
qDebug() << "Unable to grab global shortcut";
grab_error = True;
}
return 0;
}
ShortcutActivator::ShortcutActivator(QObject *parent) : QThread(parent) {
QSettings settings;
const char* k = settings.value("Shortcut/keycode","space").toString().toStdString().c_str();
this->key = XStringToKeysym(k);
this->modifier = settings.value("Shortcut/modifier",Mod1Mask).toUInt();
}
void ShortcutActivator::end() {
this->terminate = true;
}
QString ShortcutActivator::shortcut_name() {
QSettings settings;
QString r;
switch (this->modifier) {
case Mod1Mask:
r = "Alt";
break;
case ControlMask:
r = "Ctrl";
break;
default:
break;
}
r += "+" + settings.value("Shortcut/keycode","space").toString();
return r;
}
void ShortcutActivator::run() {
XSetErrorHandler(xerrorhandler);
Display* dpy = XOpenDisplay(getenv("DISPLAY"));
Window root_window = DefaultRootWindow(dpy);
XEvent ev;
unsigned int keycode = XKeysymToKeycode(dpy, this->key);
{
/*
* Caps lock and num lock count as modifiers,
* so different masks are needed for all their
* statuses.
*/
unsigned int mods[] = {
modifier,
modifier | Mod2Mask, //Num lock
modifier | LockMask, // caps lock
modifier | Mod2Mask | LockMask,
};
Bool owner_events = False;
int pointer_mode = GrabModeAsync;
int keyboard_mode = GrabModeAsync;
for (unsigned int i=0; i<(sizeof(mods)/sizeof(int)); i++) {
XGrabKey(
dpy,
keycode,
mods[i],
root_window,
owner_events,
pointer_mode,
keyboard_mode
);
}
}
XSync(dpy, false);
if (grab_error) {
grab_error = false;
emit grab_failed();
}
while(true) {
XNextEvent(dpy, &ev);
if (ev.type == KeyPress) {
printf("Key pressed\n");
emit this->activated();
}
if(this->terminate)
break;
}
XCloseDisplay(dpy);
}
trabucco1.1/clipboard.cpp 0000644 0001750 0001750 00000001566 13110635066 014606 0 ustar salvo salvo /*
This file is part of Trabucco.
Trabucco is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Trabucco is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Trabucco. If not, see .
Copyright (C) 2016 Salvo "LtWorf" Tomaselli
*/
#include "clipboard.h"
#include
#include
QString Clipboard::getSelection() {
QClipboard* cl = QApplication::clipboard();
return cl->text(QClipboard::Selection);
}
trabucco1.1/singleinstance.cpp 0000644 0001750 0001750 00000002273 13110635066 015651 0 ustar salvo salvo #include
#include
#include "singleinstance.h"
/**
* @brief filename
* @param key
* @param scope
* @return a fully qualified filename
*
* Generates an appropriate filename for the lock
*/
static QString filename(QString key, scope_t scope) {
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
QString tmp = env.value("TEMP", "/tmp") + "/";
QString user = env.value("USER", "alfio");
QString r;
switch (scope) {
case SYSTEM:
r = tmp;
break;
case SESSION:
//TODO this will prevent trabucco to run in multiple sessions
r = env.value("XDG_RUNTIME_DIR", tmp + user) + "/";
break;
}
return r + key + ".lock";
}
/**
* @brief SingleInstance::unique
* @param key the unique name of the program
* @param scope wether it needs to be system-wide or session-wide
* @return true if this is the only instance
*
* Make sure that this instance is unique.
*/
bool SingleInstance::unique(QString key, scope_t scope) {
QLockFile* lock = new QLockFile(filename(key, scope));
bool r = lock->tryLock();
if (!r)
delete lock;
return r;
}
trabucco1.1/btreeiterator.h 0000644 0001750 0001750 00000002177 13110635066 015166 0 ustar salvo salvo /*
This file is part of Trabucco.
Trabucco is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Trabucco is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Trabucco. If not, see .
Copyright (C) 2016 Salvo "LtWorf" Tomaselli
*/
#ifndef BTREEITERATOR_H
#define BTREEITERATOR_H
#include
#include
#include "btree.h"
typedef enum {
LEFT,
SELF,
} iter_state;
typedef struct {
BTree* ptr;
iter_state state;
} stack_item;
class BTreeIterator : public QObject {
Q_OBJECT
public:
BTreeIterator(BTree*, QObject* parent=NULL);
Action* next();
bool hasNext();
private:
QStack stack;
bool can_iterate;
};
#endif // BTREEITERATOR_H
trabucco1.1/action.h 0000644 0001750 0001750 00000002476 13110635066 013572 0 ustar salvo salvo /*
This file is part of Trabucco.
Trabucco is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Trabucco is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Trabucco. If not, see .
Copyright (C) 2016 Salvo "LtWorf" Tomaselli
Copyright (C) 2016 Giuseppe Bilotta
*/
#ifndef ACTION_H
#define ACTION_H
#include
#include
class Action : public QObject {
Q_OBJECT
public:
explicit Action(QObject * parent=NULL);
explicit Action(QString name, QString action, QString icon, QObject * parent=NULL);
signals:
public slots:
QString getName();
QString getAction();
virtual QString getIcon();
virtual void runAction();
virtual void runAction(QString);
virtual bool hasCornerIcon();
virtual bool isPrefix();
virtual QString getCornerIcon();
protected:
QString name;
QString action;
QString icon;
};
#endif // ACTION_H
trabucco1.1/cache.h 0000644 0001750 0001750 00000001707 13110635066 013354 0 ustar salvo salvo /*
This file is part of Trabucco.
Trabucco is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Trabucco is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Trabucco. If not, see .
Copyright (C) 2016 Salvo "LtWorf" Tomaselli
*/
#ifndef CACHE_H
#define CACHE_H
#include
#include
class Cache {
public:
static void create_cache_dir();
static QString cached_icon(QUrl);
static void download_favicon(QUrl, QString, QObject* parent, QString default_icon = NULL);
};
#endif // CACHE_H
trabucco1.1/trabucco.pro 0000644 0001750 0001750 00000003000 13110635066 014450 0 ustar salvo salvo TEMPLATE = app
VERSION = 1.1
QT += qml widgets gui sql network
CONFIG += c++11 strict_c++
LIBS += -lX11
QMAKE_LFLAGS += -Wl,--as-needed
QMAKE_CXXFLAGS += -Wextra
RESOURCES += qml.qrc
HEADERS += \
settings.h \
singleinstance.h \
action.h \
desktopaction.h \
tree.h \
node.h \
iconfinder.h \
shortcutactivator.h \
btree.h \
btreeiterator.h \
bookmarkaction.h \
cache.h \
downloader.h \
searchaction.h \
clipboard.h
SOURCES += main.cpp \
settings.cpp \
singleinstance.cpp \
action.cpp \
desktopaction.cpp \
tree.cpp \
node.cpp \
iconfinder.cpp \
shortcutactivator.cpp \
btree.cpp \
btreeiterator.cpp \
bookmarkaction.cpp \
cache.cpp \
downloader.cpp \
searchaction.cpp \
clipboard.cpp
FORMS += \
settings.ui
INSTALL += searchshortcuts
DISTFILES += main.qml extras/* \
CHANGELOG
# searchproviders/*
isEmpty(target.path) {
target.path = $${DESTDIR}/usr/bin
export(target.path)
}
INSTALLS += target
searchproviders.path = $${DESTDIR}/usr/share/kservices5/searchproviders/
searchproviders.files = searchproviders/*
INSTALLS += searchproviders
launcher.path = $${DESTDIR}/usr/share/applications/
launcher.files = extras/trabucco.desktop
INSTALLS += launcher
manpage.path = $${DESTDIR}/usr/share/man/man1/
manpage.files = extras/trabucco.1
INSTALLS += manpage
icon.path = $${DESTDIR}/usr/share/icons/hicolor/512x512/apps
icon.files = extras/trabucco.png
INSTALLS += icon
export(INSTALLS)
trabucco1.1/node.cpp 0000644 0001750 0001750 00000003705 13110635066 013571 0 ustar salvo salvo /*
This file is part of Trabucco.
Trabucco is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Trabucco is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Trabucco. If not, see .
Copyright (C) 2016 Salvo "LtWorf" Tomaselli
*/
#include "node.h"
#include
Node::Node() {
this->action = NULL;
}
Node::Node(Action* action) {
this->action = action;
}
void Node::add(Action *action) {
this->add(action,action->getName().toLower());
}
Node::~Node() {
QHashIterator i(this->hash);
while (i.hasNext()) {
i.next();
delete i.value();
}
}
void Node::add(Action *action, QString name) {
if (name.length()==0) {
return;
}
Node * n;
if (this->hash.contains(name[0])) {
n = hash[name[0]];
} else {
n = new Node(action->isPrefix() && name.size()!=1? NULL:action);
hash.insert(name[0], n);
}
if (!this->action && !action->isPrefix())
this->action = action;
n->add(action,name.right(name.length() - 1));
}
Action * Node::search(QString prefix) {
return this->_search(prefix.toLower());
}
Action * Node::_search(QString prefix) {
Action * result = this->action;
if (result && result->isPrefix() && prefix.length())
return result;
if (prefix.length() && hash.contains(prefix[0])) {
Node * n = hash.value(prefix[0]);
result = n->_search(prefix.right(prefix.length() - 1));
} else if (prefix.length()) {
result = NULL;
}
return result;
}
trabucco1.1/qml.qrc 0000644 0001750 0001750 00000000127 13110635066 013433 0 ustar salvo salvo
main.qml
trabucco1.1/extras/ 0000755 0001750 0001750 00000000000 13110635066 013441 5 ustar salvo salvo trabucco1.1/extras/trabucco.1 0000644 0001750 0001750 00000000601 13110635066 015322 0 ustar salvo salvo .TH "trabucco" "1"
.SH "NAME"
trabucco \(em Desktop launcher.
.SH "SYNOPSIS"
.PP
\fBtrabucco\fR
.SH "DESCRIPTION"
.PP
Trabucco means trebuchet in Italian, which is a siege weapon, like a catapult.
When KDE4 was released, katapult was replaced by krunner, which has several drawbacks.
Trabucco is meant to overcome these drawbacks. Mostly by having a deterministic behaviour.
trabucco1.1/extras/trabucco.png 0000644 0001750 0001750 00000601307 13110635066 015760 0 ustar salvo salvo PNG
IHDR x pHYs + IDATxwe}9 $A;@hծmi]jײLEdJ-.AEJ*VkSYٮ^
tI[Hsxw_f5 "Xׅ9s~;((((((((((((((((((((((((((((((((((
~ EQv/Vr^Ms Bq^R^[WEQa=R?@G %@ * PEyC$l2
Y-ƫpk
EQ^@K>\z8G4)Nh
EQ^g~CAi?)%i#S"ZPNP(į=@}HBP) $ (=(i7q4[t<5!|=B * PEyZ;6.#vm)b1A-HuWyQ(ky)5 )y 19~M*+)%
|ǯ- @Q5Wޗ/j⇁wKIq2kSX n)%k\-aD
EQ^e%)? ~C>]ט(" t˦0Dfr'hz (JLCjǐ| c\zyu:U +vs}Rʁ.U EQ҅T"@
1n@%ks;J`F$3
%(duh_UI?L (' @Q6l@ !NR΅
Vꥧ鷛M#;5Can FȽb`ؾ
T (
B)x$]ghB`hH~j^&7Jg(/ =ߣI~t4 AgQr
EQ^!kIdh|)"n7T)BF0ULSY>aZԯ]jf)/pHYA{ع0ֽ/38E (/KVKG#}n1;Y` +fNNT"l*f2E0
X6Ņe|qs$ P'*P(sӘw
Cg~̙4O3phAa~4Q\:Q FTJi;ax컩6x* PEy>>[H!+|`2
f&Kܵ:C*wۤKd&qkt D6Oqqò.QbG2e2I4