void MainWindow::on_label_remindCustomers_linkActivated(const QString &)
{
    unpaidJobsReminderClicked = true;
    ui->label_remindCustomers->setHidden(true);

    Setting subject = SettingController::getSetting(SettingForm::keyReminderSubject),
            body = SettingController::getSetting(SettingForm::keyReminderBody);

    if (strlen(SettingController::getSetting(SettingForm::keyEmailHost).getValue()) == 0)
    { // If no email host is specified, use a mailto link to open the user's email client
        for (unsigned i = 0; i < unpaidJobs->size(); ++i)
        {
            Customer customer = CustomerController::getCustomer(unpaidJobs->at(i).getCustomerId());

            QString mailtoLink
                    = QString("mailto:") + customer.getEmailAddress()
                    + "?subject=" + subject.getValue()
                    + "&body=" + body.getValue();

            QDesktopServices::openUrl(QUrl(mailtoLink));
        }
    }
    else
    {
        for (unsigned i = 0; i < unpaidJobs->size(); ++i)
        {
            Customer customer = CustomerController::getCustomer(unpaidJobs->at(i).getCustomerId());
            EmailerThread::enqueueEmail(EmailDetails(customer.getEmailAddress(), subject.getValue(), body.getValue()));
        }
    }
}
void ChannelGroupStorage::Save(void)
{
    QString value = setting->getValue();

    if (value == "1")
        ChannelGroup::AddChannel(chanid, grpid);
    else
        ChannelGroup::DeleteChannel(chanid, grpid);
}
Appearance *Option::parseAppearance(char *str)
{
	Appearance *app = 0;
	char *p;

	if (*str == '[') {
		char *tok;
		int mask = 0;
		int top, left, bottom, right;

		top = left = bottom = right = 0;

		p = strtok_r(str, "[] ,", &tok);
		app = parseAppearance(p);

		if (!(p = strtok_r(NULL, "[] ,", &tok))) goto err;
		top = strtol(p, 0, 10);
		if (strchr(p, '%'))
			mask |= PERPAD_TOP;

		if (!(p = strtok_r(NULL, "[] ,", &tok))) goto err;
		right = strtol(p, 0, 10);
		if (strchr(p, '%'))
			mask |= PERPAD_RIGHT;

		if ((p = strtok_r(NULL, "[] ,", &tok))) {
			bottom = strtol(p, 0, 10);
			if (strchr(p, '%'))
				mask |= PERPAD_BOT;

			if (!(p = strtok_r(NULL, "[] ,", &tok))) goto err;
			left = strtol(p, 0, 10);
			if (strchr(p, '%'))
				mask |= PERPAD_LEFT;
		}
		else {
			bottom = top;
			if (mask & PERPAD_TOP)
				mask |= PERPAD_BOT;

			right = left;
			if (mask & PERPAD_LEFT)
				mask |= PERPAD_RIGHT;
		}
		app->setPadding(Padding(mask, top, right, bottom, left));
	}
	else if ((p = strstr(str, "gradient"))) {
		int direction = 0;
		char *tok;
		p = strchr(p, '(');
		if (!p) goto err;
		p = strtok_r(p, ", ()", &tok);
		if (strcmp(p, "vert") == 0)
			direction = GRAD_VERT;
		else 
			direction = GRAD_HORZ;

		app = new GradientAppearance(direction);
		GradientAppearance *gapp = dynamic_cast<GradientAppearance *>(app);

		while((p = strtok_r(NULL, ", ()", &tok)) != NULL){
			gapp->addColor(atoc(p));
		}
	}
	else if ((p = strstr(str, "image"))) {
		char *tok;
		p = strchr(p, '(');
		if (!p) goto err;

		if (!(p = strtok_r(p, "(\")", &tok))) goto err;

		Setting *setting = Insune::getSingleton()->getSetting("style");
		const char *style = setting->getValue()->getString();
		char stylepath[256];
		snprintf(stylepath, 256, STYLEDIR "%s/%s", style, p);

		char *align = NULL;
		char *type = NULL;
		if ((p = strtok_r(NULL, "(\")", &tok))) {
			if (*p == '@') {
				align = p + 1;
				if ((p = strchr(p + 1, '!'))) {
					*p = '\0';
					type = p + 1;
				}
			} else if (*p == '!') {
				type = p + 1;
				if ((p = strchr(p + 1, '@'))) {
					*p = '\0';
					align = p + 1;
				}
			}
		}
		if (align && type)
			app = new ImageAppearance(stylepath, align, type);
		else if (align)
			app = new ImageAppearance(stylepath, align);
		else if (type)
			app = new ImageAppearance(stylepath, NULL, type);
		else
			app = new ImageAppearance(stylepath);

	}

	else {
		app = new SolidAppearance(atoc(str));
	}

	return app;
err:
	fprintf(stderr, "Error parsing appearances. Value:\n```%s'''\n", str);
	return NULL;
}