Skip to content

Commit

Permalink
Merge pull request linuxmint#288 from Centurix/cheaty
Browse files Browse the repository at this point in the history
Add a new applet for accessing cheatsheets from the panel
  • Loading branch information
brownsr committed Apr 7, 2017
2 parents 86a6e0b + 88cec37 commit 43f3292
Show file tree
Hide file tree
Showing 20 changed files with 1,103 additions and 0 deletions.
27 changes: 27 additions & 0 deletions cheaty@centurix/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Cheaty #

Cheatsheet applet for Cinnamon.

### What does this applet do? ###

Cheaty is a quick way to access various cheatsheets from within the a single cinnamon applet. Click on the applet and a drop-down
menu of cheatsheets appears broken into sections on each topic and items describing the topic and code that is copied to the clipboard
when the menu item is clicked.

### What's here at the moment? ###

Currently, there are 5 cheatsheets that come with Cheaty: Git, Twitter Bootstrap, Markdown, HTTP Status Codes and SQL.

### Can I add my own cheat sheet or maybe contribute cheat sheets to this applet? ###

Totes. There's a template.json file in this project. If you have an SVG icon for the topic, then stick it all in a folder
in the refdocs area (or whatever folder you setup in the configuration of the applet). You can use the existing cheatsheets
as a reference.

### Isn't there an easier way to do this? ###

There should be. Open to suggestions on that.

### But why is this a thing? ###

Because I keep forgetting how to Markdown. And also, some Git stuff.
243 changes: 243 additions & 0 deletions cheaty@centurix/files/cheaty@centurix/applet.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,243 @@
const Applet = imports.ui.applet;
const PopupMenu = imports.ui.popupMenu;
const Gio = imports.gi.Gio;
const St = imports.gi.St;
const Lang = imports.lang;
const MessageTray = imports.ui.messageTray;
const Main = imports.ui.main;
const Pango = imports.gi.Pango;
const Clutter = imports.gi.Clutter;
const Tooltips = imports.ui.tooltips;
const Settings = imports.ui.settings;
const GLib = imports.gi.GLib;

const UUID = "cheaty@centurix";
const APPLET_PATH = global.userdatadir + "/applets/" + UUID;
const ICON = APPLET_PATH + "/icon.png";
const REFDOCS = APPLET_PATH + "/refdocs";


function SheetMenuItem()
{
this._init.apply(this, arguments);
}

SheetMenuItem.prototype =
{
__proto__: PopupMenu.PopupSubMenuMenuItem.prototype,

_init: function(sheet, icon, params)
{
PopupMenu.PopupSubMenuMenuItem.prototype._init.call(this, sheet.name, params);

this.actor.add_style_class_name("cheatsheet");

this.icon = new St.Icon({
gicon: new Gio.FileIcon({
file: Gio.file_new_for_path(icon)
}),
style_class: 'sheeticon',
icon_size: 32
});

this.addActor(this.icon);
this.icon.realize();

this._tooltip = new Tooltips.Tooltip(this.actor, sheet.name + ' (version ' + sheet.version + ')\n' + sheet.description + '\nAuthor: ' + sheet.author + '\nEmail: ' + sheet.email + '\nRepository: ' + sheet.repository);

this.actor.style = "padding-right: 45px;";
}
}

function DescriptionMenuItem()
{
this._init.apply(this, arguments);
}

DescriptionMenuItem.prototype =
{
__proto__: PopupMenu.PopupBaseMenuItem.prototype,

_init: function(item, callback, params)
{
PopupMenu.PopupBaseMenuItem.prototype._init.call(this, params);

this.actor.add_style_class_name("sheet-item");

this.code = item.code;

let container = new St.BoxLayout({});
container.set_vertical(true);

let description_box = new St.BoxLayout({});
let description = new St.Label({ text: item.description, style_class: 'sheet-item-description' });

description.get_clutter_text().set_line_wrap(true);
description.get_clutter_text().set_line_wrap_mode(Pango.WrapMode.WORD_CHAR);

description.set_width(400);
description.get_clutter_text().ellipsize = Pango.EllipsizeMode.NONE;

description_box.add(description);

container.add_actor(description_box);

let code_box = new St.BoxLayout({});
code_box.set_vertical(true);
let code_label = new St.Label({ text: item.code, style_class: 'sheet-item-code'});
code_box.add(code_label);

if (item.alternatives) {
for (alternative in item.alternatives) {
let alt_label = new St.Label({ text: 'Alt: ' + item.alternatives[alternative].code, style_class: 'sheet-item-code-alternative'});
code_box.add(alt_label);
}
}

container.add_actor(code_box);

this.addActor(container);

return this;
}
};


function Cheaty(metadata, orientation, panelHeight, instanceId) {
this.settings = new Settings.AppletSettings(this, UUID, instanceId);
this._init(orientation, panelHeight, instanceId);
}

