diff --git a/3.0/modules/g1_import/controllers/admin_g1_import.php b/3.0/modules/g1_import/controllers/admin_g1_import.php new file mode 100644 index 00000000..9f49de24 --- /dev/null +++ b/3.0/modules/g1_import/controllers/admin_g1_import.php @@ -0,0 +1,131 @@ +page_title = t('Gallery 1 import'); + $view->content = new View('admin_g1_import.html'); + + if (is_dir(g1_import::$album_dir)) { + $view->content->g1_stats = $g1_stats = g1_import::g1_stats(); + $view->content->g3_stats = $g3_stats = g1_import::g3_stats(); + $view->content->g1_sizes = g1_import::common_sizes(); + $view->content->g1_version = g1_import::version(); + + // Don't count tags because we don't track them in g1_map + $view->content->g1_resource_count = + $g1_stats['users'] + $g1_stats['groups'] + $g1_stats['albums'] + + $g1_stats['photos'] + $g1_stats['movies'] + $g1_stats['comments']; + $view->content->g3_resource_count = + $g3_stats['user'] + $g3_stats['group'] + $g3_stats['album'] + + $g3_stats['item'] + $g3_stats['comment'] + $g3_stats['tag']; + } + + $view->content->form = $this->_get_import_form(); + $view->content->version = ''; + $view->content->thumb_size = module::get_var('gallery', 'thumb_size'); + $view->content->resize_size = module::get_var('gallery', 'resize_size'); + + if (g1_import::is_initialized()) { + + if (count(g1_import::$warn_utf8)>0) { + message::error(t('Your G1 contains %count folder(s) containing nonstandard characters that G3 doesn\'t work with:
%names
Please rename the above folders in G1 before trying to import your data.', array('count' => count(g1_import::$warn_utf8), 'names' => "\n\n ".implode("\n ", g1_import::$warn_utf8)."\n\n"))); + } + + if ((bool)ini_get('eaccelerator.enable') || (bool)ini_get('xcache.cacher')) { + message::warning(t('The eAccelerator and XCache PHP performance extensions are known to cause issues. If you\'re using either of those and are having problems, please disable them while you do your import. Add the following lines:
%lines
to gallery3/.htaccess and remove them when the import is done.', array('lines' => "\n\n php_value eaccelerator.enable 0\n php_value xcache.cacher off\n php_value xcache.optimizer off\n\n"))); + } + + foreach (array('notification', 'search', 'exif') as $module_id) { + if (module::is_active($module_id)) { + message::warning( + t('Deactivating the %module_id module during your import will make it faster', + array('url' => url::site('admin/modules'), 'module_id' => $module_id))); + } + } + } else if (g1_import::is_configured()) { + $view->content->form->configure_g1_import->albums_path->add_error('invalid', 1); + } + print $view; + } + + public function save() { + access::verify_csrf(); + + $form = $this->_get_import_form(); + if ($form->validate()) { + $albums_path = $form->configure_g1_import->albums_path->value; + if (!is_file($albums_path) && file_exists("$albums_path/albums.php")) { + $albums_path = "$albums_path/albums.php"; + } + + if (($g1_init_error = g1_import::is_valid_albums_path($albums_path)) == 'ok') { + message::success(t('Gallery 1 path saved')); + module::set_var('g1_import', 'albums_path', $albums_path); + url::redirect('admin/g1_import'); + } else { + $form->configure_g1_import->albums_path->add_error($g1_init_error, 1); + } + } + + $view = new Admin_View('admin.html'); + $view->content = new View('admin_g1_import.html'); + $view->content->form = $form; + print $view; + } + + public function autocomplete() { + $directories = array(); + $path_prefix = Input::instance()->get('q'); + foreach (glob('{$path_prefix}*') as $file) { + if (is_dir($file) && !is_link($file)) { + $directories[] = $file; + + // If we find an albums.php, include it as well + if (file_exists("$file/albums.php")) { + $directories[] = "$file/albums.php"; + } + } + } + + print implode("\n", $directories); + } + + private function _get_import_form() { + $albums_path = module::get_var('g1_import', 'albums_path', ''); + $form = new Forge( + 'admin/g1_import/save', '', 'post', array('id' => 'g-admin-configure-g1-import-form')); + $group = $form->group('configure_g1_import')->label(t('Configure Gallery 1 Import')); + $group->input('albums_path')->label(t('Filesystem path to your Gallery 1 albums.php file')) + ->value($albums_path); + $group->albums_path->error_messages( + 'invalid', t('The path you entered is not a Gallery 1 installation.')); + $group->albums_path->error_messages( + 'broken', t('Your Gallery 1 install isn\'t working properly. Please verify it!')); + $group->albums_path->error_messages( + 'missing', t('The path you entered does not exist.')); + $group->submit('')->value(g1_import::$album_dir=='' ? t('Change') : t('Continue')); + return $form; + } +} diff --git a/3.0/modules/g1_import/controllers/g1.php b/3.0/modules/g1_import/controllers/g1.php new file mode 100644 index 00000000..eb8160ba --- /dev/null +++ b/3.0/modules/g1_import/controllers/g1.php @@ -0,0 +1,106 @@ +get('path'); + $page = $input->get('page'); + if(!is_numeric($page)) $page = ''; + + if($path=='view_album.php' || $path=='slideshow.php') $path = $input->get('set_albumName'); + if($path=='view_photo.php') $path = $input->get('set_albumName').'/'.$input->get('id'); + + if($path=='main.php') { //we do only name based g2 mapping here + $item = item::root(); + access::required('view', $item); + url::redirect($item->abs_url(), '301'); + } + + // Item names come in as FolderX/ItemX + $album = 0; + $pos = strrpos($path, '/'); + if($pos!==false) { + // Get ItemX into g1_item + $g1_item = substr($path,$pos+1,strlen($path)); + // Get FolderX into g1_item + $g1_album = substr($path,0,$pos); + } + else { + $album = 1; + $g1_item = ''; + $g1_album = $path; + } + + // Only binary files (the item itself, not the html) may have file extensions + $binary = 0; + $pos = strrpos($g1_item, '.'); + if($pos!==false) { + $binary = 1; + $g1_item = substr($g1_item, 0, $pos); + } + + if(($pos=strrpos($g1_item, '.sized'))!==false||($pos=strrpos($g1_item, '.thumb'))!==false) { + $mapping = ORM::factory('g1_map')->where('album', '=', $g1_album)->where('item', '=', substr($g1_item,0, $pos))->where('resource_type', '=', $album ? 'album':'item')->find(); + } + else { + $mapping = ORM::factory('g1_map')->where('album', '=', $g1_album)->where('item', '=', $g1_item)->where('resource_type', '=', $album ? 'album':'item')->find(); + } + if(!$mapping->loaded()) { + throw new Kohana_404_Exception(); + } + $item = ORM::factory('item', $mapping->id); + if (!$item->loaded()) { + throw new Kohana_404_Exception(); + } + access::required('view', $item); + + if($binary) { + if(strrpos($g1_item, '.sized')!==false) { + url::redirect($item->resize_url(true), '301'); + } + else if(strrpos($g1_item, '.thumb')!==false) { + url::redirect($item->thumb_url(true), '301'); + } + else { + url::redirect($item->file_url(true), '301'); + } + } + else { + $url = $item->abs_url(); + if($page!='') { + $url .= (strpos($url,'?')!==false ? '&':'?').'page='.$page; + } + url::redirect($url, '301'); + } + } +} diff --git a/3.0/modules/g1_import/data/broken-image.gif b/3.0/modules/g1_import/data/broken-image.gif new file mode 100644 index 00000000..fb9c8240 Binary files /dev/null and b/3.0/modules/g1_import/data/broken-image.gif differ diff --git a/3.0/modules/g1_import/helpers/Gallery1DataParser.php b/3.0/modules/g1_import/helpers/Gallery1DataParser.php new file mode 100644 index 00000000..c4ae5ae8 --- /dev/null +++ b/3.0/modules/g1_import/helpers/Gallery1DataParser.php @@ -0,0 +1,419 @@ + $fileName))); + return array('ERROR_BAD_PARAMETER', null); + } + } + $tmp = file($fileName); + + if (empty($tmp)) { + message::warning( + t('Gallery1 inconsistency: Empty file %file', + array('file' => $fileName))); + return array('ERROR_MISSING_VALUE', null); + } + + $tmp = join('', $tmp); + + /* + * We renamed User.php to Gallery_User.php in v1.2, so port forward + * any saved user objects. + */ + if (stripos($tmp, 'O:4:"user"')!==false) { + $tmp = str_ireplace('O:4:"user"', 'O:12:"gallery_user"', $tmp); + } + + /* + * Gallery3 already contains a class named Image so + * we need to rename the G1 Image class to G1Img here + */ + if (stripos($tmp, 'O:5:"image"')!==false) { + $tmp = str_ireplace('O:5:"image"', 'O:5:"G1Img"', $tmp); + } + + $object = unserialize($tmp); + return array(null, $object); + } + + /** + * Fetch an array of albums from a given path + * + * @param string $path Path to albums directory + * @return array GalleryStatus a status code, + * array of objects + */ + function getAlbumList($path) { + + list ($ret, $albumOrder) = Gallery1DataParser::loadFile($path . 'albumdb.dat'); + if ($ret) { + return array($ret, null); + } + + /* TODO: check that there is an $albumOrder */ + foreach ($albumOrder as $albumName) { + list ($ret, $albumFields) = + Gallery1DataParser::loadAlbumFields($path . $albumName . DIRECTORY_SEPARATOR); + if ($ret) { + return array($ret,''); + } + $albumList[$albumName] = $albumFields; + } + + return array(null, $albumList); + } + + /** + * Fetch an associative array of parentalbum names from a given path to gallery1 albums + * + * @param string $path Path to albums directory + * @return array GalleryStatus a status code, + * array of albums and their parents + */ + function getParentAlbumList($path) { + + list ($ret, $albumOrder) = Gallery1DataParser::loadFile($path . 'albumdb.dat'); + if ($ret) { + return array($ret, null); + } + + foreach ($albumOrder as $albumName) { + list ($ret, $albumFields) = + Gallery1DataParser::loadAlbumFields($path . $albumName . DIRECTORY_SEPARATOR); + if ($ret) { + return array($ret,''); + } + $parentAlbumList[$albumName] = $albumFields['parentAlbumName']; + } + return array(null, $parentAlbumList); + } + + /** + * Build a data tree of albums + * + * @param string $path Path to albums directory + * @return array GalleryStatus a status code, + * array of albumnames and their children, and their children... + */ + function getAlbumHierarchy($path) { + list ($ret, $parentAlbumList) = Gallery1DataParser::getParentAlbumList($path); + if ($ret) { + return array($ret, null); + } + + foreach ($parentAlbumList as $myName => $parentName) { + if (!isset($tempAlbums[$myName])) { + $tempAlbums[$myName] = array(); + } + if (empty($parentName) || $parentName == '.root') { + $hierarchy[$myName] = &$tempAlbums[$myName]; + } else { + if (!isset($tempAlbums[$parentName])) { + $tempAlbums[$parentName] = array(); + } + $tempAlbums[$parentName][$myName] = &$tempAlbums[$myName]; + } + } + return array(null, $hierarchy); + } + + /** + * Fetch an array of albums with no parents + * + * @param string $path Path to albums directory + * @return array GalleryStatus a status code, + * array of albumnames + */ + function getRootAlbums($path) { + + list ($ret, $albumOrder) = Gallery1DataParser::loadFile($path . 'albumdb.dat'); + if ($ret) { + return array($ret, null); + } + + foreach ($albumOrder as $albumName) { + list ($ret, $albumFields) = + Gallery1DataParser::loadAlbumFields($path . $albumName . DIRECTORY_SEPARATOR); + if ($ret) { + return array($ret,''); + } + if ($albumFields['parentAlbumName'] == '.root') { + $rootAlbums[] = $albumName; + } + } + return array(null, $rootAlbums); + } + + /** + * Load and return album metadata from given directory + * + * @param string $path Path to album directory + * @return array GalleryStatus a status code, + * object Unserialized album metadata + */ + function loadAlbumFields($path) { + + $tmp = trim($path); + if ($tmp[strlen($tmp)-1] != DIRECTORY_SEPARATOR) { + $tmp .= DIRECTORY_SEPARATOR; + } + $path = trim($tmp); + $albumPath = explode(DIRECTORY_SEPARATOR, $path); + $albumName = $albumPath[count($albumPath)-2]; + list ($ret, $album) = Gallery1DataParser::loadFile($path . 'album.dat'); + if ($ret) { + return array($ret, null); + } + $album->fields['name'] = $albumName; + if (!$album->fields['parentAlbumName']) { + $album->fields['parentAlbumName'] = '.root'; + } + return array(null, $album->fields); + } + + /** + * Count the number of photos in an album dir + * + * @param string $path Path to album directory + * @return array GalleryStatus a status code, + * integer Count of photos + */ + function getPhotoCount($path) { + list ($ret, $photos) = Gallery1DataParser::loadFile($path . 'photos.dat'); + if ($ret) { + return array($ret, null); + } + $photoCount = count($photos); + return array(null, $photoCount); + } + + /** + * Count the photo data from an album dir + * + * @param string $path Path to album directory + * @return array GalleryStatus a status code, + * array Galleryphotos + */ + function getPhotos($path) { + + list ($ret, $photos) = Gallery1DataParser::loadFile($path . DIRECTORY_SEPARATOR . 'photos.dat'); + if ($ret) { + return array($ret, null); + } + return array(null, $photos); + } + + /** + * Load user uids from path + * + * @param string $path Path to album directory + * @return array GalleryStatus a status code, + * array Associative array of uids and usernames + */ + function getUserUids($path) { + static $uids; + if (!isset($uids[$path])) { + if (!isset($uids)) { + $uids = array(); + } + + list ($ret, $userDB) = + Gallery1DataParser::loadFile($path . '.users' . DIRECTORY_SEPARATOR . 'userdb.dat'); + if ($ret) { + return array($ret, null); + } + $uids[$path] = array(); + foreach ($userDB->userMap as $username => $uid) { + if (Gallery1DataParser::isValidUid($path, $uid) + && !Gallery1DataParser::isValidUid($path, $username) + && !preg_match('/nobody|everybody|loggedin/i', $username)) { + $uids[$path][$uid] = $username; + } + } + } + return array(null, $uids[$path]); + } + + /** + * Validate user id string from gallery v1.x.x + * + * @param string $uid Uid to be tested + * @return boolean + */ + function isValidUidString($uid) { + if (preg_match('/^\d{9,}_\d+$/', $uid)) { + return TRUE; + } else { + return FALSE; + } + } + + /** + * Validate user id from gallery v1.x.x + * + * @param string $path + * @param string $uid Uid to be tested + * @return boolean + */ + function isValidUid($path, $uid) { + static $valid; + if (!isset($valid[$path][$uid])) { + if (!isset($valid)) { + $valid = array(); + } + if (!isset($valid[$path])) { + $valid[$path] = array(); + } + if (Gallery1DataParser::isValidUidString($uid)) { + list ($ret, $fields) = Gallery1DataParser::getUserFieldsByUid($path, $uid); + if (!$ret) { + $valid[$path][$uid] = TRUE; + } else { + $valid[$path][$uid] = FALSE; + } + } else { + $valid[$path][$uid] = FALSE; + } + } + return $valid[$path][$uid]; + } + + /** + * Load user metadata given a path and uid + * + * @param string $path Path to album directory + * @param string $uid Uid to import + * @return array GalleryStatus a status code, + * array User metadata + */ + function getUserFieldsByUid($path, $uid) { + static $fields; + + if (!isset($fields[$path][$uid])) { + if (!isset($fields)) { + $fields = array(); + } + if (!isset($fields[$path])) { + $fields[$path] = array(); + } + $fields[$path][$uid] = array(); + if (Gallery1DataParser::isValidUidString($uid)) { + list ($ret, $user) = Gallery1DataParser::loadFile($path . '.users' . DIRECTORY_SEPARATOR . $uid); + if ($ret) { + return array($ret, null); + } + foreach ($user as $key => $value) { + $fields[$path][$uid][$key] = $value; + } + } + } + return array(null, $fields[$path][$uid]); + } + + /** + * Load user metadata given a path and username + * + * @param string $path Path to album directory + * @param string $username Username to import + * @return array GalleryStatus a status code, + * array User metadata + */ + function getUserFieldsByUsername($path, $username) { + list ($ret, $uids) = Gallery1DataParser::getUserUids($path); + if ($ret) { + return array($ret, null); + } + $usernames = array_flip($uids); + $uid = $usernames[$username]; + list ($ret, $fields) = Gallery1DataParser::getUserFieldsByUid($path, $uid); + if ($ret) { + return array($ret, null); + } + return array(null, $fields); + } +} + + +/* Define these classes so that unserialize can use them */ +/** + * A stub class into which various G1 objects can be unserialized. + */ +class G1AlbumDB{ } +/** + * A stub class into which various G1 objects can be unserialized. + */ +class Album { } +/** + * A stub class into which various G1 objects can be unserialized. + */ +class Gallery_UserDB { } +/** + * A stub class into which various G1 objects can be unserialized. + */ +class Gallery_User { } +/** + * A stub class into which various G1 objects can be unserialized. + */ +class AlbumItem { } +/** + * A stub class into which various G1 objects can be unserialized. + */ +class G1Img { } +/** + * A stub class into which various G1 objects can be unserialized. + */ +class Comment { } diff --git a/3.0/modules/g1_import/helpers/g1_import.php b/3.0/modules/g1_import/helpers/g1_import.php new file mode 100644 index 00000000..0af42cf4 --- /dev/null +++ b/3.0/modules/g1_import/helpers/g1_import.php @@ -0,0 +1,1114 @@ +app->albumDir = "/home/t-horner.com/www/albums"; + if(preg_match('/\$gallery *-> *app *-> *albumDir *= *["\']([^"\']*)["\']/i',$line,$result)==1 && count($result)==2 && $result[1]!='') + $albumDir = $result[1]; + if(preg_match('/\$gallery *-> *app *-> *albumDirURL *= *["\']([^"\']*)["\']/i',$line,$result)==1 && count($result)==2 && $result[1]!='') + $albumUrl = $result[1]; + if(preg_match('/\$gallery *-> *app *-> *photoAlbumURL *= *["\']([^"\']*)["\']/i',$line,$result)==1 && count($result)==2 && $result[1]!='') + $galleryUrl = $result[1]; + if(preg_match('/\$gallery *-> *app *-> *default\[ *["\']thumb_size["\'] *\] *= *["\']([^"\']*)["\']/i',$line,$result)==1 && count($result)==2 && $result[1]!='') + $thumbSize = $result[1]; + if(preg_match('/\$gallery *-> *app *-> *default\[ *["\']resize_size["\'] *\] *= *["\']([^"\']*)["\']/i',$line,$result)==1 && count($result)==2 && $result[1]!='') + $resizeSize = $result[1]; + } + + if ($albumDir=='' || !is_dir($albumDir) || $albumUrl=='' || $galleryUrl=='') { + return 'broken'; + } + + self::$album_dir = $albumDir; + self::$album_url = $albumUrl; + self::$gallery_url = $galleryUrl; + self::$thumb_size = $thumbSize; + self::$resize_size = $resizeSize; + self::$gallery_dir = dirname($albums_path); + + + $version = ''; + $version_path = dirname($albums_path).DIRECTORY_SEPARATOR.'Version.php'; + if (!is_file($version_path)) { + $version_path = dirname($albums_path).DIRECTORY_SEPARATOR.'version.php'; + } + if (is_file($version_path)) { + foreach(file($version_path) as $line) { + //look for a line like: $gallery->version = '1.5.10'; + if(preg_match('/\$gallery *-> *version *= *["\']([^"\']*)["\']/i',$line,$result)==1 && count($result)==2 && $result[1]!='') + $version = $result[1]; + } + } + else { + $version = '1.x'; + } + self::$version = $version; + + + return 'ok'; + } + + /** + * Return the version of Gallery 1 (eg "1.5.10") + */ + static function version() { + if(!self::is_initialized()) + return '1'; + return self::$version; + } + + static function recursiveCountGallery($albumDir, &$array, $level) { + $countAlbum = 0; + + foreach($array as $key => &$valdummy) { + $converted = utf8_encode($key); + if( $converted != $key ) + self::$warn_utf8[] = $converted; + } + + foreach($array as $key => $value) { + if($key!='') { + $countAlbum++; + self::$albums_flat[] = $level.':'.$key; + + require_once('Gallery1DataParser.php'); + list($result, $items) = Gallery1DataParser::getPhotos($albumDir.$key.DIRECTORY_SEPARATOR); + + if($result==null) + foreach($items as $object) { + + if(isset($object->image) && is_a($object->image, 'G1Img')) { + + $item = $key.DIRECTORY_SEPARATOR.$object->image->name; + self::$queued_items[] = $item; + if(isset($object->comments) && is_array($object->comments) && count($object->comments)) { + + $comments = array(); + foreach ($object->comments as $comment) { + if (is_a($comment, 'Comment')) { + $comments[] = array( 'commentText' => $comment->commentText + ,'name' => $comment->name + ,'UID' => $comment->UID + ,'datePosted' => $comment->datePosted + ,'IPNumber' => $comment->IPNumber + ); + } + } + self::$queued_comments[] = array( $item => $comments ); + } + + if(isset($object->highlight) && $object->highlight==1 && isset($object->highlightImage) && is_a($object->highlightImage, 'G1Img')) { + self::$queued_highlights[] = $level.':'.$key.DIRECTORY_SEPARATOR.$object->highlightImage->name; + } + } + else if(isset($object->isAlbumName) && $object->isAlbumName!='') { + + if(isset($object->highlight) && $object->highlight==1 && isset($object->highlightImage) && is_a($object->highlightImage, 'G1Img')) { + self::$queued_highlights[] = $level.':'.$key.DIRECTORY_SEPARATOR.$object->highlightImage->name; + } + if(isset($object->hidden) && $object->hidden==1) { + self::$albums_hidden[$object->isAlbumName] = 1; + } + } + else { + g1_import::log('Invalid object found: '.print_r($object, true)); + } + + } + } + if(is_array($value) && count($value)>0) { + $countAlbum += g1_import::recursiveCountGallery($albumDir, $value, $level+1); + } + } + return $countAlbum; + } + + /** + * Return a set of statistics about the number of users, groups, albums, photos, movies and + * comments available for import from the Gallery 1 instance. + */ + static function g1_stats() { + $stats['users'] = 0; + $stats['groups'] = 0; + $stats['albums'] = 0; + $stats['photos'] = 0; + $stats['movies'] = 0; + $stats['comments'] = 0; + $stats['tags'] = 0; + + $albumDir = self::$album_dir; + if(substr($albumDir,-1)!=DIRECTORY_SEPARATOR) $albumDir.=DIRECTORY_SEPARATOR; + + require_once('Gallery1DataParser.php'); + if(Gallery1DataParser::isValidAlbumsPath($albumDir)) { + if(count(self::$tree)==0) { + list($result, $tree) = Gallery1DataParser::getAlbumHierarchy($albumDir); + if($result==null) self::$tree = $tree; + } + + list($result, $uids) = Gallery1DataParser::getUserUids($albumDir); + if($result==null) $stats['users'] = count($uids); + + self::$queued_items = array(); + self::$queued_comments = array(); + self::$queued_highlights = array(); + self::$albums_flat = array(); + self::$albums_hidden = array(); + self::$warn_utf8 = array(); + if(count(self::$tree)) $stats['albums'] = 1 /* <= THE ROOT ALBUM!!!*/ + g1_import::recursiveCountGallery($albumDir, self::$tree, 0); + + $stats['photos'] = count(self::$queued_items); + foreach(self::$queued_comments as $element) { + foreach($element as $item => $comments) { + $stats['comments'] += count($comments); + } + } + arsort(self::$queued_highlights); + $stats['highlights'] = count(self::$queued_highlights); + + arsort(self::$albums_flat); + foreach(self::$albums_flat as $key => $value) { + $pos = strpos($value, ':'); + if($pos!==false) self::$albums_flat[$key] = substr($value, $pos+1); + } + } + + return $stats; + } + + /** + * Return a set of statistics about the number of users, groups, albums, photos, movies and + * comments already imported into the Gallery 3 instance. + */ + static function g3_stats() { + $g3_stats = array( + 'album' => 0, 'comment' => 0, 'item' => 0, 'user' => 0, 'group' => 0, 'tag' => 0); + foreach (db::build() + ->select('resource_type') + ->select(array('C' => 'COUNT("*")')) + ->from('g1_maps') + ->where('resource_type', 'IN', array('album', 'comment', 'item', 'user', 'group')) + ->group_by('resource_type') + ->execute() as $row) { + $g3_stats[$row->resource_type] = $row->C; + } + return $g3_stats; + } + + /** + * Import a single album. + */ + static function import_album(&$queue) { + $messages = array(); + + // The queue is a set of nested associative arrays where the key is the album id and the + // value is an array of similar arrays. We'll do a breadth first tree traversal using the + // queue to keep our state. Doing it breadth first means that the parent will be created by + // the time we get to the child. + + // Dequeue the current album and enqueue its children + list($album, $tree) = each($queue); + unset($queue[$album]); + g1_import::debug( t('Dequeued album %album.', array('album' => $album)) ); + + foreach($tree as $key => $value) { + $queue[$album.'/'.$key] = $value; + g1_import::debug( t('Enqueued album %album.', array('album' => $album.'/'.$key)) ); + } + + // Special handling for the root album + if ($album == '') { + if (!self::map('', '', 'album')) { + $album = item::root(); + self::set_map($album->id, '', '', 'album'); + } + return $messages; + } + + // Album names come in as /Folder1/Folder2/FolderX + $pos = strrpos($album, '/'); + if($pos===false) { + return $messages; + } + + // Get FolderX into g1_album + $parent = substr($album,0,$pos); + $g1_album = substr($album,$pos+1); + + // Reduce parent to Folder2 + $pos = strrpos($parent, '/'); + if($pos!==false) { + $parent = substr($parent,$pos+1); + } + + // Skip already-existing albums + if (self::map($g1_album, '', 'album')) { + $messages[] = t('Skipping already existing album %album.', array('album' => $parent.'/'.$g1_album)); + return $messages; + } + + $album_id = self::map($parent, '', 'album'); + if (!$album_id) { + $messages[] = t('Album %name not found', array('name' => $parent)); + return $messages; + } + + g1_import::debug( t('Now importing album %album.', array('album' => $parent.'/'.$g1_album)) ); + + + $albumDir = self::$album_dir; + if(substr($albumDir,-1)!=DIRECTORY_SEPARATOR) $albumDir.=DIRECTORY_SEPARATOR; + $importDir = $albumDir.$g1_album.DIRECTORY_SEPARATOR; + + + $parent = ORM::factory('item', $album_id); + + $album = ORM::factory('item'); + $album->type = 'album'; + $album->parent_id = $album_id; + g1_import::set_album_values($album, $g1_album); + + try { + $album->validate(); + } catch (ORM_Validation_Exception $e) { + throw new G1_Import_Exception( + t('Failed to validate Gallery 1 album with name %name.', + array('name' => $g1_album)), + $e); + } + + try { + $album->save(); + self::set_map($album->id, $g1_album, '', 'album'); + } catch (Exception $e) { + throw new G1_Import_Exception( + t('Failed to import Gallery 1 album with name %name.', + array('name' => $g1_album)), + $e); + } + + try { + require_once('Gallery1DataParser.php'); + list($result, $items) = Gallery1DataParser::getPhotos($importDir); + if($result==null) + foreach($items as $object) { + if(isset($object->highlight) && $object->highlight==1 && isset($object->highlightImage) && is_a($object->highlightImage, 'G1Img')) { + $g1_path = $importDir.$object->highlightImage->name.'.'.$object->highlightImage->type; + if (is_file($g1_path) && @copy($g1_path, $album->thumb_path())) { + $album->thumb_height = $object->highlightImage->height; + $album->thumb_width = $object->highlightImage->width; + $album->thumb_dirty = false; + $album->save(); + } + } + } + } catch (Exception $e) { + throw new G1_Import_Exception( + t('Failed to copy thumb for album %name.', + array('name' => $g1_album)), + $e); + } + + try { + if(isset(self::$albums_hidden[$g1_album])) { + access::deny(identity::everybody(), 'view', $album); + } + } catch (Exception $e) { + throw new G1_Import_Exception( + t('Failed to set access permission for hidden album %name.', + array('name' => $g1_album)), + $e); + } + + return $messages; + } + + /** + * Transfer over all the values from a G1 album to a G3 album. + */ + static function set_album_values($album, $g1_album) { + $albumDir = self::$album_dir; + if(substr($albumDir,-1)!=DIRECTORY_SEPARATOR) $albumDir.=DIRECTORY_SEPARATOR; + $albumDir .= $g1_album; + if(substr($albumDir,-1)!=DIRECTORY_SEPARATOR) $albumDir.=DIRECTORY_SEPARATOR; + + require_once('Gallery1DataParser.php'); + list($result, $fields) = Gallery1DataParser::loadAlbumFields($albumDir); + + $album->name = $fields['name']; + $album->slug = item::convert_filename_to_slug($fields['name']); // <= verification fails if this property has not been set!!! + $album->title = utf8_encode(self::_decode_html_special_chars(trim($fields['title']))); + $album->title or $album->title = $album->name; + $album->description = utf8_encode(self::_decode_html_special_chars(trim($fields['description']))); + //$album->owner_id = self::map($g1_album->getOwnerId()); + + if(strlen($album->title)>255) { + if(strlen($album->description)==0) { + $album->description = $album->title; + } + $album->title = substr($album->title, 0, 252).'...'; + } + + try { + $album->view_count = (int) $fields['clicks']; + } catch (Exception $e) { + // @todo log + $album->view_count = 0; + } + $album->created = $fields['clicks_date']; + $album->sort_column = 'weight'; //G1 was always sorted manually + $album->sort_order = 'ASC'; + } + + /** + * Set the highlight properly for a single album + */ + static function set_album_highlight(&$queue) { + $messages = array(); + if(count($queue)==0) { + $messages[] = t('Empty highlights queue'); + return $messages; + } + + $item = array_shift($queue); + if (substr($item, -10) == '.highlight') { + $item = substr($item, 0, strlen($item)-10); + } + g1_import::debug( t('Now importing highlight %item', array('item' => $item)) ); + + // Item names come in as Level:FolderX/ItemX + $pos = strpos($item, ':'); + if($pos===false) { + $messages[] = t('Invalid item %item', array('item' => $item)); + return $messages; + } + $item = substr($item, $pos+1); + + + // Item names come in as FolderX/ItemX + $pos = strrpos($item, '/'); + if($pos===false) { + $messages[] = t('Invalid item %item', array('item' => $item)); + return $messages; + } + + // Get ItemX into g1_item + $g1_item = substr($item,$pos+1); + // Get FolderX into g1_item + $g1_album = substr($item,0,$pos); + + + if (self::map($g1_album, '', 'highlight')) { + return $messages; + } + + $album_id = self::map($g1_album, '', 'album'); + if (!$album_id) { + $messages[] = t('Album %name not found', array('name' => $g1_album)); + return $messages; + } + + $item_id = self::map($g1_album, $g1_item, 'item'); + if (!$item_id) { + $item_id = self::map($g1_item, '', 'album'); + } + if (!$item_id) { + $messages[] = t('Item/Album %name not found', array('name' => $item)); + return $messages; + } + + $album = ORM::factory('item', $album_id); + $album->album_cover_item_id = $item_id; + $album->thumb_dirty = 1; + try { + $album->save(); + graphics::generate($album); + g1_import::debug( t('Added highlight %item to %album', array('item' => $item, 'album' => $album->name)) ); + } catch (Exception $e) { + $messages[] = (string) new G1_Import_Exception( + t("Failed to generate an album highlight for album '%name'.", + array('name' => $album->name)), + $e); + return $messages; + } + + $album_id = self::map($g1_album, '', 'album'); + self::set_map($album_id, $g1_album, '', 'highlight'); + + g1_import::debug( t('Added highlight %item to %album', array('item' => $item, 'album' => $album->name)) ); + return $messages; + } + + static function hotfix_all() { + $messages = array(); + $messages[] = t('Running Hotfix'); + + /* ON THE LAST RUN WE NEED TO RE-FIX ALL DAMAGED ALBUM THUMBS! */ + + $albumDir = self::$album_dir; + if(substr($albumDir,-1)!=DIRECTORY_SEPARATOR) $albumDir.=DIRECTORY_SEPARATOR; + + foreach(self::$albums_flat as $g1_album) { + $album_id = self::map($g1_album, '', 'album'); + if (!$album_id) { + $messages[] = t('Album %name not found', array('name' => $g1_album)); + continue; + } + + $album = ORM::factory('item', $album_id); + $importDir = $albumDir.$g1_album.DIRECTORY_SEPARATOR; + + try { + require_once('Gallery1DataParser.php'); + list($result, $items) = Gallery1DataParser::getPhotos($importDir); + if($result==null) + foreach($items as $object) { + if(isset($object->highlight) && $object->highlight==1 && isset($object->highlightImage) && is_a($object->highlightImage, 'G1Img')) { + $g1_path = $importDir.$object->highlightImage->name.'.'.$object->highlightImage->type; + if (is_file($g1_path) && @copy($g1_path, $album->thumb_path())) { + $album->thumb_height = $object->highlightImage->height; + $album->thumb_width = $object->highlightImage->width; + $album->thumb_dirty = false; + $album->save(); + } + } + } + } catch (Exception $e) { + $messages[] = (string) new G1_Import_Exception( + t('Failed to copy thumb for album %name.', + array('name' => $g1_album)), + $e); + } + } + + /* ON THE LAST RUN WE NEED TO RE-FIX ALL ALBUM PERMISSIONS */ + + foreach(self::$albums_hidden as $g1_album => $dummy) { + try { + $album_id = self::map($g1_album, '', 'album'); + $album = ORM::factory('item', $album_id); + access::deny(identity::everybody(), 'view', $album); + $messages[] = t('Denying access to %album', array('album' => $g1_album)); + } catch (Exception $e) { + $messages[] = (string) new G1_Import_Exception( + t('Failed to set access permission for hidden album %name.', + array('name' => $g1_album)), + $e); + } + } + + return $messages; + } + + /** + * Import a single photo or movie. + */ + static function import_item(&$queue) { + $messages = array(); + if(count($queue)==0) { + $messages[] = t('Empty item queue'); + return $messages; + } + + $item_id = array_shift($queue); + g1_import::debug( t('Now importing item %item', array('item' => $item_id)) ); + + // Item names come in as FolderX/ItemX + $pos = strrpos($item_id, '/'); + if($pos===false) { + return $messages; + } + + // Get ItemX into g1_item + $g1_item = substr($item_id,$pos+1); + // Get FolderX into g1_item + $g1_album = substr($item_id,0,$pos); + + + if (self::map($g1_album, $g1_item, 'item')) { + return $messages; + } + + $album_id = self::map($g1_album, '', 'album'); + if (!$album_id) { + $messages[] = t('Album %name not found', array('name' => $g1_album)); + return $messages; + } + + + $album_item = null; + + $albumDir = self::$album_dir; + if(substr($albumDir,-1)!=DIRECTORY_SEPARATOR) $albumDir.=DIRECTORY_SEPARATOR; + + require_once('Gallery1DataParser.php'); + list($result, $items) = Gallery1DataParser::getPhotos($albumDir.$g1_album.DIRECTORY_SEPARATOR); + if($result==null) + foreach($items as $object) { + if(isset($object->image) && is_a($object->image, 'G1Img') && isset($object->image->name) && ($object->image->name==$g1_item)) { + $album_item = $object; + } + } + + if ($album_item==null) { + $messages[] = t('Failed to import Gallery 1 item: %item', array('item' => $item_id)); + return $messages; + } + + $corrupt = 0; + self::$current_g1_item = array( $item_id => $album_item ); + $g1_path = $albumDir.$g1_album.DIRECTORY_SEPARATOR.$album_item->image->name.'.'.$album_item->image->type; + + $parent = ORM::factory('item', $album_id); + + switch($album_item->image->type) { + case 'jpg': + case 'jpeg': + case 'gif': + case 'png': + $g1_type = 'GalleryPhotoItem'; break; + case 'wmv': + case '3gp': + case 'avi': + case 'mp4': + case 'mov': + case 'flv': + $g1_type = 'GalleryMovieItem'; break; + default: + $g1_type = 'GalleryPhotoItem'; break; + } + + if (!file_exists($g1_path)) { + // If the Gallery 1 source image isn't available, this operation is going to fail. That can + // happen in cases where there's corruption in the source Gallery 1. In that case, fall + // back on using a broken image. It's important that we import *something* otherwise + // anything that refers to this item in Gallery 1 will have a dangling pointer in Gallery 3 + // + // Note that this will change movies to be photos, if there's a broken movie. Hopefully + // this case is rare enough that we don't need to take any heroic action here. + g1_import::log( + t('%path missing in import; replacing it with a placeholder', array('path' => $g1_path))); + $g1_path = MODPATH . 'g1_import/data/broken-image.gif'; + $g1_type = 'GalleryPhotoItem'; + $corrupt = 1; + } + + $item = null; + + switch ($g1_type) { + case 'GalleryPhotoItem': + + if(function_exists('mime_content_type')) + $type = mime_content_type($g1_path); + else + $type = self::get_mime_type($g1_path); + + if ($type!='' && !in_array($type, array('image/jpeg', 'image/gif', 'image/png'))) { + Kohana_Log::add('alert', "$g1_path is an unsupported image type $type; using a placeholder gif"); + $messages[] = t("'%path' is an unsupported image type '%type', using a placeholder", + array('path' => $g1_path, 'type' => $type)); + $g1_path = MODPATH . 'g1_import/data/broken-image.gif'; + $corrupt = 1; + } + + try { + $item = ORM::factory('item'); + $item->type = 'photo'; + $item->parent_id = $album_id; + $item->set_data_file($g1_path); + $item->name = $g1_item.'.'.$album_item->image->type; + $item->slug = item::convert_filename_to_slug($g1_item); + $item->mime_type = $type; + $item->title = utf8_encode(self::_decode_html_special_chars(trim($album_item->caption))); + $item->title or $item->title = ' '; //don't use $item->name as this clutters up the UI + if(isset($album_item->description) && $album_item->description!='') + $item->description = utf8_encode(self::_decode_html_special_chars(trim($album_item->description))); + //$item->owner_id = self::map($g1_item->getOwnerId()); + + try { + $item->view_count = (int) $album_item->clicks; + } catch (Exception $e) { + $item->view_count = 1; + } + + if(strlen($item->title)>255) { + if(strlen($item->description)==0) { + $item->description = $item->title; + } + $item->title = substr($item->title, 0, 252).'...'; + } + + } catch (Exception $e) { + $exception_info = (string) new G1_Import_Exception( + t("Corrupt image '%path'", array('path' => $g1_path)), + $e, $messages); + Kohana_Log::add('alert', "Corrupt image $g1_path\n" . $exception_info); + $messages[] = $exception_info; + $corrupt = 1; + $item = null; + return $messages; + } + + try { + $item->validate(); + } catch (ORM_Validation_Exception $e) { + $exception_info = (string) new G1_Import_Exception( + t('Failed to validate Gallery 1 item %item.', + array('item' => $item_id)), + $e, $messages); + Kohana_Log::add('alert', "Failed to validate Gallery 1 item $item_id.\n" . $exception_info); + $messages[] = $exception_info; + $corrupt = 1; + $item = null; + return $messages; + } + + try { + $item->save(); + } catch (Exception $e) { + $exception_info = (string) new G1_Import_Exception( + t('Failed to import Gallery 1 item %item.', + array('item' => $item_id)), + $e, $messages); + Kohana_Log::add('alert', "Failed to import Gallery 1 item $item_id.\n" . $exception_info); + $messages[] = $exception_info; + $corrupt = 1; + $item = null; + } + + break; + + case 'GalleryMovieItem': + // @todo we should transcode other types into FLV + + if(function_exists('mime_content_type')) + $type = mime_content_type($g1_path); + else + $type = self::get_mime_type($g1_path); + + if ($type=='' || in_array($type, array('video/mp4', 'video/x-flv'))) { + try { + $item = ORM::factory('item'); + $item->type = 'movie'; + $item->parent_id = $album_id; + $item->set_data_file($g1_path); + $item->name = $g1_item.'.'.$album_item->image->type; + $item->slug = item::convert_filename_to_slug($g1_item); + $item->mime_type = $type; + $item->title = utf8_encode(self::_decode_html_special_chars(trim($album_item->caption))); + $item->title or $item->title = ' '; //$item->name; + if(isset($album_item->description) && $album_item->description!='') + $item->description = utf8_encode(self::_decode_html_special_chars(trim($album_item->description))); + //$item->owner_id = self::map($g1_item->getOwnerId()); + try { + $item->view_count = (int) $album_item->clicks; + } catch (Exception $e) { + $item->view_count = 1; + } + } catch (Exception $e) { + $exception_info = (string) new G1_Import_Exception( + t("Corrupt movie '%path'", array("path" => $g1_path)), + $e, $messages); + Kohana_Log::add('alert', "Corrupt movie $g1_path\n" . $exception_info); + $messages[] = $exception_info; + $corrupt = 1; + $item = null; + return $messages; + } + + try { + $item->validate(); + } catch (ORM_Validation_Exception $e) { + $exception_info = (string) new G1_Import_Exception( + t('Failed to validate Gallery 1 item %item.', + array('item' => $item_id)), + $e, $messages); + Kohana_Log::add('alert', "Failed to validate Gallery 1 item $item_id.\n" . $exception_info); + $messages[] = $exception_info; + $corrupt = 1; + $item = null; + return $messages; + } + + try { + $item->save(); + } catch (Exception $e) { + $exception_info = (string) new G1_Import_Exception( + t('Failed to import Gallery 1 item %item.', + array('item' => $item_id)), + $e, $messages); + Kohana_Log::add('alert', "Failed to import Gallery 1 item $item_id.\n" . $exception_info); + $messages[] = $exception_info; + $corrupt = 1; + $item = null; + } + } else { + Kohana_Log::add('alert', "$g1_path is an unsupported movie type $type"); + $messages[] = t("'%path' is an unsupported movie type '%type'", array('path' => $g1_path, 'type' => $type)); + $corrupt = 1; + } + + break; + + default: + // Ignore + break; + } + + if (isset($item)) { + self::set_map($item->id, $g1_album, $g1_item, 'item'); + + if(isset($album_item->keywords) && $album_item->keywords!='') { + $keywords = utf8_encode(self::_decode_html_special_chars(trim($album_item->keywords))); + if($keywords!='') { + self::import_keywords_as_tags($keywords, $item); + } + } + } + + if ($corrupt) { + $title = utf8_encode(self::_decode_html_special_chars(trim($album_item->caption))); + $title or $title = $g1_item; + if (!empty($item)) { + $messages[] = + t('%title from Gallery 1 could not be processed; (imported as %title)', + array('g1_url' => $gallery_url.'/'.$item_id, + 'g3_url' => $item->url(), + 'title' => $title)); + } else { + $messages[] = + t('%title from Gallery 1 could not be processed', + array('g1_url' => $gallery_url.'/'.$item_id, 'title' => $title)); + } + } + + self::$current_g1_item = null; + return $messages; + } + + function get_mime_type($filename, $mimePath = '/etc') { + $fileext = substr(strrchr($filename, '.'), 1); + if (empty($fileext)) return (false); + $regex = "/^([\w\+\-\.\/]+)\s+(\w+\s)*($fileext\s)/i"; + $lines = file("$mimePath/mime.types"); + foreach($lines as $line) { + if (substr($line, 0, 1) == '#') continue; // skip comments + $line = rtrim($line) . ' '; + if (!preg_match($regex, $line, $matches)) continue; // no match to the extension + return ($matches[1]); + } + return (false); // no match at all + } + + /** + * Import a single comment. + */ + static function import_comment(&$queue) { + $messages = array(); + if(count($queue)==0) { + //this case happens if more than one comment is found on one or more items + $messages[] = t('Empty comments queue'); + return $messages; + } + + $element = array_shift($queue); + + list($item, $comments) = each($element); + g1_import::debug( t('Now importing %$comments comment(s) for item %$item', array('album' => $item, 'comments' => count($comments))) ); + + // Item names come in as FolderX/ItemX + $pos = strrpos($item, '/'); + if($pos===false) { + $messages[] = t('Invalid item %item', array('item' => $item)); + return $messages; + } + + // Get ItemX into g1_item + $g1_item = substr($item,$pos+1); + // Get FolderX into g1_item + $g1_album = substr($item,0,$pos); + + + if (self::map($g1_album, $g1_item, 'comment')) { + return $messages; + } + + $item_id = self::map($g1_album, $g1_item, 'item'); + if (empty($item_id)) { + $messages[] = t('Could not find item %item', array('item' => $item)); + return; + } + + foreach ($comments as $g1comment) { + + // Just import the fields we know about. Do this outside of the comment API for now so that + // we don't trigger spam filtering events + $comment = ORM::factory('comment'); + $comment->author_id = identity::guest()->id; + $comment->guest_name = utf8_encode(self::_decode_html_special_chars(trim($g1comment['name']))); + $comment->guest_name or $comment->guest_name = (string) t('Anonymous coward'); + $comment->guest_email = 'unknown@nobody.com'; + $comment->item_id = $item_id; + $comment->text = utf8_encode(self::_decode_html_special_chars(trim($g1comment['commentText']))); + $comment->state = 'published'; + $comment->server_http_host = utf8_encode(self::_decode_html_special_chars(trim($g1comment['IPNumber']))); + + try { + $comment->save(); + } catch (Exception $e) { + $messages[] = (string) new G1_Import_Exception( + t('Failed to import comment for item: %item.', + array('item' => $item)), + $e); + return $messages; + } + + // Backdate the creation date. We can't do this at creation time because + // Comment_Model::save() will override it. + db::update('comments') + ->set('created', utf8_encode(self::_decode_html_special_chars(trim($g1comment['datePosted'])))) + ->set('updated', utf8_encode(self::_decode_html_special_chars(trim($g1comment['datePosted'])))) + ->where('id', '=', $comment->id) + ->execute(); + } + + self::set_map($item_id, $g1_album, $g1_item, 'comment'); + return $messages; + } + + /** + * g1 encoded'&', '"', '<' and '>' as '&', '"', '<' and '>' respectively. + * This function undoes that encoding. + */ + private static function _decode_html_special_chars($value) { + return str_replace(array('&', '"', '<', '>', 'ä', 'ö', 'ü', 'Ä', 'Ö', 'Ü', 'ß'), + array('&', '"', '<', '>', 'ä', 'ö', 'ü', 'Ä', 'Ö', 'Ü', 'ß'), $value); + } + + static function import_keywords_as_tags($keywords, $item) { + // FIXME check if this is true for G1 (copied from G2 import module): + // Keywords in G1 are free form. So we don't know what our user used as a separator. Try to + // be smart about it. If we see a comma or a semicolon, expect the keywords to be separated + // by that delimeter. Otherwise, use space as the delimiter. + if (strpos($keywords, ';')) { + $delim = ';'; + } else if (strpos($keywords, ',')) { + $delim = ','; + } else { + $delim = ' '; + } + + foreach (preg_split("/$delim/", $keywords) as $keyword) { + $keyword = trim($keyword); + if ($keyword) { + tag::add($item, $keyword); + } + } + } + + /** + * If the thumbnails and resizes created for the Gallery 1 photo match the dimensions of the + * ones we expect to create for Gallery 3, then copy the files over instead of recreating them. + */ + static function copy_matching_thumbnails_and_resizes($item) { + + // We only operate on items that are being imported + if (empty(self::$current_g1_item)) { + return; + } + + // Precaution: if the Gallery 1 item was watermarked, or we have the Gallery 3 watermark module + // active then we'd have to do something a lot more sophisticated here. For now, just skip + // this step in those cases. + // @todo we should probably use an API here, eventually. + if (module::is_active('watermark') && module::get_var('watermark', 'name')) { + return; + } + + // For now just do the copy for photos and movies. Albums are tricky because we're may not + // yet be setting their album cover properly. + // @todo implement this for albums also + if (!$item->is_movie() && !$item->is_photo()) { + return; + } + + list( $item_id, $album_item ) = each(self::$current_g1_item); + + // Item names come in as FolderX/ItemX + $pos = strrpos($item_id, '/'); + if($pos===false) { + return; + } + + // Get ItemX into g1_item + $g1_item = substr($item_id,$pos+1); + // Get FolderX into g1_item + $g1_album = substr($item_id,0,$pos); + + + $target_thumb_size = module::get_var('gallery', 'thumb_size'); + $target_resize_size = module::get_var('gallery', 'resize_size'); + if ( isset($album_item->thumbnail) && is_a($album_item->thumbnail, 'G1Img') ) { + + if($item->thumb_dirty && + ($album_item->thumbnail->width == $target_thumb_size || + $album_item->thumbnail->height == $target_thumb_size)) { + + $g1_path = $albumDir.$g1_album.DIRECTORY_SEPARATOR.$album_item->thumbnail->name.'.'.$album_item->thumbnail->type; + if (@copy($g1_path, $item->thumb_path())) { + $item->thumb_height = $album_item->thumbnail->height; + $item->thumb_width = $album_item->thumbnail->width; + $item->thumb_dirty = false; + } + /** + * No use to try to take over the highlight images here as they will be overwritten anyway. + */ + } + } + + try { + $item->save(); + } catch (Exception $e) { + return (string) new G1_Import_Exception( + t("Failed to copy thumbnails and resizes for item '%name' (Gallery 1 id: %id)", + array('name' => $item->name, 'id' => $item_id)), + $e); + } + } + + /** + * Figure out the most common resize and thumb sizes in Gallery 1 so that we can tell the admin + * what theme settings to set to make the import go faster. If we match up the sizes then we + * can just copy over derivatives instead of running graphics toolkit operations. + */ + static function common_sizes() { + return array( 'resize' => array( 'size' => self::$resize_size, 'count' => 1 ) + ,'thumb' => array( 'size' => self::$thumb_size, 'count' => 1 ) + ,'total' => 1 + ); + } + + /** + * Look in our map to find the corresponding Gallery 3 id for the given Gallery 1 id. + */ + static function map($album, $item, $resource_type) { + if (!array_key_exists($resource_type.':'.$album.'/'.$item, self::$map)) { + $mapping = ORM::factory('g1_map')->where('album', '=', $album)->where('item', '=', $item)->where('resource_type', '=', $resource_type)->find(); + self::$map[$resource_type.':'.$album.'/'.$item] = $mapping->loaded() ? $mapping->id : null; + } + + return self::$map[$resource_type.':'.$album.'/'.$item]; + } + + /** + * Associate a Gallery 1 id with a Gallery 3 item id. + */ + static function set_map($id, $album, $item, $resource_type) { + $mapping = ORM::factory('g1_map'); + $mapping->id = $id; + $mapping->album = $album; + $mapping->item = $item; + $mapping->resource_type = $resource_type; + $mapping->save(); + self::$map[$resource_type.':'.$album.'/'.$item] = $id; + } + + static function log($msg) { + message::warning($msg); + Kohana_Log::add('alert', $msg); + } + + static function debug($msg) { + Kohana_Log::add('debug', $msg); + } +} diff --git a/3.0/modules/g1_import/helpers/g1_import_event.php b/3.0/modules/g1_import/helpers/g1_import_event.php new file mode 100644 index 00000000..4204f4d7 --- /dev/null +++ b/3.0/modules/g1_import/helpers/g1_import_event.php @@ -0,0 +1,40 @@ +delete("g1_maps") + ->where("id", "=", $item->id) + ->execute(); + } + + static function item_created($item) { + g1_import::copy_matching_thumbnails_and_resizes($item); + } + + static function admin_menu($menu, $theme) { + $menu + ->get("settings_menu") + ->append(Menu::factory("link") + ->id("g1_import") + ->label(t("Gallery 1 import")) + ->url(url::site("admin/g1_import"))); + } +} diff --git a/3.0/modules/g1_import/helpers/g1_import_installer.php b/3.0/modules/g1_import/helpers/g1_import_installer.php new file mode 100644 index 00000000..fb1ea1f5 --- /dev/null +++ b/3.0/modules/g1_import/helpers/g1_import_installer.php @@ -0,0 +1,46 @@ +query("CREATE TABLE IF NOT EXISTS {g1_maps} ( + `id` int(9) NOT NULL, + `album` varchar(128) NOT NULL, + `item` varchar(128) default NULL, + `resource_type` varchar(64) default NULL, + PRIMARY KEY (`id`, `resource_type`), + KEY `g1_map_index` (`album`, `item`)) + DEFAULT CHARSET=utf8;"); + + module::set_version("g1_import", 1); + } + + static function upgrade($version) { + $db = Database::instance(); + /* reserved for future versions + if ($version == 1) { + module::set_version('g1_import', $version = 2); + } + //*/ + } + + static function uninstall() { + } +} diff --git a/3.0/modules/g1_import/helpers/g1_import_task.php b/3.0/modules/g1_import/helpers/g1_import_task.php new file mode 100644 index 00000000..32edd3cc --- /dev/null +++ b/3.0/modules/g1_import/helpers/g1_import_task.php @@ -0,0 +1,215 @@ +callback('g1_import_task::import') + ->name(t('Import from Gallery 1')) + ->description( + t('Gallery %version detected', array('version' => $version))) + ->severity(log::SUCCESS)); + } + + return array(); + } + + static function import($task) { + $start = microtime(true); + g1_import::init(); + + $stats = $task->get('stats'); + $done = $task->get('done'); + $total = $task->get('total'); + $completed = $task->get('completed'); + $mode = $task->get('mode'); + $queue = $task->get('queue'); + if (!isset($mode)) { + $stats = g1_import::g1_stats(); + $stats['items'] = $stats['photos'] + $stats['movies']; + unset($stats['photos']); + unset($stats['movies']); + $stats['fix'] = 1; + $task->set('stats', $stats); + + $task->set('total', $total = array_sum(array_values($stats))); + $completed = 0; + $mode = 0; + + $done = array(); + foreach (array_keys($stats) as $key) { + $done[$key] = 0; + } + $task->set('done', $done); + } + + $modes = array('users', 'albums', 'items', 'comments', 'highlights', 'fix', 'done'); + while (!$task->done && microtime(true) - $start < 1.5) { + if ($done[$modes[$mode]] >= $stats[$modes[$mode]]) { + // Nothing left to do for this mode. Advance. + $mode++; + $task->set('last_id', 0); + $queue = array(); + + // Start the loop from the beginning again. This way if we get to a mode that requires no + // actions (eg, if the G1 comments module isn't installed) we won't try to do any comments + // queries.. in the next iteration we'll just skip over that mode. + if ($modes[$mode] != 'done') { + continue; + } + } + + switch($modes[$mode]) { + + case 'users': + $done['users'] = $stats['users']-1; + $task->status = t( + 'Ignoring users (%count of %total)', + array('count' => $done['users'], 'total' => $stats['users'])); + break; + + case 'albums': + if (empty($queue)) { + if(count(g1_import::$tree)==0) { + g1_import::g1_stats(); + } + $task->set('queue', $queue = array('' => g1_import::$tree)); + } + $log_message = g1_import::import_album($queue); + if ($log_message) { + $task->log($log_message); + } + $task->status = t( + 'Importing albums (%count of %total)', + array('count' => $done['albums'] + 1, 'total' => $stats['albums'])); + break; + + case 'items': + if (empty($queue)) { + if (count(g1_import::$queued_items)==0) { + g1_import::g1_stats(); + } + + $queuelen = 100; + $thisstart = $task->get('last_id', 0); + $nextstart = $thisstart + $queuelen; + $task->set('last_id', $nextstart); + + $task->set('queue', $queue = array_splice(g1_import::$queued_items, $thisstart, $queuelen)); + } + $log_message = g1_import::import_item($queue); + if ($log_message) { + $task->log($log_message); + } + $task->status = t( + 'Importing photos (%count of %total)', + array('count' => $done['items'] + 1, 'total' => $stats['items'])); + break; + + case 'comments': + if (empty($queue)) { + if (count(g1_import::$queued_comments)==0) { + g1_import::g1_stats(); + } + + $queuelen = 100; + $thisstart = $task->get('last_id', 0); + $nextstart = $thisstart + $queuelen; + $task->set('last_id', $nextstart); + + $task->set('queue', $queue = array_splice(g1_import::$queued_comments, $thisstart, $queuelen)); + } + $log_message = g1_import::import_comment($queue); + if ($log_message) { + $task->log($log_message); + } + $task->status = t( + 'Importing comments (%count of %total)', + array('count' => $done['comments'] + 1, 'total' => $stats['comments'])); + break; + + case 'highlights': + if (empty($queue)) { + if (count(g1_import::$queued_highlights)==0) { + g1_import::g1_stats(); + } + + $queuelen = 100; + $thisstart = $task->get('last_id', 0); + $nextstart = $thisstart + $queuelen; + $task->set('last_id', $nextstart); + + $task->set('queue', $queue = array_splice(g1_import::$queued_highlights, $thisstart, $queuelen)); + } + $log_message = g1_import::set_album_highlight($queue); + if ($log_message) { + $task->log($log_message); + } + $task->status = t( + 'Album highlights (%count of %total)', + array('count' => $done['highlights'] + 1, 'total' => $stats['highlights'])); + break; + + case 'fix': + if (empty($queue)) { + if (count(g1_import::$albums_flat)==0) { + g1_import::g1_stats(); + } + $task->set('queue', $queue = 'dummy'); + } + $log_message = g1_import::hotfix_all(); + if ($log_message) { + $task->log($log_message); + } + $task->status = t( + 'Final Hotfixing (%count of %total)', + array('count' => $done['fix'] + 1, 'total' => $stats['fix'])); + break; + + case 'done': + $task->status = t('Import complete'); + $task->done = true; + $task->state = 'success'; + break; + } + + if (!$task->done) { + $done[$modes[$mode]]++; + $completed++; + } + } + + $task->percent_complete = 100 * ($completed / $total); + $task->set('completed', $completed); + $task->set('mode', $mode); + $task->set('queue', $queue); + $task->set('done', $done); + } +} diff --git a/3.0/modules/g1_import/libraries/G1_Import_Exception.php b/3.0/modules/g1_import/libraries/G1_Import_Exception.php new file mode 100644 index 00000000..cd7e476f --- /dev/null +++ b/3.0/modules/g1_import/libraries/G1_Import_Exception.php @@ -0,0 +1,39 @@ +validation->errors(), true); + } + if ($previous) { + $message .= "\n" . (string) $previous; + } + // The $previous parameter is supported in PHP 5.3.0+. + parent::__construct($message); + } +} \ No newline at end of file diff --git a/3.0/modules/g1_import/models/g1_map.php b/3.0/modules/g1_import/models/g1_map.php new file mode 100644 index 00000000..b783426d --- /dev/null +++ b/3.0/modules/g1_import/models/g1_map.php @@ -0,0 +1,21 @@ + +css("jquery.autocomplete.css") ?> +script("jquery.autocomplete.js") ?> + + +
+

+

+ +

+ + + +
diff --git a/3.0/themes/smk/css/fix-ie.css b/3.0/themes/smk/css/fix-ie.css new file mode 100644 index 00000000..0633ff07 --- /dev/null +++ b/3.0/themes/smk/css/fix-ie.css @@ -0,0 +1,59 @@ +/** + * Fix display in IE 6, 7, and 8 + */ + +#g-banner { + z-index: 2; + zoom: 1; +} + +#g-sidebar { + overflow: hidden; +} + +#g-photo, +#g-movie { + zoom: 1; +} + +#g-photo .g-context-menu, +#g-movie .g-context-menu { + width: 240px; +} + +input.submit { + clear: none !important; + display: inline !important; +} + +.g-short-form input.text, +.g-short-form input.submit { + font-size: 1em; + line-height: 1em; + padding: .38em .3em; +} + +#g-search-form input#q { + width: 300px; +} + +#g-add-tag-form input.textbox { + width: 110px !important; +} + +#g-add-tag-form input[type='submit'] { + padding: .3em 0 !important; +} + +#g-dialog .g-cancel { + display: inline-block !important; + float: none !important; +} + +.g-paginator .g-text-right { + width: 29%; +} + +.g-paginator .ui-icon-right { + width: 60px; +} diff --git a/3.0/themes/smk/css/screen.css b/3.0/themes/smk/css/screen.css new file mode 100644 index 00000000..1f41d0b8 --- /dev/null +++ b/3.0/themes/smk/css/screen.css @@ -0,0 +1,1376 @@ +/** + * Gallery 3 Wind Theme Screen Styles + * + * @requires YUI reset, font, grids CSS + * + * Sheet organization: + * 1) Font sizes, base HTML elements + * 2) Reusable content blocks + * 3) Page layout containers + * 4) Content blocks in specific layout containers + * 5) States and interactions + * 6) Positioning and order + * 7) Navigation and menus + * 8) jQuery and jQuery UI + * 9) Right-to-left language styles + */ + +/** ******************************************************************* + * 1) Font sizes, base HTML elements + **********************************************************************/ + +body, html { + background-color: #111111; + color: #999999; + font-family: 'Lucida Grande', 'Lucida Sans', Arial, sans-serif; +} + +p { + margin-bottom: 1em; +} + +em { + font-style: oblique; +} + +h1, h2, h3, h4, h5, strong, th { + font-weight: bold; +} + +h1 { + font-size: 1.7em; +} + +#g-dialog h1 { + font-size: 1.1em; +} + +h2 { + font-size: 1.4em; +} + +#g-sidebar .g-block h2 { + font-size: 1.2em; +} + +#g-sidebar .g-block li { + margin-bottom: .6em; +} + +#g-content, +#g-site-menu, +h3 { + font-size: 1.2em; +} + +#g-sidebar, +.g-breadcrumbs { + font-size: .9em; +} + +#g-banner, +#g-footer, +.g-message { + font-size: .8em; +} + +#g-album-grid .g-item, +#g-item #g-photo, +#g-item #g-movie { + font-size: .7em; +} + +/* Links ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +a, +#g-dialog a, +.g-button, +.g-button:hover, +.g-button:active, +a.ui-state-hover, +input.ui-state-hover, +button.ui-state-hover { + color: #999999 !important; + cursor: pointer !important; + text-decoration: none; + -moz-outline-style: none; +} + +.g-menu a { + background-color: #222222; + color: #999999 !important; + border-color: #444444; + cursor: pointer !important; + text-decoration: none; + -moz-outline-style: none; +} + +a:hover, +#g-dialog a:hover { + text-decoration: underline; +} + +.g-menu a:hover { + text-decoration: none; + background-color: #111111; +} + +#g-dialog #g-action-status li { + width: 400px; + white-space: normal; + padding-left: 32px; +} + +/* Forms ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ +form { + margin: 0; +} + +fieldset { + border: 1px solid #ccc; + padding: 0 1em .8em 1em; +} + +#g-banner fieldset, +#g-sidebar fieldset { + border: none; + padding: 0; +} + +legend { + font-weight: bold; + margin: 0; + padding: 0 .2em; +} + +#g-banner legend, +#g-sidebar legend, +input[type="hidden"] { + display: none; +} + +input.textbox, +input[type="text"], +input[type="password"], +textarea { + border: 1px solid #e8e8e8; + border-top-color: #ccc; + border-left-color: #ccc; + clear: both; + color: #333; + width: 50%; +} + +textarea { + height: 12em; + width: 97%; +} + +input:focus, +input.textbox:focus, +input[type=text]:focus, +textarea:focus, +option:focus { + background-color: #ffc; + color: #000; +} + +input.checkbox, +input[type=checkbox], +input.radio, +input[type=radio] { + float: left; + margin-right: .4em; +} + +/* Form layout ~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +form li { + margin: 0; + padding: 0 0 .2em 0; +} + +form ul { + margin-top: 0; +} + +form ul ul { + clear: both; +} + +form ul ul li { + float: left; +} + +input, +select, +textarea { + display: block; + clear: both; + padding: .2em; +} + +input[type="submit"], +input[type="reset"] { + display: inline; + clear: none; + float: left; +} + +/* Forms in dialogs and panels ~~~~~~~~~ */ + +#g-dialog ul li { + padding-bottom: .8em; +} + +#g-dialog fieldset, +#g-panel fieldset { + border: none; + padding: 0; +} + +#g-panel legend { + display: none; +} + +input[readonly] { + background-color: #F4F4FC; +} + +#g-dialog input.textbox, +#g-dialog input[type=text], +#g-dialog input[type=password], +#g-dialog textarea { + width: 97%; +} + +/* Short forms ~~~~~~~~~~~~~~~~~~~~~~~ */ + +.g-short-form legend, +.g-short-form label { + display: none; +} + +.g-short-form fieldset { + border: none; + padding: 0; +} + +.g-short-form li { + float: left; + margin: 0 !important; + padding: .4em 0; +} + +.g-short-form .textbox, +.g-short-form input[type=text] { + color: #666; + padding: .3em .6em; + width: 100%; +} + +.g-short-form .textbox.g-error { + border: 1px solid #f00; + color: #f00; + padding-left: 24px; +} + +.g-short-form .g-cancel { + display: block; + margin: .3em .8em; +} + +#g-sidebar .g-short-form li { + padding-left: 0; + padding-right: 0; +} + +/* Tables ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +table { + width: 100%; +} + +#g-content table { + margin: 1em 0; +} + +caption, +th { + text-align: left; +} + +th, +td { + border: none; + border-bottom: 1px solid #ccc; + padding: .5em; +} + +td { + vertical-align: top; +} + +/* Text ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ +.g-text-small { + font-size: .8em; +} + +.g-text-big { + font-size: 1.2em; +} + +.g-text-right { + text-align: right; +} + +/** ******************************************************************* + * 2) Reusable content blocks + *********************************************************************/ + +.g-block h2 { + background-color: #111111; + padding: .3em .8em; +} + +.g-block-content { + margin-top: 1em; +} + +/** ******************************************************************* + * 3) Page layout containers + *********************************************************************/ + +/* Dimension and scale ~~~~~~~~~~~~~~~~~~~ */ +.g-one-quarter { + width: 25%; +} + +.g-one-third { + width: 33%; +} + +.g-one-half { + width: 50%; +} + +.g-two-thirds { + width: 66%; +} + +.g-three-quarters { + width: 75%; +} + +.g-whole { + width: 100%; +} + +/* View container ~~~~~~~~~~~~~~~~~~~~~~~~ */ + +.g-view { + background-color: #222222; + border: 1px solid #444444; + border-bottom: none; +} + +/* Layout containers ~~~~~~~~~~~~~~~~~~~~~ */ + +#g-header { + margin-bottom: 1em; +} + +#g-banner { + background-color: #333333; + border-bottom: 1px solid #444444; + min-height: 5em; + padding: 1em 20px; + position: relative; +} + +#g-content { + padding-left: 20px; + position: relative; + width: 696px; +} + +#g-sidebar { + padding: 0 20px; + width: 220px; +} + +#g-footer { + background-color: #333333; + border-top: 1px solid #444444; + margin-top: 20px; + padding: 10px 20px; +} + +/** ******************************************************************* + * 4) Content blocks in specific layout containers + *********************************************************************/ + +/* Header ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +#g-banner #g-quick-search-form { + clear: right; + float: right; + margin-top: 1em; +} + +#g-banner #g-quick-search-form input[type='text'] { + width: 17em; + background-color: #444444; + color: #999999; +} + +#g-content .g-block h2 { + background-color: transparent; + padding-left: 0; +} + +/* Sidebar ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +#g-sidebar .g-block-content { + padding-left: 1em; +} + +#g-sidebar #g-image-block { + overflow: hidden; +} + +/* Album content ~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +#g-content #g-album-grid { + margin: 1em 0; + position: relative; + z-index: 1; +} + +#g-content #g-album-grid .g-item { + background-color: #333333; + border: 1px solid #444444; + float: left; + padding: .6em 8px; + position: relative; + text-align: center; + width: 213px; + z-index: 1; +} + +#g-content #g-album-grid .g-item h2 { + margin: 5px 0; +} + +#g-content .g-photo h2, +#g-content .g-item .g-metadata { + display: none; + margin-bottom: .6em; +} + +#g-content #g-album-grid .g-album { + background-color: #333333; +} + +#g-content #g-album-grid .g-album h2 span.g-album { + background: transparent url('../images/ico-album.png') no-repeat top left; + display: inline-block; + height: 16px; + margin-right: 5px; + width: 16px; +} + +#g-content #g-album-grid .g-hover-item { + background-color: #333333; + border: 1px solid #000; + position: absolute !important; + z-index: 1000 !important; +} + +#g-content .g-hover-item h2, +#g-content .g-hover-item .g-metadata { + display: block; +} + +#g-content #g-album-grid #g-place-holder { + position: relative; + visibility: hidden; + z-index: 1; +} + +/* Search results ~~~~~~~~~~~~~~~~~~~~~~~~ */ + +#g-content #g-search-results { + margin-top: 1em; + padding-top: 1em; +} + +/* Individual photo content ~~~~~~~~~~~~~~ */ + +#g-item { + position: relative; + width: 100%; +} + +#g-item #g-photo, +#g-item #g-movie { + padding: 2.2em 0; + position: relative; +} + +#g-item img.g-resize, +#g-item a.g-movie { + display: block; + margin: 0 auto; +} + +/* Footer content ~~~~~~~~~~~~~~~~~~~~~~~~ */ + +#g-footer #g-credits li { + padding-right: 1.2em; +} + +/* In-line editing ~~~~~~~~~~~~~~~~~~~~~~ */ + +#g-in-place-edit-message { + background-color: #fff; +} + +/* Permissions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ +#g-edit-permissions-form td { + background-image: none; +} + +#g-edit-permissions-form fieldset { + border: 1px solid #ccc; +} + +#g-permissions .g-denied { + background-color: #fcc; +} + +#g-permissions .g-allowed { + background-color: #cfc; +} + +#g-permissions .g-breadcrumbs a { + border: 1px solid #fff; +} + +#g-permissions .g-active a { + border: 1px solid #ddd; + background: #eee; +} + +/** ******************************************************************* + * 5) States and interactions + **********************************************************************/ + +.g-active, +.g-enabled, +.g-available, +.g-selected, +.g-highlight { + font-weight: bold; +} + +.g-inactive, +.g-disabled, +.g-unavailable, +.g-uneditable, +.g-locked, +.g-deselected, +.g-understate { + color: #ccc; + font-weight: normal; +} + +.g-editable { + padding: .2em .3em; +} + +.g-editable:hover { + background-color: #ffc; + cursor: text; +} + +.g-error, +.g-info, +.g-success, +.g-warning { + padding-left: 30px; +} + +form li.g-error, +form li.g-info, +form li.g-success, +form li.g-warning { + background-image: none; + padding: .3em .8em .3em 0; +} + +.g-short-form li.g-error { + padding: .3em 0; +} + +form.g-error input[type="text"], +li.g-error input[type="text"], +form.g-error input[type="password"], +li.g-error input[type="password"], +form.g-error input[type="checkbox"], +li.g-error input[type="checkbox"], +form.g-error input[type="radio"], +li.g-error input[type="radio"], +form.g-error textarea, +li.g-error textarea, +form.g-error select, +li.g-error select { + border: 2px solid #f00; + margin-bottom: .2em; +} + +.g-error, +.g-denied, +tr.g-error td.g-error, +#g-add-photos-status .g-error { + background: #f6cbca url('../images/ico-error.png') no-repeat .4em 50%; + color: #f00; +} + +.g-info { + background: #e8e8e8 url('../images/ico-info.png') no-repeat .4em 50%; +} + +.g-success, +.g-allowed, +#g-add-photos-status .g-success { + background: #d9efc2 url('../images/ico-success.png') no-repeat .4em 50%; +} + +tr.g-success { + background-image: none; +} + +tr.g-success td.g-success { + background-image: url('../images/ico-success.png'); +} + +.g-warning, +tr.g-warning td.g-warning { + background: #fcf9ce url('../images/ico-warning.png') no-repeat .4em 50%; +} + +form .g-error { + background-color: #fff; + padding-left: 20px; +} + +.g-open { +} + +.g-closed { +} + +.g-installed { + background-color: #eeeeee; +} + +.g-default { + background-color: #444444; + font-weight: bold; +} + +.g-draggable { + cursor: move; +} + +.g-draggable:hover { + border: 1px dashed #000; +} + +.ui-sortable .g-target, +.ui-state-highlight { + background-color: #fcf9ce; + border: 2px dotted #999; + height: 2em; + margin: 1em 0; +} + +/* Ajax loading indicator ~~~~~~~~~~~~~~~~ */ + +.g-loading-large, +.g-dialog-loading-large { + background: #e8e8e8 url('../images/loading-large.gif') no-repeat center center !important; +} + +.g-loading-small { + background: #e8e8e8 url('../images/loading-small.gif') no-repeat center center !important; +} + +/** ******************************************************************* + * 6) Positioning and order + **********************************************************************/ + +.g-left { + clear: none; + float: left; +} + +.g-right { + clear: none; + float: right; +} + +.g-first { +} + +.g-last { +} + +.g-even { + background-color: #fff; +} + +.g-odd { + background-color: #eee; +} + +/** ******************************************************************* + * 7) Navigation and menus + *********************************************************************/ + +/* Login menu ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +#g-banner #g-login-menu { + color: #999; + float: right; +} + +#g-banner #g-login-menu li { + padding-left: 1.2em; +} + +/* Site Menu ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +#g-site-menu { + bottom: 0; + left: 140px; + position: absolute; +} + +#g-site-menu ul { + margin-bottom: 0 !important; +} + +/* Context Menu ~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +.g-context-menu { + background-color: #fff; + bottom: 0; + left: 0; + position: absolute; +} + +.g-item .g-context-menu { + display: none; + margin-top: 2em; + width: 100%; +} + +#g-item .g-context-menu ul { + display: none; +} + +.g-context-menu li { + border-left: none; + border-right: none; + border-bottom: none; +} + +.g-context-menu li a { + display: block; + line-height: 1.6em; + background-color: #222222; +} + +.g-hover-item .g-context-menu { + display: block; +} + +.g-hover-item .g-context-menu li { + text-align: left; +} + +.g-hover-item .g-context-menu a:hover { + text-decoration: none; +} + +/* View Menu ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +#g-view-menu { + margin-bottom: 1em; +} + +#g-view-menu a { + background-repeat: no-repeat; + background-position: 50% 50%; + height: 28px !important; + width: 43px !important; +} + +#g-view-menu #g-slideshow-link { + background-image: url('../images/ico-view-slideshow.png'); +} + +#g-view-menu .g-fullsize-link { + background-image: url('../images/ico-view-fullsize.png'); +} + +#g-view-menu #g-comments-link { + background-image: url('../images/ico-view-comments.png'); +} + +#g-view-menu #g-print-digibug-link { + background-image: url('../images/ico-print.png'); +} + +/** ******************************************************************* + * 8) jQuery and jQuery UI + *********************************************************************/ +/* Generic block container ~~~~~~~~~~~~~~~ */ + +.g-block { + clear: both; + margin-bottom: 2.5em; +} + +.g-block-content { +} + +/* Superfish menu overrides ~~~~~~~~~~~~~~ */ +.sf-menu ul { + width: 12em; +} + +ul.sf-menu li li:hover ul, +ul.sf-menu li li.sfHover ul { + left: 12em; +} + +ul.sf-menu li li li:hover ul, +ul.sf-menu li li li.sfHover ul { + left: 12em; +} + +.sf-menu li li, +.sf-menu li li ul li { + background-color: #bdd2ff; +} + +.sf-menu li:hover { + background-color: #dfe9ff; +} + +/* jQuery UI Dialog ~~~~~~~~~~~~~~~~~~~~~~ */ + +.ui-widget-overlay { + background: #000; + opacity: .7; +} + +/* Buttons ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +.g-button { + display: inline-block; + margin: 0 4px 0 0; + padding: .2em .4em; +} + +.g-button, +.g-button:hover, +.g-button:active { + cursor: pointer !important; + outline: 0; + text-decoration: none; + -moz-outline-style: none; +} + +button { + padding: 2px 4px 2px 4px; +} + +/* jQuery UI ThemeRoller buttons ~~~~~~~~~ */ + +.g-buttonset { + padding-left: 1px; +} + +.g-buttonset li { + float: left; +} + +.g-buttonset .g-button { + margin: 0; +} + +.ui-icon-left .ui-icon { + float: left; + margin-right: .2em; +} + +.ui-icon-right .ui-icon { + float: right; + margin-left: .2em; +} + +/* Rotate icon, ThemeRoller only provides one of these */ + +.ui-icon-rotate-ccw { + background-position: -192px -64px; +} + +.ui-icon-rotate-cw { + background-position: -208px -64px; +} + +.g-progress-bar { + height: 1em; + width: 100%; + margin-top: .5em; + display: inline-block; +} + +/* Status and validation messages ~~~~ */ + +.g-message-block { + background-position: .4em .3em; + border: 1px solid #ccc; + padding: 0; +} + +#g-action-status { + margin-bottom: 1em; +} + +#g-action-status li, +p#g-action-status, +div#g-action-status { + padding: .3em .3em .3em 30px; +} + +#g-site-status li { + border-bottom: 1px solid #ccc; + padding: .3em .3em .3em 30px; +} + +.g-module-status { + clear: both; + margin-bottom: 1em; +} + +.g-message { + background-position: 0 50%; +} + +/* Breadcrumbs ~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +.g-breadcrumbs { + clear: both; + padding: 0 20px; +} + +.g-breadcrumbs li { + background: transparent url('../images/ico-separator.gif') no-repeat scroll left center; + float: left; + padding: 1em 8px 1em 18px; +} + +.g-breadcrumbs .g-first { + background: none; + padding-left: 0; +} + +.g-breadcrumbs li a, +.g-breadcrumbs li span { + display: block; +} + +#g-dialog ul.g-breadcrumbs { + margin-left: 0; + padding-left: 0; +} + +/* Pagination ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +.g-paginator { + padding: .2em 0; + width: 100%; +} + +.g-paginator li { + float: left; + width: 30%; +} + +.g-paginator .g-info { + background: none; + padding: .2em 0; + text-align: center; + width: 40%; +} + +/* Dialogs and panels ~~~~~~~~~~~~~~~~~~ */ + +#g-dialog { + text-align: left; +} + +#g-dialog legend { + display: none; +} + +#g-dialog .g-cancel { + margin: .4em 1em; +} + +#g-panel { + display: none; + padding: 1em; +} + +/* Inline layout ~~~~~~~~~~ */ + +.g-inline li { + float: left; + margin-left: 1.8em; + padding-left: 0 !important; +} + +.g-inline li.g-first { + margin-left: 0; +} + +/* Autocomplete ~~~~~~~~~~ */ +.ac_loading { + background: white url('../images/loading-small.gif') right center no-repeat !important; +} + +/** ******************************************************************* + * 9) Right to left language styles + *********************************************************************/ + +.rtl { + direction: rtl; +} + +.rtl #g-header, +.rtl #g-content, +.rtl #g-sidebar, +.rtl #g-footer, +.rtl caption, +.rtl th, +.rtl #g-dialog, +.rtl .g-context-menu li a, +.rtl .g-message-box li, +.rtl #g-site-status li { + text-align: right; +} + +.rtl .g-text-right { + text-align: left; +} + +.rtl .g-error, +.rtl .g-info, +.rtl .g-success, +.rtl .g-warning, +.rtl #g-add-photos-status .g-success, +.rtl #g-add-photos-status .g-error { + background-position: center right; + padding-right: 30px !important; +} + +.rtl form li.g-error, +.rtl form li.g-info, +.rtl form li.g-success, +.rtl form li.g-warning { + padding-right: 0 !important; +} + +.rtl .g-left, +.rtl .g-inline li, +.rtl #g-content #g-album-grid .g-item, +.rtl .sf-menu li, +.rtl .g-breadcrumbs li, +.rtl .g-paginator li, +.rtl .g-buttonset li, +.rtl .ui-icon-left .ui-icon, +.rtl .g-short-form li, +.rtl form ul ul li, +.rtl input[type="submit"], +.rtl input[type="reset"], +.rtl input.checkbox, +.rtl input[type=checkbox], +.rtl input.radio, +.rtl input[type=radio] { + float: right; +} + +.rtl .g-right, +.rtl .ui-icon-right .ui-icon { + float: left; +} + +.rtl .g-inline li { + margin-right: 1em; +} + +.rtl .g-inline li.g-first { + margin-right: 0; +} + +.rtl .g-breadcrumbs li { + background: transparent url('../images/ico-separator-rtl.gif') no-repeat scroll right center; + padding: 1em 18px 1em 8px; +} + +.rtl .g-breadcrumbs .g-first { + background: none; + padding-right: 0; +} + +.rtl input.checkbox { + margin-left: .4em; +} + +.rtl #g-add-comment { + right: inherit; + left: 0; +} + +.rtl .ui-icon-left .ui-icon { + margin-left: .2em; +} + +.rtl .ui-icon-right .ui-icon { + margin-right: .2em; +} + +/* RTL Corner radius ~~~~~~~~~~~~~~~~~~~~~~ */ +.rtl .g-buttonset .ui-corner-tl { + -moz-border-radius-topleft: 0; + -webkit-border-top-left-radius: 0; + border-top-left-radius: 0; + -moz-border-radius-topright: 5px !important; + -webkit-border-top-right-radius: 5px !important; + border-top-right-radius: 5px !important; +} + +.rtl .g-buttonset .ui-corner-tr { + -moz-border-radius-topright: 0; + -webkit-border-top-right-radius: 0; + border-top-right-radius: 0; + -moz-border-radius-topleft: 5px !important; + -webkit-border-top-left-radius: 5px !important; + border-top-left-radius: 5px !important; +} + +.rtl .g-buttonset .ui-corner-bl { + -moz-border-radius-bottomleft: 0; + -webkit-border-bottom-left-radius: 0; + border-bottom-left-radius: 0; + -moz-border-radius-bottomright: 5px !important; + -webkit-border-bottom-right-radius: 5px !important; + border-bottom-right-radius: 5px !important; +} + +.rtl .g-buttonset .ui-corner-br { + -moz-border-radius-bottomright: 0; + -webkit-border-bottom-right-radius: 0; + border-bottom-right-radius: 0; + -moz-border-radius-bottomleft: 5px !important; + -webkit-border-bottom-left-radius: 5px !important; + border-bottom-left-radius: 5px !important; +} + +.rtl .g-buttonset .ui-corner-right, +.rtl .ui-progressbar .ui-corner-right { + -moz-border-radius-topright: 0; + -webkit-border-top-right-radius: 0; + border-top-right-radius: 0; + -moz-border-radius-topleft: 5px !important; + -webkit-border-top-left-radius: 5px !important; + border-top-left-radius: 5px !important; + -moz-border-radius-bottomright: 0; + -webkit-border-bottom-right-radius: 0; + border-bottom-right-radius: 0; + -moz-border-radius-bottomleft: 5px !important; + -webkit-border-bottom-left-radius: 5px !important; + border-bottom-left-radius: 5px !important; +} + +.rtl .g-buttonset .ui-corner-left, +.rtl .ui-progressbar .ui-corner-left { + -moz-border-radius-topleft: 0; + -webkit-border-top-left-radius: 0; + border-top-left-radius: 0; + -moz-border-radius-topright: 5px !important; + -webkit-border-top-right-radius: 5px !important; + border-top-right-radius: 5px !important; + -moz-border-radius-bottomleft: 0; + -webkit-border-bottom-left-radius: 0; + border-bottom-left-radius: 0; + -moz-border-radius-bottomright: 5px !important; + -webkit-border-bottom-right-radius: 5px !important; + border-bottom-right-radius: 5px !important; +} + +/* RTL Superfish ~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +.rtl .sf-menu a { + border-left: none; + border-right:1px solid #fff; +} + +.rtl .sf-menu a.sf-with-ul { + padding-left: 2.25em; + padding-right: 1em; +} + +.rtl .sf-sub-indicator { + left: .75em !important; + right: auto; + background: url('../../../lib/superfish/images/arrows-ffffff-rtl.png') no-repeat -10px -100px; /* 8-bit indexed alpha png. IE6 gets solid image only */ +} +.rtl a > .sf-sub-indicator { /* give all except IE6 the correct values */ + top: .8em; + background-position: -10px -100px; /* use translucent arrow for modern browsers*/ +} +/* apply hovers to modern browsers */ +.rtl a:focus > .sf-sub-indicator, +.rtl a:hover > .sf-sub-indicator, +.rtl a:active > .sf-sub-indicator, +.rtl li:hover > a > .sf-sub-indicator, +.rtl li.sfHover > a > .sf-sub-indicator { + background-position: 0 -100px; /* arrow hovers for modern browsers*/ +} + +/* point right for anchors in subs */ +.rtl .sf-menu ul .sf-sub-indicator { background-position: 0 0; } +.rtl .sf-menu ul a > .sf-sub-indicator { background-position: -10px 0; } +/* apply hovers to modern browsers */ +.rtl .sf-menu ul a:focus > .sf-sub-indicator, +.rtl .sf-menu ul a:hover > .sf-sub-indicator, +.rtl .sf-menu ul a:active > .sf-sub-indicator, +.rtl .sf-menu ul li:hover > a > .sf-sub-indicator, +.rtl .sf-menu ul li.sfHover > a > .sf-sub-indicator { + background-position: 0 0; /* arrow hovers for modern browsers*/ +} + +.rtl .sf-menu li:hover ul, +.rtl .sf-menu li.sfHover ul { + right: 0; + left: auto; +} + +.rtl ul.sf-menu li li:hover ul, +.rtl ul.sf-menu li li.sfHover ul { + right: 12em; /* match ul width */ + left: auto; +} +.rtl ul.sf-menu li li li:hover ul, +.rtl ul.sf-menu li li li.sfHover ul { + right: 12em; /* match ul width */ + left: auto; +} + +/*** shadows for all but IE6 ***/ +.rtl .sf-shadow ul { + background: url('../../../lib/superfish/images/shadow.png') no-repeat bottom left; + padding: 0 0 9px 8px; + border-top-right-radius: 0; + border-bottom-left-radius: 0; + -moz-border-radius-topright: 0; + -moz-border-radius-bottomleft: 0; + -webkit-border-top-right-radius: 0; + -webkit-border-bottom-left-radius: 0; + -moz-border-radius-topleft: 17px; + -moz-border-radius-bottomright: 17px; + -webkit-border-top-left-radius: 17px; + -webkit-border-bottom-right-radius: 17px; + border-top-left-radius: 17px; + border-bottom-right-radius: 17px; +} + +/* RTL ThemeRoller ~~~~~~~~~~~~~~~~~~~~~~~~ */ + +.rtl .ui-dialog .ui-dialog-titlebar { + padding: 0.5em 1em 0.3em 0.3em; +} + +.rtl .ui-dialog .ui-dialog-title { + float: right; +} + +.rtl .ui-dialog .ui-dialog-titlebar-close { + left: 0.3em; + right: auto; +} + + +/* RTL paginator ~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +.rtl .g-paginator .g-info { + width: 35%; +} + +.rtl .g-paginator .g-text-right { + margin-left: 0; +} + +.rtl .g-paginator .ui-icon-seek-end { + background-position: -80px -160px; +} + +.rtl .g-paginator .ui-icon-seek-next { + background-position: -48px -160px; +} + +.rtl .g-paginator .ui-icon-seek-prev { + background-position: -32px -160px; +} + +.rtl .g-paginator .ui-icon-seek-first { + background-position: -64px -160px; +} + +.rtl #g-header #g-login-menu, +.rtl #g-header #g-quick-search-form { + clear: left; + float: left; +} + +.rtl #g-header #g-login-menu li { + margin-left: 0; + padding-left: 0; + padding-right: 1.2em; +} + +.rtl #g-site-menu { + left: auto; + right: 150px; +} + +.rtl #g-view-menu #g-slideshow-link { + background-image: url('../images/ico-view-slideshow-rtl.png'); +} + +.rtl #g-sidebar .g-block-content { + padding-right: 1em; + padding-left: 0; +} + +.rtl #g-footer #g-credits li { + padding-left: 1.2em !important; + padding-right: 0; +} diff --git a/3.0/themes/smk/css/themeroller/images/ui-bg_flat_0_aaaaaa_40x100.png b/3.0/themes/smk/css/themeroller/images/ui-bg_flat_0_aaaaaa_40x100.png new file mode 100644 index 00000000..5b5dab2a Binary files /dev/null and b/3.0/themes/smk/css/themeroller/images/ui-bg_flat_0_aaaaaa_40x100.png differ diff --git a/3.0/themes/smk/css/themeroller/images/ui-bg_flat_55_fbec88_40x100.png b/3.0/themes/smk/css/themeroller/images/ui-bg_flat_55_fbec88_40x100.png new file mode 100644 index 00000000..47acaadd Binary files /dev/null and b/3.0/themes/smk/css/themeroller/images/ui-bg_flat_55_fbec88_40x100.png differ diff --git a/3.0/themes/smk/css/themeroller/images/ui-bg_glass_75_d0e5f5_1x400.png b/3.0/themes/smk/css/themeroller/images/ui-bg_glass_75_d0e5f5_1x400.png new file mode 100644 index 00000000..9fb564f8 Binary files /dev/null and b/3.0/themes/smk/css/themeroller/images/ui-bg_glass_75_d0e5f5_1x400.png differ diff --git a/3.0/themes/smk/css/themeroller/images/ui-bg_glass_85_dfeffc_1x400.png b/3.0/themes/smk/css/themeroller/images/ui-bg_glass_85_dfeffc_1x400.png new file mode 100644 index 00000000..01495152 Binary files /dev/null and b/3.0/themes/smk/css/themeroller/images/ui-bg_glass_85_dfeffc_1x400.png differ diff --git a/3.0/themes/smk/css/themeroller/images/ui-bg_glass_95_fef1ec_1x400.png b/3.0/themes/smk/css/themeroller/images/ui-bg_glass_95_fef1ec_1x400.png new file mode 100644 index 00000000..4443fdc1 Binary files /dev/null and b/3.0/themes/smk/css/themeroller/images/ui-bg_glass_95_fef1ec_1x400.png differ diff --git a/3.0/themes/smk/css/themeroller/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png b/3.0/themes/smk/css/themeroller/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png new file mode 100644 index 00000000..0cdbda36 Binary files /dev/null and b/3.0/themes/smk/css/themeroller/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png differ diff --git a/3.0/themes/smk/css/themeroller/images/ui-bg_inset-hard_100_f5f8f9_1x100.png b/3.0/themes/smk/css/themeroller/images/ui-bg_inset-hard_100_f5f8f9_1x100.png new file mode 100644 index 00000000..4f3faf8a Binary files /dev/null and b/3.0/themes/smk/css/themeroller/images/ui-bg_inset-hard_100_f5f8f9_1x100.png differ diff --git a/3.0/themes/smk/css/themeroller/images/ui-bg_inset-hard_100_fcfdfd_1x100.png b/3.0/themes/smk/css/themeroller/images/ui-bg_inset-hard_100_fcfdfd_1x100.png new file mode 100644 index 00000000..38c38335 Binary files /dev/null and b/3.0/themes/smk/css/themeroller/images/ui-bg_inset-hard_100_fcfdfd_1x100.png differ diff --git a/3.0/themes/smk/css/themeroller/images/ui-icons_217bc0_256x240.png b/3.0/themes/smk/css/themeroller/images/ui-icons_217bc0_256x240.png new file mode 100644 index 00000000..7719d487 Binary files /dev/null and b/3.0/themes/smk/css/themeroller/images/ui-icons_217bc0_256x240.png differ diff --git a/3.0/themes/smk/css/themeroller/images/ui-icons_2e83ff_256x240.png b/3.0/themes/smk/css/themeroller/images/ui-icons_2e83ff_256x240.png new file mode 100644 index 00000000..d9897d25 Binary files /dev/null and b/3.0/themes/smk/css/themeroller/images/ui-icons_2e83ff_256x240.png differ diff --git a/3.0/themes/smk/css/themeroller/images/ui-icons_469bdd_256x240.png b/3.0/themes/smk/css/themeroller/images/ui-icons_469bdd_256x240.png new file mode 100644 index 00000000..d8161854 Binary files /dev/null and b/3.0/themes/smk/css/themeroller/images/ui-icons_469bdd_256x240.png differ diff --git a/3.0/themes/smk/css/themeroller/images/ui-icons_6da8d5_256x240.png b/3.0/themes/smk/css/themeroller/images/ui-icons_6da8d5_256x240.png new file mode 100644 index 00000000..b3c7d662 Binary files /dev/null and b/3.0/themes/smk/css/themeroller/images/ui-icons_6da8d5_256x240.png differ diff --git a/3.0/themes/smk/css/themeroller/images/ui-icons_cd0a0a_256x240.png b/3.0/themes/smk/css/themeroller/images/ui-icons_cd0a0a_256x240.png new file mode 100644 index 00000000..2db88b79 Binary files /dev/null and b/3.0/themes/smk/css/themeroller/images/ui-icons_cd0a0a_256x240.png differ diff --git a/3.0/themes/smk/css/themeroller/images/ui-icons_d8e7f3_256x240.png b/3.0/themes/smk/css/themeroller/images/ui-icons_d8e7f3_256x240.png new file mode 100644 index 00000000..2c8aac46 Binary files /dev/null and b/3.0/themes/smk/css/themeroller/images/ui-icons_d8e7f3_256x240.png differ diff --git a/3.0/themes/smk/css/themeroller/images/ui-icons_f9bd01_256x240.png b/3.0/themes/smk/css/themeroller/images/ui-icons_f9bd01_256x240.png new file mode 100644 index 00000000..e81603f5 Binary files /dev/null and b/3.0/themes/smk/css/themeroller/images/ui-icons_f9bd01_256x240.png differ diff --git a/3.0/themes/smk/css/themeroller/ui.base.css b/3.0/themes/smk/css/themeroller/ui.base.css new file mode 100644 index 00000000..1a1810c8 --- /dev/null +++ b/3.0/themes/smk/css/themeroller/ui.base.css @@ -0,0 +1,7 @@ +@import "ui.core.css"; +@import "ui.theme.css"; +@import "ui.datepicker.css"; +@import "ui.dialog.css"; +@import "ui.progressbar.css"; +@import "ui.resizable.css"; +@import "ui.tabs.css"; diff --git a/3.0/themes/smk/css/themeroller/ui.core.css b/3.0/themes/smk/css/themeroller/ui.core.css new file mode 100644 index 00000000..d832ad7d --- /dev/null +++ b/3.0/themes/smk/css/themeroller/ui.core.css @@ -0,0 +1,37 @@ +/* +* jQuery UI CSS Framework +* Copyright (c) 2009 AUTHORS.txt (http://ui.jquery.com/about) +* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses. +*/ + +/* Layout helpers +----------------------------------*/ +.ui-helper-hidden { display: none; } +.ui-helper-hidden-accessible { position: absolute; left: -99999999px; } +.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; } +.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } +.ui-helper-clearfix { display: inline-block; } +/* required comment for clearfix to work in Opera \*/ +* html .ui-helper-clearfix { height:1%; } +.ui-helper-clearfix { display:block; } +/* end clearfix */ +.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); } + + +/* Interaction Cues +----------------------------------*/ +.ui-state-disabled { cursor: default !important; } + + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; } + + +/* Misc visuals +----------------------------------*/ + +/* Overlays */ +.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } \ No newline at end of file diff --git a/3.0/themes/smk/css/themeroller/ui.datepicker.css b/3.0/themes/smk/css/themeroller/ui.datepicker.css new file mode 100644 index 00000000..92986c9e --- /dev/null +++ b/3.0/themes/smk/css/themeroller/ui.datepicker.css @@ -0,0 +1,62 @@ +/* Datepicker +----------------------------------*/ +.ui-datepicker { width: 17em; padding: .2em .2em 0; } +.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; } +.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; } +.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; } +.ui-datepicker .ui-datepicker-prev { left:2px; } +.ui-datepicker .ui-datepicker-next { right:2px; } +.ui-datepicker .ui-datepicker-prev-hover { left:1px; } +.ui-datepicker .ui-datepicker-next-hover { right:1px; } +.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; } +.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; } +.ui-datepicker .ui-datepicker-title select { float:left; font-size:1em; margin:1px 0; } +.ui-datepicker select.ui-datepicker-month-year {width: 100%;} +.ui-datepicker select.ui-datepicker-month, +.ui-datepicker select.ui-datepicker-year { width: 49%;} +.ui-datepicker .ui-datepicker-title select.ui-datepicker-year { float: right; } +.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; } +.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; } +.ui-datepicker td { border: 0; padding: 1px; } +.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; } +.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; } +.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; } +.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; } + +/* with multiple calendars */ +.ui-datepicker.ui-datepicker-multi { width:auto; } +.ui-datepicker-multi .ui-datepicker-group { float:left; } +.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; } +.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; } +.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; } +.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; } +.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; } +.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; } +.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; } +.ui-datepicker-row-break { clear:left; width:100%; } + +/* RTL support */ +.ui-datepicker-rtl { direction: rtl; } +.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; } +.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; } +.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; } +.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; } +.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; } +.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; } +.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; } +.ui-datepicker-rtl .ui-datepicker-group { float:right; } +.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; } +.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; } + +/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */ +.ui-datepicker-cover { + display: none; /*sorry for IE5*/ + display/**/: block; /*sorry for IE5*/ + position: absolute; /*must have*/ + z-index: -1; /*must have*/ + filter: mask(); /*must have*/ + top: -4px; /*must have*/ + left: -4px; /*must have*/ + width: 200px; /*must have*/ + height: 200px; /*must have*/ +} \ No newline at end of file diff --git a/3.0/themes/smk/css/themeroller/ui.dialog.css b/3.0/themes/smk/css/themeroller/ui.dialog.css new file mode 100644 index 00000000..f10f4090 --- /dev/null +++ b/3.0/themes/smk/css/themeroller/ui.dialog.css @@ -0,0 +1,13 @@ +/* Dialog +----------------------------------*/ +.ui-dialog { position: relative; padding: .2em; width: 300px; } +.ui-dialog .ui-dialog-titlebar { padding: .5em .3em .3em 1em; position: relative; } +.ui-dialog .ui-dialog-title { float: left; margin: .1em 0 .2em; } +.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; } +.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; } +.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; } +.ui-dialog .ui-dialog-content { border: 0; padding: .5em 1em; background: none; overflow: auto; } +.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; } +.ui-dialog .ui-dialog-buttonpane button { float: right; margin: .5em .4em .5em 0; cursor: pointer; padding: .2em .6em .3em .6em; line-height: 1.4em; width:auto; overflow:visible; } +.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; } +.ui-draggable .ui-dialog-titlebar { cursor: move; } \ No newline at end of file diff --git a/3.0/themes/smk/css/themeroller/ui.progressbar.css b/3.0/themes/smk/css/themeroller/ui.progressbar.css new file mode 100644 index 00000000..bc0939ec --- /dev/null +++ b/3.0/themes/smk/css/themeroller/ui.progressbar.css @@ -0,0 +1,4 @@ +/* Progressbar +----------------------------------*/ +.ui-progressbar { height:2em; text-align: left; } +.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; } \ No newline at end of file diff --git a/3.0/themes/smk/css/themeroller/ui.resizable.css b/3.0/themes/smk/css/themeroller/ui.resizable.css new file mode 100644 index 00000000..44efeb2e --- /dev/null +++ b/3.0/themes/smk/css/themeroller/ui.resizable.css @@ -0,0 +1,13 @@ +/* Resizable +----------------------------------*/ +.ui-resizable { position: relative;} +.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;} +.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; } +.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0px; } +.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0px; } +.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0px; height: 100%; } +.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0px; height: 100%; } +.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; } +.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; } +.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; } +.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;} \ No newline at end of file diff --git a/3.0/themes/smk/css/themeroller/ui.tabs.css b/3.0/themes/smk/css/themeroller/ui.tabs.css new file mode 100644 index 00000000..70ed3ef4 --- /dev/null +++ b/3.0/themes/smk/css/themeroller/ui.tabs.css @@ -0,0 +1,9 @@ +/* Tabs +----------------------------------*/ +.ui-tabs {padding: .2em;} +.ui-tabs .ui-tabs-nav { padding: .2em .2em 0 .2em; position: relative; } +.ui-tabs .ui-tabs-nav li { float: left; border-bottom: 0 !important; margin: 0 .2em -1px 0; padding: 0; list-style: none; } +.ui-tabs .ui-tabs-nav li a { display:block; text-decoration: none; padding: .5em 1em; } +.ui-tabs .ui-tabs-nav li.ui-tabs-selected { padding-bottom: .1em; border-bottom: 0; } +.ui-tabs .ui-tabs-panel { padding: 1em 1.4em; display: block; border: 0; background: none; } +.ui-tabs .ui-tabs-hide { display: none !important; } \ No newline at end of file diff --git a/3.0/themes/smk/css/themeroller/ui.theme.css b/3.0/themes/smk/css/themeroller/ui.theme.css new file mode 100644 index 00000000..faa04463 --- /dev/null +++ b/3.0/themes/smk/css/themeroller/ui.theme.css @@ -0,0 +1,243 @@ + + +/* +* jQuery UI CSS Framework +* Copyright (c) 2009 AUTHORS.txt (http://ui.jquery.com/about) +* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses. +* To view and modify this theme, visit http://ui.jquery.com/themeroller/?tr=&ffDefault=Lucida%20Grande,%20Lucida%20Sans,%20Arial,%20sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=5px&bgColorHeader=5c9ccc&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=55&borderColorHeader=4297d7&fcHeader=ffffff&iconColorHeader=d8e7f3&bgColorContent=fcfdfd&bgTextureContent=06_inset_hard.png&bgImgOpacityContent=100&borderColorContent=a6c9e2&fcContent=222222&iconColorContent=469bdd&bgColorDefault=dfeffc&bgTextureDefault=02_glass.png&bgImgOpacityDefault=85&borderColorDefault=c5dbec&fcDefault=2e6e9e&iconColorDefault=6da8d5&bgColorHover=d0e5f5&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=79b7e7&fcHover=1d5987&iconColorHover=217bc0&bgColorActive=f5f8f9&bgTextureActive=06_inset_hard.png&bgImgOpacityActive=100&borderColorActive=79b7e7&fcActive=e17009&iconColorActive=f9bd01&bgColorHighlight=fbec88&bgTextureHighlight=01_flat.png&bgImgOpacityHighlight=55&borderColorHighlight=fad42e&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px +*/ + + +/* Component containers +----------------------------------*/ +.ui-widget { font-family: Lucida Grande, Lucida Sans, Arial, sans-serif; font-size: 1.1em; } +.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Lucida Grande, Lucida Sans, Arial, sans-serif; font-size: 1em; } +.ui-widget-header { border: 1px solid #4297d7; background: #5c9ccc url(images/ui-bg_gloss-wave_55_5c9ccc_500x100.png) 50% 50% repeat-x; color: #ffffff; font-weight: bold; } +.ui-widget-header a { color: #ffffff; } +.ui-widget-content { border: 1px solid #a6c9e2; background: #fcfdfd url(images/ui-bg_inset-hard_100_fcfdfd_1x100.png) 50% bottom repeat-x; color: #222222; } +.ui-widget-content a { color: #222222; } + +/* Interaction states +----------------------------------*/ +.ui-state-default, .ui-widget-content .ui-state-default { border: 1px solid #444444; background: #444444 50% 50% repeat-x; font-weight: bold; color: #999999; outline: none; } +.ui-state-default a { color: #2e6e9e; text-decoration: none; outline: none; } +.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus { border: 1px solid #999999; background: #444444 50% 50% repeat-x; font-weight: bold; color: #999999; outline: none; } +.ui-state-hover a { color: #1d5987; text-decoration: none; outline: none; } +.ui-state-active, .ui-widget-content .ui-state-active { border: 1px solid #999999; background: #444444 50% 50% repeat-x; font-weight: bold; color: #e17009; outline: none; } +.ui-state-active a { color: #e17009; outline: none; text-decoration: none; } + +/* Interaction Cues +----------------------------------*/ +.ui-state-highlight, .ui-widget-content .ui-state-highlight {border: 1px solid #fad42e; background: #fbec88 50% 50% repeat-x; color: #363636; } +.ui-state-error, .ui-widget-content .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec 50% 50% repeat-x; color: #cd0a0a; } +.ui-state-error-text, .ui-widget-content .ui-state-error-text { color: #cd0a0a; } +.ui-state-disabled, .ui-widget-content .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } +.ui-priority-primary, .ui-widget-content .ui-priority-primary { font-weight: bold; } +.ui-priority-secondary, .ui-widget-content .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_f9bd01_256x240.png); } +.ui-widget-content .ui-icon {background-image: url(images/ui-icons_f9bd01_256x240.png); } +.ui-widget-header .ui-icon {background-image: url(images/ui-icons_f9bd01_256x240.png); } +.ui-state-default .ui-icon { background-image: url(images/ui-icons_f9bd01_256x240.png); } +.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_f9bd01_256x240.png); } +.ui-state-active .ui-icon {background-image: url(images/ui-icons_f9bd01_256x240.png); } +.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_f9bd01_256x240.png); } +.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); } + +/* positioning */ +.ui-icon-carat-1-n { background-position: 0 0; } +.ui-icon-carat-1-ne { background-position: -16px 0; } +.ui-icon-carat-1-e { background-position: -32px 0; } +.ui-icon-carat-1-se { background-position: -48px 0; } +.ui-icon-carat-1-s { background-position: -64px 0; } +.ui-icon-carat-1-sw { background-position: -80px 0; } +.ui-icon-carat-1-w { background-position: -96px 0; } +.ui-icon-carat-1-nw { background-position: -112px 0; } +.ui-icon-carat-2-n-s { background-position: -128px 0; } +.ui-icon-carat-2-e-w { background-position: -144px 0; } +.ui-icon-triangle-1-n { background-position: 0 -16px; } +.ui-icon-triangle-1-ne { background-position: -16px -16px; } +.ui-icon-triangle-1-e { background-position: -32px -16px; } +.ui-icon-triangle-1-se { background-position: -48px -16px; } +.ui-icon-triangle-1-s { background-position: -64px -16px; } +.ui-icon-triangle-1-sw { background-position: -80px -16px; } +.ui-icon-triangle-1-w { background-position: -96px -16px; } +.ui-icon-triangle-1-nw { background-position: -112px -16px; } +.ui-icon-triangle-2-n-s { background-position: -128px -16px; } +.ui-icon-triangle-2-e-w { background-position: -144px -16px; } +.ui-icon-arrow-1-n { background-position: 0 -32px; } +.ui-icon-arrow-1-ne { background-position: -16px -32px; } +.ui-icon-arrow-1-e { background-position: -32px -32px; } +.ui-icon-arrow-1-se { background-position: -48px -32px; } +.ui-icon-arrow-1-s { background-position: -64px -32px; } +.ui-icon-arrow-1-sw { background-position: -80px -32px; } +.ui-icon-arrow-1-w { background-position: -96px -32px; } +.ui-icon-arrow-1-nw { background-position: -112px -32px; } +.ui-icon-arrow-2-n-s { background-position: -128px -32px; } +.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } +.ui-icon-arrow-2-e-w { background-position: -160px -32px; } +.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } +.ui-icon-arrowstop-1-n { background-position: -192px -32px; } +.ui-icon-arrowstop-1-e { background-position: -208px -32px; } +.ui-icon-arrowstop-1-s { background-position: -224px -32px; } +.ui-icon-arrowstop-1-w { background-position: -240px -32px; } +.ui-icon-arrowthick-1-n { background-position: 0 -48px; } +.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } +.ui-icon-arrowthick-1-e { background-position: -32px -48px; } +.ui-icon-arrowthick-1-se { background-position: -48px -48px; } +.ui-icon-arrowthick-1-s { background-position: -64px -48px; } +.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } +.ui-icon-arrowthick-1-w { background-position: -96px -48px; } +.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } +.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } +.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } +.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } +.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } +.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } +.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } +.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } +.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } +.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } +.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } +.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } +.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } +.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } +.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } +.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } +.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } +.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } +.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } +.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } +.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } +.ui-icon-arrow-4 { background-position: 0 -80px; } +.ui-icon-arrow-4-diag { background-position: -16px -80px; } +.ui-icon-extlink { background-position: -32px -80px; } +.ui-icon-newwin { background-position: -48px -80px; } +.ui-icon-refresh { background-position: -64px -80px; } +.ui-icon-shuffle { background-position: -80px -80px; } +.ui-icon-transfer-e-w { background-position: -96px -80px; } +.ui-icon-transferthick-e-w { background-position: -112px -80px; } +.ui-icon-folder-collapsed { background-position: 0 -96px; } +.ui-icon-folder-open { background-position: -16px -96px; } +.ui-icon-document { background-position: -32px -96px; } +.ui-icon-document-b { background-position: -48px -96px; } +.ui-icon-note { background-position: -64px -96px; } +.ui-icon-mail-closed { background-position: -80px -96px; } +.ui-icon-mail-open { background-position: -96px -96px; } +.ui-icon-suitcase { background-position: -112px -96px; } +.ui-icon-comment { background-position: -128px -96px; } +.ui-icon-person { background-position: -144px -96px; } +.ui-icon-print { background-position: -160px -96px; } +.ui-icon-trash { background-position: -176px -96px; } +.ui-icon-locked { background-position: -192px -96px; } +.ui-icon-unlocked { background-position: -208px -96px; } +.ui-icon-bookmark { background-position: -224px -96px; } +.ui-icon-tag { background-position: -240px -96px; } +.ui-icon-home { background-position: 0 -112px; } +.ui-icon-flag { background-position: -16px -112px; } +.ui-icon-calendar { background-position: -32px -112px; } +.ui-icon-cart { background-position: -48px -112px; } +.ui-icon-pencil { background-position: -64px -112px; } +.ui-icon-clock { background-position: -80px -112px; } +.ui-icon-disk { background-position: -96px -112px; } +.ui-icon-calculator { background-position: -112px -112px; } +.ui-icon-zoomin { background-position: -128px -112px; } +.ui-icon-zoomout { background-position: -144px -112px; } +.ui-icon-search { background-position: -160px -112px; } +.ui-icon-wrench { background-position: -176px -112px; } +.ui-icon-gear { background-position: -192px -112px; } +.ui-icon-heart { background-position: -208px -112px; } +.ui-icon-star { background-position: -224px -112px; } +.ui-icon-link { background-position: -240px -112px; } +.ui-icon-cancel { background-position: 0 -128px; } +.ui-icon-plus { background-position: -16px -128px; } +.ui-icon-plusthick { background-position: -32px -128px; } +.ui-icon-minus { background-position: -48px -128px; } +.ui-icon-minusthick { background-position: -64px -128px; } +.ui-icon-close { background-position: -80px -128px; } +.ui-icon-closethick { background-position: -96px -128px; } +.ui-icon-key { background-position: -112px -128px; } +.ui-icon-lightbulb { background-position: -128px -128px; } +.ui-icon-scissors { background-position: -144px -128px; } +.ui-icon-clipboard { background-position: -160px -128px; } +.ui-icon-copy { background-position: -176px -128px; } +.ui-icon-contact { background-position: -192px -128px; } +.ui-icon-image { background-position: -208px -128px; } +.ui-icon-video { background-position: -224px -128px; } +.ui-icon-script { background-position: -240px -128px; } +.ui-icon-alert { background-position: 0 -144px; } +.ui-icon-info { background-position: -16px -144px; } +.ui-icon-notice { background-position: -32px -144px; } +.ui-icon-help { background-position: -48px -144px; } +.ui-icon-check { background-position: -64px -144px; } +.ui-icon-bullet { background-position: -80px -144px; } +.ui-icon-radio-off { background-position: -96px -144px; } +.ui-icon-radio-on { background-position: -112px -144px; } +.ui-icon-pin-w { background-position: -128px -144px; } +.ui-icon-pin-s { background-position: -144px -144px; } +.ui-icon-play { background-position: 0 -160px; } +.ui-icon-pause { background-position: -16px -160px; } +.ui-icon-seek-next { background-position: -32px -160px; } +.ui-icon-seek-prev { background-position: -48px -160px; } +.ui-icon-seek-end { background-position: -64px -160px; } +.ui-icon-seek-first { background-position: -80px -160px; } +.ui-icon-stop { background-position: -96px -160px; } +.ui-icon-eject { background-position: -112px -160px; } +.ui-icon-volume-off { background-position: -128px -160px; } +.ui-icon-volume-on { background-position: -144px -160px; } +.ui-icon-power { background-position: 0 -176px; } +.ui-icon-signal-diag { background-position: -16px -176px; } +.ui-icon-signal { background-position: -32px -176px; } +.ui-icon-battery-0 { background-position: -48px -176px; } +.ui-icon-battery-1 { background-position: -64px -176px; } +.ui-icon-battery-2 { background-position: -80px -176px; } +.ui-icon-battery-3 { background-position: -96px -176px; } +.ui-icon-circle-plus { background-position: 0 -192px; } +.ui-icon-circle-minus { background-position: -16px -192px; } +.ui-icon-circle-close { background-position: -32px -192px; } +.ui-icon-circle-triangle-e { background-position: -48px -192px; } +.ui-icon-circle-triangle-s { background-position: -64px -192px; } +.ui-icon-circle-triangle-w { background-position: -80px -192px; } +.ui-icon-circle-triangle-n { background-position: -96px -192px; } +.ui-icon-circle-arrow-e { background-position: -112px -192px; } +.ui-icon-circle-arrow-s { background-position: -128px -192px; } +.ui-icon-circle-arrow-w { background-position: -144px -192px; } +.ui-icon-circle-arrow-n { background-position: -160px -192px; } +.ui-icon-circle-zoomin { background-position: -176px -192px; } +.ui-icon-circle-zoomout { background-position: -192px -192px; } +.ui-icon-circle-check { background-position: -208px -192px; } +.ui-icon-circlesmall-plus { background-position: 0 -208px; } +.ui-icon-circlesmall-minus { background-position: -16px -208px; } +.ui-icon-circlesmall-close { background-position: -32px -208px; } +.ui-icon-squaresmall-plus { background-position: -48px -208px; } +.ui-icon-squaresmall-minus { background-position: -64px -208px; } +.ui-icon-squaresmall-close { background-position: -80px -208px; } +.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } +.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } +.ui-icon-grip-solid-vertical { background-position: -32px -224px; } +.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } +.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } +.ui-icon-grip-diagonal-se { background-position: -80px -224px; } + + +/* Misc visuals +----------------------------------*/ + +/* Corner radius */ +.ui-corner-tl { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; border-top-left-radius: 5px; } +.ui-corner-tr { -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; border-top-right-radius: 5px; } +.ui-corner-bl { -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; border-bottom-left-radius: 5px; } +.ui-corner-br { -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; border-bottom-right-radius: 5px; } +.ui-corner-top { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; border-top-left-radius: 5px; -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; border-top-right-radius: 5px; } +.ui-corner-bottom { -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; border-bottom-left-radius: 5px; -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; border-bottom-right-radius: 5px; } +.ui-corner-right { -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; border-top-right-radius: 5px; -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; border-bottom-right-radius: 5px; } +.ui-corner-left { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; border-top-left-radius: 5px; -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; border-bottom-left-radius: 5px; } +.ui-corner-all { -moz-border-radius: 5px; -webkit-border-radius: 5px; border-radius: 5px; } + +/* Overlays */ +.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); } +.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; } diff --git a/3.0/themes/smk/images/avatar.jpg b/3.0/themes/smk/images/avatar.jpg new file mode 100644 index 00000000..acad9314 Binary files /dev/null and b/3.0/themes/smk/images/avatar.jpg differ diff --git a/3.0/themes/smk/images/ico-album.png b/3.0/themes/smk/images/ico-album.png new file mode 100644 index 00000000..affa1b84 Binary files /dev/null and b/3.0/themes/smk/images/ico-album.png differ diff --git a/3.0/themes/smk/images/ico-denied-inactive.png b/3.0/themes/smk/images/ico-denied-inactive.png new file mode 100644 index 00000000..56db3ff5 Binary files /dev/null and b/3.0/themes/smk/images/ico-denied-inactive.png differ diff --git a/3.0/themes/smk/images/ico-denied-passive.png b/3.0/themes/smk/images/ico-denied-passive.png new file mode 100644 index 00000000..1e992230 Binary files /dev/null and b/3.0/themes/smk/images/ico-denied-passive.png differ diff --git a/3.0/themes/smk/images/ico-denied.png b/3.0/themes/smk/images/ico-denied.png new file mode 100644 index 00000000..08f24936 Binary files /dev/null and b/3.0/themes/smk/images/ico-denied.png differ diff --git a/3.0/themes/smk/images/ico-error.png b/3.0/themes/smk/images/ico-error.png new file mode 100644 index 00000000..c37bd062 Binary files /dev/null and b/3.0/themes/smk/images/ico-error.png differ diff --git a/3.0/themes/smk/images/ico-help.png b/3.0/themes/smk/images/ico-help.png new file mode 100644 index 00000000..5c870176 Binary files /dev/null and b/3.0/themes/smk/images/ico-help.png differ diff --git a/3.0/themes/smk/images/ico-info.png b/3.0/themes/smk/images/ico-info.png new file mode 100644 index 00000000..12cd1aef Binary files /dev/null and b/3.0/themes/smk/images/ico-info.png differ diff --git a/3.0/themes/smk/images/ico-lock.png b/3.0/themes/smk/images/ico-lock.png new file mode 100644 index 00000000..2ebc4f6f Binary files /dev/null and b/3.0/themes/smk/images/ico-lock.png differ diff --git a/3.0/themes/smk/images/ico-print.png b/3.0/themes/smk/images/ico-print.png new file mode 100644 index 00000000..b82a8e1e Binary files /dev/null and b/3.0/themes/smk/images/ico-print.png differ diff --git a/3.0/themes/smk/images/ico-separator-rtl.gif b/3.0/themes/smk/images/ico-separator-rtl.gif new file mode 100644 index 00000000..d9061a46 Binary files /dev/null and b/3.0/themes/smk/images/ico-separator-rtl.gif differ diff --git a/3.0/themes/smk/images/ico-separator.gif b/3.0/themes/smk/images/ico-separator.gif new file mode 100644 index 00000000..3de2d0d3 Binary files /dev/null and b/3.0/themes/smk/images/ico-separator.gif differ diff --git a/3.0/themes/smk/images/ico-success-inactive.png b/3.0/themes/smk/images/ico-success-inactive.png new file mode 100644 index 00000000..74b2032f Binary files /dev/null and b/3.0/themes/smk/images/ico-success-inactive.png differ diff --git a/3.0/themes/smk/images/ico-success-passive.png b/3.0/themes/smk/images/ico-success-passive.png new file mode 100644 index 00000000..dc8d1ded Binary files /dev/null and b/3.0/themes/smk/images/ico-success-passive.png differ diff --git a/3.0/themes/smk/images/ico-success.png b/3.0/themes/smk/images/ico-success.png new file mode 100644 index 00000000..a9925a06 Binary files /dev/null and b/3.0/themes/smk/images/ico-success.png differ diff --git a/3.0/themes/smk/images/ico-view-comments.png b/3.0/themes/smk/images/ico-view-comments.png new file mode 100644 index 00000000..e5d3630f Binary files /dev/null and b/3.0/themes/smk/images/ico-view-comments.png differ diff --git a/3.0/themes/smk/images/ico-view-fullsize.png b/3.0/themes/smk/images/ico-view-fullsize.png new file mode 100644 index 00000000..0be23e9b Binary files /dev/null and b/3.0/themes/smk/images/ico-view-fullsize.png differ diff --git a/3.0/themes/smk/images/ico-view-slideshow-rtl.png b/3.0/themes/smk/images/ico-view-slideshow-rtl.png new file mode 100644 index 00000000..5788b3c3 Binary files /dev/null and b/3.0/themes/smk/images/ico-view-slideshow-rtl.png differ diff --git a/3.0/themes/smk/images/ico-view-slideshow.png b/3.0/themes/smk/images/ico-view-slideshow.png new file mode 100644 index 00000000..82f61f63 Binary files /dev/null and b/3.0/themes/smk/images/ico-view-slideshow.png differ diff --git a/3.0/themes/smk/images/ico-warning.png b/3.0/themes/smk/images/ico-warning.png new file mode 100644 index 00000000..628cf2da Binary files /dev/null and b/3.0/themes/smk/images/ico-warning.png differ diff --git a/3.0/themes/smk/images/loading-large.gif b/3.0/themes/smk/images/loading-large.gif new file mode 100644 index 00000000..cc70a7a8 Binary files /dev/null and b/3.0/themes/smk/images/loading-large.gif differ diff --git a/3.0/themes/smk/images/loading-small.gif b/3.0/themes/smk/images/loading-small.gif new file mode 100644 index 00000000..d0bce154 Binary files /dev/null and b/3.0/themes/smk/images/loading-small.gif differ diff --git a/3.0/themes/smk/images/select-photos-backg.png b/3.0/themes/smk/images/select-photos-backg.png new file mode 100644 index 00000000..81c2d616 Binary files /dev/null and b/3.0/themes/smk/images/select-photos-backg.png differ diff --git a/3.0/themes/smk/js/ui.init.js b/3.0/themes/smk/js/ui.init.js new file mode 100644 index 00000000..2c67bf3a --- /dev/null +++ b/3.0/themes/smk/js/ui.init.js @@ -0,0 +1,131 @@ +/** + * Initialize jQuery UI and Gallery Plugins + */ + +$(document).ready(function() { + + // Initialize Superfish menus (hidden, then shown to address IE issue) + $("#g-site-menu .g-menu").hide().addClass("sf-menu"); + $("#g-site-menu .g-menu").superfish({ + delay: 500, + animation: { + opacity:'show', + height:'show' + }, + pathClass: "g-selected", + speed: 'fast' + }).show(); + + // Initialize status message effects + $("#g-action-status li").gallery_show_message(); + + // Initialize dialogs + $(".g-dialog-link").gallery_dialog(); + + // Initialize short forms + $(".g-short-form").gallery_short_form(); + + // Apply jQuery UI icon, hover, and rounded corner styles + $("input[type=submit]:not(.g-short-form input)").addClass("ui-state-default ui-corner-all"); + if ($("#g-view-menu").length) { + $("#g-view-menu ul").removeClass("g-menu").removeClass("sf-menu"); + $("#g-view-menu a").addClass("ui-icon"); + } + + // Apply jQuery UI icon and hover styles to context menus + if ($(".g-context-menu").length) { + $(".g-context-menu li").addClass("ui-state-default"); + $(".g-context-menu a").addClass("g-button ui-icon-left"); + $(".g-context-menu a").prepend(""); + $(".g-context-menu a span").each(function() { + var iconClass = $(this).parent().attr("class").match(/ui-icon-.[^\s]+/).toString(); + $(this).addClass(iconClass); + }); + } + + // Remove titles for menu options since we're displaying that text anyway + $(".sf-menu a, .sf-menu li").removeAttr("title"); + + // Album and search results views + if ($("#g-album-grid").length) { + // Set equal height for album items and vertically align thumbnails/metadata + $('.g-item').equal_heights().gallery_valign(); + + // Initialize thumbnail hover effect + $(".g-item").hover( + function() { + // Insert a placeholder to hold the item's position in the grid + var placeHolder = $(this).clone().attr("id", "g-place-holder"); + $(this).after($(placeHolder)); + // Style and position the hover item + var position = $(this).position(); + $(this).css("top", position.top).css("left", position.left); + $(this).addClass("g-hover-item"); + // Initialize the contextual menu + $(this).gallery_context_menu(); + // Set the hover item's height + $(this).height("auto"); + var context_menu = $(this).find(".g-context-menu"); + var adj_height = $(this).height() + context_menu.height(); + if ($(this).next().height() > $(this).height()) { + $(this).height($(this).next().height()); + } else if ($(this).prev().height() > $(this).height()) { + $(this).height($(this).prev().height()); + } else { + $(this).height(adj_height); + } + }, + function() { + // Reset item height and position + if ($(this).next().height()) { + var sib_height = $(this).next().height(); + } else { + var sib_height = $(this).prev().height(); + } + if ($.browser.msie && $.browser.version >= 8) { + sib_height = sib_height + 1; + } + $(this).css("height", sib_height); + $(this).css("position", "relative"); + $(this).css("top", 0).css("left", 0); + // Remove the placeholder and hover class from the item + $(this).removeClass("g-hover-item"); + $(this).gallery_valign(); + $("#g-place-holder").remove(); + } + ); + + // Realign any thumbnails that change so that when we rotate a thumb it stays centered. + $(".g-item").bind("gallery.change", function() { + $(".g-item").each(function() { + $(this).height($(this).find("img").height() + 2); + }); + $(".g-item").equal_heights().gallery_valign(); + }); + } + + // Photo/Item item view + if ($("#g-photo,#g-movie").length) { + // Ensure the resized image fits within its container + $("#g-photo,#g-movie").gallery_fit_photo(); + + // Initialize context menus + $("#g-photo,#g-movie").hover(function(){ + $(this).gallery_context_menu(); + }); + + // Add scroll effect for links to named anchors + $.localScroll({ + queue: true, + duration: 1000, + hash: true + }); + + $(this).find(".g-dialog-link").gallery_dialog(); + $(this).find(".g-ajax-link").gallery_ajax(); + } + + // Initialize button hover effect + $.fn.gallery_hover_init(); + +}); diff --git a/3.0/themes/smk/theme.info b/3.0/themes/smk/theme.info new file mode 100644 index 00000000..06a45f5c --- /dev/null +++ b/3.0/themes/smk/theme.info @@ -0,0 +1,6 @@ +name = "Gallery SMK Theme" +description = "A crisp and distinctive theme that uses large fonts and icons for easy navigation and an enjoyable browsing experience mod with carbon elements." +version = 1 +author = "Thomas E. Horner" +site = 1 +admin = 0 diff --git a/3.0/themes/smk/thumbnail.png b/3.0/themes/smk/thumbnail.png new file mode 100755 index 00000000..c8d45ec9 Binary files /dev/null and b/3.0/themes/smk/thumbnail.png differ diff --git a/3.0/themes/smk/views/album.html.php b/3.0/themes/smk/views/album.html.php new file mode 100644 index 00000000..1a56af67 --- /dev/null +++ b/3.0/themes/smk/views/album.html.php @@ -0,0 +1,44 @@ + + +
+ album_top() ?> +

title) ?>

