2012-07-19 11:25:49 -04:00
/ * HexChat Theme Manager
2012-06-16 23:45:08 -04:00
*
* Copyright ( C ) 2012 Patrick Griffs
* Copyright ( C ) 2012 Berke Viktor
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
2012-12-23 14:36:54 -05:00
* Foundation , Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 , USA
2012-06-16 23:45:08 -04:00
* /
using System ;
using System.Collections.Generic ;
using System.Collections ;
using System.ComponentModel ;
using System.Data ;
using System.Drawing ;
using System.IO ;
/* using System.IO.Compression; */
using System.IO.Packaging ;
using System.Linq ;
using System.Text ;
using System.Windows.Forms ;
using System.Net ;
namespace thememan
{
2012-07-13 09:01:54 -04:00
public partial class HTM : Form
2012-06-16 23:45:08 -04:00
{
2012-10-04 08:51:00 -04:00
public string hexchatdir ;
public string themedir ;
2012-06-16 23:45:08 -04:00
OpenFileDialog importDialog ;
2012-07-13 09:01:54 -04:00
public HTM ( )
2012-10-04 08:51:00 -04:00
{
InitializeComponent ( ) ;
if ( RunningOnWindows ( ) & & File . Exists ( "portable-mode" ) )
{
hexchatdir = ( "config\\" ) ;
if ( ! Directory . Exists ( hexchatdir ) )
{
MessageBox . Show ( "HexChat installation not found!\nCheck your .\\config folder" , "Error" , MessageBoxButtons . OK , MessageBoxIcon . Error ) ;
Environment . Exit ( 1 ) ;
}
}
else
{
2012-10-04 08:53:55 -04:00
/ * Environment . SpecialFolder . ApplicationData
* Windows : % APPDATA %
* Unix : ~ / . config
* Windows is case - insensitive so ' hexchat ' should be fine for both
* /
2012-10-04 08:51:00 -04:00
hexchatdir = Path . Combine ( Environment . GetFolderPath ( Environment . SpecialFolder . ApplicationData ) , "hexchat" ) ;
2012-06-16 23:45:08 -04:00
2012-10-04 08:51:00 -04:00
if ( ! Directory . Exists ( hexchatdir ) )
{
if ( RunningOnWindows ( ) )
{
MessageBox . Show ( "HexChat installation not found!\nCheck your %APPDATA%\\HexChat folder" , "Error" , MessageBoxButtons . OK , MessageBoxIcon . Error ) ;
}
else
{
MessageBox . Show ( "HexChat installation not found!\nCheck your ~/.config/hexchat folder" , "Error" , MessageBoxButtons . OK , MessageBoxIcon . Error ) ;
}
Environment . Exit ( 1 ) ;
}
}
themedir = Path . Combine ( hexchatdir , "themes" ) ;
2012-06-16 23:45:08 -04:00
ListThemes ( ) ;
2012-06-17 04:08:39 -04:00
String [ ] arguments = Environment . GetCommandLineArgs ( ) ;
if ( arguments . Length > 1 )
{
FileInfo fi = new FileInfo ( arguments [ 1 ] ) ;
attemptImport ( fi ) ;
}
2012-06-16 23:45:08 -04:00
}
2012-10-04 08:51:00 -04:00
private bool RunningOnWindows ( )
{
if ( Environment . OSVersion . ToString ( ) . ToLower ( ) . Contains ( "windows" ) )
{
return true ;
}
else
{
return false ;
}
}
2012-06-16 23:45:08 -04:00
private void ListThemes ( )
{
themelist . Items . Clear ( ) ;
2012-10-04 08:51:00 -04:00
if ( Directory . Exists ( themedir ) )
2012-06-16 23:45:08 -04:00
{
2012-10-04 08:51:00 -04:00
foreach ( string theme in Directory . GetDirectories ( themedir ) )
2012-06-16 23:45:08 -04:00
{
2012-10-04 08:51:00 -04:00
themelist . Items . Add ( theme . Remove ( 0 , themedir . Length + 1 ) ) ;
2012-06-16 23:45:08 -04:00
}
}
else
{
2012-10-04 08:51:00 -04:00
Directory . CreateDirectory ( themedir ) ;
2012-06-16 23:45:08 -04:00
}
if ( themelist . Items . Count = = 0 )
{
applybutton . Enabled = false ;
2012-06-17 04:08:39 -04:00
deleteButton . Enabled = false ;
2012-06-16 23:45:08 -04:00
}
else
{
themelist . SetSelected ( 0 , true ) ;
}
}
private void ShowColors ( List < List < string > > themecolors )
{
List < Control > labels = this . Controls . OfType < Label > ( ) . Cast < Control > ( ) . OrderBy ( label = > label . Name ) . ToList ( ) ;
for ( byte themecolor = 0 ; themecolor < themecolors . Count ; themecolor + + )
{
byte rval = Convert . ToByte ( int . Parse ( themecolors [ themecolor ] [ 0 ] . ToString ( ) , System . Globalization . NumberStyles . HexNumber ) / 257 ) ;
byte gval = Convert . ToByte ( int . Parse ( themecolors [ themecolor ] [ 1 ] . ToString ( ) , System . Globalization . NumberStyles . HexNumber ) / 257 ) ;
byte bval = Convert . ToByte ( int . Parse ( themecolors [ themecolor ] [ 2 ] . ToString ( ) , System . Globalization . NumberStyles . HexNumber ) / 257 ) ;
if ( themecolor < = 15 )
labels [ themecolor ] . BackColor = Color . FromArgb ( rval , gval , bval ) ;
else if ( themecolor = = 16 )
themecolorfgmarked . ForeColor = Color . FromArgb ( rval , gval , bval ) ;
else if ( themecolor = = 17 )
themecolorfgmarked . BackColor = Color . FromArgb ( rval , gval , bval ) ;
else if ( themecolor = = 18 )
themecolorfg . ForeColor = Color . FromArgb ( rval , gval , bval ) ;
else if ( themecolor = = 19 )
{
themecolortextbg . BackColor = Color . FromArgb ( rval , gval , bval ) ;
themecolorfg . BackColor = themecolortextbg . BackColor ;
}
}
}
private List < List < string > > ReadTheme ( string theme )
{
List < List < string > > themecolors = new List < List < string > > ( ) ;
2012-10-04 08:51:00 -04:00
foreach ( string line in File . ReadLines ( Path . Combine ( themedir , theme , "colors.conf" ) ) )
2012-06-16 23:45:08 -04:00
{
List < string > colors = new List < string > ( ) ;
List < string > colorlist = new List < string > ( ) ;
string [ ] possiblecolors = { "color_256" , "color_257" , "color_258" , "color_259" } ;
for ( byte num = 16 ; num < = 31 ; num + + )
colorlist . Add ( "color_" + num ) ;
colorlist . AddRange ( possiblecolors ) ;
string [ ] config = line . Split ( new char [ ] { ' ' } ) ;
if ( colorlist . Contains ( config [ 0 ] ) = = true )
{
colors . Add ( config [ 2 ] ) ;
colors . Add ( config [ 3 ] ) ;
colors . Add ( config [ 4 ] ) ;
themecolors . Add ( colors ) ;
}
}
return themecolors ;
}
private void applybutton_Click_1 ( object sender , EventArgs e )
{
2012-07-13 10:38:39 -04:00
DialogResult result = MessageBox . Show ( "HexChat must be closed and this will overwrite your current theme!\n\nDo you wish to continue?" , "Warning" , MessageBoxButtons . OKCancel , MessageBoxIcon . Warning ) ;
2012-06-16 23:45:08 -04:00
if ( result = = DialogResult . OK )
{
2012-10-04 08:51:00 -04:00
File . Copy ( Path . Combine ( themedir , themelist . SelectedItem . ToString ( ) , "colors.conf" ) , Path . Combine ( hexchatdir , "colors.conf" ) , true ) ;
if ( File . Exists ( Path . Combine ( themedir , themelist . SelectedItem . ToString ( ) , "pevents.conf" ) ) )
2012-06-16 23:45:08 -04:00
{
2012-10-04 08:51:00 -04:00
File . Copy ( Path . Combine ( themedir , themelist . SelectedItem . ToString ( ) , "pevents.conf" ) , Path . Combine ( hexchatdir , "pevents.conf" ) , true ) ;
2012-06-16 23:45:08 -04:00
}
}
}
private void theme_selected ( object sender , EventArgs e )
{
if ( themelist . SelectedItem ! = null )
{
ShowColors ( ReadTheme ( themelist . SelectedItem . ToString ( ) ) ) ;
applybutton . Enabled = true ;
2012-06-17 04:08:39 -04:00
deleteButton . Enabled = true ;
2012-06-16 23:45:08 -04:00
}
}
private void importbutton_Click_1 ( object sender , EventArgs e )
{
importDialog = new OpenFileDialog ( ) ;
2012-07-13 10:38:39 -04:00
importDialog . Filter = "HexChat Theme Files|*.hct" ;
2012-06-16 23:45:08 -04:00
importDialog . FilterIndex = 1 ;
importDialog . FileOk + = new CancelEventHandler ( importdialog_FileOk ) ;
importDialog . ShowDialog ( ) ;
}
private void importdialog_FileOk ( object sender , System . ComponentModel . CancelEventArgs e )
{
FileInfo fi = new FileInfo ( importDialog . FileName ) ;
2012-06-17 04:08:39 -04:00
attemptImport ( fi ) ;
}
private void attemptImport ( FileInfo fi )
{
2012-06-17 00:41:29 -04:00
string themeName = fi . Name . Remove ( fi . Name . Length - fi . Extension . Length ) ;
int result = extractTheme ( fi ) ;
2012-06-16 23:45:08 -04:00
ListThemes ( ) ;
2012-06-17 00:41:29 -04:00
/* although a check is added to ListThemes(), this would still fail if the theme file was invalid or the theme is already installed */
switch ( result )
{
case 0 :
themelist . SetSelected ( themelist . FindStringExact ( themeName ) , true ) ;
2012-06-17 04:08:39 -04:00
/* required for command line invoking */
ShowColors ( ReadTheme ( themeName ) ) ;
2012-06-17 00:41:29 -04:00
break ;
case 1 :
2012-06-17 04:08:39 -04:00
MessageBox . Show ( "This theme is already installed!" , "Warning" , MessageBoxButtons . OK , MessageBoxIcon . Warning ) ;
themelist . SetSelected ( themelist . FindStringExact ( themeName ) , true ) ;
/* required for command line invoking */
ShowColors ( ReadTheme ( themeName ) ) ;
2012-06-17 00:41:29 -04:00
break ;
case 2 :
MessageBox . Show ( "Invalid theme file!" , "Error" , MessageBoxButtons . OK , MessageBoxIcon . Error ) ;
break ;
}
2012-06-16 23:45:08 -04:00
}
/ * gzip solution , not good enough coz we need multiple files
*
public string extractTheme ( FileInfo fi )
{
using ( FileStream inFile = fi . OpenRead ( ) )
{
string themeName = fi . Name . Remove ( fi . Name . Length - fi . Extension . Length ) ;
string destFolder = xchatdir + themedir + themeName ;
if ( ! Directory . Exists ( destFolder ) )
{
Directory . CreateDirectory ( destFolder ) ;
}
using ( FileStream outFile = File . Create ( destFolder + "\\colors.conf" ) )
{
using ( GZipStream Decompress = new GZipStream ( inFile , CompressionMode . Decompress ) )
{
Decompress . CopyTo ( outFile ) ;
}
}
return themeName ;
}
}
* /
/ * using System.IO.Package :
* http : //weblogs.asp.net/jgalloway/archive/2007/10/25/creating-zip-archives-in-net-without-an-external-library-like-sharpziplib.aspx
* [ Content_Types ] . xml must be present for every zip file
* /
private const long BUFFER_SIZE = 4096 ;
2012-06-17 00:41:29 -04:00
private int extractTheme ( FileInfo zipFile )
2012-06-16 23:45:08 -04:00
{
string themeName = zipFile . Name . Remove ( zipFile . Name . Length - zipFile . Extension . Length ) ;
2012-10-04 08:51:00 -04:00
string destFolder = Path . Combine ( themedir , themeName ) ;
2012-06-16 23:45:08 -04:00
2012-06-17 04:08:39 -04:00
try
2012-06-16 23:45:08 -04:00
{
2013-03-03 18:38:29 -05:00
using ( Package zip = Package . Open ( zipFile . FullName , FileMode . Open , FileAccess . Read ) )
2012-06-16 23:45:08 -04:00
{
2012-06-17 04:08:39 -04:00
PackagePartCollection parts = zip . GetParts ( ) ;
2012-06-16 23:45:08 -04:00
2012-06-17 04:08:39 -04:00
if ( Directory . Exists ( destFolder ) )
{
return 1 ;
}
else
{
Directory . CreateDirectory ( destFolder ) ;
}
2012-06-16 23:45:08 -04:00
2012-06-17 04:08:39 -04:00
foreach ( PackagePart part in parts )
2012-06-16 23:45:08 -04:00
{
2012-06-17 04:08:39 -04:00
/* not sure what's this good for */
/* String archive = part.Uri.ToString().Replace(@"/", @"\"); */
String destFile = destFolder + part . Uri . ToString ( ) ;
using ( FileStream outFileStream = new FileStream ( destFile , FileMode . CreateNew , FileAccess . ReadWrite ) )
2012-06-16 23:45:08 -04:00
{
2012-06-17 04:08:39 -04:00
using ( Stream inStream = part . GetStream ( ) )
{
long bufferSize = inStream . Length < BUFFER_SIZE ? inStream . Length : BUFFER_SIZE ;
byte [ ] buffer = new byte [ bufferSize ] ;
int bytesRead = 0 ;
long bytesWritten = 0 ;
while ( ( bytesRead = inStream . Read ( buffer , 0 , buffer . Length ) ) ! = 0 )
{
outFileStream . Write ( buffer , 0 , bytesRead ) ;
bytesWritten + = bufferSize ;
}
}
2012-06-16 23:45:08 -04:00
}
2012-06-17 04:08:39 -04:00
2012-06-16 23:45:08 -04:00
}
}
}
2012-06-17 04:08:39 -04:00
catch ( System . IO . FileFormatException )
{
return 2 ;
}
2012-06-16 23:45:08 -04:00
if ( IsDirectoryEmpty ( destFolder ) )
{
Directory . Delete ( destFolder ) ;
2012-06-17 00:41:29 -04:00
return 2 ;
2012-06-16 23:45:08 -04:00
}
else
{
2012-06-17 00:41:29 -04:00
return 0 ;
2012-06-16 23:45:08 -04:00
}
}
public bool IsDirectoryEmpty ( string path )
{
return ! Directory . EnumerateFileSystemEntries ( path ) . Any ( ) ;
}
2012-06-17 04:08:39 -04:00
private void deleteButton_Click ( object sender , EventArgs e )
{
DialogResult result = MessageBox . Show ( "Are you sure you want to delete this theme from the theme repo?\n\nYour currently applied theme won't be affected." , "Warning" , MessageBoxButtons . OKCancel , MessageBoxIcon . Warning ) ;
if ( result = = DialogResult . OK )
{
2012-10-04 08:51:00 -04:00
Directory . Delete ( Path . Combine ( themedir , themelist . SelectedItem . ToString ( ) ) , true ) ;
2012-06-17 04:08:39 -04:00
ListThemes ( ) ;
if ( themelist . Items . Count = = 0 )
{
deleteButton . Enabled = false ;
}
}
}
2012-06-16 23:45:08 -04:00
}
}