Cheaty.prototype = {
__proto__: Applet.IconApplet.prototype,

_init: function(orientation, panelHeight, instanceId) {
Applet.IconApplet.prototype._init.call(this, orientation, panelHeight, instanceId);
this.set_applet_icon_path(ICON);
this.set_applet_tooltip('Cheaty: Easy access cheatsheets');

this.menu = new Applet.AppletPopupMenu(this, orientation);
this._menuManager.addMenu(this.menu);

this.settingsApiCheck();

this.cheatsheetFolder = REFDOCS;

this.settings.bindProperty(
Settings.BindingDirection.IN,
"cheatsheetFolder",
"cheatsheetFolder",
this.onCheatsheetFolderUpdate,
null
);

this._msgsrc = new MessageTray.SystemNotificationSource("Cheaty");
Main.messageTray.add(this._msgsrc);

let currentDir = Gio.file_new_for_path(resolveHome(this.cheatsheetFolder));

let enumerator = currentDir.enumerate_children("standard::*", Gio.FileQueryInfoFlags.NONE, null, null);
let file;

this._sheets = [];

while ((file = enumerator.next_file(null)) !== null) {
if (file.get_file_type() === Gio.FileType.DIRECTORY) {
let sheetName = file.get_name();
// For this to be a valid cheat sheet it must have a sheet.json file
try {
let sheet = Gio.file_new_for_path(resolveHome(this.cheatsheetFolder) + '/' + sheetName + '/sheet.json');
if (!sheet.query_exists(null)) {
global.log('No valid sheet.json file found in "' + sheetName + '"');
continue;
}

let [ok, data, etag] = sheet.load_contents(null);
if (ok) {
contents = JSON.parse(data);

let iconPath = resolveHome(this.cheatsheetFolder) + '/' + sheetName + '/icon.svg';

this._sheets[sheetName] = new SheetMenuItem(contents, iconPath);
this._sheets[sheetName]._sections = [];

for (var section in contents.sections) {
this._sheets[sheetName]._sections[section] = new PopupMenu.PopupSubMenuMenuItem('\t' + section);
this._sheets[sheetName]._sections[section]._items = [];
for (var item in contents.sections[section]) {
this._sheets[sheetName]._sections[section]._items[item] = new PopupMenu.PopupSubMenuMenuItem('\t\t' + item);

code = new DescriptionMenuItem(contents.sections[section][item]);
code.connect("activate", Lang.bind(this, this.copyToClipboard));

this._sheets[sheetName]._sections[section]._items[item].menu.addMenuItem(code);
this._sheets[sheetName]._sections[section].menu.addMenuItem(this._sheets[sheetName]._sections[section]._items[item]);
}
this._sheets[sheetName].menu.addMenuItem(this._sheets[sheetName]._sections[section]);
}
this.menu.addMenuItem(this._sheets[sheetName]);
}
} catch (e) {
global.log('Exception: ' + e)
}
}
}
},

onCheatsheetFolderUpdate: function() {
},

settingsApiCheck: function() {
const Config = imports.misc.config;
const SETTINGS_API_MIN_VERSION = 2;
const CMD_SETTINGS = "cinnamon-settings applets " + UUID;

let cinnamonVersion = Config.PACKAGE_VERSION.split('.');
let majorVersion = parseInt(cinnamonVersion[0]);

if (majorVersion >= SETTINGS_API_MIN_VERSION) {
return;
}

let mi = new Applet.MenuItem("Configure...", Gtk.STOCK_EDIT, Lang.bind(this, function() {
Util.spawnCommandLine(CMD_SETTINGS)
}));
this._applet_context_menu.addMenuItem(mi);
},

notification: function(message) {
let notification = new MessageTray.Notification(this._msgsrc, "Cheaty", message);
notification.setTransient(true);
this._msgsrc.notify(notification);
},

copyToClipboard: function(text) {
St.Clipboard.get_default().set_text(text.code);
this.notification('Code copied to the clipboard');
},

on_applet_clicked: function(event) {
try {
if (!this.menu.isOpen) {
this.menu.toggle();
}
} catch(e) {
}
}
}

function resolveHome(path) {
home = GLib.get_home_dir();
return path.replace('~', home);
}

function showProperties(debug_object) {
global.log('SHOWING PROPERTIES FOR: ' + debug_object);
for (var prop in debug_object) {
global.log('PROP: ' + prop);
}
}

function main(metadata, orientation, panelHeight, instanceId) {
return new Cheaty(metadata, orientation, panelHeight, instanceId);
}
Binary file added cheaty@centurix/files/cheaty@centurix/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions cheaty@centurix/files/cheaty@centurix/metadata.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"dangerous": false,
"description": "An applet to provide quick access to a variety of cheat sheets.",
"version": "0.0.1",
"uuid": "cheaty@centurix",
"name": "Cheaty - Cheatsheet keeper"
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 43f3292

Please sign in to comment.