+
description)) ?>
+
+ + +album_bottom() ?> + +paginator() ?> diff --git a/3.0/themes/smk/views/block.html.php b/3.0/themes/smk/views/block.html.php new file mode 100644 index 00000000..699d7c22 --- /dev/null +++ b/3.0/themes/smk/views/block.html.php @@ -0,0 +1,10 @@ + + + + +
+

+
+ +
+
diff --git a/3.0/themes/smk/views/dynamic.html.php b/3.0/themes/smk/views/dynamic.html.php new file mode 100644 index 00000000..a8a4d362 --- /dev/null +++ b/3.0/themes/smk/views/dynamic.html.php @@ -0,0 +1,29 @@ + +
+
+ dynamic_top() ?> +
+

+
+ + +dynamic_bottom() ?> + +paginator() ?> diff --git a/3.0/themes/smk/views/movie.html.php b/3.0/themes/smk/views/movie.html.php new file mode 100644 index 00000000..158857db --- /dev/null +++ b/3.0/themes/smk/views/movie.html.php @@ -0,0 +1,19 @@ + +
+ photo_top() ?> + + paginator() ?> + +
+ resize_top($item) ?> + movie_img(array("class" => "g-movie", "id" => "g-item-id-{$item->id}")) ?> + resize_bottom($item) ?> +
+ +
+

