Overview
SHA1 Hash: | 007d0a9b3f7c0288c072cc4909571b50d2e54392 |
---|---|
Date: | 2009-12-19 21:04:29 |
User: | drh |
Comment: | Add a new "Skins" configuration page that allows the look and feel of the web interface to be changed to one of several prototypes at the click of a button. Currently, there are only two built-in prototypes. |
Timelines: | ancestors | descendants | both | trunk |
Other Links: | files | ZIP archive | manifest |
Tags And Properties
- branch=trunk inherited from [a28c83647d]
- sym-trunk inherited from [a28c83647d]
Changes
[hide diffs]Modified src/main.mk from [08be0ee0ca] to [0f9d767d5d].
@@ -60,10 +60,11 @@ $(SRCDIR)/schema.c \ $(SRCDIR)/search.c \ $(SRCDIR)/setup.c \ $(SRCDIR)/sha1.c \ $(SRCDIR)/shun.c \ + $(SRCDIR)/skins.c \ $(SRCDIR)/stat.c \ $(SRCDIR)/style.c \ $(SRCDIR)/sync.c \ $(SRCDIR)/tag.c \ $(SRCDIR)/th_main.c \ @@ -130,10 +131,11 @@ schema_.c \ search_.c \ setup_.c \ sha1_.c \ shun_.c \ + skins_.c \ stat_.c \ style_.c \ sync_.c \ tag_.c \ th_main_.c \ @@ -200,10 +202,11 @@ schema.o \ search.o \ setup.o \ sha1.o \ shun.o \ + skins.o \ stat.o \ style.o \ sync.o \ tag.o \ th_main.o \ @@ -261,16 +264,16 @@ # noop clean: rm -f *.o *_.c $(APPNAME) VERSION.h rm -f translate makeheaders mkindex page_index.h headers - rm -f add.h allrepo.h bag.h blob.h branch.h browse.h captcha.h cgi.h checkin.h checkout.h clearsign.h clone.h comformat.h configure.h construct.h content.h db.h delta.h deltacmd.h descendants.h diff.h diffcmd.h doc.h encode.h file.h finfo.h http.h http_socket.h http_transport.h info.h login.h main.h manifest.h md5.h merge.h merge3.h name.h pivot.h pqueue.h printf.h rebuild.h report.h rss.h rstats.h schema.h search.h setup.h sha1.h shun.h stat.h style.h sync.h tag.h th_main.h timeline.h tkt.h tktsetup.h undo.h update.h url.h user.h verify.h vfile.h wiki.h wikiformat.h winhttp.h xfer.h zip.h + rm -f add.h allrepo.h bag.h blob.h branch.h browse.h captcha.h cgi.h checkin.h checkout.h clearsign.h clone.h comformat.h configure.h construct.h content.h db.h delta.h deltacmd.h descendants.h diff.h diffcmd.h doc.h encode.h file.h finfo.h http.h http_socket.h http_transport.h info.h login.h main.h manifest.h md5.h merge.h merge3.h name.h pivot.h pqueue.h printf.h rebuild.h report.h rss.h rstats.h schema.h search.h setup.h sha1.h shun.h skins.h stat.h style.h sync.h tag.h th_main.h timeline.h tkt.h tktsetup.h undo.h update.h url.h user.h verify.h vfile.h wiki.h wikiformat.h winhttp.h xfer.h zip.h page_index.h: $(TRANS_SRC) mkindex ./mkindex $(TRANS_SRC) >$@ headers: page_index.h makeheaders VERSION.h - ./makeheaders add_.c:add.h allrepo_.c:allrepo.h bag_.c:bag.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h construct_.c:construct.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h file_.c:file.h finfo_.c:finfo.h http_.c:http.h http_socket_.c:http_socket.h http_transport_.c:http_transport.h info_.c:info.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h pivot_.c:pivot.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h rstats_.c:rstats.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h VERSION.h + ./makeheaders add_.c:add.h allrepo_.c:allrepo.h bag_.c:bag.h blob_.c:blob.h branch_.c:branch.h browse_.c:browse.h captcha_.c:captcha.h cgi_.c:cgi.h checkin_.c:checkin.h checkout_.c:checkout.h clearsign_.c:clearsign.h clone_.c:clone.h comformat_.c:comformat.h configure_.c:configure.h construct_.c:construct.h content_.c:content.h db_.c:db.h delta_.c:delta.h deltacmd_.c:deltacmd.h descendants_.c:descendants.h diff_.c:diff.h diffcmd_.c:diffcmd.h doc_.c:doc.h encode_.c:encode.h file_.c:file.h finfo_.c:finfo.h http_.c:http.h http_socket_.c:http_socket.h http_transport_.c:http_transport.h info_.c:info.h login_.c:login.h main_.c:main.h manifest_.c:manifest.h md5_.c:md5.h merge_.c:merge.h merge3_.c:merge3.h name_.c:name.h pivot_.c:pivot.h pqueue_.c:pqueue.h printf_.c:printf.h rebuild_.c:rebuild.h report_.c:report.h rss_.c:rss.h rstats_.c:rstats.h schema_.c:schema.h search_.c:search.h setup_.c:setup.h sha1_.c:sha1.h shun_.c:shun.h skins_.c:skins.h stat_.c:stat.h style_.c:style.h sync_.c:sync.h tag_.c:tag.h th_main_.c:th_main.h timeline_.c:timeline.h tkt_.c:tkt.h tktsetup_.c:tktsetup.h undo_.c:undo.h update_.c:update.h url_.c:url.h user_.c:user.h verify_.c:verify.h vfile_.c:vfile.h wiki_.c:wiki.h wikiformat_.c:wikiformat.h winhttp_.c:winhttp.h xfer_.c:xfer.h zip_.c:zip.h $(SRCDIR)/sqlite3.h $(SRCDIR)/th.h VERSION.h touch headers headers: Makefile Makefile: add_.c: $(SRCDIR)/add.c translate ./translate $(SRCDIR)/add.c >add_.c @@ -613,10 +616,17 @@ shun.o: shun_.c shun.h $(SRCDIR)/config.h $(XTCC) -o shun.o -c shun_.c shun.h: headers +skins_.c: $(SRCDIR)/skins.c translate + ./translate $(SRCDIR)/skins.c >skins_.c + +skins.o: skins_.c skins.h $(SRCDIR)/config.h + $(XTCC) -o skins.o -c skins_.c + +skins.h: headers stat_.c: $(SRCDIR)/stat.c translate ./translate $(SRCDIR)/stat.c >stat_.c stat.o: stat_.c stat.h $(SRCDIR)/config.h $(XTCC) -o stat.o -c stat_.c
Modified src/makemake.tcl from [8696139730] to [1776157a16].
@@ -54,10 +54,11 @@ schema search setup sha1 shun + skins stat style sync tag th_main
Modified src/setup.c from [d61571ef37] to [7bbb5e4563].
@@ -70,10 +70,12 @@ "Configure the SCM behavior of the repository"); setup_menu_entry("Timeline", "setup_timeline", "Timeline display preferences"); setup_menu_entry("Tickets", "tktsetup", "Configure the trouble-ticketing system for this repository"); + setup_menu_entry("Skins", "setup_skin", + "Select from a menu of prepackaged \"skins\" for the web interface"); setup_menu_entry("CSS", "setup_editcss", "Edit the Cascading Style Sheet used by all pages of this repository"); setup_menu_entry("Header", "setup_header", "Edit HTML text inserted at the top of every page"); setup_menu_entry("Footer", "setup_footer", @@ -723,10 +725,19 @@ @ from the ~/.fossil database. Password login is always required @ for incoming web connections on internet addresses other than @ 127.0.0.1.</p></li> @ <hr> + onoff_attribute("Show javascript button to fill in CAPTCHA", + "auto-captcha", "autocaptcha", 0); + @ <p>When enabled, a button appears on the login screen for user + @ "anonymous" that will automatically fill in the CAPTCHA password. + @ This is less secure that forcing the user to do it manually, but is + @ probably secure enough and it is certainly more convenient for + @ anonymous users.</p> + + @ <hr> entry_attribute("Login expiration time", 6, "cookie-expire", "cex", "8766"); @ <p>The number of hours for which a login is valid. This must be a @ positive number. The default is 8760 hours which is approximately equal @ to a year.</p> @@ -816,11 +827,12 @@ onoff_attribute("Show javascript button to fill in CAPTCHA", "auto-captcha", "autocaptcha", 0); @ <p>When enabled, a button appears on the login screen for user @ "anonymous" that will automatically fill in the CAPTCHA password. @ This is less secure that forcing the user to do it manually, but is - @ usually secure enough.</p> + @ probably secure enough and it is certainly more convenient for + @ anonymous users.</p> @ <hr> onoff_attribute("Sign all commits with GPG", "clearsign", "clearsign", 1); @ <p>When enabled (the default), fossil will attempt to @@ -943,18 +955,19 @@ textarea_attribute(0, 0, 0, "css", "css", zDefaultCSS); } style_header("Edit CSS"); @ <form action="%s(g.zBaseURL)/setup_editcss" method="POST"> login_insert_csrf_secret(); - @ Edit the CSS:<br /> + @ Edit the CSS below:<br /> textarea_attribute("", 40, 80, "css", "css", zDefaultCSS); @ <br /> @ <input type="submit" name="submit" value="Apply Changes"> @ <input type="submit" name="clear" value="Revert To Default"> @ </form> @ <hr> - @ Here is the default CSS: + @ The default CSS is shown below for reference. Other examples + @ of CSS files can be seen on the <a href="setup_skin">skins page</a>. @ <blockquote><pre> @ %h(zDefaultCSS) @ </pre></blockquote> style_footer(); db_end_transaction(0); @@ -985,11 +998,12 @@ @ <br /> @ <input type="submit" name="submit" value="Apply Changes"> @ <input type="submit" name="clear" value="Revert To Default"> @ </form> @ <hr> - @ Here is the default page header: + @ The default header is shown below for reference. Other examples + @ of headers can be seen on the <a href="setup_skin">skins page</a>. @ <blockquote><pre> @ %h(zDefaultHeader) @ </pre></blockquote> style_footer(); db_end_transaction(0); @@ -1019,11 +1033,12 @@ @ <br /> @ <input type="submit" name="submit" value="Apply Changes"> @ <input type="submit" name="clear" value="Revert To Default"> @ </form> @ <hr> - @ Here is the default page footer: + @ The default footer is shown below for reference. Other examples + @ of footers can be seen on the <a href="setup_skin">skins page</a>. @ <blockquote><pre> @ %h(zDefaultFooter) @ </pre></blockquote> style_footer(); db_end_transaction(0); @@ -1067,15 +1082,19 @@ style_header("Edit Project Logo"); @ <p>The current project logo has a MIME-Type of <b>%h(zMime)</b> and looks @ like this:</p> @ <blockquote><img src="%s(g.zTop)/logo" alt="logo"></blockquote> @ - @ <form action="%s(g.zBaseURL)/setup_logo" method="POST" - @ enctype="multipart/form-data"> @ <p>The logo is accessible to all users at this URL: @ <a href="%s(g.zBaseURL)/logo">%s(g.zBaseURL)/logo</a>. - @ To set a new logo image, select a file to use as the logo using + @ The logo may or may not appear on each + @ page depending on the <a href="setup_editcss">CSS</a> and + @ <a href="setup_header">header setup</a>.</p> + @ + @ <form action="%s(g.zBaseURL)/setup_logo" method="POST" + @ enctype="multipart/form-data"> + @ <p>To set a new logo image, select a file to use as the logo using @ the entry box below and then press the "Change Logo" button.</p> login_insert_csrf_secret(); @ Logo Image file: @ <input type="file" name="im" size="60" accepts="image/*"><br> @ <input type="submit" name="set" value="Change Logo">
Added src/skins.c version [4b8e7e2c10]
@@ -1,1 +1,410 @@ +/* +** Copyright (c) 2009 D. Richard Hipp +** +** This program 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 2 of the License, or (at your option) any later version. +** +** This program 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 this library; if not, write to the +** Free Software Foundation, Inc., 59 Temple Place - Suite 330, +** Boston, MA 02111-1307, USA. +** +** Author contact information: +** drh@hwaci.com +** http://www.hwaci.com/drh/ +** +******************************************************************************* +** +** Implementation of the Setup page for "skins". +*/ +#include <assert.h> +#include "config.h" +#include "skins.h" + +/* +** A black-and-white theme with the project title in a bar across the top +** and no logo image. +*/ +static const char zBuiltinSkin1[] = +@ REPLACE INTO config VALUES('css','/* General settings for the entire page */ +@ body { +@ margin: 0ex 1ex; +@ padding: 0px; +@ background-color: white; +@ font-family: "sans serif"; +@ } +@ +@ /* The project logo in the upper left-hand corner of each page */ +@ div.logo { +@ display: table-row; +@ text-align: center; +@ /* vertical-align: bottom;*/ +@ font-size: 2em; +@ font-weight: bold; +@ background-color: #707070; +@ color: #ffffff; +@ } +@ +@ /* The page title centered at the top of each page */ +@ div.title { +@ display: table-cell; +@ font-size: 1.5em; +@ font-weight: bold; +@ text-align: left; +@ padding: 0 0 0 10px; +@ color: #404040; +@ vertical-align: bottom; +@ width: 100%; +@ } +@ +@ /* The login status message in the top right-hand corner */ +@ div.status { +@ display: table-cell; +@ text-align: right; +@ vertical-align: bottom; +@ color: #404040; +@ font-size: 0.8em; +@ font-weight: bold; +@ } +@ +@ /* The header across the top of the page */ +@ div.header { +@ display: table; +@ width: 100%; +@ } +@ +@ /* The main menu bar that appears at the top of the page beneath +@ ** the header */ +@ div.mainmenu { +@ padding: 5px 10px 5px 10px; +@ font-size: 0.9em; +@ font-weight: bold; +@ text-align: center; +@ letter-spacing: 1px; +@ background-color: #404040; +@ color: white; +@ } +@ +@ /* The submenu bar that *sometimes* appears below the main menu */ +@ div.submenu { +@ padding: 3px 10px 3px 0px; +@ font-size: 0.9em; +@ text-align: center; +@ background-color: #606060; +@ color: white; +@ } +@ div.mainmenu a, div.mainmenu a:visited, div.submenu a, div.submenu a:visited { +@ padding: 3px 10px 3px 10px; +@ color: white; +@ text-decoration: none; +@ } +@ div.mainmenu a:hover, div.submenu a:hover { +@ color: #404040; +@ background-color: white; +@ } +@ +@ /* All page content from the bottom of the menu or submenu down to +@ ** the footer */ +@ div.content { +@ padding: 0ex 0ex 0ex 0ex; +@ } +@ /* Hyperlink colors */ +@ div.content a { color: #604000; } +@ div.content a:link { color: #604000;} +@ div.content a:visited { color: #600000; } +@ +@ /* Some pages have section dividers */ +@ div.section { +@ margin-bottom: 0px; +@ margin-top: 1em; +@ padding: 1px 1px 1px 1px; +@ font-size: 1.2em; +@ font-weight: bold; +@ background-color: #404040; +@ color: white; +@ } +@ +@ /* The "Date" that occurs on the left hand side of timelines */ +@ div.divider { +@ background: #a0a0a0; +@ border: 2px #505050 solid; +@ font-size: 1em; font-weight: normal; +@ padding: .25em; +@ margin: .2em 0 .2em 0; +@ float: left; +@ clear: left; +@ } +@ +@ /* The footer at the very bottom of the page */ +@ div.footer { +@ font-size: 0.8em; +@ margin-top: 12px; +@ padding: 5px 10px 5px 10px; +@ text-align: right; +@ background-color: #404040; +@ color: white; +@ } +@ +@ /* The label/value pairs on (for example) the vinfo page */ +@ table.label-value th { +@ vertical-align: top; +@ text-align: right; +@ padding: 0.2ex 2ex; +@ }'); +@ REPLACE INTO config VALUES('header','<html> +@ <head> +@ <title>$<project_name>: $<title></title> +@ <link rel="alternate" type="application/rss+xml" title="RSS Feed" +@ href="$baseurl/timeline.rss"> +@ <link rel="stylesheet" href="$baseurl/style.css" type="text/css" +@ media="screen"> +@ </head> +@ <body> +@ <div class="header"> +@ <div class="logo"> +@ <nobr>$<project_name></nobr> +@ </div> +@ </div> +@ <div class="header"> +@ <div class="title">$<title></div> +@ <div class="status"><nobr><th1> +@ if {[info exists login]} { +@ puts "Logged in as $login" +@ } else { +@ puts "Not logged in" +@ } +@ </th1></nobr></div> +@ </div> +@ <div class="mainmenu"><th1> +@ html "<a href=''$baseurl$index_page''>Home</a> " +@ if {[hascap h]} { +@ html "<a href=''$baseurl/dir''>Files</a> " +@ } +@ if {[hascap o]} { +@ html "<a href=''$baseurl/leaves''>Leaves</a> " +@ html "<a href=''$baseurl/timeline''>Timeline</a> " +@ html "<a href=''$baseurl/brlist''>Branches</a> " +@ html "<a href=''$baseurl/taglist''>Tags</a> " +@ } +@ if {[hascap r]} { +@ html "<a href=''$baseurl/reportlist''>Tickets</a> " +@ } +@ if {[hascap j]} { +@ html "<a href=''$baseurl/wiki''>Wiki</a> " +@ } +@ if {[hascap s]} { +@ html "<a href=''$baseurl/setup''>Admin</a> " +@ } elseif {[hascap a]} { +@ html "<a href=''$baseurl/setup_ulist''>Users</a> " +@ } +@ if {[info exists login]} { +@ html "<a href=''$baseurl/login''>Logout</a> " +@ } else { +@ html "<a href=''$baseurl/login''>Login</a> " +@ } +@ </th1></div> +@ '); +@ REPLACE INTO config VALUES('footer','<div class="footer"> +@ Fossil version $manifest_version $manifest_date +@ </div> +@ </body></html> +@ '); +; + +/* +** An array of available built-in skins. +*/ +static struct BuiltinSkin { + const char *zName; + const char *zValue; +} aBuiltinSkin[] = { + { "Default", 0 /* Filled in at runtime */ }, + { "Plain Gray, No Logo", zBuiltinSkin1 }, +}; + +/* +** For a skin named zSkinName, compute the name of the CONFIG table +** entry where that skin is stored and return it. +** +** Return NULL if zSkinName is NULL or an empty string. +** +** If ifExists is true, and the named skin does not exist, return NULL. +*/ +static char *skinVarName(const char *zSkinName, int ifExists){ + char *z; + if( zSkinName==0 || zSkinName[0]==0 ) return 0; + z = mprintf("skin:%s", zSkinName); + if( ifExists && !db_exists("SELECT 1 FROM config WHERE name=%Q", z) ){ + free(z); + z = 0; + } + return z; +} + +/* +** Construct and return a string that represents the current skin if +** useDefault==0 or a string for the default skin if useDefault==1. +** +** Memory to hold the returned string is obtained from malloc. +*/ +static char *getSkin(int useDefault){ + Blob val; + blob_zero(&val); + blob_appendf(&val, "REPLACE INTO config VALUES('css',%Q);\n", + useDefault ? zDefaultCSS : db_get("css", (char*)zDefaultCSS) + ); + blob_appendf(&val, "REPLACE INTO config VALUES('header',%Q);\n", + useDefault ? zDefaultHeader : db_get("header", (char*)zDefaultHeader) + ); + blob_appendf(&val, "REPLACE INTO config VALUES('footer',%Q);\n", + useDefault ? zDefaultFooter : db_get("footer", (char*)zDefaultFooter) + ); + return blob_str(&val); +} + +/* +** Construct the default skin string and fill in the corresponding +** entry in aBuildinSkin[] +*/ +static void setDefaultSkin(void){ + aBuiltinSkin[0].zValue = getSkin(1); +} + +/* +** WEBPAGE: setup_skin +*/ +void setup_skin(void){ + const char *z; + char *zName; + char *zErr = 0; + const char *zCurrent; /* Current skin */ + int i; /* Loop counter */ + Stmt q; + + login_check_credentials(); + if( !g.okSetup ){ + login_needed(); + } + db_begin_transaction(); + + /* Process requests to delete a user-defined skin */ + if( P("del1") && (zName = skinVarName(P("sn"), 1))!=0 ){ + style_header("Confirm Custom Skin Delete"); + @ <form action="%s(g.zBaseURL)/setup_skin" method="POST"> + @ <p>Deletion of a custom skin is a permanent action that cannot + @ be undone. Please confirm that this is what you want to do:</p> + @ <input type="hidden" name="sn" value="%h(P("sn"))"> + @ <input type="submit" name="del2" value="Confirm - Delete The Skin"> + @ <input type="submit" name="cancel" value="Cancel - Do Not Delete"> + login_insert_csrf_secret(); + @ </form> + style_footer(); + return; + } + if( P("del2")!=0 && (zName = skinVarName(P("sn"), 1))!=0 ){ + db_multi_exec("DELETE FROM config WHERE name=%Q", zName); + } + + setDefaultSkin(); + zCurrent = getSkin(0); + + if( P("save")!=0 && (zName = skinVarName(P("save"),0))!=0 ){ + if( db_exists("SELECT 1 FROM config WHERE name=%Q", zName) + || strcmp(zName, "Default")==0 ){ + zErr = mprintf("Skin name \"%h\" already exists. " + "Choose a different name.", P("sn")); + }else{ + db_multi_exec("INSERT INTO config VALUES(%Q,%Q)", + zName, zCurrent + ); + } + } + + /* The user pressed the "Use This Skin" button. */ + if( P("load") && (z = P("sn"))!=0 && z[0] ){ + int seen = 0; + for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){ + if( strcmp(aBuiltinSkin[i].zValue, zCurrent)==0 ){ + seen = 1; + break; + } + } + if( !seen ){ + seen = db_exists("SELECT 1 FROM config WHERE name GLOB 'skin:*'" + " AND value=%Q", zCurrent); + } + if( !seen ){ + db_multi_exec( + "INSERT INTO config VALUES(" + " strftime('skin:Backup On %%Y-%%m-%%d %%H:%%M:%%S')," + " %Q)", zCurrent + ); + } + seen = 0; + for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){ + if( strcmp(aBuiltinSkin[i].zName, z)==0 ){ + seen = 1; + zCurrent = aBuiltinSkin[i].zValue; + db_multi_exec("%s", zCurrent); + break; + } + } + if( !seen ){ + zName = skinVarName(z,0); + zCurrent = db_get(zName, 0); + db_multi_exec("%s", zCurrent); + } + } + style_header("Skins"); + @ <p>A "skin" is a combination of + @ <a href="setup_editcss">CSS</a>, + @ <a href="setup_header">Header</a>, and + @ <a href="setup_footer">Footer</a> that determines the look and feel + @ of the web interface.</p> + @ + @ <h2>Available Skins:</h2> + @ <ol> + for(i=0; i<sizeof(aBuiltinSkin)/sizeof(aBuiltinSkin[0]); i++){ + z = aBuiltinSkin[i].zName; + if( strcmp(aBuiltinSkin[i].zValue, zCurrent)==0 ){ + @ <li><p>%h(z). <b>Currently In Use</b></p> + }else{ + @ <li><form action="%s(g.zBaseURL)/setup_skin" method="POST"> + @ %h(z). + @ <input type="hidden" name="sn" value="%h(z)"> + @ <input type="submit" name="load" value="Use This Skin"> + @ </form></li> + } + } + db_prepare(&q, + "SELECT substr(name, 6), value FROM config" + " WHERE name GLOB 'skin:*'" + " ORDER BY name" + ); + while( db_step(&q)==SQLITE_ROW ){ + const char *zN = db_column_text(&q, 0); + const char *zV = db_column_text(&q, 1); + if( strcmp(zV, zCurrent)==0 ){ + @ <li><p>%h(zN) <b>Currently In Use</b></p> + }else{ + @ <li><form action="%s(g.zBaseURL)/setup_skin" method="POST"> + @ %h(zN). + @ <input type="hidden" name="sn" value="%h(zN)"> + @ <input type="submit" name="load" value="Use This Skin"> + @ <input type="submit" name="del1" value="Delete This Skin"> + @ </form></li> + } + } + db_finalize(&q); + @ </ol> + style_footer(); + db_end_transaction(0); +}
Modified src/style.c from [c7fc56d774] to [d8b310372d].
@@ -360,11 +360,11 @@ @ text-align: right; @ background-color: #558195; @ color: white; @ } @ -@ /* Make the links in the footer less ugly... */ +@ /* Hyperlink colors */ @ div.footer a { color: white; } @ div.footer a:link { color: white; } @ div.footer a:visited { color: white; } @ div.footer a:hover { background-color: white; color: #558195; } @ @@ -377,25 +377,10 @@ @ /* The label/value pairs on (for example) the ci page */ @ table.label-value th { @ vertical-align: top; @ text-align: right; @ padding: 0.2ex 2ex; -@ } -@ -@ /* For marking important UI elements which shouldn't be -@ lightly dismissed. I mainly use it to mark "not yet -@ implemented" parts of a page. Whether or not to have -@ a 'border' attribute set is arguable. */ -@ .achtung { -@ color: #ff0000; -@ background: #ffff00; -@ border: 1px solid #ff0000; -@ } -@ -@ div.miniform { -@ font-size: smaller; -@ margin: 8px; @ } ; /* ** WEBPAGE: style.css