diff --git a/Makefile.am b/Makefile.am index e0209bca..32d9c93b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -66,7 +66,7 @@ lms_SOURCES = \ $(top_srcdir)/ui/video/VideoMediaPlayerWidget.cpp \ $(top_srcdir)/ui/video/VideoParametersDialog.cpp \ $(top_srcdir)/ui/settings/Settings.cpp \ - $(top_srcdir)/ui/settings/SettingsDatabase.cpp + $(top_srcdir)/ui/settings/SettingsDatabaseFormView.cpp lms_CXXFLAGS=-std=c++11 -Wall -I$(top_srcdir)/boost/ -I$(top_srcdir)/ui -I$(top_srcdir)/remote diff --git a/README b/README index a7fa60ce..8351c50b 100644 --- a/README +++ b/README @@ -3,7 +3,7 @@ I) DEPENCIES libboost-dev libextractor-dev libavcodec-dev libwt-dev -Warning: your distrib may provide an outdated wt library. Latest Wt highly recommended (http://www.webtoolkit.eu/wt) +Warning: your distrib may provide an outdated wt library. Using the latest Wt (>= 3.3.3) is highly recommended (http://www.webtoolkit.eu/wt) II) BUILD @@ -18,11 +18,9 @@ II) BUILD # make -j 4 -III) RUNNING +III) Setting up SSL (required by the Remote mobile service and the web server) -# ./lms --docroot=../ --http-port=8080 --http-address=0.0.0.0 - -IV) Setting up SSL (required by the Remote mobile service) +Just an example, you could do whatever you want (ca, self signed cert, etc.) Generate a dh file: # openssl dhparam -out dh2048.pem 2048 @@ -30,3 +28,11 @@ Generate a dh file: Generate a self signed certificate: # openssl req -x509 -out cert.pem -keyout privkey.pem -newkey rsa:4096 + +IV) RUNNING + +In the build directory: +# ./lms --docroot=../ui --approot=../ui/approot --https-port=5081 --https-address=0.0.0.0 --ssl-certificate=./certUI.pem --ssl-private-key ./privkeyUI.pem --ssl-tmp-dh dh2048.pem + +Depending of your SSL parameters, you may be asked for the PEM passphrase to unlock the private key. + diff --git a/TODO b/TODO index 0607a5de..7f82397c 100644 --- a/TODO +++ b/TODO @@ -9,15 +9,18 @@ - consider using external web server instead of builtin httpd (new FCGI service?) [Settings] -- [admin] Add/remove users +- [admin/Users] + - Add/remove users - max audio/video bitrates for user - - capabilities -- [admin] Add path to Audio/Video files -- [admin] Manual/autorefresh settings -- [admin] Display some stats about the database: - - nb audio/video files - - last scan/update -- Prefered bitrate and codecs for audio/video + - capabilities (admin) +- [admin/DB] + - Add path to Audio/Video files + - Do not make the update start time active when update perdiod is "Never" + - Do not restart the db update service if user applied no changes +- [user/transcoding] + - Prefered bitrate and codecs for audio/video +- [user/Personal] + - password, email [Users] - Handle login lifetime? diff --git a/ui/LmsApplication.cpp b/ui/LmsApplication.cpp index 97a415d4..fbcd1fd0 100644 --- a/ui/LmsApplication.cpp +++ b/ui/LmsApplication.cpp @@ -29,7 +29,13 @@ LmsApplication::LmsApplication(const Wt::WEnvironment& env, boost::filesystem::p _home(nullptr) { - setTheme(new Wt::WBootstrapTheme()); + Wt::WBootstrapTheme *bootstrapTheme = new Wt::WBootstrapTheme(this); + bootstrapTheme->setVersion(Wt::WBootstrapTheme::Version3); + bootstrapTheme->setResponsive(true); + setTheme(bootstrapTheme); + + // Add a resource bundle + messageResourceBundle().use(appRoot() + "templates"); setTitle("LMS"); // application title diff --git a/ui/approot/templates.xml b/ui/approot/templates.xml new file mode 100644 index 00000000..9c972819 --- /dev/null +++ b/ui/approot/templates.xml @@ -0,0 +1,66 @@ + + + + + + ${title} +
+
+ +
+ ${path} +
+
+ ${path-info} +
+
+ +
+ +
+ ${update-period} +
+
+ ${update-period-info} +
+
+ +
+ +
+ ${update-start-time} +
+
+ ${update-start-time-info} +
+
+ +
+ +
+ ${update-request-immediate-scan} +
+
+ ${update-request-immediate-scan-info} +
+
+ +
+
+ ${apply-button} ${discard-button} +
+
+ ${apply-info} +
+
+
+ + diff --git a/ui/common/DirectoryValidator.cpp b/ui/common/DirectoryValidator.cpp index 2709d2df..f43c1c9d 100644 --- a/ui/common/DirectoryValidator.cpp +++ b/ui/common/DirectoryValidator.cpp @@ -4,8 +4,8 @@ namespace UserInterface { -DirectoryValidator::DirectoryValidator(bool mandatory, Wt::WObject *parent) -: Wt::WValidator(mandatory, parent) +DirectoryValidator::DirectoryValidator(Wt::WObject *parent) +: Wt::WValidator(parent) { } @@ -20,7 +20,7 @@ DirectoryValidator::validate(const Wt::WString& input) const if (ec) return Wt::WValidator::Result(Wt::WValidator::Invalid, ec.message()); else if (res) - return Wt::WValidator::Result(Wt::WValidator::Valid, "Valid"); + return Wt::WValidator::Result(Wt::WValidator::Valid); else return Wt::WValidator::Result(Wt::WValidator::Invalid, "Not a directory"); } diff --git a/ui/common/DirectoryValidator.hpp b/ui/common/DirectoryValidator.hpp index c24cb816..3e6e2239 100644 --- a/ui/common/DirectoryValidator.hpp +++ b/ui/common/DirectoryValidator.hpp @@ -5,7 +5,7 @@ namespace UserInterface { class DirectoryValidator : public Wt::WValidator { public: - DirectoryValidator(bool mandatory, Wt::WObject *parent = 0); + DirectoryValidator(Wt::WObject *parent = 0); Wt::WValidator::Result validate(const Wt::WString& input) const; diff --git a/ui/resources/font-awesome/css/font-awesome.css b/ui/resources/font-awesome/css/font-awesome.css index 7ede1828..048cff97 100644 --- a/ui/resources/font-awesome/css/font-awesome.css +++ b/ui/resources/font-awesome/css/font-awesome.css @@ -1,145 +1,69 @@ /*! - * Font Awesome 3.2.1 - * the iconic font designed for Bootstrap - * ------------------------------------------------------------------------------ - * The full suite of pictographic icons, examples, and documentation can be - * found at http://fontawesome.io. Stay up to date on Twitter at - * http://twitter.com/fontawesome. - * - * License - * ------------------------------------------------------------------------------ - * - The Font Awesome font is licensed under SIL OFL 1.1 - - * http://scripts.sil.org/OFL - * - Font Awesome CSS, LESS, and SASS files are licensed under MIT License - - * http://opensource.org/licenses/mit-license.html - * - Font Awesome documentation licensed under CC BY 3.0 - - * http://creativecommons.org/licenses/by/3.0/ - * - Attribution is no longer required in Font Awesome 3.0, but much appreciated: - * "Font Awesome by Dave Gandy - http://fontawesome.io" - * - * Author - Dave Gandy - * ------------------------------------------------------------------------------ - * Email: dave@fontawesome.io - * Twitter: http://twitter.com/davegandy - * Work: Lead Product Designer @ Kyruus - http://kyruus.com + * Font Awesome 4.0.3 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) */ /* FONT PATH * -------------------------- */ @font-face { font-family: 'FontAwesome'; - src: url('../font/fontawesome-webfont.eot?v=3.2.1'); - src: url('../font/fontawesome-webfont.eot?#iefix&v=3.2.1') format('embedded-opentype'), url('../font/fontawesome-webfont.woff?v=3.2.1') format('woff'), url('../font/fontawesome-webfont.ttf?v=3.2.1') format('truetype'), url('../font/fontawesome-webfont.svg#fontawesomeregular?v=3.2.1') format('svg'); + src: url('../fonts/fontawesome-webfont.eot?v=4.0.3'); + src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.0.3') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff?v=4.0.3') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.0.3') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.0.3#fontawesomeregular') format('svg'); font-weight: normal; font-style: normal; } -/* FONT AWESOME CORE - * -------------------------- */ -[class^="icon-"], -[class*=" icon-"] { - font-family: FontAwesome; - font-weight: normal; - font-style: normal; - text-decoration: inherit; - -webkit-font-smoothing: antialiased; - *margin-right: .3em; -} -[class^="icon-"]:before, -[class*=" icon-"]:before { - text-decoration: inherit; +.fa { display: inline-block; - speak: none; + font-family: FontAwesome; + font-style: normal; + font-weight: normal; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; } /* makes the font 33% larger relative to the icon container */ -.icon-large:before { - vertical-align: -10%; +.fa-lg { font-size: 1.3333333333333333em; + line-height: 0.75em; + vertical-align: -15%; } -/* makes sure icons active on rollover in links */ -a [class^="icon-"], -a [class*=" icon-"] { - display: inline; +.fa-2x { + font-size: 2em; } -/* increased font size for icon-large */ -[class^="icon-"].icon-fixed-width, -[class*=" icon-"].icon-fixed-width { - display: inline-block; - width: 1.1428571428571428em; - text-align: right; - padding-right: 0.2857142857142857em; +.fa-3x { + font-size: 3em; } -[class^="icon-"].icon-fixed-width.icon-large, -[class*=" icon-"].icon-fixed-width.icon-large { - width: 1.4285714285714286em; +.fa-4x { + font-size: 4em; } -.icons-ul { +.fa-5x { + font-size: 5em; +} +.fa-fw { + width: 1.2857142857142858em; + text-align: center; +} +.fa-ul { + padding-left: 0; margin-left: 2.142857142857143em; list-style-type: none; } -.icons-ul > li { +.fa-ul > li { position: relative; } -.icons-ul .icon-li { +.fa-li { position: absolute; left: -2.142857142857143em; width: 2.142857142857143em; + top: 0.14285714285714285em; text-align: center; - line-height: inherit; } -[class^="icon-"].hide, -[class*=" icon-"].hide { - display: none; +.fa-li.fa-lg { + left: -1.8571428571428572em; } -.icon-muted { - color: #eeeeee; -} -.icon-light { - color: #ffffff; -} -.icon-dark { - color: #333333; -} -.icon-border { - border: solid 1px #eeeeee; +.fa-border { padding: .2em .25em .15em; - -webkit-border-radius: 3px; - -moz-border-radius: 3px; - border-radius: 3px; -} -.icon-2x { - font-size: 2em; -} -.icon-2x.icon-border { - border-width: 2px; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; -} -.icon-3x { - font-size: 3em; -} -.icon-3x.icon-border { - border-width: 3px; - -webkit-border-radius: 5px; - -moz-border-radius: 5px; - border-radius: 5px; -} -.icon-4x { - font-size: 4em; -} -.icon-4x.icon-border { - border-width: 4px; - -webkit-border-radius: 6px; - -moz-border-radius: 6px; - border-radius: 6px; -} -.icon-5x { - font-size: 5em; -} -.icon-5x.icon-border { - border-width: 5px; - -webkit-border-radius: 7px; - -moz-border-radius: 7px; - border-radius: 7px; + border: solid 0.08em #eeeeee; + border-radius: .1em; } .pull-right { float: right; @@ -147,147 +71,18 @@ a [class*=" icon-"] { .pull-left { float: left; } -[class^="icon-"].pull-left, -[class*=" icon-"].pull-left { +.fa.pull-left { margin-right: .3em; } -[class^="icon-"].pull-right, -[class*=" icon-"].pull-right { +.fa.pull-right { margin-left: .3em; } -/* BOOTSTRAP SPECIFIC CLASSES - * -------------------------- */ -/* Bootstrap 2.0 sprites.less reset */ -[class^="icon-"], -[class*=" icon-"] { - display: inline; - width: auto; - height: auto; - line-height: normal; - vertical-align: baseline; - background-image: none; - background-position: 0% 0%; - background-repeat: repeat; - margin-top: 0; -} -/* more sprites.less reset */ -.icon-white, -.nav-pills > .active > a > [class^="icon-"], -.nav-pills > .active > a > [class*=" icon-"], -.nav-list > .active > a > [class^="icon-"], -.nav-list > .active > a > [class*=" icon-"], -.navbar-inverse .nav > .active > a > [class^="icon-"], -.navbar-inverse .nav > .active > a > [class*=" icon-"], -.dropdown-menu > li > a:hover > [class^="icon-"], -.dropdown-menu > li > a:hover > [class*=" icon-"], -.dropdown-menu > .active > a > [class^="icon-"], -.dropdown-menu > .active > a > [class*=" icon-"], -.dropdown-submenu:hover > a > [class^="icon-"], -.dropdown-submenu:hover > a > [class*=" icon-"] { - background-image: none; -} -/* keeps Bootstrap styles with and without icons the same */ -.btn [class^="icon-"].icon-large, -.nav [class^="icon-"].icon-large, -.btn [class*=" icon-"].icon-large, -.nav [class*=" icon-"].icon-large { - line-height: .9em; -} -.btn [class^="icon-"].icon-spin, -.nav [class^="icon-"].icon-spin, -.btn [class*=" icon-"].icon-spin, -.nav [class*=" icon-"].icon-spin { - display: inline-block; -} -.nav-tabs [class^="icon-"], -.nav-pills [class^="icon-"], -.nav-tabs [class*=" icon-"], -.nav-pills [class*=" icon-"], -.nav-tabs [class^="icon-"].icon-large, -.nav-pills [class^="icon-"].icon-large, -.nav-tabs [class*=" icon-"].icon-large, -.nav-pills [class*=" icon-"].icon-large { - line-height: .9em; -} -.btn [class^="icon-"].pull-left.icon-2x, -.btn [class*=" icon-"].pull-left.icon-2x, -.btn [class^="icon-"].pull-right.icon-2x, -.btn [class*=" icon-"].pull-right.icon-2x { - margin-top: .18em; -} -.btn [class^="icon-"].icon-spin.icon-large, -.btn [class*=" icon-"].icon-spin.icon-large { - line-height: .8em; -} -.btn.btn-small [class^="icon-"].pull-left.icon-2x, -.btn.btn-small [class*=" icon-"].pull-left.icon-2x, -.btn.btn-small [class^="icon-"].pull-right.icon-2x, -.btn.btn-small [class*=" icon-"].pull-right.icon-2x { - margin-top: .25em; -} -.btn.btn-large [class^="icon-"], -.btn.btn-large [class*=" icon-"] { - margin-top: 0; -} -.btn.btn-large [class^="icon-"].pull-left.icon-2x, -.btn.btn-large [class*=" icon-"].pull-left.icon-2x, -.btn.btn-large [class^="icon-"].pull-right.icon-2x, -.btn.btn-large [class*=" icon-"].pull-right.icon-2x { - margin-top: .05em; -} -.btn.btn-large [class^="icon-"].pull-left.icon-2x, -.btn.btn-large [class*=" icon-"].pull-left.icon-2x { - margin-right: .2em; -} -.btn.btn-large [class^="icon-"].pull-right.icon-2x, -.btn.btn-large [class*=" icon-"].pull-right.icon-2x { - margin-left: .2em; -} -/* Fixes alignment in nav lists */ -.nav-list [class^="icon-"], -.nav-list [class*=" icon-"] { - line-height: inherit; -} -/* EXTRAS - * -------------------------- */ -/* Stacked and layered icon */ -.icon-stack { - position: relative; - display: inline-block; - width: 2em; - height: 2em; - line-height: 2em; - vertical-align: -35%; -} -.icon-stack [class^="icon-"], -.icon-stack [class*=" icon-"] { - display: block; - text-align: center; - position: absolute; - width: 100%; - height: 100%; - font-size: 1em; - line-height: inherit; - *line-height: 2em; -} -.icon-stack .icon-stack-base { - font-size: 2em; - *line-height: 1em; -} -/* Animated rotating icon */ -.icon-spin { - display: inline-block; +.fa-spin { + -webkit-animation: spin 2s infinite linear; -moz-animation: spin 2s infinite linear; -o-animation: spin 2s infinite linear; - -webkit-animation: spin 2s infinite linear; animation: spin 2s infinite linear; } -/* Prevent stack and spinners from being taken inline when inside a link */ -a .icon-stack, -a .icon-spin { - display: inline-block; - text-decoration: none; -} @-moz-keyframes spin { 0% { -moz-transform: rotate(0deg); @@ -328,1152 +123,1216 @@ a .icon-spin { transform: rotate(359deg); } } -/* Icon rotations and mirroring */ -.icon-rotate-90:before { +.fa-rotate-90 { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1); -webkit-transform: rotate(90deg); -moz-transform: rotate(90deg); -ms-transform: rotate(90deg); -o-transform: rotate(90deg); transform: rotate(90deg); - filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=1); } -.icon-rotate-180:before { +.fa-rotate-180 { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2); -webkit-transform: rotate(180deg); -moz-transform: rotate(180deg); -ms-transform: rotate(180deg); -o-transform: rotate(180deg); transform: rotate(180deg); - filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2); } -.icon-rotate-270:before { +.fa-rotate-270 { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3); -webkit-transform: rotate(270deg); -moz-transform: rotate(270deg); -ms-transform: rotate(270deg); -o-transform: rotate(270deg); transform: rotate(270deg); - filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3); } -.icon-flip-horizontal:before { +.fa-flip-horizontal { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1); -webkit-transform: scale(-1, 1); -moz-transform: scale(-1, 1); -ms-transform: scale(-1, 1); -o-transform: scale(-1, 1); transform: scale(-1, 1); } -.icon-flip-vertical:before { +.fa-flip-vertical { + filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1); -webkit-transform: scale(1, -1); -moz-transform: scale(1, -1); -ms-transform: scale(1, -1); -o-transform: scale(1, -1); transform: scale(1, -1); } -/* ensure rotation occurs inside anchor tags */ -a .icon-rotate-90:before, -a .icon-rotate-180:before, -a .icon-rotate-270:before, -a .icon-flip-horizontal:before, -a .icon-flip-vertical:before { +.fa-stack { + position: relative; display: inline-block; + width: 2em; + height: 2em; + line-height: 2em; + vertical-align: middle; +} +.fa-stack-1x, +.fa-stack-2x { + position: absolute; + left: 0; + width: 100%; + text-align: center; +} +.fa-stack-1x { + line-height: inherit; +} +.fa-stack-2x { + font-size: 2em; +} +.fa-inverse { + color: #ffffff; } /* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen readers do not read off random characters that represent icons */ -.icon-glass:before { +.fa-glass:before { content: "\f000"; } -.icon-music:before { +.fa-music:before { content: "\f001"; } -.icon-search:before { +.fa-search:before { content: "\f002"; } -.icon-envelope-alt:before { +.fa-envelope-o:before { content: "\f003"; } -.icon-heart:before { +.fa-heart:before { content: "\f004"; } -.icon-star:before { +.fa-star:before { content: "\f005"; } -.icon-star-empty:before { +.fa-star-o:before { content: "\f006"; } -.icon-user:before { +.fa-user:before { content: "\f007"; } -.icon-film:before { +.fa-film:before { content: "\f008"; } -.icon-th-large:before { +.fa-th-large:before { content: "\f009"; } -.icon-th:before { +.fa-th:before { content: "\f00a"; } -.icon-th-list:before { +.fa-th-list:before { content: "\f00b"; } -.icon-ok:before { +.fa-check:before { content: "\f00c"; } -.icon-remove:before { +.fa-times:before { content: "\f00d"; } -.icon-zoom-in:before { +.fa-search-plus:before { content: "\f00e"; } -.icon-zoom-out:before { +.fa-search-minus:before { content: "\f010"; } -.icon-power-off:before, -.icon-off:before { +.fa-power-off:before { content: "\f011"; } -.icon-signal:before { +.fa-signal:before { content: "\f012"; } -.icon-gear:before, -.icon-cog:before { +.fa-gear:before, +.fa-cog:before { content: "\f013"; } -.icon-trash:before { +.fa-trash-o:before { content: "\f014"; } -.icon-home:before { +.fa-home:before { content: "\f015"; } -.icon-file-alt:before { +.fa-file-o:before { content: "\f016"; } -.icon-time:before { +.fa-clock-o:before { content: "\f017"; } -.icon-road:before { +.fa-road:before { content: "\f018"; } -.icon-download-alt:before { +.fa-download:before { content: "\f019"; } -.icon-download:before { +.fa-arrow-circle-o-down:before { content: "\f01a"; } -.icon-upload:before { +.fa-arrow-circle-o-up:before { content: "\f01b"; } -.icon-inbox:before { +.fa-inbox:before { content: "\f01c"; } -.icon-play-circle:before { +.fa-play-circle-o:before { content: "\f01d"; } -.icon-rotate-right:before, -.icon-repeat:before { +.fa-rotate-right:before, +.fa-repeat:before { content: "\f01e"; } -.icon-refresh:before { +.fa-refresh:before { content: "\f021"; } -.icon-list-alt:before { +.fa-list-alt:before { content: "\f022"; } -.icon-lock:before { +.fa-lock:before { content: "\f023"; } -.icon-flag:before { +.fa-flag:before { content: "\f024"; } -.icon-headphones:before { +.fa-headphones:before { content: "\f025"; } -.icon-volume-off:before { +.fa-volume-off:before { content: "\f026"; } -.icon-volume-down:before { +.fa-volume-down:before { content: "\f027"; } -.icon-volume-up:before { +.fa-volume-up:before { content: "\f028"; } -.icon-qrcode:before { +.fa-qrcode:before { content: "\f029"; } -.icon-barcode:before { +.fa-barcode:before { content: "\f02a"; } -.icon-tag:before { +.fa-tag:before { content: "\f02b"; } -.icon-tags:before { +.fa-tags:before { content: "\f02c"; } -.icon-book:before { +.fa-book:before { content: "\f02d"; } -.icon-bookmark:before { +.fa-bookmark:before { content: "\f02e"; } -.icon-print:before { +.fa-print:before { content: "\f02f"; } -.icon-camera:before { +.fa-camera:before { content: "\f030"; } -.icon-font:before { +.fa-font:before { content: "\f031"; } -.icon-bold:before { +.fa-bold:before { content: "\f032"; } -.icon-italic:before { +.fa-italic:before { content: "\f033"; } -.icon-text-height:before { +.fa-text-height:before { content: "\f034"; } -.icon-text-width:before { +.fa-text-width:before { content: "\f035"; } -.icon-align-left:before { +.fa-align-left:before { content: "\f036"; } -.icon-align-center:before { +.fa-align-center:before { content: "\f037"; } -.icon-align-right:before { +.fa-align-right:before { content: "\f038"; } -.icon-align-justify:before { +.fa-align-justify:before { content: "\f039"; } -.icon-list:before { +.fa-list:before { content: "\f03a"; } -.icon-indent-left:before { +.fa-dedent:before, +.fa-outdent:before { content: "\f03b"; } -.icon-indent-right:before { +.fa-indent:before { content: "\f03c"; } -.icon-facetime-video:before { +.fa-video-camera:before { content: "\f03d"; } -.icon-picture:before { +.fa-picture-o:before { content: "\f03e"; } -.icon-pencil:before { +.fa-pencil:before { content: "\f040"; } -.icon-map-marker:before { +.fa-map-marker:before { content: "\f041"; } -.icon-adjust:before { +.fa-adjust:before { content: "\f042"; } -.icon-tint:before { +.fa-tint:before { content: "\f043"; } -.icon-edit:before { +.fa-edit:before, +.fa-pencil-square-o:before { content: "\f044"; } -.icon-share:before { +.fa-share-square-o:before { content: "\f045"; } -.icon-check:before { +.fa-check-square-o:before { content: "\f046"; } -.icon-move:before { +.fa-arrows:before { content: "\f047"; } -.icon-step-backward:before { +.fa-step-backward:before { content: "\f048"; } -.icon-fast-backward:before { +.fa-fast-backward:before { content: "\f049"; } -.icon-backward:before { +.fa-backward:before { content: "\f04a"; } -.icon-play:before { +.fa-play:before { content: "\f04b"; } -.icon-pause:before { +.fa-pause:before { content: "\f04c"; } -.icon-stop:before { +.fa-stop:before { content: "\f04d"; } -.icon-forward:before { +.fa-forward:before { content: "\f04e"; } -.icon-fast-forward:before { +.fa-fast-forward:before { content: "\f050"; } -.icon-step-forward:before { +.fa-step-forward:before { content: "\f051"; } -.icon-eject:before { +.fa-eject:before { content: "\f052"; } -.icon-chevron-left:before { +.fa-chevron-left:before { content: "\f053"; } -.icon-chevron-right:before { +.fa-chevron-right:before { content: "\f054"; } -.icon-plus-sign:before { +.fa-plus-circle:before { content: "\f055"; } -.icon-minus-sign:before { +.fa-minus-circle:before { content: "\f056"; } -.icon-remove-sign:before { +.fa-times-circle:before { content: "\f057"; } -.icon-ok-sign:before { +.fa-check-circle:before { content: "\f058"; } -.icon-question-sign:before { +.fa-question-circle:before { content: "\f059"; } -.icon-info-sign:before { +.fa-info-circle:before { content: "\f05a"; } -.icon-screenshot:before { +.fa-crosshairs:before { content: "\f05b"; } -.icon-remove-circle:before { +.fa-times-circle-o:before { content: "\f05c"; } -.icon-ok-circle:before { +.fa-check-circle-o:before { content: "\f05d"; } -.icon-ban-circle:before { +.fa-ban:before { content: "\f05e"; } -.icon-arrow-left:before { +.fa-arrow-left:before { content: "\f060"; } -.icon-arrow-right:before { +.fa-arrow-right:before { content: "\f061"; } -.icon-arrow-up:before { +.fa-arrow-up:before { content: "\f062"; } -.icon-arrow-down:before { +.fa-arrow-down:before { content: "\f063"; } -.icon-mail-forward:before, -.icon-share-alt:before { +.fa-mail-forward:before, +.fa-share:before { content: "\f064"; } -.icon-resize-full:before { +.fa-expand:before { content: "\f065"; } -.icon-resize-small:before { +.fa-compress:before { content: "\f066"; } -.icon-plus:before { +.fa-plus:before { content: "\f067"; } -.icon-minus:before { +.fa-minus:before { content: "\f068"; } -.icon-asterisk:before { +.fa-asterisk:before { content: "\f069"; } -.icon-exclamation-sign:before { +.fa-exclamation-circle:before { content: "\f06a"; } -.icon-gift:before { +.fa-gift:before { content: "\f06b"; } -.icon-leaf:before { +.fa-leaf:before { content: "\f06c"; } -.icon-fire:before { +.fa-fire:before { content: "\f06d"; } -.icon-eye-open:before { +.fa-eye:before { content: "\f06e"; } -.icon-eye-close:before { +.fa-eye-slash:before { content: "\f070"; } -.icon-warning-sign:before { +.fa-warning:before, +.fa-exclamation-triangle:before { content: "\f071"; } -.icon-plane:before { +.fa-plane:before { content: "\f072"; } -.icon-calendar:before { +.fa-calendar:before { content: "\f073"; } -.icon-random:before { +.fa-random:before { content: "\f074"; } -.icon-comment:before { +.fa-comment:before { content: "\f075"; } -.icon-magnet:before { +.fa-magnet:before { content: "\f076"; } -.icon-chevron-up:before { +.fa-chevron-up:before { content: "\f077"; } -.icon-chevron-down:before { +.fa-chevron-down:before { content: "\f078"; } -.icon-retweet:before { +.fa-retweet:before { content: "\f079"; } -.icon-shopping-cart:before { +.fa-shopping-cart:before { content: "\f07a"; } -.icon-folder-close:before { +.fa-folder:before { content: "\f07b"; } -.icon-folder-open:before { +.fa-folder-open:before { content: "\f07c"; } -.icon-resize-vertical:before { +.fa-arrows-v:before { content: "\f07d"; } -.icon-resize-horizontal:before { +.fa-arrows-h:before { content: "\f07e"; } -.icon-bar-chart:before { +.fa-bar-chart-o:before { content: "\f080"; } -.icon-twitter-sign:before { +.fa-twitter-square:before { content: "\f081"; } -.icon-facebook-sign:before { +.fa-facebook-square:before { content: "\f082"; } -.icon-camera-retro:before { +.fa-camera-retro:before { content: "\f083"; } -.icon-key:before { +.fa-key:before { content: "\f084"; } -.icon-gears:before, -.icon-cogs:before { +.fa-gears:before, +.fa-cogs:before { content: "\f085"; } -.icon-comments:before { +.fa-comments:before { content: "\f086"; } -.icon-thumbs-up-alt:before { +.fa-thumbs-o-up:before { content: "\f087"; } -.icon-thumbs-down-alt:before { +.fa-thumbs-o-down:before { content: "\f088"; } -.icon-star-half:before { +.fa-star-half:before { content: "\f089"; } -.icon-heart-empty:before { +.fa-heart-o:before { content: "\f08a"; } -.icon-signout:before { +.fa-sign-out:before { content: "\f08b"; } -.icon-linkedin-sign:before { +.fa-linkedin-square:before { content: "\f08c"; } -.icon-pushpin:before { +.fa-thumb-tack:before { content: "\f08d"; } -.icon-external-link:before { +.fa-external-link:before { content: "\f08e"; } -.icon-signin:before { +.fa-sign-in:before { content: "\f090"; } -.icon-trophy:before { +.fa-trophy:before { content: "\f091"; } -.icon-github-sign:before { +.fa-github-square:before { content: "\f092"; } -.icon-upload-alt:before { +.fa-upload:before { content: "\f093"; } -.icon-lemon:before { +.fa-lemon-o:before { content: "\f094"; } -.icon-phone:before { +.fa-phone:before { content: "\f095"; } -.icon-unchecked:before, -.icon-check-empty:before { +.fa-square-o:before { content: "\f096"; } -.icon-bookmark-empty:before { +.fa-bookmark-o:before { content: "\f097"; } -.icon-phone-sign:before { +.fa-phone-square:before { content: "\f098"; } -.icon-twitter:before { +.fa-twitter:before { content: "\f099"; } -.icon-facebook:before { +.fa-facebook:before { content: "\f09a"; } -.icon-github:before { +.fa-github:before { content: "\f09b"; } -.icon-unlock:before { +.fa-unlock:before { content: "\f09c"; } -.icon-credit-card:before { +.fa-credit-card:before { content: "\f09d"; } -.icon-rss:before { +.fa-rss:before { content: "\f09e"; } -.icon-hdd:before { +.fa-hdd-o:before { content: "\f0a0"; } -.icon-bullhorn:before { +.fa-bullhorn:before { content: "\f0a1"; } -.icon-bell:before { - content: "\f0a2"; -} -.icon-certificate:before { - content: "\f0a3"; -} -.icon-hand-right:before { - content: "\f0a4"; -} -.icon-hand-left:before { - content: "\f0a5"; -} -.icon-hand-up:before { - content: "\f0a6"; -} -.icon-hand-down:before { - content: "\f0a7"; -} -.icon-circle-arrow-left:before { - content: "\f0a8"; -} -.icon-circle-arrow-right:before { - content: "\f0a9"; -} -.icon-circle-arrow-up:before { - content: "\f0aa"; -} -.icon-circle-arrow-down:before { - content: "\f0ab"; -} -.icon-globe:before { - content: "\f0ac"; -} -.icon-wrench:before { - content: "\f0ad"; -} -.icon-tasks:before { - content: "\f0ae"; -} -.icon-filter:before { - content: "\f0b0"; -} -.icon-briefcase:before { - content: "\f0b1"; -} -.icon-fullscreen:before { - content: "\f0b2"; -} -.icon-group:before { - content: "\f0c0"; -} -.icon-link:before { - content: "\f0c1"; -} -.icon-cloud:before { - content: "\f0c2"; -} -.icon-beaker:before { - content: "\f0c3"; -} -.icon-cut:before { - content: "\f0c4"; -} -.icon-copy:before { - content: "\f0c5"; -} -.icon-paperclip:before, -.icon-paper-clip:before { - content: "\f0c6"; -} -.icon-save:before { - content: "\f0c7"; -} -.icon-sign-blank:before { - content: "\f0c8"; -} -.icon-reorder:before { - content: "\f0c9"; -} -.icon-list-ul:before { - content: "\f0ca"; -} -.icon-list-ol:before { - content: "\f0cb"; -} -.icon-strikethrough:before { - content: "\f0cc"; -} -.icon-underline:before { - content: "\f0cd"; -} -.icon-table:before { - content: "\f0ce"; -} -.icon-magic:before { - content: "\f0d0"; -} -.icon-truck:before { - content: "\f0d1"; -} -.icon-pinterest:before { - content: "\f0d2"; -} -.icon-pinterest-sign:before { - content: "\f0d3"; -} -.icon-google-plus-sign:before { - content: "\f0d4"; -} -.icon-google-plus:before { - content: "\f0d5"; -} -.icon-money:before { - content: "\f0d6"; -} -.icon-caret-down:before { - content: "\f0d7"; -} -.icon-caret-up:before { - content: "\f0d8"; -} -.icon-caret-left:before { - content: "\f0d9"; -} -.icon-caret-right:before { - content: "\f0da"; -} -.icon-columns:before { - content: "\f0db"; -} -.icon-sort:before { - content: "\f0dc"; -} -.icon-sort-down:before { - content: "\f0dd"; -} -.icon-sort-up:before { - content: "\f0de"; -} -.icon-envelope:before { - content: "\f0e0"; -} -.icon-linkedin:before { - content: "\f0e1"; -} -.icon-rotate-left:before, -.icon-undo:before { - content: "\f0e2"; -} -.icon-legal:before { - content: "\f0e3"; -} -.icon-dashboard:before { - content: "\f0e4"; -} -.icon-comment-alt:before { - content: "\f0e5"; -} -.icon-comments-alt:before { - content: "\f0e6"; -} -.icon-bolt:before { - content: "\f0e7"; -} -.icon-sitemap:before { - content: "\f0e8"; -} -.icon-umbrella:before { - content: "\f0e9"; -} -.icon-paste:before { - content: "\f0ea"; -} -.icon-lightbulb:before { - content: "\f0eb"; -} -.icon-exchange:before { - content: "\f0ec"; -} -.icon-cloud-download:before { - content: "\f0ed"; -} -.icon-cloud-upload:before { - content: "\f0ee"; -} -.icon-user-md:before { - content: "\f0f0"; -} -.icon-stethoscope:before { - content: "\f0f1"; -} -.icon-suitcase:before { - content: "\f0f2"; -} -.icon-bell-alt:before { +.fa-bell:before { content: "\f0f3"; } -.icon-coffee:before { +.fa-certificate:before { + content: "\f0a3"; +} +.fa-hand-o-right:before { + content: "\f0a4"; +} +.fa-hand-o-left:before { + content: "\f0a5"; +} +.fa-hand-o-up:before { + content: "\f0a6"; +} +.fa-hand-o-down:before { + content: "\f0a7"; +} +.fa-arrow-circle-left:before { + content: "\f0a8"; +} +.fa-arrow-circle-right:before { + content: "\f0a9"; +} +.fa-arrow-circle-up:before { + content: "\f0aa"; +} +.fa-arrow-circle-down:before { + content: "\f0ab"; +} +.fa-globe:before { + content: "\f0ac"; +} +.fa-wrench:before { + content: "\f0ad"; +} +.fa-tasks:before { + content: "\f0ae"; +} +.fa-filter:before { + content: "\f0b0"; +} +.fa-briefcase:before { + content: "\f0b1"; +} +.fa-arrows-alt:before { + content: "\f0b2"; +} +.fa-group:before, +.fa-users:before { + content: "\f0c0"; +} +.fa-chain:before, +.fa-link:before { + content: "\f0c1"; +} +.fa-cloud:before { + content: "\f0c2"; +} +.fa-flask:before { + content: "\f0c3"; +} +.fa-cut:before, +.fa-scissors:before { + content: "\f0c4"; +} +.fa-copy:before, +.fa-files-o:before { + content: "\f0c5"; +} +.fa-paperclip:before { + content: "\f0c6"; +} +.fa-save:before, +.fa-floppy-o:before { + content: "\f0c7"; +} +.fa-square:before { + content: "\f0c8"; +} +.fa-bars:before { + content: "\f0c9"; +} +.fa-list-ul:before { + content: "\f0ca"; +} +.fa-list-ol:before { + content: "\f0cb"; +} +.fa-strikethrough:before { + content: "\f0cc"; +} +.fa-underline:before { + content: "\f0cd"; +} +.fa-table:before { + content: "\f0ce"; +} +.fa-magic:before { + content: "\f0d0"; +} +.fa-truck:before { + content: "\f0d1"; +} +.fa-pinterest:before { + content: "\f0d2"; +} +.fa-pinterest-square:before { + content: "\f0d3"; +} +.fa-google-plus-square:before { + content: "\f0d4"; +} +.fa-google-plus:before { + content: "\f0d5"; +} +.fa-money:before { + content: "\f0d6"; +} +.fa-caret-down:before { + content: "\f0d7"; +} +.fa-caret-up:before { + content: "\f0d8"; +} +.fa-caret-left:before { + content: "\f0d9"; +} +.fa-caret-right:before { + content: "\f0da"; +} +.fa-columns:before { + content: "\f0db"; +} +.fa-unsorted:before, +.fa-sort:before { + content: "\f0dc"; +} +.fa-sort-down:before, +.fa-sort-asc:before { + content: "\f0dd"; +} +.fa-sort-up:before, +.fa-sort-desc:before { + content: "\f0de"; +} +.fa-envelope:before { + content: "\f0e0"; +} +.fa-linkedin:before { + content: "\f0e1"; +} +.fa-rotate-left:before, +.fa-undo:before { + content: "\f0e2"; +} +.fa-legal:before, +.fa-gavel:before { + content: "\f0e3"; +} +.fa-dashboard:before, +.fa-tachometer:before { + content: "\f0e4"; +} +.fa-comment-o:before { + content: "\f0e5"; +} +.fa-comments-o:before { + content: "\f0e6"; +} +.fa-flash:before, +.fa-bolt:before { + content: "\f0e7"; +} +.fa-sitemap:before { + content: "\f0e8"; +} +.fa-umbrella:before { + content: "\f0e9"; +} +.fa-paste:before, +.fa-clipboard:before { + content: "\f0ea"; +} +.fa-lightbulb-o:before { + content: "\f0eb"; +} +.fa-exchange:before { + content: "\f0ec"; +} +.fa-cloud-download:before { + content: "\f0ed"; +} +.fa-cloud-upload:before { + content: "\f0ee"; +} +.fa-user-md:before { + content: "\f0f0"; +} +.fa-stethoscope:before { + content: "\f0f1"; +} +.fa-suitcase:before { + content: "\f0f2"; +} +.fa-bell-o:before { + content: "\f0a2"; +} +.fa-coffee:before { content: "\f0f4"; } -.icon-food:before { +.fa-cutlery:before { content: "\f0f5"; } -.icon-file-text-alt:before { +.fa-file-text-o:before { content: "\f0f6"; } -.icon-building:before { +.fa-building-o:before { content: "\f0f7"; } -.icon-hospital:before { +.fa-hospital-o:before { content: "\f0f8"; } -.icon-ambulance:before { +.fa-ambulance:before { content: "\f0f9"; } -.icon-medkit:before { +.fa-medkit:before { content: "\f0fa"; } -.icon-fighter-jet:before { +.fa-fighter-jet:before { content: "\f0fb"; } -.icon-beer:before { +.fa-beer:before { content: "\f0fc"; } -.icon-h-sign:before { +.fa-h-square:before { content: "\f0fd"; } -.icon-plus-sign-alt:before { +.fa-plus-square:before { content: "\f0fe"; } -.icon-double-angle-left:before { +.fa-angle-double-left:before { content: "\f100"; } -.icon-double-angle-right:before { +.fa-angle-double-right:before { content: "\f101"; } -.icon-double-angle-up:before { +.fa-angle-double-up:before { content: "\f102"; } -.icon-double-angle-down:before { +.fa-angle-double-down:before { content: "\f103"; } -.icon-angle-left:before { +.fa-angle-left:before { content: "\f104"; } -.icon-angle-right:before { +.fa-angle-right:before { content: "\f105"; } -.icon-angle-up:before { +.fa-angle-up:before { content: "\f106"; } -.icon-angle-down:before { +.fa-angle-down:before { content: "\f107"; } -.icon-desktop:before { +.fa-desktop:before { content: "\f108"; } -.icon-laptop:before { +.fa-laptop:before { content: "\f109"; } -.icon-tablet:before { +.fa-tablet:before { content: "\f10a"; } -.icon-mobile-phone:before { +.fa-mobile-phone:before, +.fa-mobile:before { content: "\f10b"; } -.icon-circle-blank:before { +.fa-circle-o:before { content: "\f10c"; } -.icon-quote-left:before { +.fa-quote-left:before { content: "\f10d"; } -.icon-quote-right:before { +.fa-quote-right:before { content: "\f10e"; } -.icon-spinner:before { +.fa-spinner:before { content: "\f110"; } -.icon-circle:before { +.fa-circle:before { content: "\f111"; } -.icon-mail-reply:before, -.icon-reply:before { +.fa-mail-reply:before, +.fa-reply:before { content: "\f112"; } -.icon-github-alt:before { +.fa-github-alt:before { content: "\f113"; } -.icon-folder-close-alt:before { +.fa-folder-o:before { content: "\f114"; } -.icon-folder-open-alt:before { +.fa-folder-open-o:before { content: "\f115"; } -.icon-expand-alt:before { - content: "\f116"; -} -.icon-collapse-alt:before { - content: "\f117"; -} -.icon-smile:before { +.fa-smile-o:before { content: "\f118"; } -.icon-frown:before { +.fa-frown-o:before { content: "\f119"; } -.icon-meh:before { +.fa-meh-o:before { content: "\f11a"; } -.icon-gamepad:before { +.fa-gamepad:before { content: "\f11b"; } -.icon-keyboard:before { +.fa-keyboard-o:before { content: "\f11c"; } -.icon-flag-alt:before { +.fa-flag-o:before { content: "\f11d"; } -.icon-flag-checkered:before { +.fa-flag-checkered:before { content: "\f11e"; } -.icon-terminal:before { +.fa-terminal:before { content: "\f120"; } -.icon-code:before { +.fa-code:before { content: "\f121"; } -.icon-reply-all:before { +.fa-reply-all:before { content: "\f122"; } -.icon-mail-reply-all:before { +.fa-mail-reply-all:before { content: "\f122"; } -.icon-star-half-full:before, -.icon-star-half-empty:before { +.fa-star-half-empty:before, +.fa-star-half-full:before, +.fa-star-half-o:before { content: "\f123"; } -.icon-location-arrow:before { +.fa-location-arrow:before { content: "\f124"; } -.icon-crop:before { +.fa-crop:before { content: "\f125"; } -.icon-code-fork:before { +.fa-code-fork:before { content: "\f126"; } -.icon-unlink:before { +.fa-unlink:before, +.fa-chain-broken:before { content: "\f127"; } -.icon-question:before { +.fa-question:before { content: "\f128"; } -.icon-info:before { +.fa-info:before { content: "\f129"; } -.icon-exclamation:before { +.fa-exclamation:before { content: "\f12a"; } -.icon-superscript:before { +.fa-superscript:before { content: "\f12b"; } -.icon-subscript:before { +.fa-subscript:before { content: "\f12c"; } -.icon-eraser:before { +.fa-eraser:before { content: "\f12d"; } -.icon-puzzle-piece:before { +.fa-puzzle-piece:before { content: "\f12e"; } -.icon-microphone:before { +.fa-microphone:before { content: "\f130"; } -.icon-microphone-off:before { +.fa-microphone-slash:before { content: "\f131"; } -.icon-shield:before { +.fa-shield:before { content: "\f132"; } -.icon-calendar-empty:before { +.fa-calendar-o:before { content: "\f133"; } -.icon-fire-extinguisher:before { +.fa-fire-extinguisher:before { content: "\f134"; } -.icon-rocket:before { +.fa-rocket:before { content: "\f135"; } -.icon-maxcdn:before { +.fa-maxcdn:before { content: "\f136"; } -.icon-chevron-sign-left:before { +.fa-chevron-circle-left:before { content: "\f137"; } -.icon-chevron-sign-right:before { +.fa-chevron-circle-right:before { content: "\f138"; } -.icon-chevron-sign-up:before { +.fa-chevron-circle-up:before { content: "\f139"; } -.icon-chevron-sign-down:before { +.fa-chevron-circle-down:before { content: "\f13a"; } -.icon-html5:before { +.fa-html5:before { content: "\f13b"; } -.icon-css3:before { +.fa-css3:before { content: "\f13c"; } -.icon-anchor:before { +.fa-anchor:before { content: "\f13d"; } -.icon-unlock-alt:before { +.fa-unlock-alt:before { content: "\f13e"; } -.icon-bullseye:before { +.fa-bullseye:before { content: "\f140"; } -.icon-ellipsis-horizontal:before { +.fa-ellipsis-h:before { content: "\f141"; } -.icon-ellipsis-vertical:before { +.fa-ellipsis-v:before { content: "\f142"; } -.icon-rss-sign:before { +.fa-rss-square:before { content: "\f143"; } -.icon-play-sign:before { +.fa-play-circle:before { content: "\f144"; } -.icon-ticket:before { +.fa-ticket:before { content: "\f145"; } -.icon-minus-sign-alt:before { +.fa-minus-square:before { content: "\f146"; } -.icon-check-minus:before { +.fa-minus-square-o:before { content: "\f147"; } -.icon-level-up:before { +.fa-level-up:before { content: "\f148"; } -.icon-level-down:before { +.fa-level-down:before { content: "\f149"; } -.icon-check-sign:before { +.fa-check-square:before { content: "\f14a"; } -.icon-edit-sign:before { +.fa-pencil-square:before { content: "\f14b"; } -.icon-external-link-sign:before { +.fa-external-link-square:before { content: "\f14c"; } -.icon-share-sign:before { +.fa-share-square:before { content: "\f14d"; } -.icon-compass:before { +.fa-compass:before { content: "\f14e"; } -.icon-collapse:before { +.fa-toggle-down:before, +.fa-caret-square-o-down:before { content: "\f150"; } -.icon-collapse-top:before { +.fa-toggle-up:before, +.fa-caret-square-o-up:before { content: "\f151"; } -.icon-expand:before { +.fa-toggle-right:before, +.fa-caret-square-o-right:before { content: "\f152"; } -.icon-euro:before, -.icon-eur:before { +.fa-euro:before, +.fa-eur:before { content: "\f153"; } -.icon-gbp:before { +.fa-gbp:before { content: "\f154"; } -.icon-dollar:before, -.icon-usd:before { +.fa-dollar:before, +.fa-usd:before { content: "\f155"; } -.icon-rupee:before, -.icon-inr:before { +.fa-rupee:before, +.fa-inr:before { content: "\f156"; } -.icon-yen:before, -.icon-jpy:before { +.fa-cny:before, +.fa-rmb:before, +.fa-yen:before, +.fa-jpy:before { content: "\f157"; } -.icon-renminbi:before, -.icon-cny:before { +.fa-ruble:before, +.fa-rouble:before, +.fa-rub:before { content: "\f158"; } -.icon-won:before, -.icon-krw:before { +.fa-won:before, +.fa-krw:before { content: "\f159"; } -.icon-bitcoin:before, -.icon-btc:before { +.fa-bitcoin:before, +.fa-btc:before { content: "\f15a"; } -.icon-file:before { +.fa-file:before { content: "\f15b"; } -.icon-file-text:before { +.fa-file-text:before { content: "\f15c"; } -.icon-sort-by-alphabet:before { +.fa-sort-alpha-asc:before { content: "\f15d"; } -.icon-sort-by-alphabet-alt:before { +.fa-sort-alpha-desc:before { content: "\f15e"; } -.icon-sort-by-attributes:before { +.fa-sort-amount-asc:before { content: "\f160"; } -.icon-sort-by-attributes-alt:before { +.fa-sort-amount-desc:before { content: "\f161"; } -.icon-sort-by-order:before { +.fa-sort-numeric-asc:before { content: "\f162"; } -.icon-sort-by-order-alt:before { +.fa-sort-numeric-desc:before { content: "\f163"; } -.icon-thumbs-up:before { +.fa-thumbs-up:before { content: "\f164"; } -.icon-thumbs-down:before { +.fa-thumbs-down:before { content: "\f165"; } -.icon-youtube-sign:before { +.fa-youtube-square:before { content: "\f166"; } -.icon-youtube:before { +.fa-youtube:before { content: "\f167"; } -.icon-xing:before { +.fa-xing:before { content: "\f168"; } -.icon-xing-sign:before { +.fa-xing-square:before { content: "\f169"; } -.icon-youtube-play:before { +.fa-youtube-play:before { content: "\f16a"; } -.icon-dropbox:before { +.fa-dropbox:before { content: "\f16b"; } -.icon-stackexchange:before { +.fa-stack-overflow:before { content: "\f16c"; } -.icon-instagram:before { +.fa-instagram:before { content: "\f16d"; } -.icon-flickr:before { +.fa-flickr:before { content: "\f16e"; } -.icon-adn:before { +.fa-adn:before { content: "\f170"; } -.icon-bitbucket:before { +.fa-bitbucket:before { content: "\f171"; } -.icon-bitbucket-sign:before { +.fa-bitbucket-square:before { content: "\f172"; } -.icon-tumblr:before { +.fa-tumblr:before { content: "\f173"; } -.icon-tumblr-sign:before { +.fa-tumblr-square:before { content: "\f174"; } -.icon-long-arrow-down:before { +.fa-long-arrow-down:before { content: "\f175"; } -.icon-long-arrow-up:before { +.fa-long-arrow-up:before { content: "\f176"; } -.icon-long-arrow-left:before { +.fa-long-arrow-left:before { content: "\f177"; } -.icon-long-arrow-right:before { +.fa-long-arrow-right:before { content: "\f178"; } -.icon-apple:before { +.fa-apple:before { content: "\f179"; } -.icon-windows:before { +.fa-windows:before { content: "\f17a"; } -.icon-android:before { +.fa-android:before { content: "\f17b"; } -.icon-linux:before { +.fa-linux:before { content: "\f17c"; } -.icon-dribbble:before { +.fa-dribbble:before { content: "\f17d"; } -.icon-skype:before { +.fa-skype:before { content: "\f17e"; } -.icon-foursquare:before { +.fa-foursquare:before { content: "\f180"; } -.icon-trello:before { +.fa-trello:before { content: "\f181"; } -.icon-female:before { +.fa-female:before { content: "\f182"; } -.icon-male:before { +.fa-male:before { content: "\f183"; } -.icon-gittip:before { +.fa-gittip:before { content: "\f184"; } -.icon-sun:before { +.fa-sun-o:before { content: "\f185"; } -.icon-moon:before { +.fa-moon-o:before { content: "\f186"; } -.icon-archive:before { +.fa-archive:before { content: "\f187"; } -.icon-bug:before { +.fa-bug:before { content: "\f188"; } -.icon-vk:before { +.fa-vk:before { content: "\f189"; } -.icon-weibo:before { +.fa-weibo:before { content: "\f18a"; } -.icon-renren:before { +.fa-renren:before { content: "\f18b"; } +.fa-pagelines:before { + content: "\f18c"; +} +.fa-stack-exchange:before { + content: "\f18d"; +} +.fa-arrow-circle-o-right:before { + content: "\f18e"; +} +.fa-arrow-circle-o-left:before { + content: "\f190"; +} +.fa-toggle-left:before, +.fa-caret-square-o-left:before { + content: "\f191"; +} +.fa-dot-circle-o:before { + content: "\f192"; +} +.fa-wheelchair:before { + content: "\f193"; +} +.fa-vimeo-square:before { + content: "\f194"; +} +.fa-turkish-lira:before, +.fa-try:before { + content: "\f195"; +} +.fa-plus-square-o:before { + content: "\f196"; +} diff --git a/ui/resources/font-awesome/css/font-awesome.min.css b/ui/resources/font-awesome/css/font-awesome.min.css index 866437fa..449d6ac5 100644 --- a/ui/resources/font-awesome/css/font-awesome.min.css +++ b/ui/resources/font-awesome/css/font-awesome.min.css @@ -1,403 +1,4 @@ -@font-face{font-family:'FontAwesome';src:url('../font/fontawesome-webfont.eot?v=3.2.1');src:url('../font/fontawesome-webfont.eot?#iefix&v=3.2.1') format('embedded-opentype'),url('../font/fontawesome-webfont.woff?v=3.2.1') format('woff'),url('../font/fontawesome-webfont.ttf?v=3.2.1') format('truetype'),url('../font/fontawesome-webfont.svg#fontawesomeregular?v=3.2.1') format('svg');font-weight:normal;font-style:normal;}[class^="icon-"],[class*=" icon-"]{font-family:FontAwesome;font-weight:normal;font-style:normal;text-decoration:inherit;-webkit-font-smoothing:antialiased;*margin-right:.3em;} -[class^="icon-"]:before,[class*=" icon-"]:before{text-decoration:inherit;display:inline-block;speak:none;} -.icon-large:before{vertical-align:-10%;font-size:1.3333333333333333em;} -a [class^="icon-"],a [class*=" icon-"]{display:inline;} -[class^="icon-"].icon-fixed-width,[class*=" icon-"].icon-fixed-width{display:inline-block;width:1.1428571428571428em;text-align:right;padding-right:0.2857142857142857em;}[class^="icon-"].icon-fixed-width.icon-large,[class*=" icon-"].icon-fixed-width.icon-large{width:1.4285714285714286em;} -.icons-ul{margin-left:2.142857142857143em;list-style-type:none;}.icons-ul>li{position:relative;} -.icons-ul .icon-li{position:absolute;left:-2.142857142857143em;width:2.142857142857143em;text-align:center;line-height:inherit;} -[class^="icon-"].hide,[class*=" icon-"].hide{display:none;} -.icon-muted{color:#eeeeee;} -.icon-light{color:#ffffff;} -.icon-dark{color:#333333;} -.icon-border{border:solid 1px #eeeeee;padding:.2em .25em .15em;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px;} -.icon-2x{font-size:2em;}.icon-2x.icon-border{border-width:2px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;} -.icon-3x{font-size:3em;}.icon-3x.icon-border{border-width:3px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px;} -.icon-4x{font-size:4em;}.icon-4x.icon-border{border-width:4px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;} -.icon-5x{font-size:5em;}.icon-5x.icon-border{border-width:5px;-webkit-border-radius:7px;-moz-border-radius:7px;border-radius:7px;} -.pull-right{float:right;} -.pull-left{float:left;} -[class^="icon-"].pull-left,[class*=" icon-"].pull-left{margin-right:.3em;} -[class^="icon-"].pull-right,[class*=" icon-"].pull-right{margin-left:.3em;} -[class^="icon-"],[class*=" icon-"]{display:inline;width:auto;height:auto;line-height:normal;vertical-align:baseline;background-image:none;background-position:0% 0%;background-repeat:repeat;margin-top:0;} -.icon-white,.nav-pills>.active>a>[class^="icon-"],.nav-pills>.active>a>[class*=" icon-"],.nav-list>.active>a>[class^="icon-"],.nav-list>.active>a>[class*=" icon-"],.navbar-inverse .nav>.active>a>[class^="icon-"],.navbar-inverse .nav>.active>a>[class*=" icon-"],.dropdown-menu>li>a:hover>[class^="icon-"],.dropdown-menu>li>a:hover>[class*=" icon-"],.dropdown-menu>.active>a>[class^="icon-"],.dropdown-menu>.active>a>[class*=" icon-"],.dropdown-submenu:hover>a>[class^="icon-"],.dropdown-submenu:hover>a>[class*=" icon-"]{background-image:none;} -.btn [class^="icon-"].icon-large,.nav [class^="icon-"].icon-large,.btn [class*=" icon-"].icon-large,.nav [class*=" icon-"].icon-large{line-height:.9em;} -.btn [class^="icon-"].icon-spin,.nav [class^="icon-"].icon-spin,.btn [class*=" icon-"].icon-spin,.nav [class*=" icon-"].icon-spin{display:inline-block;} -.nav-tabs [class^="icon-"],.nav-pills [class^="icon-"],.nav-tabs [class*=" icon-"],.nav-pills [class*=" icon-"],.nav-tabs [class^="icon-"].icon-large,.nav-pills [class^="icon-"].icon-large,.nav-tabs [class*=" icon-"].icon-large,.nav-pills [class*=" icon-"].icon-large{line-height:.9em;} -.btn [class^="icon-"].pull-left.icon-2x,.btn [class*=" icon-"].pull-left.icon-2x,.btn [class^="icon-"].pull-right.icon-2x,.btn [class*=" icon-"].pull-right.icon-2x{margin-top:.18em;} -.btn [class^="icon-"].icon-spin.icon-large,.btn [class*=" icon-"].icon-spin.icon-large{line-height:.8em;} -.btn.btn-small [class^="icon-"].pull-left.icon-2x,.btn.btn-small [class*=" icon-"].pull-left.icon-2x,.btn.btn-small [class^="icon-"].pull-right.icon-2x,.btn.btn-small [class*=" icon-"].pull-right.icon-2x{margin-top:.25em;} -.btn.btn-large [class^="icon-"],.btn.btn-large [class*=" icon-"]{margin-top:0;}.btn.btn-large [class^="icon-"].pull-left.icon-2x,.btn.btn-large [class*=" icon-"].pull-left.icon-2x,.btn.btn-large [class^="icon-"].pull-right.icon-2x,.btn.btn-large [class*=" icon-"].pull-right.icon-2x{margin-top:.05em;} -.btn.btn-large [class^="icon-"].pull-left.icon-2x,.btn.btn-large [class*=" icon-"].pull-left.icon-2x{margin-right:.2em;} -.btn.btn-large [class^="icon-"].pull-right.icon-2x,.btn.btn-large [class*=" icon-"].pull-right.icon-2x{margin-left:.2em;} -.nav-list [class^="icon-"],.nav-list [class*=" icon-"]{line-height:inherit;} -.icon-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:-35%;}.icon-stack [class^="icon-"],.icon-stack [class*=" icon-"]{display:block;text-align:center;position:absolute;width:100%;height:100%;font-size:1em;line-height:inherit;*line-height:2em;} -.icon-stack .icon-stack-base{font-size:2em;*line-height:1em;} -.icon-spin{display:inline-block;-moz-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;-webkit-animation:spin 2s infinite linear;animation:spin 2s infinite linear;} -a .icon-stack,a .icon-spin{display:inline-block;text-decoration:none;} -@-moz-keyframes spin{0%{-moz-transform:rotate(0deg);} 100%{-moz-transform:rotate(359deg);}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg);} 100%{-webkit-transform:rotate(359deg);}}@-o-keyframes spin{0%{-o-transform:rotate(0deg);} 100%{-o-transform:rotate(359deg);}}@-ms-keyframes spin{0%{-ms-transform:rotate(0deg);} 100%{-ms-transform:rotate(359deg);}}@keyframes spin{0%{transform:rotate(0deg);} 100%{transform:rotate(359deg);}}.icon-rotate-90:before{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg);filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);} -.icon-rotate-180:before{-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg);filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);} -.icon-rotate-270:before{-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg);filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);} -.icon-flip-horizontal:before{-webkit-transform:scale(-1, 1);-moz-transform:scale(-1, 1);-ms-transform:scale(-1, 1);-o-transform:scale(-1, 1);transform:scale(-1, 1);} -.icon-flip-vertical:before{-webkit-transform:scale(1, -1);-moz-transform:scale(1, -1);-ms-transform:scale(1, -1);-o-transform:scale(1, -1);transform:scale(1, -1);} -a .icon-rotate-90:before,a .icon-rotate-180:before,a .icon-rotate-270:before,a .icon-flip-horizontal:before,a .icon-flip-vertical:before{display:inline-block;} -.icon-glass:before{content:"\f000";} -.icon-music:before{content:"\f001";} -.icon-search:before{content:"\f002";} -.icon-envelope-alt:before{content:"\f003";} -.icon-heart:before{content:"\f004";} -.icon-star:before{content:"\f005";} -.icon-star-empty:before{content:"\f006";} -.icon-user:before{content:"\f007";} -.icon-film:before{content:"\f008";} -.icon-th-large:before{content:"\f009";} -.icon-th:before{content:"\f00a";} -.icon-th-list:before{content:"\f00b";} -.icon-ok:before{content:"\f00c";} -.icon-remove:before{content:"\f00d";} -.icon-zoom-in:before{content:"\f00e";} -.icon-zoom-out:before{content:"\f010";} -.icon-power-off:before,.icon-off:before{content:"\f011";} -.icon-signal:before{content:"\f012";} -.icon-gear:before,.icon-cog:before{content:"\f013";} -.icon-trash:before{content:"\f014";} -.icon-home:before{content:"\f015";} -.icon-file-alt:before{content:"\f016";} -.icon-time:before{content:"\f017";} -.icon-road:before{content:"\f018";} -.icon-download-alt:before{content:"\f019";} -.icon-download:before{content:"\f01a";} -.icon-upload:before{content:"\f01b";} -.icon-inbox:before{content:"\f01c";} -.icon-play-circle:before{content:"\f01d";} -.icon-rotate-right:before,.icon-repeat:before{content:"\f01e";} -.icon-refresh:before{content:"\f021";} -.icon-list-alt:before{content:"\f022";} -.icon-lock:before{content:"\f023";} -.icon-flag:before{content:"\f024";} -.icon-headphones:before{content:"\f025";} -.icon-volume-off:before{content:"\f026";} -.icon-volume-down:before{content:"\f027";} -.icon-volume-up:before{content:"\f028";} -.icon-qrcode:before{content:"\f029";} -.icon-barcode:before{content:"\f02a";} -.icon-tag:before{content:"\f02b";} -.icon-tags:before{content:"\f02c";} -.icon-book:before{content:"\f02d";} -.icon-bookmark:before{content:"\f02e";} -.icon-print:before{content:"\f02f";} -.icon-camera:before{content:"\f030";} -.icon-font:before{content:"\f031";} -.icon-bold:before{content:"\f032";} -.icon-italic:before{content:"\f033";} -.icon-text-height:before{content:"\f034";} -.icon-text-width:before{content:"\f035";} -.icon-align-left:before{content:"\f036";} -.icon-align-center:before{content:"\f037";} -.icon-align-right:before{content:"\f038";} -.icon-align-justify:before{content:"\f039";} -.icon-list:before{content:"\f03a";} -.icon-indent-left:before{content:"\f03b";} -.icon-indent-right:before{content:"\f03c";} -.icon-facetime-video:before{content:"\f03d";} -.icon-picture:before{content:"\f03e";} -.icon-pencil:before{content:"\f040";} -.icon-map-marker:before{content:"\f041";} -.icon-adjust:before{content:"\f042";} -.icon-tint:before{content:"\f043";} -.icon-edit:before{content:"\f044";} -.icon-share:before{content:"\f045";} -.icon-check:before{content:"\f046";} -.icon-move:before{content:"\f047";} -.icon-step-backward:before{content:"\f048";} -.icon-fast-backward:before{content:"\f049";} -.icon-backward:before{content:"\f04a";} -.icon-play:before{content:"\f04b";} -.icon-pause:before{content:"\f04c";} -.icon-stop:before{content:"\f04d";} -.icon-forward:before{content:"\f04e";} -.icon-fast-forward:before{content:"\f050";} -.icon-step-forward:before{content:"\f051";} -.icon-eject:before{content:"\f052";} -.icon-chevron-left:before{content:"\f053";} -.icon-chevron-right:before{content:"\f054";} -.icon-plus-sign:before{content:"\f055";} -.icon-minus-sign:before{content:"\f056";} -.icon-remove-sign:before{content:"\f057";} -.icon-ok-sign:before{content:"\f058";} -.icon-question-sign:before{content:"\f059";} -.icon-info-sign:before{content:"\f05a";} -.icon-screenshot:before{content:"\f05b";} -.icon-remove-circle:before{content:"\f05c";} -.icon-ok-circle:before{content:"\f05d";} -.icon-ban-circle:before{content:"\f05e";} -.icon-arrow-left:before{content:"\f060";} -.icon-arrow-right:before{content:"\f061";} -.icon-arrow-up:before{content:"\f062";} -.icon-arrow-down:before{content:"\f063";} -.icon-mail-forward:before,.icon-share-alt:before{content:"\f064";} -.icon-resize-full:before{content:"\f065";} -.icon-resize-small:before{content:"\f066";} -.icon-plus:before{content:"\f067";} -.icon-minus:before{content:"\f068";} -.icon-asterisk:before{content:"\f069";} -.icon-exclamation-sign:before{content:"\f06a";} -.icon-gift:before{content:"\f06b";} -.icon-leaf:before{content:"\f06c";} -.icon-fire:before{content:"\f06d";} -.icon-eye-open:before{content:"\f06e";} -.icon-eye-close:before{content:"\f070";} -.icon-warning-sign:before{content:"\f071";} -.icon-plane:before{content:"\f072";} -.icon-calendar:before{content:"\f073";} -.icon-random:before{content:"\f074";} -.icon-comment:before{content:"\f075";} -.icon-magnet:before{content:"\f076";} -.icon-chevron-up:before{content:"\f077";} -.icon-chevron-down:before{content:"\f078";} -.icon-retweet:before{content:"\f079";} -.icon-shopping-cart:before{content:"\f07a";} -.icon-folder-close:before{content:"\f07b";} -.icon-folder-open:before{content:"\f07c";} -.icon-resize-vertical:before{content:"\f07d";} -.icon-resize-horizontal:before{content:"\f07e";} -.icon-bar-chart:before{content:"\f080";} -.icon-twitter-sign:before{content:"\f081";} -.icon-facebook-sign:before{content:"\f082";} -.icon-camera-retro:before{content:"\f083";} -.icon-key:before{content:"\f084";} -.icon-gears:before,.icon-cogs:before{content:"\f085";} -.icon-comments:before{content:"\f086";} -.icon-thumbs-up-alt:before{content:"\f087";} -.icon-thumbs-down-alt:before{content:"\f088";} -.icon-star-half:before{content:"\f089";} -.icon-heart-empty:before{content:"\f08a";} -.icon-signout:before{content:"\f08b";} -.icon-linkedin-sign:before{content:"\f08c";} -.icon-pushpin:before{content:"\f08d";} -.icon-external-link:before{content:"\f08e";} -.icon-signin:before{content:"\f090";} -.icon-trophy:before{content:"\f091";} -.icon-github-sign:before{content:"\f092";} -.icon-upload-alt:before{content:"\f093";} -.icon-lemon:before{content:"\f094";} -.icon-phone:before{content:"\f095";} -.icon-unchecked:before,.icon-check-empty:before{content:"\f096";} -.icon-bookmark-empty:before{content:"\f097";} -.icon-phone-sign:before{content:"\f098";} -.icon-twitter:before{content:"\f099";} -.icon-facebook:before{content:"\f09a";} -.icon-github:before{content:"\f09b";} -.icon-unlock:before{content:"\f09c";} -.icon-credit-card:before{content:"\f09d";} -.icon-rss:before{content:"\f09e";} -.icon-hdd:before{content:"\f0a0";} -.icon-bullhorn:before{content:"\f0a1";} -.icon-bell:before{content:"\f0a2";} -.icon-certificate:before{content:"\f0a3";} -.icon-hand-right:before{content:"\f0a4";} -.icon-hand-left:before{content:"\f0a5";} -.icon-hand-up:before{content:"\f0a6";} -.icon-hand-down:before{content:"\f0a7";} -.icon-circle-arrow-left:before{content:"\f0a8";} -.icon-circle-arrow-right:before{content:"\f0a9";} -.icon-circle-arrow-up:before{content:"\f0aa";} -.icon-circle-arrow-down:before{content:"\f0ab";} -.icon-globe:before{content:"\f0ac";} -.icon-wrench:before{content:"\f0ad";} -.icon-tasks:before{content:"\f0ae";} -.icon-filter:before{content:"\f0b0";} -.icon-briefcase:before{content:"\f0b1";} -.icon-fullscreen:before{content:"\f0b2";} -.icon-group:before{content:"\f0c0";} -.icon-link:before{content:"\f0c1";} -.icon-cloud:before{content:"\f0c2";} -.icon-beaker:before{content:"\f0c3";} -.icon-cut:before{content:"\f0c4";} -.icon-copy:before{content:"\f0c5";} -.icon-paperclip:before,.icon-paper-clip:before{content:"\f0c6";} -.icon-save:before{content:"\f0c7";} -.icon-sign-blank:before{content:"\f0c8";} -.icon-reorder:before{content:"\f0c9";} -.icon-list-ul:before{content:"\f0ca";} -.icon-list-ol:before{content:"\f0cb";} -.icon-strikethrough:before{content:"\f0cc";} -.icon-underline:before{content:"\f0cd";} -.icon-table:before{content:"\f0ce";} -.icon-magic:before{content:"\f0d0";} -.icon-truck:before{content:"\f0d1";} -.icon-pinterest:before{content:"\f0d2";} -.icon-pinterest-sign:before{content:"\f0d3";} -.icon-google-plus-sign:before{content:"\f0d4";} -.icon-google-plus:before{content:"\f0d5";} -.icon-money:before{content:"\f0d6";} -.icon-caret-down:before{content:"\f0d7";} -.icon-caret-up:before{content:"\f0d8";} -.icon-caret-left:before{content:"\f0d9";} -.icon-caret-right:before{content:"\f0da";} -.icon-columns:before{content:"\f0db";} -.icon-sort:before{content:"\f0dc";} -.icon-sort-down:before{content:"\f0dd";} -.icon-sort-up:before{content:"\f0de";} -.icon-envelope:before{content:"\f0e0";} -.icon-linkedin:before{content:"\f0e1";} -.icon-rotate-left:before,.icon-undo:before{content:"\f0e2";} -.icon-legal:before{content:"\f0e3";} -.icon-dashboard:before{content:"\f0e4";} -.icon-comment-alt:before{content:"\f0e5";} -.icon-comments-alt:before{content:"\f0e6";} -.icon-bolt:before{content:"\f0e7";} -.icon-sitemap:before{content:"\f0e8";} -.icon-umbrella:before{content:"\f0e9";} -.icon-paste:before{content:"\f0ea";} -.icon-lightbulb:before{content:"\f0eb";} -.icon-exchange:before{content:"\f0ec";} -.icon-cloud-download:before{content:"\f0ed";} -.icon-cloud-upload:before{content:"\f0ee";} -.icon-user-md:before{content:"\f0f0";} -.icon-stethoscope:before{content:"\f0f1";} -.icon-suitcase:before{content:"\f0f2";} -.icon-bell-alt:before{content:"\f0f3";} -.icon-coffee:before{content:"\f0f4";} -.icon-food:before{content:"\f0f5";} -.icon-file-text-alt:before{content:"\f0f6";} -.icon-building:before{content:"\f0f7";} -.icon-hospital:before{content:"\f0f8";} -.icon-ambulance:before{content:"\f0f9";} -.icon-medkit:before{content:"\f0fa";} -.icon-fighter-jet:before{content:"\f0fb";} -.icon-beer:before{content:"\f0fc";} -.icon-h-sign:before{content:"\f0fd";} -.icon-plus-sign-alt:before{content:"\f0fe";} -.icon-double-angle-left:before{content:"\f100";} -.icon-double-angle-right:before{content:"\f101";} -.icon-double-angle-up:before{content:"\f102";} -.icon-double-angle-down:before{content:"\f103";} -.icon-angle-left:before{content:"\f104";} -.icon-angle-right:before{content:"\f105";} -.icon-angle-up:before{content:"\f106";} -.icon-angle-down:before{content:"\f107";} -.icon-desktop:before{content:"\f108";} -.icon-laptop:before{content:"\f109";} -.icon-tablet:before{content:"\f10a";} -.icon-mobile-phone:before{content:"\f10b";} -.icon-circle-blank:before{content:"\f10c";} -.icon-quote-left:before{content:"\f10d";} -.icon-quote-right:before{content:"\f10e";} -.icon-spinner:before{content:"\f110";} -.icon-circle:before{content:"\f111";} -.icon-mail-reply:before,.icon-reply:before{content:"\f112";} -.icon-github-alt:before{content:"\f113";} -.icon-folder-close-alt:before{content:"\f114";} -.icon-folder-open-alt:before{content:"\f115";} -.icon-expand-alt:before{content:"\f116";} -.icon-collapse-alt:before{content:"\f117";} -.icon-smile:before{content:"\f118";} -.icon-frown:before{content:"\f119";} -.icon-meh:before{content:"\f11a";} -.icon-gamepad:before{content:"\f11b";} -.icon-keyboard:before{content:"\f11c";} -.icon-flag-alt:before{content:"\f11d";} -.icon-flag-checkered:before{content:"\f11e";} -.icon-terminal:before{content:"\f120";} -.icon-code:before{content:"\f121";} -.icon-reply-all:before{content:"\f122";} -.icon-mail-reply-all:before{content:"\f122";} -.icon-star-half-full:before,.icon-star-half-empty:before{content:"\f123";} -.icon-location-arrow:before{content:"\f124";} -.icon-crop:before{content:"\f125";} -.icon-code-fork:before{content:"\f126";} -.icon-unlink:before{content:"\f127";} -.icon-question:before{content:"\f128";} -.icon-info:before{content:"\f129";} -.icon-exclamation:before{content:"\f12a";} -.icon-superscript:before{content:"\f12b";} -.icon-subscript:before{content:"\f12c";} -.icon-eraser:before{content:"\f12d";} -.icon-puzzle-piece:before{content:"\f12e";} -.icon-microphone:before{content:"\f130";} -.icon-microphone-off:before{content:"\f131";} -.icon-shield:before{content:"\f132";} -.icon-calendar-empty:before{content:"\f133";} -.icon-fire-extinguisher:before{content:"\f134";} -.icon-rocket:before{content:"\f135";} -.icon-maxcdn:before{content:"\f136";} -.icon-chevron-sign-left:before{content:"\f137";} -.icon-chevron-sign-right:before{content:"\f138";} -.icon-chevron-sign-up:before{content:"\f139";} -.icon-chevron-sign-down:before{content:"\f13a";} -.icon-html5:before{content:"\f13b";} -.icon-css3:before{content:"\f13c";} -.icon-anchor:before{content:"\f13d";} -.icon-unlock-alt:before{content:"\f13e";} -.icon-bullseye:before{content:"\f140";} -.icon-ellipsis-horizontal:before{content:"\f141";} -.icon-ellipsis-vertical:before{content:"\f142";} -.icon-rss-sign:before{content:"\f143";} -.icon-play-sign:before{content:"\f144";} -.icon-ticket:before{content:"\f145";} -.icon-minus-sign-alt:before{content:"\f146";} -.icon-check-minus:before{content:"\f147";} -.icon-level-up:before{content:"\f148";} -.icon-level-down:before{content:"\f149";} -.icon-check-sign:before{content:"\f14a";} -.icon-edit-sign:before{content:"\f14b";} -.icon-external-link-sign:before{content:"\f14c";} -.icon-share-sign:before{content:"\f14d";} -.icon-compass:before{content:"\f14e";} -.icon-collapse:before{content:"\f150";} -.icon-collapse-top:before{content:"\f151";} -.icon-expand:before{content:"\f152";} -.icon-euro:before,.icon-eur:before{content:"\f153";} -.icon-gbp:before{content:"\f154";} -.icon-dollar:before,.icon-usd:before{content:"\f155";} -.icon-rupee:before,.icon-inr:before{content:"\f156";} -.icon-yen:before,.icon-jpy:before{content:"\f157";} -.icon-renminbi:before,.icon-cny:before{content:"\f158";} -.icon-won:before,.icon-krw:before{content:"\f159";} -.icon-bitcoin:before,.icon-btc:before{content:"\f15a";} -.icon-file:before{content:"\f15b";} -.icon-file-text:before{content:"\f15c";} -.icon-sort-by-alphabet:before{content:"\f15d";} -.icon-sort-by-alphabet-alt:before{content:"\f15e";} -.icon-sort-by-attributes:before{content:"\f160";} -.icon-sort-by-attributes-alt:before{content:"\f161";} -.icon-sort-by-order:before{content:"\f162";} -.icon-sort-by-order-alt:before{content:"\f163";} -.icon-thumbs-up:before{content:"\f164";} -.icon-thumbs-down:before{content:"\f165";} -.icon-youtube-sign:before{content:"\f166";} -.icon-youtube:before{content:"\f167";} -.icon-xing:before{content:"\f168";} -.icon-xing-sign:before{content:"\f169";} -.icon-youtube-play:before{content:"\f16a";} -.icon-dropbox:before{content:"\f16b";} -.icon-stackexchange:before{content:"\f16c";} -.icon-instagram:before{content:"\f16d";} -.icon-flickr:before{content:"\f16e";} -.icon-adn:before{content:"\f170";} -.icon-bitbucket:before{content:"\f171";} -.icon-bitbucket-sign:before{content:"\f172";} -.icon-tumblr:before{content:"\f173";} -.icon-tumblr-sign:before{content:"\f174";} -.icon-long-arrow-down:before{content:"\f175";} -.icon-long-arrow-up:before{content:"\f176";} -.icon-long-arrow-left:before{content:"\f177";} -.icon-long-arrow-right:before{content:"\f178";} -.icon-apple:before{content:"\f179";} -.icon-windows:before{content:"\f17a";} -.icon-android:before{content:"\f17b";} -.icon-linux:before{content:"\f17c";} -.icon-dribbble:before{content:"\f17d";} -.icon-skype:before{content:"\f17e";} -.icon-foursquare:before{content:"\f180";} -.icon-trello:before{content:"\f181";} -.icon-female:before{content:"\f182";} -.icon-male:before{content:"\f183";} -.icon-gittip:before{content:"\f184";} -.icon-sun:before{content:"\f185";} -.icon-moon:before{content:"\f186";} -.icon-archive:before{content:"\f187";} -.icon-bug:before{content:"\f188";} -.icon-vk:before{content:"\f189";} -.icon-weibo:before{content:"\f18a";} -.icon-renren:before{content:"\f18b";} +/*! + * Font Awesome 4.0.3 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.0.3');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.0.3') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff?v=4.0.3') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.0.3') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.0.3#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.3333333333333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.2857142857142858em;text-align:center}.fa-ul{padding-left:0;margin-left:2.142857142857143em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.142857142857143em;width:2.142857142857143em;top:.14285714285714285em;text-align:center}.fa-li.fa-lg{left:-1.8571428571428572em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:spin 2s infinite linear;-moz-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;animation:spin 2s infinite linear}@-moz-keyframes spin{0%{-moz-transform:rotate(0deg)}100%{-moz-transform:rotate(359deg)}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg)}}@-o-keyframes spin{0%{-o-transform:rotate(0deg)}100%{-o-transform:rotate(359deg)}}@-ms-keyframes spin{0%{-ms-transform:rotate(0deg)}100%{-ms-transform:rotate(359deg)}}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0,mirror=1);-webkit-transform:scale(-1,1);-moz-transform:scale(-1,1);-ms-transform:scale(-1,1);-o-transform:scale(-1,1);transform:scale(-1,1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2,mirror=1);-webkit-transform:scale(1,-1);-moz-transform:scale(1,-1);-ms-transform:scale(1,-1);-o-transform:scale(1,-1);transform:scale(1,-1)}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-asc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-desc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-reply-all:before{content:"\f122"}.fa-mail-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"} \ No newline at end of file diff --git a/ui/resources/font-awesome/fonts/FontAwesome.otf b/ui/resources/font-awesome/fonts/FontAwesome.otf new file mode 100644 index 00000000..8b0f54e4 Binary files /dev/null and b/ui/resources/font-awesome/fonts/FontAwesome.otf differ diff --git a/ui/resources/font-awesome/fonts/fontawesome-webfont.eot b/ui/resources/font-awesome/fonts/fontawesome-webfont.eot new file mode 100644 index 00000000..7c79c6a6 Binary files /dev/null and b/ui/resources/font-awesome/fonts/fontawesome-webfont.eot differ diff --git a/ui/resources/font-awesome/fonts/fontawesome-webfont.svg b/ui/resources/font-awesome/fonts/fontawesome-webfont.svg new file mode 100644 index 00000000..45fdf338 --- /dev/null +++ b/ui/resources/font-awesome/fonts/fontawesome-webfont.svg @@ -0,0 +1,414 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ui/resources/font-awesome/fonts/fontawesome-webfont.ttf b/ui/resources/font-awesome/fonts/fontawesome-webfont.ttf new file mode 100644 index 00000000..e89738de Binary files /dev/null and b/ui/resources/font-awesome/fonts/fontawesome-webfont.ttf differ diff --git a/ui/resources/font-awesome/fonts/fontawesome-webfont.woff b/ui/resources/font-awesome/fonts/fontawesome-webfont.woff new file mode 100644 index 00000000..8c1748aa Binary files /dev/null and b/ui/resources/font-awesome/fonts/fontawesome-webfont.woff differ diff --git a/ui/resources/themes/polished/wt.css b/ui/resources/themes/polished/wt.css index 7fbb1403..1c7d869d 100644 --- a/ui/resources/themes/polished/wt.css +++ b/ui/resources/themes/polished/wt.css @@ -474,6 +474,12 @@ span.Wt-disabled, fieldset.Wt-disabled legend { border: 1px inset #CCC; } +.Wt-btn[disabled] { + border: 1px outset #CCC; + cursor: not-allowed; + opacity: 0.75; +} + .Wt-btn-default { font-weight: bold; border: 1px outset #37E; diff --git a/ui/settings/Settings.cpp b/ui/settings/Settings.cpp index 9b7eb71e..1b762d71 100644 --- a/ui/settings/Settings.cpp +++ b/ui/settings/Settings.cpp @@ -2,7 +2,7 @@ #include #include -#include "SettingsDatabase.hpp" +#include "SettingsDatabaseFormView.hpp" #include "Settings.hpp" @@ -30,7 +30,7 @@ _sessionData(sessionData) if (user->isAdmin()) { // TODO Special admin settings - menu->addItem("Database", new Database(sessionData)); + menu->addItem("Database", new DatabaseFormView(sessionData)); menu->addItem("Users", new Wt::WTextArea("Users here!")); } diff --git a/ui/settings/SettingsDatabase.cpp b/ui/settings/SettingsDatabase.cpp deleted file mode 100644 index 66c74ca5..00000000 --- a/ui/settings/SettingsDatabase.cpp +++ /dev/null @@ -1,328 +0,0 @@ -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "database/MediaDirectory.hpp" -#include "service/ServiceManager.hpp" -#include "service/DatabaseUpdateService.hpp" - -#include "common/DirectoryValidator.hpp" - -#include "SettingsDatabase.hpp" - -namespace UserInterface { -namespace Settings { - - -Database::Database(SessionData& sessionData, Wt::WContainerWidget *parent) -: Wt::WContainerWidget(parent), -_sessionData(sessionData) -{ - - // Media directories - { - Wt::WGroupBox *container = new Wt::WGroupBox("Media directories", this); - - _table = new Wt::WTable(container); - - _table->addStyleClass("table form-inline"); - _table->toggleStyleClass("table-hover", true); - _table->toggleStyleClass("table-striped", true); - - _table->setHeaderCount(1); - _table->elementAt(0, 0)->addWidget(new Wt::WText("Path")); - _table->elementAt(0, 1)->addWidget(new Wt::WText("Status")); - _table->elementAt(0, 2)->addWidget(new Wt::WText("Delete")); - - { - Wt::WPushButton* btn = new Wt::WPushButton("Add"); - container->addWidget(btn); - btn->clicked().connect(this, &Database::handleAddDirectory); - } - { - Wt::WPushButton* btn = new Wt::WPushButton("Delete"); - container->addWidget(btn); - btn->clicked().connect(this, &Database::handleDelDirectory); - } - - } - addWidget(new Wt::WBreak()); - - // Refresh settings - { - Wt::WGroupBox *container = new Wt::WGroupBox("Refresh settings", this); - - Wt::WTable *table = new Wt::WTable(container); - table->addStyleClass("table form-inline"); - - table->setHeaderCount(1, Wt::Vertical); - std::size_t line = 0; - table->elementAt(line, 0)->addWidget(new Wt::WText("Update period")); - table->elementAt(line, 1)->addWidget(_updatePeriod = new Wt::WComboBox() ); - // Populate combo - _updatePeriodModel = new Wt::WStringListModel(_updatePeriod); - - _updatePeriodModel->addString("Never"); - _updatePeriodModel->setData(0, 0, boost::posix_time::time_duration( boost::posix_time::hours(0) ), Wt::UserRole); - - _updatePeriodModel->addString("Daily"); - _updatePeriodModel->setData(1, 0, boost::posix_time::time_duration( boost::posix_time::hours(24) ), Wt::UserRole); - - _updatePeriodModel->addString("Weekly"); - _updatePeriodModel->setData(2, 0, boost::posix_time::time_duration( boost::posix_time::hours(24*7) ), Wt::UserRole); - - _updatePeriodModel->addString("Monthly"); - _updatePeriodModel->setData(3, 0, boost::posix_time::time_duration(boost::posix_time::hours(24*30) ), Wt::UserRole); - - _updatePeriod->setModel(_updatePeriodModel); - - line++; - - table->elementAt(line, 0)->addWidget(new Wt::WText("Update start time")); - table->elementAt(line, 1)->addWidget(_updateStartTime = new Wt::WComboBox( )); - // populate combo - _updateStartTimeModel = new Wt::WStringListModel(_updateStartTime); - - for (std::size_t i = 0; i < 24; ++i) - { - boost::posix_time::time_duration dur = boost::posix_time::hours(i); - - boost::posix_time::time_facet* facet = new boost::posix_time::time_facet("%H:%M"); - facet->time_duration_format("%H:%M"); - - std::ostringstream oss; - oss.imbue(std::locale(oss.getloc(), facet)); - - oss << dur; - - _updateStartTimeModel->addString( oss.str() ); - _updateStartTimeModel->setData(i, 0, dur, Wt::UserRole); - } - - _updateStartTime->setModel(_updateStartTimeModel); - - line++; - - Wt::WPushButton* btn = new Wt::WPushButton("Scan now", container); - btn->clicked().connect(this, &Database::handleScanNow); - } - - addWidget(new Wt::WBreak()); - addWidget(new Wt::WBreak()); - { - Wt::WPushButton* btn = new Wt::WPushButton("Apply", this); - btn->clicked().connect(this, &Database::handleApply); - } - { - Wt::WPushButton* btn = new Wt::WPushButton("Discard", this); - btn->clicked().connect(this, &Database::loadSettings); - } - - loadSettings(); -} - -void -Database::addDirectory(const std::string& path) -{ - int line = _table->rowCount(); - - Wt::WLineEdit* lineEdit = new Wt::WLineEdit( path ); - _table->elementAt(line, 0)->addWidget( lineEdit ); - - DirectoryValidator* validator = new DirectoryValidator(true); - lineEdit->setValidator(validator); - - std::string status; - - if (!path.empty()) - status = validator->validate( path ).message().toUTF8(); - - Wt::WText* statusText = new Wt::WText( status ); - _table->elementAt(line, 1)->addWidget( statusText ); - _table->elementAt(line, 2)->addWidget( new Wt::WCheckBox() ); - - lineEdit->blurred().connect(boost::bind(&Database::handleCheckDirectory, this, lineEdit, statusText)); -} - -void -Database::loadSettings(void) -{ - Wt::Dbo::Transaction transaction(_sessionData.getDatabaseHandler().getSession()); - - // Get directories - std::vector<::Database::MediaDirectory::pointer> directories = ::Database::MediaDirectory::getAll(_sessionData.getDatabaseHandler().getSession()); - - // delete rows - assert(_table->rowCount() > 0 ); - for (int i = _table->rowCount() - 1; i > 0; --i) - _table->deleteRow(i); - - BOOST_FOREACH(::Database::MediaDirectory::pointer directory, directories) - addDirectory( directory->getPath().string() ); - - // Get refresh settings - ::Database::MediaDirectorySettings::pointer settings = ::Database::MediaDirectorySettings::get(_sessionData.getDatabaseHandler().getSession()); - - { - int i; - for (i = 0; i < _updatePeriodModel->rowCount(); ++i) - { - if (boost::any_cast - (_updatePeriodModel->data(_updatePeriodModel->index(i, 0), Wt::UserRole)) - >= settings->getUpdatePeriod()) - break; - } - _updatePeriod->setCurrentIndex(i); - } - { - int i; - for (i = 0; i < _updateStartTimeModel->rowCount(); ++i) - { - if (boost::any_cast - (_updateStartTimeModel->data(_updateStartTimeModel->index(i, 0), Wt::UserRole)) - >= settings->getUpdateStartTime()) - break; - } - _updateStartTime->setCurrentIndex(i); - } - -} - -void -Database::handleAddDirectory(void) -{ - // TODO check if the previous entry is empty too - addDirectory(); -} - -void -Database::handleDelDirectory() -{ - assert(_table->rowCount() > 0 ); - for (int i = _table->rowCount() - 1; i > 0; --i) - { - assert(_table->elementAt(i, 2)->count() == 1); - Wt::WCheckBox *checkBox = dynamic_cast(_table->elementAt(i, 2)->widget(0)); - - if (checkBox->checkState() == Wt::CheckState::Checked) - _table->deleteRow(i); - } -} - -void -Database::handleCheckDirectory(Wt::WLineEdit* edit, Wt::WText* status) -{ - Wt::WValidator* validator = edit->validator(); - if (validator) - status->setText( validator->validate( edit->text().toUTF8() ).message().toUTF8()); -} - -bool -Database::saveSettings(void) -{ - Wt::Dbo::Transaction transaction(_sessionData.getDatabaseHandler().getSession()); - - assert(_table->rowCount() > 0 ); - // Validate each directory in the table - for (int i = 1; i < _table->rowCount(); ++i) - { - assert(_table->elementAt(i, 0)->count() == 1); - - Wt::WLineEdit* lineEdit = dynamic_cast(_table->elementAt(i, 0)->widget(0)); - if (!lineEdit->validate()) - return false;; - - } - - // erase all directories and add from the table - ::Database::MediaDirectory::eraseAll( _sessionData.getDatabaseHandler().getSession() ); - - for (int i = 1; i < _table->rowCount(); ++i) - { - Wt::WLineEdit* lineEdit = dynamic_cast(_table->elementAt(i, 0)->widget(0)); - - ::Database::MediaDirectory::create( _sessionData.getDatabaseHandler().getSession(), lineEdit->text().toUTF8(), ::Database::MediaDirectory::Audio); - } - - ::Database::MediaDirectorySettings::pointer settings = ::Database::MediaDirectorySettings::get(_sessionData.getDatabaseHandler().getSession() ); - { - int row = _updateStartTime->currentIndex(); - settings.modify()->setUpdateStartTime( boost::any_cast( _updateStartTimeModel->data(_updateStartTimeModel->index(row, 0), Wt::UserRole))); - } - { - int row = _updatePeriod->currentIndex(); - settings.modify()->setUpdatePeriod( boost::any_cast( _updatePeriodModel->data(_updatePeriodModel->index(row, 0), Wt::UserRole))); - } - - - return true; -} - -void -Database::handleApply(void) -{ - if (saveSettings()) - { - boost::lock_guard serviceLock (ServiceManager::instance().mutex()); - - DatabaseUpdateService::pointer service = ServiceManager::instance().getService(); - if (service) - service->restart(); - - // Show a popup to say it's fine! - Wt::WMessageBox *messageBox = new Wt::WMessageBox - ("Status", - "New settings applied!", - Wt::Information, Wt::Ok); - - messageBox->setModal(true); - - messageBox->buttonClicked().connect(std::bind([=] () - { - delete messageBox; - } - )); - - messageBox->show(); - } - else - { - Wt::WMessageBox *messageBox = new Wt::WMessageBox - ("Error", - "Cannot apply settings", - Wt::Critical, Wt::Ok); - - messageBox->setModal(true); - - messageBox->buttonClicked().connect(std::bind([=] () - { - delete messageBox; - } - )); - - messageBox->show(); - } - -} - -void -Database::handleScanNow(void) -{ - -} - - - - -} // namespace Settings -} // namespace UserInterface - - diff --git a/ui/settings/SettingsDatabase.hpp b/ui/settings/SettingsDatabase.hpp deleted file mode 100644 index 5b95de99..00000000 --- a/ui/settings/SettingsDatabase.hpp +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef UI_SETTINGS_DB_HPP -#define UI_SETTINGS_DB_HPP - -#include -#include -#include -#include -#include - -#include "common/SessionData.hpp" - -namespace UserInterface { -namespace Settings { - -class Database : public Wt::WContainerWidget -{ - public: - Database(SessionData& sessionData, Wt::WContainerWidget *parent = 0); - - private: - void handleApply(); - - void handleCheckDirectory(Wt::WLineEdit* edit, Wt::WText* status); - void handleAddDirectory(); - void handleDelDirectory(); - - void handleScanNow(void); - - void loadSettings(void); // load from db - bool saveSettings(void); // save into db - - void addDirectory(const std::string& path = ""); - - SessionData& _sessionData; - - Wt::WTable* _table; - - Wt::WComboBox* _updatePeriod; - Wt::WStringListModel* _updatePeriodModel; - - Wt::WComboBox* _updateStartTime; - Wt::WStringListModel* _updateStartTimeModel; -}; - - -} // namespace Settings -} // namespace UserInterface - -#endif - diff --git a/ui/settings/SettingsDatabaseFormView.cpp b/ui/settings/SettingsDatabaseFormView.cpp new file mode 100644 index 00000000..58c68498 --- /dev/null +++ b/ui/settings/SettingsDatabaseFormView.cpp @@ -0,0 +1,343 @@ +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "database/MediaDirectory.hpp" + +#include "service/ServiceManager.hpp" +#include "service/DatabaseUpdateService.hpp" + +#include "common/DirectoryValidator.hpp" + +#include "SettingsDatabaseFormView.hpp" + +namespace UserInterface { +namespace Settings { + +class DatabaseFormModel : public Wt::WFormModel +{ + public: + // Associate each field with a unique string literal. + static const Field PathField; + static const Field UpdatePeriodField; + static const Field UpdateStartTimeField; + static const Field UpdateRequestImmediateField; + + DatabaseFormModel(SessionData& sessionData, Wt::WObject *parent = 0) + : Wt::WFormModel(parent), + _sessionData(sessionData) + { + initializeModels(); + + addField(PathField); + addField(UpdatePeriodField); + addField(UpdateStartTimeField); + addField(UpdateRequestImmediateField); + + setValidator(PathField, createPathValidator(PathField)); + setValidator(UpdatePeriodField, createUpdatePeriodValidator(UpdatePeriodField)); + setValidator(UpdateStartTimeField, createStartTimeValidator(UpdateStartTimeField)); + setValidator(UpdateRequestImmediateField, createRequestImmediateFieldValidator(UpdateRequestImmediateField)); + + // populate the model with initial data + loadData(); + } + + Wt::WAbstractItemModel *updatePeriodModel() { return _updatePeriodModel; } + Wt::WAbstractItemModel *updateStartTimeModel() { return _updateStartTimeModel; } + + void loadData() + { + Wt::Dbo::Transaction transaction(_sessionData.getDatabaseHandler().getSession()); + + // Get directories + std::vector<::Database::MediaDirectory::pointer> directories = ::Database::MediaDirectory::getAll(_sessionData.getDatabaseHandler().getSession()); + + BOOST_FOREACH(::Database::MediaDirectory::pointer directory, directories) + { + setValue(PathField, directory->getPath().string() ); + // TODO, handle multiple directories + break; + } + + // Get refresh settings + ::Database::MediaDirectorySettings::pointer settings = ::Database::MediaDirectorySettings::get(_sessionData.getDatabaseHandler().getSession()); + + int periodRow = getUpdatePeriodModelRow( settings->getUpdatePeriod() ); + if (periodRow != -1) + setValue(UpdatePeriodField, updatePeriod(periodRow)); + + int startTimeRow = getUpdateStartTimeModelRow( settings->getUpdateStartTime() ); + if (startTimeRow != -1) + setValue(UpdateStartTimeField, updateStartTime( startTimeRow ) ); + + setValue(UpdateRequestImmediateField, settings->getManualScanRequested() ); + } + + void saveData() + { + Wt::Dbo::Session& session( _sessionData.getDatabaseHandler().getSession()); + Wt::Dbo::Transaction transaction(session); + + ::Database::MediaDirectory::eraseAll( session ); + ::Database::MediaDirectory::create(session, valueText(PathField).toUTF8(), ::Database::MediaDirectory::Audio); + + ::Database::MediaDirectorySettings::pointer settings = ::Database::MediaDirectorySettings::get(_sessionData.getDatabaseHandler().getSession() ); + + int periodRow = getUpdatePeriodModelRow( boost::any_cast(value(UpdatePeriodField))); + assert(periodRow != -1); + settings.modify()->setUpdatePeriod( updatePeriodDuration( periodRow ) ); + + int startTimeRow = getUpdateStartTimeModelRow( boost::any_cast(value(UpdateStartTimeField))); + assert(startTimeRow != -1); + settings.modify()->setUpdateStartTime( updateStartTimeDuration( startTimeRow ) ); + + settings.modify()->setManualScanRequested( boost::any_cast(value(UpdateRequestImmediateField )) ); + } + + + int getUpdatePeriodModelRow(Wt::WString value) + { + for (int i = 0; i < _updatePeriodModel->rowCount(); ++i) + { + if (updatePeriod(i) == value) + return i; + } + return -1; + } + + int getUpdatePeriodModelRow(boost::posix_time::time_duration duration) + { + for (int i = 0; i < _updatePeriodModel->rowCount(); ++i) + { + if (updatePeriodDuration(i) == duration) + return i; + } + + return -1; + } + + boost::posix_time::time_duration updatePeriodDuration(int row) { + return boost::any_cast + (_updatePeriodModel->data(_updatePeriodModel->index(row, 0), Wt::UserRole)); + } + + Wt::WString updatePeriod(int row) { + return boost::any_cast + (_updatePeriodModel->data(_updatePeriodModel->index(row, 0), Wt::DisplayRole)); + } + + + int getUpdateStartTimeModelRow(Wt::WString value) + { + for (int i = 0; i < _updateStartTimeModel->rowCount(); ++i) + { + if (updateStartTime(i) == value) + return i; + } + + return -1; + } + + int getUpdateStartTimeModelRow(boost::posix_time::time_duration duration) + { + for (int i = 0; i < _updateStartTimeModel->rowCount(); ++i) + { + if (updateStartTimeDuration(i) == duration) + return i; + } + + return -1; + } + + boost::posix_time::time_duration updateStartTimeDuration(int row) { + return boost::any_cast + (_updateStartTimeModel->data(_updateStartTimeModel->index(row, 0), Wt::UserRole)); + } + + Wt::WString updateStartTime(int row) { + return boost::any_cast + (_updateStartTimeModel->data(_updateStartTimeModel->index(row, 0), Wt::DisplayRole)); + } + + + private: + + void initializeModels() { + + _updatePeriodModel = new Wt::WStringListModel(this); + + _updatePeriodModel->addString("Never"); + _updatePeriodModel->setData(0, 0, boost::posix_time::time_duration( boost::posix_time::hours(0) ), Wt::UserRole); + + _updatePeriodModel->addString("Daily"); + _updatePeriodModel->setData(1, 0, boost::posix_time::time_duration( boost::posix_time::hours(24) ), Wt::UserRole); + + _updatePeriodModel->addString("Weekly"); + _updatePeriodModel->setData(2, 0, boost::posix_time::time_duration( boost::posix_time::hours(24*7) ), Wt::UserRole); + + _updatePeriodModel->addString("Monthly"); + _updatePeriodModel->setData(3, 0, boost::posix_time::time_duration(boost::posix_time::hours(24*30) ), Wt::UserRole); + + + _updateStartTimeModel = new Wt::WStringListModel(this); + + for (std::size_t i = 0; i < 24; ++i) + { + boost::posix_time::time_duration dur = boost::posix_time::hours(i); + + boost::posix_time::time_facet* facet = new boost::posix_time::time_facet("%H:%M"); + facet->time_duration_format("%H:%M"); + + std::ostringstream oss; + oss.imbue(std::locale(oss.getloc(), facet)); + + oss << dur; + + _updateStartTimeModel->addString( oss.str() ); + _updateStartTimeModel->setData(i, 0, dur, Wt::UserRole); + } + + } + + Wt::WValidator *createPathValidator(const std::string& field) { + DirectoryValidator* v = new DirectoryValidator(); + v->setMandatory(true); + return v; + } + + Wt::WValidator *createUpdatePeriodValidator(const std::string& field) { + Wt::WValidator* v = new Wt::WValidator(); + v->setMandatory(true); + return v; + } + + Wt::WValidator *createStartTimeValidator(const std::string& field) { + Wt::WValidator* v = new Wt::WValidator(); + v->setMandatory(true); + return v; + } + + Wt::WValidator *createRequestImmediateFieldValidator(const std::string& field) { + Wt::WValidator* v = new Wt::WValidator(); + return v; + } + + SessionData& _sessionData; + Wt::WStringListModel* _updatePeriodModel; + Wt::WStringListModel* _updateStartTimeModel; + +}; + +const Wt::WFormModel::Field DatabaseFormModel::PathField = "path"; +const Wt::WFormModel::Field DatabaseFormModel::UpdatePeriodField = "update-period"; +const Wt::WFormModel::Field DatabaseFormModel::UpdateStartTimeField = "update-start-time"; +const Wt::WFormModel::Field DatabaseFormModel::UpdateRequestImmediateField = "update-request-immediate-scan"; + + +DatabaseFormView::DatabaseFormView(SessionData& sessionData, Wt::WContainerWidget *parent) +: Wt::WTemplateFormView(parent) +{ + model = new DatabaseFormModel(sessionData, this); + + setTemplateText(tr("databaseForm-template")); + addFunction("id", &WTemplate::Functions::id); + addFunction("block", &WTemplate::Functions::id); + + // Path + setFormWidget(DatabaseFormModel::PathField, new Wt::WLineEdit()); + + // Update Period + Wt::WComboBox *updatePeriodCB = new Wt::WComboBox(); + setFormWidget(DatabaseFormModel::UpdatePeriodField, updatePeriodCB); + updatePeriodCB->setModel(model->updatePeriodModel()); + + // Update Start Time + Wt::WComboBox *updateStartTimeCB = new Wt::WComboBox(); + setFormWidget(DatabaseFormModel::UpdateStartTimeField, updateStartTimeCB); + updateStartTimeCB->setModel(model->updateStartTimeModel()); + + // Request Immediate scan + setFormWidget(DatabaseFormModel::UpdateRequestImmediateField, new Wt::WCheckBox()); + + // Title & Buttons + Wt::WString title = Wt::WString("Media directories settings"); + bindString("title", title); + + Wt::WPushButton *saveButton = new Wt::WPushButton("Apply"); + bindWidget("apply-button", saveButton); + saveButton->setStyleClass("btn-primary"); + + Wt::WPushButton *discardButton = new Wt::WPushButton("Discard"); + bindWidget("discard-button", discardButton); + + applyInfo = new Wt::WText(); + applyInfo->setInline(false); + applyInfo->hide(); + bindWidget("apply-info", applyInfo); + + saveButton->clicked().connect(this, &DatabaseFormView::processSave); + discardButton->clicked().connect(this, &DatabaseFormView::processDiscard); + + updateView(model); + +} + +void +DatabaseFormView::processDiscard() +{ + applyInfo->show(); + + applyInfo->setText( Wt::WString::fromUTF8("Parameters reverted!")); + applyInfo->setStyleClass("alert alert-info"); + + model->loadData(); + + model->validate(); + updateView(model); +} + +void +DatabaseFormView::processSave() +{ + updateModel(model); + + applyInfo->show(); + + if (model->validate()) { + // Make the model to commit data into DB + model->saveData(); + + // Restarting the update service + { + boost::lock_guard serviceLock (ServiceManager::instance().mutex()); + + DatabaseUpdateService::pointer service = ServiceManager::instance().getService(); + if (service) + service->restart(); + } + + applyInfo->setText( Wt::WString::fromUTF8("New parameters successfully applied!")); + applyInfo->setStyleClass("alert alert-success"); + + // Udate the view: Delete any validation message in the view, etc. + updateView(model); + + } else { + applyInfo->setText( Wt::WString::fromUTF8("Cannot apply new parameters!")); + applyInfo->setStyleClass("alert alert-danger"); + updateView(model); + } +} + + +} // namespace Settings +} // namespace UserInterface + + diff --git a/ui/settings/SettingsDatabaseFormView.hpp b/ui/settings/SettingsDatabaseFormView.hpp new file mode 100644 index 00000000..fcedc0a4 --- /dev/null +++ b/ui/settings/SettingsDatabaseFormView.hpp @@ -0,0 +1,34 @@ +#ifndef UI_SETTINGS_DB_FORM_VIEW_HPP +#define UI_SETTINGS_DB_FORM_VIEW_HPP + +#include +#include +#include + +#include "common/SessionData.hpp" + +namespace UserInterface { +namespace Settings { + +class DatabaseFormModel; + +class DatabaseFormView : public Wt::WTemplateFormView +{ + public: + DatabaseFormView(SessionData& sessionData, Wt::WContainerWidget *parent = 0); + + private: + void processSave(); + void processDiscard(); + + Wt::WText *applyInfo; + DatabaseFormModel *model; + +}; + + +} // namespace Settings +} // namespace UserInterface + +#endif +