title) ?>

+
description)) ?>
+
+ + photo_bottom() ?> +
diff --git a/3.0/themes/smk/views/no_sidebar.html.php b/3.0/themes/smk/views/no_sidebar.html.php new file mode 100644 index 00000000..58c57256 --- /dev/null +++ b/3.0/themes/smk/views/no_sidebar.html.php @@ -0,0 +1,11 @@ + + diff --git a/3.0/themes/smk/views/page.html.php b/3.0/themes/smk/views/page.html.php new file mode 100644 index 00000000..0e5bdf6b --- /dev/null +++ b/3.0/themes/smk/views/page.html.php @@ -0,0 +1,161 @@ + + +html_attributes() ?> xml:lang="en" lang="en"> + + + start_combining("script,css") ?> + + <? if ($page_title): ?> + <?= $page_title ?> + <? else: ?> + <? if ($theme->item()): ?> + <?= $theme->item()->title ?> + <? elseif ($theme->tag()): ?> + <?= t("Photos tagged with %tag_title", array("tag_title" => $theme->tag()->name)) ?> + <? else: /* Not an item, not a tag, no page_title specified. Help! */ ?> + <?= item::root()->title ?> + <? endif ?> + <? endif ?> + + " + type="image/x-icon" /> + + page_type == "collection"): ?> + + + + + + + + script("json2-min.js") ?> + script("jquery.js") ?> + script("jquery.form.js") ?> + script("jquery-ui.js") ?> + script("gallery.common.js") ?> + + + script("gallery.ajax.js") ?> + script("gallery.dialog.js") ?> + script("superfish/js/superfish.js") ?> + script("jquery.localscroll.js") ?> + + + page_subtype == "photo"): ?> + script("jquery.scrollTo.js") ?> + script("gallery.show_full_size.js") ?> + page_subtype == "movie"): ?> + script("flowplayer.js") ?> + + + head() ?> + + + script("ui.init.js") ?> + css("yui/reset-fonts-grids.css") ?> + css("superfish/css/superfish.css") ?> + css("themeroller/ui.base.css") ?> + css("screen.css") ?> + + + + get_combined("script") ?> + + + get_combined("css") ?> + + + body_attributes() ?>> + page_top() ?> +
+ site_status() ?> +
+
+ + + + + + user_menu() ?> + header_top() ?> + + + + + + header_bottom() ?> +
+ + item() && !empty($parents)): ?> + + +
+
+
+
+
+ messages() ?> + +
+
+
+
+ page_subtype != "login"): ?> + + +
+
+ +
+ page_bottom() ?> + + diff --git a/3.0/themes/smk/views/paginator.html.php b/3.0/themes/smk/views/paginator.html.php new file mode 100644 index 00000000..5034c965 --- /dev/null +++ b/3.0/themes/smk/views/paginator.html.php @@ -0,0 +1,87 @@ + + + + diff --git a/3.0/themes/smk/views/photo.html.php b/3.0/themes/smk/views/photo.html.php new file mode 100644 index 00000000..b42ab987 --- /dev/null +++ b/3.0/themes/smk/views/photo.html.php @@ -0,0 +1,51 @@ + + +item())): ?> + + + + +
+ photo_top() ?> + + paginator() ?> + +
+ resize_top($item) ?> + + for_html_attr() ?>"> + + resize_img(array("id" => "g-item-id-{$item->id}", "class" => "g-resize")) ?> + + + + resize_bottom($item) ?> +
+ +
+

title) ?>

+
description)) ?>
+
+ + photo_bottom() ?> +
diff --git a/3.0/themes/smk/views/sidebar.html.php b/3.0/themes/smk/views/sidebar.html.php new file mode 100644 index 00000000..086d1359 --- /dev/null +++ b/3.0/themes/smk/views/sidebar.html.php @@ -0,0 +1,16 @@ + +sidebar_top() ?> +
+ + album_menu() ?> + + photo_menu() ?> + + movie_menu() ?> + + tag_menu() ?> + +
+ +sidebar_blocks() ?> +sidebar_bottom() ?>