4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | using System;
20 | using System.Text;
21 | using System.Text.RegularExpressions;
22 | using System.Xml;
23 |
24 |
25 | namespace BalloonRss
26 | {
27 | public class RssItem
28 | {
29 | public String title = null;
30 | public String description = null;
31 | public String author = null;
32 | public String link = null;
33 | public DateTime pubDate = DateTime.MinValue;
34 |
35 | public DateTime creationDate = DateTime.MinValue;
36 | public DateTime dispDate = DateTime.MinValue;
37 | public RssChannel channel;
38 |
39 |
40 | protected RssItem()
41 | {
42 | pubDate = DateTime.MinValue;
43 | creationDate = DateTime.Now;
44 | channel = null;
45 | dispDate = DateTime.MinValue;
46 | }
47 |
48 | public RssItem(XmlNode xmlNode, RssChannel channel)
49 | {
50 | this.creationDate = DateTime.Now;
51 | this.channel = channel;
52 |
53 | // parse it
54 | foreach (XmlNode curXmlNode in xmlNode.ChildNodes)
55 | {
56 | String curTag = curXmlNode.Name.Trim().ToLower();
57 |
58 | switch (curTag)
59 | {
60 | // mandatory attributes
61 | case "title":
62 | this.title = StripHtml(curXmlNode.InnerText);
63 | break;
64 | case "link":
65 | if (channel.channelType != "feed")
66 | {
67 | this.link = curXmlNode.InnerText;
68 | }
69 | else
70 | {
71 | this.link = curXmlNode.Attributes.GetNamedItem("href").Value;
72 | }
73 | break;
74 | case "description": // for rss and rdf feeds
75 | case "summary": // for atom feeds
76 | this.description = StripHtml(curXmlNode.InnerText);
77 | break;
78 |
79 | // optional attributes
80 | case "author":
81 | this.author = curXmlNode.InnerText;
82 | break;
83 | case "pubdate": // for rss and rdf feeds
84 | case "updated": // for atom feeds
85 | this.pubDate = ParseDate(curXmlNode.InnerText);
86 | break;
87 |
88 | default:
89 | // skip all other tags
90 | break;
91 | }
92 | }
93 |
94 | // some feeds use empty fields which is not acceptable
95 | if (title == "")
96 | title = null;
97 | if (description == "")
98 | description = null;
99 |
100 | // the title and description fields are mandatory
101 | if ((title == null) && (description == null))
102 | throw new FormatException("Could not find title and description field in RSS item");
103 | }
104 |
105 |
106 | private String StripHtml(String text)
107 | {
108 | String escapedText = null;
109 |
110 | // strip all html tags like and translate special chars like &
111 | try
112 | {
113 | // let the XML classes do the format conversion
114 | XmlNode xmlNode = new XmlDocument().CreateElement("stripEntity");
115 | xmlNode.InnerXml = text;
116 | escapedText = xmlNode.InnerText;
117 | }
118 | catch (XmlException)
119 | {
120 | // the XML classes could not convert the text
121 | // it seems that the text was already escaped or is illegal (which happens!)
122 | // e.g. we get an exception for strings like "harry & sally"
123 |
124 | // should we still remove the tags like ? Yes.
125 |
126 | // first, remove special characters like &
127 | int lastMatchPosEnd = 0;
128 | escapedText = "";
129 | foreach (Match match in Regex.Matches(text, @"&[^;]{2,10};"))
130 | {
131 | // convert identified character
132 | // again, try to use the XML classes for this
133 | string replacement;
134 | try
135 | {
136 | XmlNode charXmlNode = new XmlDocument().CreateElement("charNode");
137 | charXmlNode.InnerXml = match.Value;
138 | replacement = charXmlNode.InnerText;
139 | }
140 | catch (Exception)
141 | {
142 | // fallback to "?" in case of wrong regex match
143 | replacement = "?";
144 | }
145 |
146 | // append to string
147 | escapedText += text.Substring(lastMatchPosEnd, match.Index - lastMatchPosEnd) + replacement;
148 | lastMatchPosEnd = match.Index + match.Length;
149 | }
150 | // append rest of string
151 | escapedText += text.Substring(lastMatchPosEnd);
152 |
153 | // replace and
with carrige returns
154 | escapedText = Regex.Replace(escapedText, @"<(p|br)\s?/?>", "\n");
155 |
156 | // remove the remaining tags
157 | escapedText = Regex.Replace(escapedText, @"<[^>]+>", "");
158 | }
159 | catch (Exception)
160 | {
161 | // we do not expect any other exceptions here
162 | // just take the unmodified text in this case
163 | escapedText = text;
164 | }
165 |
166 | return escapedText;
167 | }
168 |
169 |
170 | private DateTime ParseDate(String text)
171 | {
172 | DateTime dateTime = DateTime.MinValue;
173 |
174 | try
175 | {
176 | dateTime = DateTime.Parse(text);
177 | }
178 | catch (FormatException)
179 | {
180 | // we might get an parse exception in case of US non-standard time, like "Thu, 05 May 2005 14:50:52 EDT"
181 | // truncate until last blank then and retry
182 | text = text.Substring(0, text.LastIndexOf(" "));
183 | try
184 | {
185 | dateTime = DateTime.Parse(text);
186 | }
187 | catch (FormatException)
188 | {
189 | }
190 | }
191 |
192 | return dateTime;
193 | }
194 |
195 |
196 | public DateTime GetDate()
197 | {
198 | if (pubDate != DateTime.MinValue)
199 | return pubDate;
200 | else
201 | return creationDate;
202 | }
203 | }
204 | }
205 |
--------------------------------------------------------------------------------
/src/FormChannelInfo.cs:
--------------------------------------------------------------------------------
1 | /*
2 | BalloonRSS - Simple RSS news aggregator using balloon tooltips
3 | Copyright (C) 2010 Roman Morawek
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | using System;
20 | using System.Windows.Forms;
21 | using BalloonRss.Properties;
22 |
23 |
24 | namespace BalloonRss
25 | {
26 | class FormChannelInfo : Form
27 | {
28 | private const int panelWidth = 600;
29 | private const int panelHeight = 200;
30 |
31 | private RssChannel[] rssChannel;
32 | private ListView listView;
33 | private ListViewItem[] listItems;
34 | private ContextMenuStrip contextMenu;
35 |
36 |
37 | public FormChannelInfo(RssChannel[] rssChannel)
38 | {
39 | // store references to the channels
40 | this.rssChannel = rssChannel;
41 |
42 | // build GUI
43 | this.SuspendLayout();
44 | InitializeComponent();
45 | FillChannelList();
46 | this.ResumeLayout();
47 | }
48 |
49 |
50 | private void InitializeComponent()
51 | {
52 | // contextMenu
53 | contextMenu = new ContextMenuStrip();
54 | ToolStripMenuItem menuItem = new ToolStripMenuItem();
55 | menuItem.Text = Resources.str_channelContextMenuMarkRead;
56 | menuItem.Click += new EventHandler(MiMarkAllReadClick);
57 | contextMenu.Items.Add(menuItem);
58 | menuItem = new ToolStripMenuItem();
59 | menuItem.Text = Resources.str_channelContextMenuClearData;
60 | menuItem.Click += new EventHandler(MiClearChannelDataClick);
61 | contextMenu.Items.Add(menuItem);
62 |
63 | // listView
64 | this.listView = new System.Windows.Forms.ListView();
65 | this.listView.Dock = System.Windows.Forms.DockStyle.Fill;
66 | this.listView.UseCompatibleStateImageBehavior = false;
67 | this.listView.View = View.Details;
68 | this.listView.AllowColumnReorder = true;
69 | this.listView.FullRowSelect = true;
70 | this.listView.DoubleClick += new EventHandler(OnItemActivate);
71 | //this.listView.ContextMenuStrip = contextMenu;
72 | this.listView.MouseClick += new MouseEventHandler(ListView_MouseClick);
73 |
74 | // Form
75 | this.ClientSize = new System.Drawing.Size(panelWidth, panelHeight);
76 | this.Controls.Add(this.listView);
77 | this.MinimizeBox = false;
78 | this.MaximizeBox = false;
79 | this.Text = Resources.str_channelFormTitle;
80 | this.Icon = Resources.ico_yellow32;
81 | this.HelpButton = true;
82 | this.HelpRequested += new HelpEventHandler(FormChannelInfo_HelpRequested);
83 | }
84 |
85 | void FormChannelInfo_HelpRequested(object sender, HelpEventArgs hlpevent)
86 | {
87 | Help.ShowHelp(this, Settings.Default.helpFilename, HelpNavigator.Topic, Settings.Default.helpNameChannelInfo);
88 | }
89 |
90 |
91 | protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
92 | {
93 | try
94 | {
95 | // close window using Escape key
96 | if (msg.WParam.ToInt32() == (int)Keys.Escape)
97 | Dispose();
98 | }
99 | catch (Exception)
100 | {
101 | }
102 |
103 | return base.ProcessCmdKey(ref msg, keyData);
104 | }
105 |
106 |
107 | private void FillChannelList()
108 | {
109 | listItems = new ListViewItem[rssChannel.Length];
110 |
111 | // set the table headers
112 | listView.Columns.Add(Resources.str_channelHeaderTitle, -2, HorizontalAlignment.Left);
113 | listView.Columns.Add(Resources.str_channelHeaderPrio, -2, HorizontalAlignment.Center);
114 | listView.Columns.Add(Resources.str_channelHeaderClickRate, -2, HorizontalAlignment.Center);
115 | listView.Columns.Add(Resources.str_channelHeaderEffPrio, -2, HorizontalAlignment.Center);
116 | listView.Columns.Add(Resources.str_channelHeaderCount, -2, HorizontalAlignment.Center);
117 | listView.Columns.Add(Resources.str_channelHeaderTotal, -2, HorizontalAlignment.Center);
118 | listView.Columns.Add(Resources.str_channelHeaderLastUpdate, -2, HorizontalAlignment.Center);
119 |
120 | // create the list items
121 | for (int i = 0; i < rssChannel.Length; i++)
122 | {
123 | listItems[i] = new ListViewItem();
124 | FillListSubItems(i);
125 | }
126 | listView.Items.AddRange(listItems);
127 | }
128 |
129 | // this fills the text of a list item
130 | // the list item has to be created before
131 | private void FillListSubItems(int index)
132 | {
133 | string viewCount = "-";
134 | if (rssChannel[index].channelViewedCount > 0)
135 | viewCount = "" + 100 * rssChannel[index].channelOpenedCount / rssChannel[index].channelViewedCount + " %";
136 |
137 | // we need to clear potential old list data for the case of a refresh
138 | listItems[index].SubItems.Clear();
139 |
140 | // add the text data
141 | listItems[index].Text = rssChannel[index].title;
142 | listItems[index].SubItems.AddRange(new string[] {
143 | "" + rssChannel[index].channelInfo.priority,
144 | viewCount,
145 | "" + rssChannel[index].effectivePriority,
146 | "" + rssChannel[index].Count,
147 | "" + rssChannel[index].channelMessageCount,
148 | "" + rssChannel[index].lastUpdate,
149 | "" + rssChannel[index].channelInfo.link,
150 | } );
151 | }
152 |
153 |
154 | // start link to channel on double click
155 | private void OnItemActivate(object sender, EventArgs e)
156 | {
157 | foreach (ListViewItem item in listView.SelectedItems)
158 | {
159 | // start the link of the channel
160 | System.Diagnostics.Process.Start(item.SubItems[7].Text);
161 | }
162 |
163 | // close window
164 | Dispose();
165 | }
166 |
167 |
168 | // display context menu
169 | private void ListView_MouseClick(object sender, MouseEventArgs e)
170 | {
171 | if ((e.Button == MouseButtons.Right) && (e.Clicks == 1))
172 | {
173 | contextMenu.Show(listView, e.Location);
174 | }
175 | }
176 |
177 |
178 | // mark all channel data as read for all selected list items
179 | private void MiMarkAllReadClick(object sender, EventArgs e)
180 | {
181 | foreach (ListViewItem item in listView.SelectedItems)
182 | {
183 | rssChannel[item.Index].MarkAllRead();
184 | // also update the display
185 | FillListSubItems(item.Index);
186 | }
187 | }
188 |
189 | // clear channel data as read for all selected list items
190 | private void MiClearChannelDataClick(object sender, EventArgs e)
191 | {
192 | foreach (ListViewItem item in listView.SelectedItems)
193 | {
194 | rssChannel[item.Index].ClearChannelData();
195 | // also update the display
196 | FillListSubItems(item.Index);
197 | }
198 | }
199 | }
200 | }
--------------------------------------------------------------------------------
/install/dotnet.nsh:
--------------------------------------------------------------------------------
1 | ;
2 | ;BalloonRSS - Simple RSS news aggregator using balloon tooltips
3 | ; Copyright (C) 2007 Roman Morawek
4 | ;
5 | ; This program is free software: you can redistribute it and/or modify
6 | ; it under the terms of the GNU General Public License as published by
7 | ; the Free Software Foundation, either version 3 of the License, or
8 | ; (at your option) any later version.
9 | ;
10 | ; This program is distributed in the hope that it will be useful,
11 | ; but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ; GNU General Public License for more details.
14 | ;
15 | ; You should have received a copy of the GNU General Public License
16 | ; along with this program. If not, see .
17 | ;
18 |
19 |
20 | ;--------------------------------
21 | ;Definitions
22 | ; URL to the .NET Framework 2.0 download
23 | ; No different locales needed for it is multilingual
24 | !define URL_DOTNET "http://download.microsoft.com/download/5/6/7/567758a3-759e-473e-bf8f-52154438565a/dotnetfx.exe"
25 |
26 |
27 | ;--------------------------------
28 | ; Declaring variables
29 | Var "DOTNET_RETURN_CODE"
30 |
31 |
32 | ;--------------------------------
33 | ; Section for .NET Framework
34 | ; This downloads and installs Miscrosoft .NET Framework 2.0
35 | ; if not found on the system
36 |
37 | Section $(SEC_DOTNET) SecDotNet
38 | Call IsDotNETInstalled
39 | Pop $R3
40 | ; IsDotNETInstalled returns 1 for yes and 0 for no
41 | StrCmp $R3 "1" lbl_isinstalled lbl_notinstalled
42 |
43 | lbl_notinstalled:
44 |
45 | SectionIn RO
46 | ; the following Goto and Label is for consistencey.
47 | Goto lbl_DownloadRequired
48 |
49 | lbl_DownloadRequired:
50 | MessageBox MB_ICONEXCLAMATION|MB_YESNO|MB_DEFBUTTON2 "$(DESC_DOTNET_DECISION)" /SD IDNO \
51 | IDYES +2 IDNO lbl_Done
52 | DetailPrint "$(DESC_DOWNLOADING1) $(DESC_SHORTDOTNET)..."
53 | ; "Downloading Microsoft .Net Framework"
54 | ;AddSize 286720 ;already included above
55 | nsisdl::download /TRANSLATE "$(DESC_DOWNLOADING)" "$(DESC_CONNECTING)" \
56 | "$(DESC_SECOND)" "$(DESC_MINUTE)" "$(DESC_HOUR)" "$(DESC_PLURAL)" \
57 | "$(DESC_PROGRESS)" "$(DESC_REMAINING)" \
58 | /TIMEOUT=30000 "${URL_DOTNET}" "$PLUGINSDIR\dotnetfx.exe"
59 | Pop $0
60 | StrCmp "$0" "success" lbl_continue
61 | DetailPrint "$(DESC_DOWNLOADFAILED) $0"
62 | Abort
63 |
64 | ; start installation of .NET framework
65 | lbl_continue:
66 | DetailPrint "$(DESC_INSTALLING) $(DESC_SHORTDOTNET)..."
67 | Banner::show /NOUNLOAD "$(DESC_INSTALLING) $(DESC_SHORTDOTNET)..."
68 | nsExec::ExecToStack '"$PLUGINSDIR\dotnetfx.exe" /q /c:"install.exe /noaspupgrade /q"'
69 | pop $DOTNET_RETURN_CODE
70 | Banner::destroy
71 | SetRebootFlag false
72 | ; silence the compiler
73 | Goto lbl_NoDownloadRequired
74 |
75 | lbl_NoDownloadRequired:
76 |
77 | ; obtain any error code and inform the user ($DOTNET_RETURN_CODE)
78 | ; If nsExec is unable to execute the process,
79 | ; it will return "error"
80 | ; If the process timed out it will return "timeout"
81 | ; else it will return the return code from the executed process.
82 | StrCmp "$DOTNET_RETURN_CODE" "" lbl_NoError
83 | StrCmp "$DOTNET_RETURN_CODE" "0" lbl_NoError
84 | StrCmp "$DOTNET_RETURN_CODE" "3010" lbl_NoError
85 | StrCmp "$DOTNET_RETURN_CODE" "8192" lbl_NoError
86 | StrCmp "$DOTNET_RETURN_CODE" "error" lbl_Error
87 | StrCmp "$DOTNET_RETURN_CODE" "timeout" lbl_TimeOut
88 | ; It's a .Net Error
89 | StrCmp "$DOTNET_RETURN_CODE" "4101" lbl_Error_DuplicateInstance
90 | StrCmp "$DOTNET_RETURN_CODE" "4097" lbl_Error_NotAdministrator
91 | StrCmp "$DOTNET_RETURN_CODE" "1633" lbl_Error_InvalidPlatform lbl_FatalError
92 | ; all others are fatal
93 |
94 | lbl_Error_DuplicateInstance:
95 | DetailPrint "$(ERROR_DUPLICATE_INSTANCE)"
96 | GoTo lbl_Done
97 |
98 | lbl_Error_NotAdministrator:
99 | DetailPrint "$(ERROR_NOT_ADMINISTRATOR)"
100 | GoTo lbl_Done
101 |
102 | lbl_Error_InvalidPlatform:
103 | DetailPrint "$(ERROR_INVALID_PLATFORM)"
104 | GoTo lbl_Done
105 |
106 | lbl_TimeOut:
107 | DetailPrint "$(DESC_DOTNET_TIMEOUT)"
108 | GoTo lbl_Done
109 |
110 | lbl_Error:
111 | DetailPrint "$(ERROR_DOTNET_INVALID_PATH)"
112 | GoTo lbl_Done
113 |
114 | lbl_FatalError:
115 | DetailPrint "$(ERROR_DOTNET_FATAL)[$DOTNET_RETURN_CODE]"
116 | GoTo lbl_Done
117 |
118 | lbl_Done:
119 | DetailPrint "$(DESC_LONGDOTNET) $(NOT_INSTALLED)"
120 | MessageBox MB_ICONEXCLAMATION|MB_YESNO|MB_DEFBUTTON2 "$(FAILED_DOTNET_INSTALL)" /SD IDNO \
121 | IDYES +2 IDNO 0
122 | DetailPrint "${APPL_NAME} $(NOT_INSTALLED)"
123 | Abort
124 |
125 | lbl_NoError:
126 |
127 | lbl_isinstalled:
128 | SectionEnd
129 |
130 |
131 | ;--------------------------------
132 | ;Descriptions
133 |
134 | ; Language strings
135 |
136 |
137 | ; strings needed for .NET install
138 | LangString DESC_REMAINING ${LANG_ENGLISH} " (%d %s%s remaining)"
139 | LangString DESC_PROGRESS ${LANG_ENGLISH} "%dkB of %dkB @ %d.%01dkB/s"
140 | LangString DESC_PLURAL ${LANG_ENGLISH} "s"
141 | LangString DESC_HOUR ${LANG_ENGLISH} "hour"
142 | LangString DESC_MINUTE ${LANG_ENGLISH} "minute"
143 | LangString DESC_SECOND ${LANG_ENGLISH} "second"
144 | LangString DESC_CONNECTING ${LANG_ENGLISH} "Connecting..."
145 | LangString DESC_DOWNLOADING ${LANG_ENGLISH} "Downloading %s"
146 | LangString DESC_LONGDOTNET ${LANG_ENGLISH} "Microsoft .Net Framework 2.0"
147 | LangString DESC_SHORTDOTNET ${LANG_ENGLISH} "Microsoft .Net Framework 2.0"
148 | LangString DESC_DOTNET_DECISION ${LANG_ENGLISH} "$(DESC_SHORTDOTNET) was not \
149 | found on your system. \
150 | $\nIt is strongly advised that you install $(DESC_SHORTDOTNET) before continuing. \
151 | $\nIf you choose to continue, you will need to connect to the Internet \
152 | $\nbefore proceeding. \
153 | $\n$\nShould $(DESC_SHORTDOTNET) be installed now?"
154 | LangString SEC_DOTNET ${LANG_ENGLISH} "$(DESC_SHORTDOTNET)"
155 | LangString DESC_INSTALLING ${LANG_ENGLISH} "Installing"
156 | LangString DESC_DOWNLOADING1 ${LANG_ENGLISH} "Downloading"
157 | LangString DESC_DOWNLOADFAILED ${LANG_ENGLISH} "Download Failed:"
158 | LangString ERROR_DUPLICATE_INSTANCE ${LANG_ENGLISH} "The $(DESC_SHORTDOTNET) Installer is already running."
159 | LangString ERROR_NOT_ADMINISTRATOR ${LANG_ENGLISH} "You are not administrator."
160 | LangString ERROR_INVALID_PLATFORM ${LANG_ENGLISH} "OS not supported."
161 | LangString DESC_DOTNET_TIMEOUT ${LANG_ENGLISH} "The installation of the $(DESC_SHORTDOTNET) has timed out."
162 | LangString ERROR_DOTNET_INVALID_PATH ${LANG_ENGLISH} "The $(DESC_SHORTDOTNET) Installation $\n was not found in the following location:$\n"
163 | LangString ERROR_DOTNET_FATAL ${LANG_ENGLISH} "A fatal error occurred during the installation $\nof $(DESC_SHORTDOTNET)."
164 | LangString FAILED_DOTNET_INSTALL ${LANG_ENGLISH} "$(DESC_LONGDOTNET) was not installed. \
165 | $\n${APPL_NAME} may not function properly until $(DESC_LONGDOTNET) is installed. \
166 | $\n$\nDo you still want to install ${APPL_NAME}?"
167 | LangString NOT_INSTALLED ${LANG_ENGLISH} "was not installed."
168 |
169 |
170 | ;--------------------------------
171 | ; diverse functions
172 |
173 | ;--------------------------------
174 | ; Check for .NET Framework install
175 |
176 | Function IsDotNETInstalled
177 | Push $0
178 | Push $1
179 | Push $2
180 | Push $3
181 | Push $4
182 |
183 | ReadRegStr $4 HKEY_LOCAL_MACHINE \
184 | "Software\Microsoft\.NETFramework" "InstallRoot"
185 | # remove trailing back slash
186 | Push $4
187 | Exch $EXEDIR
188 | Exch $EXEDIR
189 | Pop $4
190 | # if the root directory doesn't exist .NET is not installed
191 | IfFileExists $4 0 noDotNET
192 |
193 | StrCpy $0 0
194 |
195 | EnumStart:
196 | EnumRegKey $2 HKEY_LOCAL_MACHINE \
197 | "Software\Microsoft\.NETFramework\Policy" $0
198 | IntOp $0 $0 + 1
199 | StrCmp $2 "" noDotNET
200 |
201 | StrCpy $1 0
202 |
203 | EnumPolicy:
204 | EnumRegValue $3 HKEY_LOCAL_MACHINE \
205 | "Software\Microsoft\.NETFramework\Policy\$2" $1
206 | IntOp $1 $1 + 1
207 | StrCmp $3 "" EnumStart
208 | IfFileExists "$4\$2.$3" foundDotNET EnumPolicy
209 |
210 | noDotNET:
211 | StrCpy $0 0
212 | Goto done
213 |
214 | foundDotNET:
215 | StrCpy $0 1
216 |
217 | done:
218 | Pop $4
219 | Pop $3
220 | Pop $2
221 | Pop $1
222 | Exch $0
223 | FunctionEnd
224 |
--------------------------------------------------------------------------------
/src/ChannelList.cs:
--------------------------------------------------------------------------------
1 | /*
2 | BalloonRSS - Simple RSS news aggregator using balloon tooltips
3 | Copyright (C) 2009 Roman Morawek
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | using System;
20 | using System.Collections.Generic;
21 | using System.Text;
22 | using System.Xml;
23 | using System.IO;
24 | using BalloonRss.Properties;
25 |
26 |
27 | namespace BalloonRss
28 | {
29 | class ChannelList : List
30 | {
31 | private const String xmlRootNodeName = "channels";
32 | private const String xmlItemName = "item";
33 |
34 |
35 | // the constructor loads the channel config file
36 | public ChannelList(out bool fallbackToDefaultChannels)
37 | {
38 | fallbackToDefaultChannels = false;
39 |
40 | // first, we try to read the global config file;
41 | try
42 | {
43 | ParseChannelConfigFile(GetGlobalChannelConfigFilename());
44 | }
45 | catch (Exception)
46 | {
47 | // if it does not exist we just ignore it
48 | }
49 | // mark the global channels (to distinguish for editing)
50 | foreach (ChannelInfo curChannel in this)
51 | curChannel.globalChannel = true;
52 |
53 | // second, we try to read the user config file;
54 | // if it does not exist and the global config was also empty, we use default settings
55 | try
56 | {
57 | ParseChannelConfigFile(GetUserChannelConfigFilename());
58 | }
59 | catch (DirectoryNotFoundException)
60 | {
61 | // create settings directory
62 | Directory.CreateDirectory(Path.GetDirectoryName(GetUserChannelConfigFilename()));
63 |
64 | // if the global config file was inexistant or empty, create default channels
65 | if (this.Count == 0)
66 | {
67 | LoadDefaultChannelSettings();
68 | fallbackToDefaultChannels = true;
69 | }
70 | }
71 | catch (Exception)
72 | {
73 | // this may be a FileNotFoundException or another exception in case of an illegal config file
74 | // we have to load default channels
75 | // if the global config file was inexistant or empty, create default channels
76 | if (this.Count == 0)
77 | {
78 | LoadDefaultChannelSettings();
79 | fallbackToDefaultChannels = true;
80 | }
81 | }
82 | }
83 |
84 |
85 | private static String GetUserChannelConfigFilename()
86 | {
87 | return System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
88 | + Path.DirectorySeparatorChar + "BalloonRSS"
89 | + Path.DirectorySeparatorChar + Settings.Default.configFilename;
90 | }
91 |
92 | private static String GetGlobalChannelConfigFilename()
93 | {
94 | return Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath)
95 | + Path.DirectorySeparatorChar + Settings.Default.configFilename;
96 | }
97 |
98 |
99 | private void LoadDefaultChannelSettings()
100 | {
101 | // there might be channels left from a config file read attempt; clear them
102 | this.Clear();
103 |
104 | // create up to 4 default channels
105 | try
106 | {
107 | ChannelInfo newChannel = new ChannelInfo(
108 | Properties.Resources.str_channelSettingsDefault1Link,
109 | Properties.Resources.str_channelSettingsDefault1Priority);
110 | this.Add(newChannel);
111 | }
112 | catch (Exception) { };
113 |
114 | try
115 | {
116 | ChannelInfo newChannel = new ChannelInfo(
117 | Properties.Resources.str_channelSettingsDefault2Link,
118 | Properties.Resources.str_channelSettingsDefault2Priority);
119 | if (IsNewChannel(newChannel, null))
120 | this.Add(newChannel);
121 | }
122 | catch (Exception) { };
123 |
124 | try
125 | {
126 | ChannelInfo newChannel = new ChannelInfo(
127 | Properties.Resources.str_channelSettingsDefault3Link,
128 | Properties.Resources.str_channelSettingsDefault3Priority);
129 | if (IsNewChannel(newChannel, null))
130 | this.Add(newChannel);
131 | }
132 | catch (Exception) { };
133 |
134 | try
135 | {
136 | ChannelInfo newChannel = new ChannelInfo(
137 | Properties.Resources.str_channelSettingsDefault4Link,
138 | Properties.Resources.str_channelSettingsDefault4Priority);
139 | if (IsNewChannel(newChannel, null))
140 | this.Add(newChannel);
141 | }
142 | catch (Exception) { };
143 |
144 | // as the last step, dump the settings file
145 | SaveToFile();
146 | }
147 |
148 |
149 | // this parses and loads the channel config file
150 | // in case of any error an exception shall be thrown
151 | private void ParseChannelConfigFile(string configFilename)
152 | {
153 | // open xml configuration file
154 | XmlDocument configFile = new XmlDocument();
155 | configFile.Load(configFilename);
156 |
157 | // check root tag
158 | if (configFile.DocumentElement.Name != xmlRootNodeName)
159 | throw new FormatException(Resources.str_balloonErrorConfigChannelTag);
160 |
161 | // loop over all channel entries
162 | XmlNodeList itemList = configFile.GetElementsByTagName(xmlItemName);
163 | foreach (XmlNode xmlNode in itemList)
164 | {
165 | // create new channel with this information
166 | ChannelInfo newChannel = new ChannelInfo(xmlNode);
167 |
168 | // search for duplicate node
169 | if (!IsNewChannel(newChannel, null))
170 | throw new FormatException("duplicate link found");
171 |
172 | this.Add(newChannel);
173 | }
174 | // configuration read finished
175 | }
176 |
177 |
178 | public bool IsNewChannel(ChannelInfo searchChannel, ChannelInfo excludeChannel)
179 | {
180 | foreach (ChannelInfo curChannel in this)
181 | {
182 | if (curChannel != excludeChannel)
183 | {
184 | if (curChannel.link == searchChannel.link)
185 | return false;
186 | }
187 | }
188 | return true;
189 | }
190 |
191 |
192 | // dump the current channel list to the xml file
193 | public void SaveToFile()
194 | {
195 | // write this information in the channel file
196 | XmlDocument channelFile = new XmlDocument();
197 | XmlNode xmlRoot;
198 |
199 | // create root node
200 | xmlRoot = channelFile.CreateElement(xmlRootNodeName);
201 | channelFile.AppendChild(xmlRoot);
202 |
203 | // add content
204 | foreach (ChannelInfo curChannelInfo in this)
205 | {
206 | // only store user specific channel settings and do not modify global channels
207 | if (curChannelInfo.globalChannel == false)
208 | {
209 | XmlElement xmlChannelInfo = channelFile.CreateElement(xmlItemName);
210 | curChannelInfo.DumpChannelInfo(channelFile, xmlChannelInfo);
211 | xmlRoot.AppendChild(xmlChannelInfo);
212 | }
213 | }
214 |
215 | // save the file
216 | channelFile.Save(GetUserChannelConfigFilename());
217 | }
218 | }
219 | }
220 |
--------------------------------------------------------------------------------
/install/balloonRSS.nsi:
--------------------------------------------------------------------------------
1 | ;
2 | ;BalloonRSS - Simple RSS news aggregator using balloon tooltips
3 | ; Copyright (C) 2008 Roman Morawek
4 | ;
5 | ; This program is free software: you can redistribute it and/or modify
6 | ; it under the terms of the GNU General Public License as published by
7 | ; the Free Software Foundation, either version 3 of the License, or
8 | ; (at your option) any later version.
9 | ;
10 | ; This program is distributed in the hope that it will be useful,
11 | ; but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | ; GNU General Public License for more details.
14 | ;
15 | ; You should have received a copy of the GNU General Public License
16 | ; along with this program. If not, see .
17 | ;
18 |
19 | ;--------------------------------
20 | ;Definitions
21 | !define APPL_NAME "BalloonRSS"
22 | !define APPL_VERSION "2.9" ; keep this consistent with AssemblyInfo.cs!
23 | !define PRODUCT_PUBLISHER "Roman Morawek"
24 | !define PRODUCT_PUBLISHER_WEB_SITE "https://www.embyt.com"
25 | !define PRODUCT_WEB_SITE "https://embyt.github.io/balloonrss"
26 | !define PRODUCT_DOWNLOAD_SITE "https://github.com/embyt/balloonrss/releases"
27 |
28 | !define BASEDIR ".."
29 |
30 |
31 | ;--------------------------------
32 | ;Includes
33 | !include dotnet.nsh
34 | !include "MUI2.nsh"
35 |
36 |
37 | ;--------------------------------
38 | ;User defined macros
39 | !macro CheckAppRunning APP_PROCESS_NAME
40 | StrCpy $0 "${APP_PROCESS_NAME}"
41 | DetailPrint "Searching for processes called '$0'"
42 | KillProc::FindProcesses
43 | StrCmp $1 "-1" wooops
44 | Goto AppRunning
45 |
46 | AppRunning:
47 | DetailPrint "-> Found $0 processes running"
48 | StrCmp $0 "0" AppNotRunning
49 | MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 "${APP_PROCESS_NAME} is currently running. $\n$\nDo you want to close it and continue installation?" IDYES KillApp
50 | DetailPrint "Installation Aborted!"
51 | Abort
52 | KillApp:
53 | StrCpy $0 "${APP_PROCESS_NAME}"
54 | DetailPrint "Killing all processes called '$0'"
55 | KillProc::KillProcesses
56 | StrCmp $1 "-1" wooops
57 | DetailPrint "-> Killed $0 processes, failed to kill $1 processes"
58 | sleep 1500
59 | Goto AppNotRunning
60 | wooops:
61 | DetailPrint "-> Error: Something went wrong :-("
62 | Abort
63 | AppNotRunning:
64 | DetailPrint "No Application Instances Found"
65 | !macroend
66 |
67 |
68 | ;--------------------------------
69 | ;General
70 |
71 | ;Name and file
72 | Name "${APPL_NAME} ${APPL_VERSION}"
73 | OutFile "${APPL_NAME}_${APPL_VERSION}_setup.exe"
74 |
75 | ;Default installation folder
76 | InstallDir "$PROGRAMFILES\${APPL_NAME}"
77 |
78 | ;Get installation folder from registry if available
79 | InstallDirRegKey HKLM "Software\${APPL_NAME}" "Install_Dir"
80 |
81 | ;Start Menu Folder Page Configuration
82 | !define MUI_STARTMENUPAGE_DEFAULTFOLDER "${APPL_NAME}"
83 | !define MUI_STARTMENUPAGE_REGISTRY_ROOT "HKCU"
84 | !define MUI_STARTMENUPAGE_REGISTRY_KEY "Software\${APPL_NAME}"
85 | !define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "Start_Menu_Folder"
86 |
87 | ;Set installer icon
88 | !define MUI_ICON yellow32.ico
89 | !define MUI_UNICON yellow32.ico
90 |
91 | ;--------------------------------
92 | ;Variables
93 |
94 | Var StartMenuFolder
95 |
96 | ;--------------------------------
97 | ;Pages
98 |
99 | !insertmacro MUI_PAGE_WELCOME
100 | !insertmacro MUI_PAGE_LICENSE "${BASEDIR}\license.txt"
101 | !insertmacro MUI_PAGE_DIRECTORY
102 | !insertmacro MUI_PAGE_COMPONENTS
103 | !insertmacro MUI_PAGE_STARTMENU Application $StartMenuFolder
104 | !insertmacro MUI_PAGE_INSTFILES
105 | !define MUI_FINISHPAGE_RUN "$INSTDIR\BalloonRss.exe"
106 | !define MUI_FINISHPAGE_SHOWREADME "$INSTDIR\README.txt"
107 | !insertmacro MUI_PAGE_FINISH
108 |
109 | !insertmacro MUI_UNPAGE_CONFIRM
110 | !insertmacro MUI_UNPAGE_COMPONENTS
111 | !insertmacro MUI_UNPAGE_INSTFILES
112 |
113 |
114 | ;--------------------------------
115 | ;Languages
116 |
117 | !insertmacro MUI_LANGUAGE "English"
118 |
119 |
120 | ;--------------------------------
121 | ;Installer Sections
122 |
123 | Section "General" SecGeneral
124 |
125 | SectionIn RO
126 |
127 | ; Kill application if it already runs
128 | !insertmacro CheckAppRunning "BalloonRss.exe"
129 |
130 | ; Set output path to the installation directory.
131 | SetOutPath "$INSTDIR"
132 |
133 | File "${BASEDIR}\bin\BalloonRss.exe"
134 | File "${BASEDIR}\README.txt"
135 | File "${BASEDIR}\help\balloonrss.chm"
136 |
137 | ;Create shortcuts
138 | !insertmacro MUI_STARTMENU_WRITE_BEGIN Application
139 | CreateDirectory "$SMPROGRAMS\$StartMenuFolder"
140 | CreateShortCut "$SMPROGRAMS\$StartMenuFolder\${APPL_NAME}.lnk" "$INSTDIR\BalloonRss.exe"
141 | !insertmacro MUI_STARTMENU_WRITE_END
142 |
143 | ;Store installation folder
144 | WriteRegStr HKLM "Software\${APPL_NAME}" "Install_Dir" $INSTDIR
145 |
146 | ; Write the uninstall keys for Windows
147 | WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPL_NAME}" "DisplayName" "${APPL_NAME}"
148 | WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPL_NAME}" "UninstallString" '"$INSTDIR\uninstall.exe"'
149 | WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPL_NAME}" "NoModify" 1
150 | WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPL_NAME}" "NoRepair" 1
151 | WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPL_NAME}" "Publisher" "${PRODUCT_PUBLISHER}"
152 | WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPL_NAME}" "URLInfoAbout" "${PRODUCT_PUBLISHER_WEB_SITE}"
153 | WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPL_NAME}" "DisplayVersion" "${APPL_VERSION}"
154 | WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPL_NAME}" "HelpLink" "${PRODUCT_WEB_SITE}"
155 | WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPL_NAME}" "URLUpdateInfo" "${PRODUCT_DOWNLOAD_SITE}"
156 | ;also available: ReadMe, Comments
157 |
158 | ; Create uninstaller
159 | WriteUninstaller "uninstall.exe"
160 |
161 | SectionEnd
162 |
163 |
164 | ;--------------------------------
165 | ; Optional section (can be disabled by the user)
166 |
167 | Section "Language Files" SecLanguage
168 | File /r /x .svn "${BASEDIR}\bin\de"
169 | File /r /x .svn "${BASEDIR}\bin\pt"
170 | SectionEnd
171 |
172 | Section "Source Code" SecSource
173 | File "${BASEDIR}\license.txt"
174 | File "${BASEDIR}\balloonRss.sln"
175 | File /r /x obj /x .svn /x BalloonRss.csproj.user "${BASEDIR}\src"
176 | SectionEnd
177 |
178 | Section "Autostart Program" SecAutostart
179 | CreateShortCut "$SMSTARTUP\${APPL_NAME}.lnk" "$INSTDIR\BalloonRss.exe" "" "$INSTDIR\BalloonRss.exe" 0
180 | SectionEnd
181 |
182 |
183 | ;--------------------------------
184 | ;Uninstaller Sections
185 |
186 | Section "un.General" SecUnGeneral
187 |
188 | ; Kill application if it already runs
189 | !insertmacro CheckAppRunning "BalloonRss.exe"
190 |
191 | ; Remove files and uninstaller
192 | Delete /REBOOTOK "$INSTDIR\BalloonRss.exe"
193 | RMDir /r "$INSTDIR"
194 |
195 | ; Remove shortcuts, if any
196 | !insertmacro MUI_STARTMENU_GETFOLDER Application $StartMenuFolder
197 | Delete "$SMPROGRAMS\$StartMenuFolder\${APPL_NAME}.lnk"
198 | RMDir "$SMPROGRAMS\$StartMenuFolder" ; this will just remove the dir if it is emty
199 | Delete "$SMSTARTUP\${APPL_NAME}.lnk"
200 |
201 | ; Remove registry keys
202 | DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPL_NAME}"
203 | DeleteRegKey HKLM "SOFTWARE\${APPL_NAME}"
204 | DeleteRegKey HKCU "Software\${APPL_NAME}"
205 |
206 | SectionEnd
207 |
208 |
209 | Section "un.Data" SecUnData
210 | RMDir /r "$APPDATA\${APPL_NAME}"
211 | SectionEnd
212 |
213 |
214 | ;--------------------------------
215 | ;Descriptions
216 |
217 | ; Language strings
218 | LangString DESC_SecGeneral ${LANG_ENGLISH} "Installs the required application files."
219 | LangString DESC_SecDotNet ${LANG_ENGLISH} "Installs the Microsoft .NET framework, which is required for this application. This will be skipped if the .NET framework is already present."
220 | LangString DESC_SecLanguage ${LANG_ENGLISH} "Installs language files for German and Portuguese."
221 | LangString DESC_SecSource ${LANG_ENGLISH} "Installs the source code."
222 | LangString DESC_SecAutostart ${LANG_ENGLISH} "Launch ${APPL_NAME} on start-up."
223 |
224 | LangString DESC_SecUnGeneral ${LANG_ENGLISH} "Uninstalls the application."
225 | LangString DESC_SecUnData ${LANG_ENGLISH} "Removes application specific settings and data."
226 |
227 |
228 | ;Assign language strings to sections
229 | !insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
230 | !insertmacro MUI_DESCRIPTION_TEXT ${SecGeneral} $(DESC_SecGeneral)
231 | !insertmacro MUI_DESCRIPTION_TEXT ${SecDotNet} $(DESC_SecDotNet)
232 | !insertmacro MUI_DESCRIPTION_TEXT ${SecLanguage} $(DESC_SecLanguage)
233 | !insertmacro MUI_DESCRIPTION_TEXT ${SecSource} $(DESC_SecSource)
234 | !insertmacro MUI_DESCRIPTION_TEXT ${SecAutostart} $(DESC_SecAutostart)
235 | !insertmacro MUI_FUNCTION_DESCRIPTION_END
236 |
237 | !insertmacro MUI_UNFUNCTION_DESCRIPTION_BEGIN
238 | !insertmacro MUI_DESCRIPTION_TEXT ${SecUnGeneral} $(DESC_SecUnGeneral)
239 | !insertmacro MUI_DESCRIPTION_TEXT ${SecUnData} $(DESC_SecUnData)
240 | !insertmacro MUI_UNFUNCTION_DESCRIPTION_END
241 |
--------------------------------------------------------------------------------
/src/FormChannelSettingsEdit.cs:
--------------------------------------------------------------------------------
1 | /*
2 | BalloonRSS - Simple RSS news aggregator using balloon tooltips
3 | Copyright (C) 2009 Roman Morawek
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | using System;
20 | using System.Windows.Forms;
21 | using BalloonRss.Properties;
22 |
23 |
24 | namespace BalloonRss
25 | {
26 | class FormChannelSettingsEdit : Form
27 | {
28 | // GUI elements
29 | private Label fillLabel;
30 | private Control cntlUrl;
31 | private Control cntlPriority;
32 | private Control cntlMarkAsRead;
33 |
34 | // class data
35 | private ChannelInfo channelInfo;
36 |
37 |
38 | public FormChannelSettingsEdit(ChannelInfo channelInfo, bool newChannel)
39 | {
40 | this.channelInfo = channelInfo;
41 |
42 | // create panel
43 | InitializeComponent(newChannel);
44 | }
45 |
46 |
47 | private void InitializeComponent(bool newChannel)
48 | {
49 | this.SuspendLayout();
50 |
51 | // the main container panel
52 | FlowLayoutPanel flPanelMain = new FlowLayoutPanel();
53 | flPanelMain.FlowDirection = FlowDirection.TopDown;
54 | flPanelMain.AutoSize = true;
55 | //flPanelMain.Dock = DockStyle.Fill;
56 | flPanelMain.Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top;
57 |
58 | // setting controls
59 | Panel panel;
60 | int maxXSize = 0;
61 | cntlUrl = CreateSettingControl(channelInfo.link, Resources.str_channelSettingsHeaderTitle, out panel);
62 | maxXSize = Math.Max(maxXSize, panel.Width);
63 | flPanelMain.Controls.Add(panel);
64 | cntlPriority = CreateSettingControl(channelInfo.priority, Resources.str_channelSettingsHeaderPriority, out panel, 0, Byte.MaxValue);
65 | maxXSize = Math.Max(maxXSize, panel.Width);
66 | flPanelMain.Controls.Add(panel);
67 | cntlMarkAsRead = CreateSettingControl(channelInfo.markAsReadAtStartup, Resources.str_channelSettingsHeaderMarkAsRead, out panel);
68 | maxXSize = Math.Max(maxXSize, panel.Width);
69 | flPanelMain.Controls.Add(panel);
70 |
71 | // OK/Cancel button panel
72 | FlowLayoutPanel flPanel = new FlowLayoutPanel();
73 | flPanel.FlowDirection = FlowDirection.LeftToRight;
74 | Button okButton = new Button();
75 | okButton.Text = Resources.str_settingsFormOKButton;
76 | okButton.Click += new EventHandler(this.OnOK);
77 | this.AcceptButton = okButton;
78 | flPanel.Controls.Add(okButton);
79 | Button cancelButton = new Button();
80 | cancelButton.Text = Resources.str_settingsFormCancelButton;
81 | cancelButton.Click += new EventHandler(this.OnCancel);
82 | this.CancelButton = cancelButton;
83 | flPanel.Controls.Add(cancelButton);
84 | flPanel.AutoSize = true;
85 | flPanel.Anchor = AnchorStyles.Right;
86 | flPanelMain.Controls.Add(flPanel);
87 |
88 | // add a dummy element to resize the settings to full horizontal scale
89 | fillLabel = new Label();
90 | fillLabel.Size = new System.Drawing.Size(maxXSize, 0);
91 | flPanelMain.Controls.Add(fillLabel);
92 |
93 | // dialog settings
94 | if (newChannel)
95 | this.Text = Resources.str_channelSettingsNewFormTitle;
96 | else
97 | this.Text = Resources.str_channelSettingsEditFormTitle;
98 | this.MinimizeBox = false;
99 | this.MaximizeBox = false;
100 | this.Icon = Resources.ico_yellow32;
101 | this.Controls.Add(flPanelMain);
102 | this.Resize += new EventHandler(this.OnResize);
103 | this.HelpButton = true;
104 | this.HelpRequested += new HelpEventHandler(FormChannelSettingsEdit_HelpRequested);
105 |
106 | this.ResumeLayout();
107 |
108 | // now, we can resize it
109 | this.ClientSize = new System.Drawing.Size(maxXSize, flPanelMain.Height);
110 | this.MinimumSize = this.Size;
111 | }
112 |
113 | void FormChannelSettingsEdit_HelpRequested(object sender, HelpEventArgs hlpevent)
114 | {
115 | Help.ShowHelp(this, Settings.Default.helpFilename, HelpNavigator.Topic, Settings.Default.helpNameChannelSettingsEdit);
116 | }
117 |
118 |
119 | private Control CreateSettingControl(Object settingsObject, String labelText, out Panel panel)
120 | {
121 | return CreateSettingControl(settingsObject, labelText, out panel, 0, 0);
122 | }
123 |
124 | private Control CreateSettingControl(Object settingsObject, String labelText, out Panel panel, int minValue, int maxValue)
125 | {
126 | // create the label
127 | Label label = new Label();
128 | label.Text = labelText + ":";
129 | label.Anchor = System.Windows.Forms.AnchorStyles.Left;
130 | label.Size = new System.Drawing.Size(
131 | TextRenderer.MeasureText(label.Text, label.Font).Width,
132 | TextRenderer.MeasureText(label.Text, label.Font).Height);
133 |
134 | // create the settings control
135 | Control control;
136 | if ( (settingsObject.GetType() == typeof(int)) || (settingsObject.GetType() == typeof(byte)) )
137 | {
138 | control = new NumericTextBox(minValue, maxValue, labelText);
139 | control.Width = TextRenderer.MeasureText(maxValue.ToString(), control.Font).Width;
140 | control.Text = "" + settingsObject;
141 | }
142 | else if (settingsObject.GetType() == typeof(String))
143 | {
144 | control = new TextBox();
145 | control.Text = "" + settingsObject;
146 | control.Width = Math.Max(
147 | TextRenderer.MeasureText(control.Text, control.Font).Width,
148 | TextRenderer.MeasureText(Settings.Default.channelSettingsLinkTextfieldSize, control.Font).Width);
149 | (control as TextBox).TextAlign = HorizontalAlignment.Left;
150 | }
151 | else if (settingsObject.GetType() == typeof(bool))
152 | {
153 | control = new CheckBox();
154 | ((CheckBox)control).Checked = (bool)settingsObject;
155 | }
156 | else
157 | throw new Exception("Internal error: Illegal settings data type");
158 |
159 | //control.Anchor = AnchorStyles.Right;
160 | control.Dock = DockStyle.Right;
161 | control.AutoSize = true;
162 |
163 | // create the panel
164 | panel = new Panel();
165 | label.Location = new System.Drawing.Point(0, Math.Max((control.Height - label.Height) / 2, 0));
166 | panel.Size = new System.Drawing.Size(label.Width + control.Width + 5, Math.Max(label.Height, control.Height));
167 | panel.Anchor = AnchorStyles.Left | AnchorStyles.Right;
168 | panel.Controls.Add(label);
169 | panel.Controls.Add(control);
170 |
171 | return control;
172 | }
173 |
174 |
175 | private bool CheckData(out String errorMessage)
176 | {
177 | errorMessage = null;
178 |
179 | // check link format
180 | if (!ChannelInfo.IsValidLink(cntlUrl.Text))
181 | {
182 | errorMessage = Resources.str_channelSettingsIllegalLink + cntlUrl.Text;
183 | return false;
184 | }
185 |
186 | // check data ranges
187 | if (!(cntlPriority as NumericTextBox).IsValueValid())
188 | {
189 | errorMessage = (cntlPriority as NumericTextBox).GetErrorMessage();
190 | return false;
191 | }
192 |
193 | return true;
194 | }
195 |
196 |
197 | private void GetData()
198 | {
199 | // store the data in the associated channel info
200 | // the data were already checked for validy before
201 | channelInfo.link = cntlUrl.Text;
202 |
203 | // do not use "feed://" prefix
204 | if (channelInfo.link.StartsWith("feed://"))
205 | {
206 | channelInfo.link = "http://" + channelInfo.link.Substring(7);
207 | }
208 |
209 | channelInfo.priority = (byte)(cntlPriority as NumericTextBox).IntValue;
210 | channelInfo.markAsReadAtStartup = (cntlMarkAsRead as CheckBox).Checked;
211 | }
212 |
213 |
214 | private void OnResize(object sender, EventArgs e)
215 | {
216 | fillLabel.Size = new System.Drawing.Size(this.ClientSize.Width-5, 0);
217 | }
218 |
219 | private void OnOK(object sender, EventArgs e)
220 | {
221 | String errorMessage;
222 |
223 | // close window
224 | if (CheckData(out errorMessage) == false)
225 | {
226 | MessageBox.Show(
227 | errorMessage,
228 | Resources.str_settingsFormErrorHeader,
229 | MessageBoxButtons.OK,
230 | MessageBoxIcon.Error);
231 | }
232 | else
233 | {
234 | GetData();
235 | this.DialogResult = DialogResult.OK;
236 | Dispose();
237 | }
238 | }
239 |
240 | private void OnCancel(object sender, EventArgs e)
241 | {
242 | // close window
243 | this.DialogResult = DialogResult.Cancel;
244 | Dispose();
245 | }
246 | }
247 | }
--------------------------------------------------------------------------------
/src/AboutBox.Designer.cs:
--------------------------------------------------------------------------------
1 | /*
2 | BalloonRSS - Simple RSS news aggregator using balloon tooltips
3 | Copyright (C) 2010 Roman Morawek
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | namespace BalloonRss
20 | {
21 | partial class AboutBox
22 | {
23 | ///
24 | /// Required designer variable.
25 | ///
26 | private System.ComponentModel.IContainer components = null;
27 |
28 | ///
29 | /// Clean up any resources being used.
30 | ///
31 | protected override void Dispose(bool disposing)
32 | {
33 | if (disposing && (components != null))
34 | {
35 | components.Dispose();
36 | }
37 | base.Dispose(disposing);
38 | }
39 |
40 | #region Windows Form Designer generated code
41 |
42 | ///
43 | /// Required method for Designer support - do not modify
44 | /// the contents of this method with the code editor.
45 | ///
46 | private void InitializeComponent()
47 | {
48 | this.tableLayoutPanel = new System.Windows.Forms.TableLayoutPanel();
49 | this.logoPictureBox = new System.Windows.Forms.PictureBox();
50 | this.labelProductName = new System.Windows.Forms.Label();
51 | this.labelCopyright = new System.Windows.Forms.Label();
52 | this.okButton = new System.Windows.Forms.Button();
53 | this.labelEmail = new System.Windows.Forms.Label();
54 | this.linkLabel1 = new System.Windows.Forms.LinkLabel();
55 | this.tableLayoutPanel.SuspendLayout();
56 | ((System.ComponentModel.ISupportInitialize)(this.logoPictureBox)).BeginInit();
57 | this.SuspendLayout();
58 | //
59 | // tableLayoutPanel
60 | //
61 | this.tableLayoutPanel.ColumnCount = 2;
62 | this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 120F));
63 | this.tableLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
64 | this.tableLayoutPanel.Controls.Add(this.logoPictureBox, 0, 0);
65 | this.tableLayoutPanel.Controls.Add(this.labelProductName, 1, 0);
66 | this.tableLayoutPanel.Controls.Add(this.labelCopyright, 1, 1);
67 | this.tableLayoutPanel.Controls.Add(this.okButton, 1, 4);
68 | this.tableLayoutPanel.Controls.Add(this.labelEmail, 1, 2);
69 | this.tableLayoutPanel.Controls.Add(this.linkLabel1, 1, 3);
70 | this.tableLayoutPanel.Dock = System.Windows.Forms.DockStyle.Fill;
71 | this.tableLayoutPanel.Location = new System.Drawing.Point(12, 11);
72 | this.tableLayoutPanel.Margin = new System.Windows.Forms.Padding(4);
73 | this.tableLayoutPanel.Name = "tableLayoutPanel";
74 | this.tableLayoutPanel.RowCount = 5;
75 | this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 25F));
76 | this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 25F));
77 | this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 25F));
78 | this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 25F));
79 | this.tableLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 31F));
80 | this.tableLayoutPanel.Size = new System.Drawing.Size(403, 142);
81 | this.tableLayoutPanel.TabIndex = 0;
82 | //
83 | // logoPictureBox
84 | //
85 | this.logoPictureBox.Dock = System.Windows.Forms.DockStyle.Fill;
86 | this.logoPictureBox.Image = global::BalloonRss.Properties.Resources.rss;
87 | this.logoPictureBox.Location = new System.Drawing.Point(0, 0);
88 | this.logoPictureBox.Margin = new System.Windows.Forms.Padding(0, 0, 13, 0);
89 | this.logoPictureBox.Name = "logoPictureBox";
90 | this.tableLayoutPanel.SetRowSpan(this.logoPictureBox, 4);
91 | this.logoPictureBox.Size = new System.Drawing.Size(107, 108);
92 | this.logoPictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
93 | this.logoPictureBox.TabIndex = 12;
94 | this.logoPictureBox.TabStop = false;
95 | //
96 | // labelProductName
97 | //
98 | this.labelProductName.Dock = System.Windows.Forms.DockStyle.Fill;
99 | this.labelProductName.Location = new System.Drawing.Point(128, 0);
100 | this.labelProductName.Margin = new System.Windows.Forms.Padding(8, 0, 4, 0);
101 | this.labelProductName.MaximumSize = new System.Drawing.Size(0, 21);
102 | this.labelProductName.Name = "labelProductName";
103 | this.labelProductName.Size = new System.Drawing.Size(271, 21);
104 | this.labelProductName.TabIndex = 19;
105 | this.labelProductName.Text = "BalloonRSS";
106 | this.labelProductName.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
107 | //
108 | // labelCopyright
109 | //
110 | this.labelCopyright.Dock = System.Windows.Forms.DockStyle.Fill;
111 | this.labelCopyright.Location = new System.Drawing.Point(128, 27);
112 | this.labelCopyright.Margin = new System.Windows.Forms.Padding(8, 0, 4, 0);
113 | this.labelCopyright.MaximumSize = new System.Drawing.Size(0, 21);
114 | this.labelCopyright.Name = "labelCopyright";
115 | this.labelCopyright.Size = new System.Drawing.Size(271, 21);
116 | this.labelCopyright.TabIndex = 21;
117 | this.labelCopyright.Text = "(C) 2009, Roman Morawek";
118 | this.labelCopyright.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
119 | //
120 | // okButton
121 | //
122 | this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
123 | this.okButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
124 | this.okButton.Location = new System.Drawing.Point(303, 115);
125 | this.okButton.Margin = new System.Windows.Forms.Padding(0);
126 | this.okButton.Name = "okButton";
127 | this.okButton.Size = new System.Drawing.Size(100, 27);
128 | this.okButton.TabIndex = 24;
129 | this.okButton.Text = "&OK";
130 | //
131 | // labelEmail
132 | //
133 | this.labelEmail.Dock = System.Windows.Forms.DockStyle.Fill;
134 | this.labelEmail.Location = new System.Drawing.Point(128, 54);
135 | this.labelEmail.Margin = new System.Windows.Forms.Padding(8, 0, 4, 0);
136 | this.labelEmail.MaximumSize = new System.Drawing.Size(0, 21);
137 | this.labelEmail.Name = "labelEmail";
138 | this.labelEmail.Size = new System.Drawing.Size(271, 21);
139 | this.labelEmail.TabIndex = 25;
140 | this.labelEmail.Text = "balloonrss@embyt.com";
141 | this.labelEmail.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
142 | //
143 | // linkLabel1
144 | //
145 | this.linkLabel1.AutoSize = true;
146 | this.linkLabel1.Dock = System.Windows.Forms.DockStyle.Fill;
147 | this.linkLabel1.Location = new System.Drawing.Point(128, 81);
148 | this.linkLabel1.Margin = new System.Windows.Forms.Padding(8, 0, 4, 0);
149 | this.linkLabel1.MaximumSize = new System.Drawing.Size(0, 21);
150 | this.linkLabel1.Name = "linkLabel1";
151 | this.linkLabel1.Size = new System.Drawing.Size(271, 21);
152 | this.linkLabel1.TabIndex = 26;
153 | this.linkLabel1.TabStop = true;
154 | this.linkLabel1.Text = "https://embyt.github.io/balloonrss";
155 | this.linkLabel1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
156 | this.linkLabel1.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel1_LinkClicked);
157 | //
158 | // AboutBox
159 | //
160 | this.AcceptButton = this.okButton;
161 | this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
162 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
163 | this.CancelButton = this.okButton;
164 | this.ClientSize = new System.Drawing.Size(427, 164);
165 | this.Controls.Add(this.tableLayoutPanel);
166 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
167 | this.Margin = new System.Windows.Forms.Padding(4);
168 | this.MaximizeBox = false;
169 | this.MinimizeBox = false;
170 | this.Name = "AboutBox";
171 | this.Padding = new System.Windows.Forms.Padding(12, 11, 12, 11);
172 | this.ShowIcon = false;
173 | this.ShowInTaskbar = false;
174 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
175 | this.Text = "AboutBox";
176 | this.tableLayoutPanel.ResumeLayout(false);
177 | this.tableLayoutPanel.PerformLayout();
178 | ((System.ComponentModel.ISupportInitialize)(this.logoPictureBox)).EndInit();
179 | this.ResumeLayout(false);
180 |
181 | }
182 |
183 | #endregion
184 |
185 | private System.Windows.Forms.TableLayoutPanel tableLayoutPanel;
186 | private System.Windows.Forms.PictureBox logoPictureBox;
187 | private System.Windows.Forms.Label labelProductName;
188 | private System.Windows.Forms.Label labelCopyright;
189 | private System.Windows.Forms.Button okButton;
190 | private System.Windows.Forms.Label labelEmail;
191 | private System.Windows.Forms.LinkLabel linkLabel1;
192 | }
193 | }
194 |
--------------------------------------------------------------------------------
/src/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace BalloonRss.Properties {
12 |
13 |
14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.5.0.0")]
16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
17 |
18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
19 |
20 | public static Settings Default {
21 | get {
22 | return defaultInstance;
23 | }
24 | }
25 |
26 | [global::System.Configuration.UserScopedSettingAttribute()]
27 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
28 | [global::System.Configuration.DefaultSettingValueAttribute("5")]
29 | public int displayIntervall {
30 | get {
31 | return ((int)(this["displayIntervall"]));
32 | }
33 | set {
34 | this["displayIntervall"] = value;
35 | }
36 | }
37 |
38 | [global::System.Configuration.UserScopedSettingAttribute()]
39 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
40 | [global::System.Configuration.DefaultSettingValueAttribute("30")]
41 | public int retrieveIntervall {
42 | get {
43 | return ((int)(this["retrieveIntervall"]));
44 | }
45 | set {
46 | this["retrieveIntervall"] = value;
47 | }
48 | }
49 |
50 | [global::System.Configuration.UserScopedSettingAttribute()]
51 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
52 | [global::System.Configuration.DefaultSettingValueAttribute("10")]
53 | public int balloonTimespan {
54 | get {
55 | return ((int)(this["balloonTimespan"]));
56 | }
57 | set {
58 | this["balloonTimespan"] = value;
59 | }
60 | }
61 |
62 | [global::System.Configuration.UserScopedSettingAttribute()]
63 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
64 | [global::System.Configuration.DefaultSettingValueAttribute("15")]
65 | public int historyDepth {
66 | get {
67 | return ((int)(this["historyDepth"]));
68 | }
69 | set {
70 | this["historyDepth"] = value;
71 | }
72 | }
73 |
74 | [global::System.Configuration.UserScopedSettingAttribute()]
75 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
76 | [global::System.Configuration.DefaultSettingValueAttribute("False")]
77 | public bool channelAsTitle {
78 | get {
79 | return ((bool)(this["channelAsTitle"]));
80 | }
81 | set {
82 | this["channelAsTitle"] = value;
83 | }
84 | }
85 |
86 | [global::System.Configuration.UserScopedSettingAttribute()]
87 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
88 | [global::System.Configuration.DefaultSettingValueAttribute("5")]
89 | public byte clickInfluence {
90 | get {
91 | return ((byte)(this["clickInfluence"]));
92 | }
93 | set {
94 | this["clickInfluence"] = value;
95 | }
96 | }
97 |
98 | [global::System.Configuration.UserScopedSettingAttribute()]
99 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
100 | [global::System.Configuration.DefaultSettingValueAttribute("True")]
101 | public bool checkForUpdates {
102 | get {
103 | return ((bool)(this["checkForUpdates"]));
104 | }
105 | set {
106 | this["checkForUpdates"] = value;
107 | }
108 | }
109 |
110 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
111 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
112 | [global::System.Configuration.DefaultSettingValueAttribute("100")]
113 | public int updateCheckIntervall {
114 | get {
115 | return ((int)(this["updateCheckIntervall"]));
116 | }
117 | }
118 |
119 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
120 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
121 | [global::System.Configuration.DefaultSettingValueAttribute("40")]
122 | public int updateDisplayIntervall {
123 | get {
124 | return ((int)(this["updateDisplayIntervall"]));
125 | }
126 | }
127 |
128 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
129 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
130 | [global::System.Configuration.DefaultSettingValueAttribute("http://balloonrss.sourceforge.net/checkforupdates.php?curVersion=")]
131 | public string updateCheckUrl {
132 | get {
133 | return ((string)(this["updateCheckUrl"]));
134 | }
135 | }
136 |
137 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
138 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
139 | [global::System.Configuration.DefaultSettingValueAttribute("channelConfig.xml")]
140 | public string configFilename {
141 | get {
142 | return ((string)(this["configFilename"]));
143 | }
144 | }
145 |
146 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
147 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
148 | [global::System.Configuration.DefaultSettingValueAttribute("####################################")]
149 | public string channelSettingsLinkTextfieldSize {
150 | get {
151 | return ((string)(this["channelSettingsLinkTextfieldSize"]));
152 | }
153 | }
154 |
155 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
156 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
157 | [global::System.Configuration.DefaultSettingValueAttribute("###########")]
158 | public string SettingsTextfieldSize {
159 | get {
160 | return ((string)(this["SettingsTextfieldSize"]));
161 | }
162 | }
163 |
164 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
165 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
166 | [global::System.Configuration.DefaultSettingValueAttribute("http://balloonrss.sourceforge.net/releaseinfo.html?curVersion=")]
167 | public string updateInfoUrl {
168 | get {
169 | return ((string)(this["updateInfoUrl"]));
170 | }
171 | }
172 |
173 | [global::System.Configuration.UserScopedSettingAttribute()]
174 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
175 | [global::System.Configuration.DefaultSettingValueAttribute("False")]
176 | public bool startPaused {
177 | get {
178 | return ((bool)(this["startPaused"]));
179 | }
180 | set {
181 | this["startPaused"] = value;
182 | }
183 | }
184 |
185 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
186 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
187 | [global::System.Configuration.DefaultSettingValueAttribute("5")]
188 | public byte defaultChannelPriority {
189 | get {
190 | return ((byte)(this["defaultChannelPriority"]));
191 | }
192 | }
193 |
194 | [global::System.Configuration.UserScopedSettingAttribute()]
195 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
196 | [global::System.Configuration.DefaultSettingValueAttribute("True")]
197 | public bool reportNetworkErrors {
198 | get {
199 | return ((bool)(this["reportNetworkErrors"]));
200 | }
201 | set {
202 | this["reportNetworkErrors"] = value;
203 | }
204 | }
205 |
206 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
207 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
208 | [global::System.Configuration.DefaultSettingValueAttribute("balloonrss.chm")]
209 | public string helpFilename {
210 | get {
211 | return ((string)(this["helpFilename"]));
212 | }
213 | }
214 |
215 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
216 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
217 | [global::System.Configuration.DefaultSettingValueAttribute("applicationSettings.html")]
218 | public string helpNameApplicationSettings {
219 | get {
220 | return ((string)(this["helpNameApplicationSettings"]));
221 | }
222 | }
223 |
224 | [global::System.Configuration.ApplicationScopedSettingAttribute()]
225 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
226 | [global::System.Configuration.DefaultSettingValueAttribute("channelInformation.html")]
227 | public string helpNameChannelInfo {
228 | get {
229 | return ((string)(this["helpNameChannelInfo"]));
230 | }
231 | }
232 |
233 | [global::System.Configuration.UserScopedSettingAttribute()]
234 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
235 | [global::System.Configuration.DefaultSettingValueAttribute("channelSettings.html")]
236 | public string helpNameChannelSettings {
237 | get {
238 | return ((string)(this["helpNameChannelSettings"]));
239 | }
240 | set {
241 | this["helpNameChannelSettings"] = value;
242 | }
243 | }
244 |
245 | [global::System.Configuration.UserScopedSettingAttribute()]
246 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
247 | [global::System.Configuration.DefaultSettingValueAttribute("channelSettings.html#channel_edit")]
248 | public string helpNameChannelSettingsEdit {
249 | get {
250 | return ((string)(this["helpNameChannelSettingsEdit"]));
251 | }
252 | set {
253 | this["helpNameChannelSettingsEdit"] = value;
254 | }
255 | }
256 |
257 | [global::System.Configuration.UserScopedSettingAttribute()]
258 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
259 | [global::System.Configuration.DefaultSettingValueAttribute("0")]
260 | public int doubleClickAction {
261 | get {
262 | return ((int)(this["doubleClickAction"]));
263 | }
264 | set {
265 | this["doubleClickAction"] = value;
266 | }
267 | }
268 | }
269 | }
270 |
--------------------------------------------------------------------------------
/src/FormSettings.cs:
--------------------------------------------------------------------------------
1 | /*
2 | BalloonRSS - Simple RSS news aggregator using balloon tooltips
3 | Copyright (C) 2009 Roman Morawek
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | using System;
20 | using System.Windows.Forms;
21 | using BalloonRss.Properties;
22 |
23 |
24 | namespace BalloonRss
25 | {
26 | class FormSettings : Form
27 | {
28 | private Label fillLabel;
29 | private Control cntlDisplayIntervall;
30 | private Control cntlRetrieveIntervall;
31 | private Control cntlBalloonTimespan;
32 | private Control cntlChannelAsTitle;
33 | private Control cntlHistoryDepth;
34 | private Control cntlClickInfluence;
35 | private Control cntlCheckForUpdates;
36 | private Control cntlStartPaused;
37 | private Control cntlReportNetworkErrors;
38 | private Control cntlDoubleClickAction;
39 |
40 |
41 | public FormSettings()
42 | {
43 | // create panel
44 | InitializeComponent();
45 | }
46 |
47 |
48 | private void InitializeComponent()
49 | {
50 | Panel panel;
51 | Button button;
52 |
53 | this.SuspendLayout();
54 |
55 | // the main container panel
56 | FlowLayoutPanel flPanelMain = new FlowLayoutPanel();
57 | flPanelMain.FlowDirection = FlowDirection.TopDown;
58 | flPanelMain.AutoSize = true;
59 | flPanelMain.Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top;
60 |
61 | // setting
62 | int maxXSize = 0;
63 | cntlDisplayIntervall = CreateSettingControl(Settings.Default.displayIntervall, Resources.str_settingsDisplayIntervall, out panel, 1, Int32.MaxValue);
64 | maxXSize = Math.Max(maxXSize, panel.Width);
65 | flPanelMain.Controls.Add(panel);
66 | cntlRetrieveIntervall = CreateSettingControl(Settings.Default.retrieveIntervall, Resources.str_settingsRetrieveIntervall, out panel, 5, Int32.MaxValue);
67 | maxXSize = Math.Max(maxXSize, panel.Width);
68 | flPanelMain.Controls.Add(panel);
69 | cntlBalloonTimespan = CreateSettingControl(Settings.Default.balloonTimespan, Resources.str_settingsBalloonTimespan, out panel, 10, Int32.MaxValue);
70 | maxXSize = Math.Max(maxXSize, panel.Width);
71 | flPanelMain.Controls.Add(panel);
72 | cntlStartPaused = CreateSettingControl(Settings.Default.startPaused, Resources.str_settingsStartPaused, out panel);
73 | maxXSize = Math.Max(maxXSize, panel.Width);
74 | flPanelMain.Controls.Add(panel);
75 | cntlChannelAsTitle = CreateSettingControl(Settings.Default.channelAsTitle, Resources.str_settingsChannelAsTitle, out panel);
76 | maxXSize = Math.Max(maxXSize, panel.Width);
77 | flPanelMain.Controls.Add(panel);
78 | cntlHistoryDepth = CreateSettingControl(Settings.Default.historyDepth, Resources.str_settingsHistoryDepth, out panel, 0, Int32.MaxValue);
79 | maxXSize = Math.Max(maxXSize, panel.Width);
80 | flPanelMain.Controls.Add(panel);
81 | cntlClickInfluence = CreateSettingControl(Settings.Default.clickInfluence, Resources.str_settingsClickInfluence, out panel, 0, 10);
82 | maxXSize = Math.Max(maxXSize, panel.Width);
83 | flPanelMain.Controls.Add(panel);
84 | cntlCheckForUpdates = CreateSettingControl(Settings.Default.checkForUpdates, Resources.str_settingsCheckForUpdates, out panel);
85 | maxXSize = Math.Max(maxXSize, panel.Width);
86 | flPanelMain.Controls.Add(panel);
87 | cntlReportNetworkErrors = CreateSettingControl(Settings.Default.reportNetworkErrors, Resources.str_settingsReportNetworkErrors, out panel);
88 | maxXSize = Math.Max(maxXSize, panel.Width);
89 | flPanelMain.Controls.Add(panel);
90 | String[] settingsList = new String[] { Resources.str_settingsDoubleClickActionOption0, Resources.str_settingsDoubleClickActionOption1, Resources.str_settingsDoubleClickActionOption2 };
91 | cntlDoubleClickAction = CreateSettingControl(Settings.Default.doubleClickAction, Resources.str_settingsDoubleClickAction, out panel, settingsList);
92 | maxXSize = Math.Max(maxXSize, panel.Width);
93 | flPanelMain.Controls.Add(panel);
94 |
95 | // OK/Cancel button panel
96 | FlowLayoutPanel flPanel = new FlowLayoutPanel();
97 | flPanel.FlowDirection = FlowDirection.LeftToRight;
98 | button = new Button();
99 | button.Text = Resources.str_settingsFormOKButton;
100 | button.Click += new EventHandler(this.OnOK);
101 | this.AcceptButton = button;
102 | flPanel.Controls.Add(button);
103 | button = new Button();
104 | button.Text = Resources.str_settingsFormCancelButton;
105 | button.Click += new EventHandler(this.OnCancel);
106 | this.CancelButton = button;
107 | flPanel.Controls.Add(button);
108 | flPanel.AutoSize = true;
109 | flPanel.Anchor = AnchorStyles.Right;
110 | flPanelMain.Controls.Add(flPanel);
111 |
112 | // add a dummy element to resize the settings to full horizontal scale
113 | fillLabel = new Label();
114 | fillLabel.Size = new System.Drawing.Size(maxXSize, 0);
115 | flPanelMain.Controls.Add(fillLabel);
116 |
117 | // dialog settings
118 | this.MinimizeBox = false;
119 | this.MaximizeBox = false;
120 | this.Text = Resources.str_settingsFormTitle;
121 | this.Icon = Resources.ico_yellow32;
122 | this.Controls.Add(flPanelMain);
123 | this.Resize += new EventHandler(this.OnResize);
124 | this.HelpButton = true;
125 | this.HelpRequested += new HelpEventHandler(FormSettings_HelpRequested);
126 |
127 | this.ResumeLayout();
128 |
129 | // now, we can resize it
130 | this.ClientSize = new System.Drawing.Size(maxXSize, flPanelMain.Height);
131 | this.MinimumSize = this.Size;
132 | }
133 |
134 | void FormSettings_HelpRequested(object sender, HelpEventArgs hlpevent)
135 | {
136 | Help.ShowHelp(this, Settings.Default.helpFilename, HelpNavigator.Topic, Settings.Default.helpNameApplicationSettings);
137 | }
138 |
139 |
140 | private Control CreateSettingControl(Object settingsObject, String labelText, out Panel panel)
141 | {
142 | return CreateSettingControl(settingsObject, labelText, out panel, 0, 0, null);
143 | }
144 |
145 | private Control CreateSettingControl(Object settingsObject, String labelText, out Panel panel, int minValue, int maxValue)
146 | {
147 | return CreateSettingControl(settingsObject, labelText, out panel, minValue, maxValue, null);
148 | }
149 |
150 | private Control CreateSettingControl(Object settingsObject, String labelText, out Panel panel, string[] optionValues)
151 | {
152 | return CreateSettingControl(settingsObject, labelText, out panel, 0, 0, optionValues);
153 | }
154 |
155 | private Control CreateSettingControl(Object settingsObject, String labelText, out Panel panel, int minValue, int maxValue, string[] optionValues)
156 | {
157 | // create the label
158 | Label label = new Label();
159 | label.Text = labelText + ":";
160 | label.Anchor = AnchorStyles.Left;
161 | label.Size = new System.Drawing.Size(
162 | TextRenderer.MeasureText(label.Text, label.Font).Width,
163 | TextRenderer.MeasureText(label.Text, label.Font).Height);
164 |
165 | // create the settings control
166 | Control control;
167 | if (optionValues != null)
168 | {
169 | // we face a list box
170 | control = new ComboBox();
171 | (control as ComboBox).Items.AddRange(optionValues);
172 | (control as ComboBox).SelectedIndex = (int)settingsObject;
173 | (control as ComboBox).DropDownStyle = ComboBoxStyle.DropDownList;
174 | // measure largest text
175 | int maxWidth = 0;
176 | foreach (string option in optionValues)
177 | maxWidth = Math.Max(maxWidth, TextRenderer.MeasureText(option, control.Font).Width);
178 | control.Width = maxWidth+20;
179 | }
180 | else if (settingsObject.GetType() == typeof(int))
181 | {
182 | control = new NumericTextBox(minValue, maxValue, labelText);
183 | control.Width = TextRenderer.MeasureText(maxValue.ToString(), control.Font).Width;
184 | control.Text = "" + settingsObject;
185 | }
186 | else if (settingsObject.GetType() == typeof(String))
187 | {
188 | control = new TextBox();
189 | control.Text = "" + settingsObject;
190 | control.Width = Math.Max(
191 | TextRenderer.MeasureText(control.Text, control.Font).Width,
192 | TextRenderer.MeasureText(Settings.Default.SettingsTextfieldSize, control.Font).Width);
193 | (control as TextBox).TextAlign = HorizontalAlignment.Right;
194 | }
195 | else if (settingsObject.GetType() == typeof(bool))
196 | {
197 | control = new CheckBox();
198 | ((CheckBox)control).Checked = (bool)settingsObject;
199 | }
200 | else if (settingsObject.GetType() == typeof(byte))
201 | {
202 | control = new TrackBar();
203 | ((TrackBar)control).Minimum = minValue;
204 | ((TrackBar)control).Maximum = maxValue;
205 | ((TrackBar)control).Value = (byte)settingsObject;
206 | }
207 | else
208 | throw new Exception("Internal error: Illegal settings data type");
209 |
210 | control.Dock = DockStyle.Right;
211 | control.AutoSize = true;
212 |
213 | // create the panel
214 | panel = new Panel();
215 | label.Location = new System.Drawing.Point(0, Math.Max((control.Height - label.Height) / 2, 0));
216 | panel.Size = new System.Drawing.Size(label.Width + control.Width + 5, Math.Max(label.Height, control.Height));
217 | panel.Anchor = AnchorStyles.Left | AnchorStyles.Right;
218 | panel.Controls.Add(label);
219 | panel.Controls.Add(control);
220 |
221 | return control;
222 | }
223 |
224 |
225 | private bool CheckData(out String errorMessage)
226 | {
227 | errorMessage = null;
228 |
229 | // check data ranges
230 | if (!(cntlBalloonTimespan as NumericTextBox).IsValueValid())
231 | {
232 | errorMessage = (cntlBalloonTimespan as NumericTextBox).GetErrorMessage();
233 | return false;
234 | }
235 | if (!(cntlDisplayIntervall as NumericTextBox).IsValueValid())
236 | {
237 | errorMessage = (cntlDisplayIntervall as NumericTextBox).GetErrorMessage();
238 | return false;
239 | }
240 | if (!(cntlHistoryDepth as NumericTextBox).IsValueValid())
241 | {
242 | errorMessage = (cntlHistoryDepth as NumericTextBox).GetErrorMessage();
243 | return false;
244 | }
245 | if (!(cntlRetrieveIntervall as NumericTextBox).IsValueValid())
246 | {
247 | errorMessage = (cntlRetrieveIntervall as NumericTextBox).GetErrorMessage();
248 | return false;
249 | }
250 | // no check for cntlConfigFilename and boolean variables
251 |
252 | // interdependencies
253 | if ( (cntlRetrieveIntervall as NumericTextBox).IntValue <= (cntlDisplayIntervall as NumericTextBox).IntValue)
254 | {
255 | errorMessage = Resources.str_settingsErrorRetrieveSmallerDisplay;
256 | return false;
257 | }
258 |
259 | return true;
260 | }
261 |
262 |
263 | private void GetData()
264 | {
265 | // get data
266 | Settings.Default.balloonTimespan = (cntlBalloonTimespan as NumericTextBox).IntValue;
267 | Settings.Default.channelAsTitle = (cntlChannelAsTitle as CheckBox).Checked;
268 | Settings.Default.displayIntervall = (cntlDisplayIntervall as NumericTextBox).IntValue;
269 | Settings.Default.historyDepth = (cntlHistoryDepth as NumericTextBox).IntValue;
270 | Settings.Default.retrieveIntervall = (cntlRetrieveIntervall as NumericTextBox).IntValue;
271 | Settings.Default.clickInfluence = (byte)(cntlClickInfluence as TrackBar).Value;
272 | Settings.Default.checkForUpdates = (cntlCheckForUpdates as CheckBox).Checked;
273 | Settings.Default.startPaused = (cntlStartPaused as CheckBox).Checked;
274 | Settings.Default.reportNetworkErrors = (cntlReportNetworkErrors as CheckBox).Checked;
275 | Settings.Default.doubleClickAction = (cntlDoubleClickAction as ComboBox).SelectedIndex;
276 | }
277 |
278 |
279 | private void OnResize(object sender, EventArgs e)
280 | {
281 | fillLabel.Size = new System.Drawing.Size(this.ClientSize.Width-5, 0);
282 | }
283 |
284 | private void OnOK(object sender, EventArgs e)
285 | {
286 | String errorMessage;
287 |
288 | // close window
289 | if (CheckData(out errorMessage) == false)
290 | {
291 | MessageBox.Show(
292 | errorMessage,
293 | Resources.str_settingsFormErrorHeader,
294 | MessageBoxButtons.OK,
295 | MessageBoxIcon.Error);
296 | }
297 | else
298 | {
299 | // transfer data from GUI into settings block
300 | GetData();
301 | // save the settings file
302 | Settings.Default.Save();
303 | // close window
304 | this.DialogResult = DialogResult.OK;
305 | Dispose();
306 | }
307 | }
308 |
309 | private void OnCancel(object sender, EventArgs e)
310 | {
311 | // close window
312 | this.DialogResult = DialogResult.Cancel;
313 | Dispose();
314 | }
315 | }
316 | }
--------------------------------------------------------------------------------
/src/FormChannelSettings.cs:
--------------------------------------------------------------------------------
1 | /*
2 | BalloonRSS - Simple RSS news aggregator using balloon tooltips
3 | Copyright (C) 2009 Roman Morawek
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU General Public License for more details.
14 |
15 | You should have received a copy of the GNU General Public License
16 | along with this program. If not, see .
17 | */
18 |
19 | using System;
20 | using System.Windows.Forms;
21 | using BalloonRss.Properties;
22 |
23 | using System.Drawing;
24 | using System.Reflection;
25 | using System.IO;
26 |
27 |
28 | namespace BalloonRss
29 | {
30 | class FormChannelSettings : Form
31 | {
32 | private const int panelWidth = 480;
33 | private const int panelHeight = 145;
34 | private const int splitterBorder = 10;
35 |
36 | // GUI elements
37 | private ListView listView;
38 | private Button editButton;
39 | private Button deleteButton;
40 |
41 | // other class data
42 | private ChannelList channelList;
43 |
44 |
45 | public FormChannelSettings(String rssLink)
46 | {
47 | // initialise with current channel settings
48 | bool firstRun;
49 | channelList = new ChannelList(out firstRun);
50 |
51 | // setup GUI
52 | this.SuspendLayout();
53 | InitializeComponent();
54 | FillChannelList();
55 | this.ResumeLayout();
56 |
57 | if (rssLink != null)
58 | OnNew(rssLink, null);
59 | }
60 |
61 |
62 | private void InitializeComponent()
63 | {
64 | // list control
65 | this.listView = new ListView();
66 | this.listView.Dock = DockStyle.Fill;
67 | this.listView.UseCompatibleStateImageBehavior = false;
68 | this.listView.View = View.Details;
69 | this.listView.AllowColumnReorder = true;
70 | this.listView.FullRowSelect = true;
71 | this.listView.DoubleClick += new EventHandler(OnEdit);
72 | this.listView.SelectedIndexChanged += new EventHandler(listView_SelectedIndexChanged);
73 |
74 | // button panel
75 | FlowLayoutPanel flPanel = new FlowLayoutPanel();
76 | flPanel.FlowDirection = FlowDirection.TopDown;
77 | flPanel.Dock = DockStyle.Fill;
78 | // "new" button
79 | Button button = new Button();
80 | button.Text = Resources.str_channelSettingsFormNewButton;
81 | button.Click += new EventHandler(this.OnNew);
82 | button.Anchor = AnchorStyles.Top;
83 | flPanel.Controls.Add(button);
84 | // "delete" button
85 | deleteButton = new Button();
86 | deleteButton.Text = Resources.str_channelSettingsFormDeleteButton;
87 | deleteButton.Click += new EventHandler(this.OnDelete);
88 | deleteButton.Anchor = AnchorStyles.Top;
89 | deleteButton.Enabled = false;
90 | flPanel.Controls.Add(deleteButton);
91 | // "edit" button
92 | editButton = new Button();
93 | editButton.Text = Resources.str_channelSettingsFormEditButton;
94 | editButton.Click += new EventHandler(this.OnEdit);
95 | editButton.Anchor = AnchorStyles.Top;
96 | editButton.Enabled = false;
97 | flPanel.Controls.Add(editButton);
98 | // "OK" button
99 | button = new Button();
100 | button.Text = Resources.str_settingsFormOKButton;
101 | button.Click += new EventHandler(this.OnOK);
102 | this.AcceptButton = button;
103 | button.Anchor = AnchorStyles.Bottom;
104 | flPanel.Controls.Add(button);
105 | // "Cancel" button
106 | button = new Button();
107 | button.Text = Resources.str_settingsFormCancelButton;
108 | button.Click += new EventHandler(this.OnCancel);
109 | this.CancelButton = button;
110 | button.Anchor = AnchorStyles.Bottom;
111 | flPanel.Controls.Add(button);
112 |
113 | // main split container
114 | SplitContainer mainContainer = new SplitContainer();
115 | mainContainer.FixedPanel = FixedPanel.Panel2;
116 | mainContainer.Panel1.Controls.Add(listView);
117 | mainContainer.Panel2.Controls.Add(flPanel);
118 | mainContainer.Dock = DockStyle.Fill;
119 | mainContainer.IsSplitterFixed = true;
120 | mainContainer.SplitterDistance = mainContainer.Width - button.Width - splitterBorder;
121 |
122 | //
123 | // form settings
124 | //
125 | this.Controls.Add(mainContainer);
126 | this.ClientSize = new System.Drawing.Size(panelWidth, panelHeight);
127 | this.MinimizeBox = false;
128 | this.MaximizeBox = false;
129 | this.Text = Resources.str_channelSettingsFormTitle;
130 | this.Icon = Resources.ico_yellow32;
131 | this.HelpButton = true;
132 | this.HelpRequested += new HelpEventHandler(FormChannelSettings_HelpRequested);
133 | }
134 |
135 | void FormChannelSettings_HelpRequested(object sender, HelpEventArgs hlpevent)
136 | {
137 | Help.ShowHelp(this, Settings.Default.helpFilename, HelpNavigator.Topic, Settings.Default.helpNameChannelSettings);
138 | }
139 |
140 |
141 | private void FillChannelList()
142 | {
143 | // clear any old data
144 | listView.Clear();
145 |
146 | // populate and set image list
147 | ImageList imageList = new ImageList();
148 | imageList.Images.Add(Resources.img_unlocked);
149 | imageList.Images.Add(Resources.img_locked);
150 | listView.StateImageList = imageList;
151 |
152 | // check whether we have only non-global channels
153 | bool onlyUserChannels = true;
154 | foreach (ChannelInfo curChannel in channelList)
155 | {
156 | if (curChannel.globalChannel)
157 | onlyUserChannels = false;
158 | }
159 |
160 | // set the table headers
161 | // the locked image column has no header and is invisible if only user items exist
162 | listView.Columns.Add(null, onlyUserChannels ? 0 : -1, HorizontalAlignment.Left);
163 | listView.Columns.Add(Resources.str_historyHeaderId, 0, HorizontalAlignment.Left); // hide the ID column
164 | listView.Columns.Add(Resources.str_channelSettingsHeaderTitle, -2, HorizontalAlignment.Left);
165 | listView.Columns.Add(Resources.str_channelSettingsHeaderPriority, -2, HorizontalAlignment.Left);
166 |
167 | // create the list items
168 | ListViewItem[] listItems = new ListViewItem[channelList.Count];
169 | for (int i = 0; i < listItems.Length; i++)
170 | {
171 | listItems[i] = new ListViewItem();
172 | listItems[i].SubItems.Add(i.ToString());
173 | listItems[i].SubItems.Add(channelList[i].link);
174 | listItems[i].SubItems.Add(channelList[i].priority.ToString());
175 | listItems[i].StateImageIndex = Convert.ToInt16(channelList[i].globalChannel);
176 | }
177 |
178 | // fill the list
179 | listView.Items.AddRange(listItems);
180 | }
181 |
182 |
183 | void listView_SelectedIndexChanged(object sender, EventArgs e)
184 | {
185 | // get selected enty
186 | if (listView.SelectedItems.Count > 0)
187 | {
188 | foreach (ListViewItem curItem in listView.SelectedItems)
189 | {
190 | int selectedChannel = Int32.Parse(curItem.SubItems[1].Text);
191 |
192 | editButton.Enabled = !channelList[selectedChannel].globalChannel;
193 | deleteButton.Enabled = !channelList[selectedChannel].globalChannel;
194 |
195 | // we just use the first selection
196 | break;
197 | }
198 | }
199 | else
200 | {
201 | editButton.Enabled = false;
202 | deleteButton.Enabled = false;
203 | }
204 | }
205 |
206 |
207 | // open a child window to create a new channel
208 | private void OnNew(object sender, EventArgs e)
209 | {
210 | // create new enty
211 | ChannelInfo channelInfo = new ChannelInfo();
212 |
213 | // set link if specified
214 | if (sender is String)
215 | channelInfo.link = sender as String;
216 |
217 | // diaplay edit box
218 | FormChannelSettingsEdit channelEdit = new FormChannelSettingsEdit(channelInfo, true);
219 | DialogResult dialogResult = channelEdit.ShowDialog(this);
220 |
221 | // if edit is confirmed, store the entry
222 | if (dialogResult == DialogResult.OK)
223 | {
224 | // check for duplicate channel
225 | if (channelList.IsNewChannel(channelInfo, null))
226 | {
227 | // OK, let's add it
228 | channelList.Add(channelInfo);
229 |
230 | ListViewItem listItem = new ListViewItem();
231 | listItem.SubItems.Add(listView.Items.Count.ToString());
232 | listItem.SubItems.Add(channelInfo.link);
233 | listItem.SubItems.Add(channelInfo.priority.ToString());
234 | listItem.StateImageIndex = Convert.ToInt16(channelInfo.globalChannel);
235 | listView.Items.Add(listItem);
236 | }
237 | else
238 | {
239 | MessageBox.Show(
240 | Resources.str_channelSettingsDuplicateLink,
241 | Resources.str_settingsFormErrorHeader,
242 | MessageBoxButtons.OK,
243 | MessageBoxIcon.Error);
244 | }
245 | }
246 |
247 | // we need to reselect an entry after this operation
248 | editButton.Enabled = false;
249 | deleteButton.Enabled = false;
250 | }
251 |
252 | // open child window to edit channel
253 | private void OnEdit(object sender, EventArgs e)
254 | {
255 | // get selected enty
256 | foreach (ListViewItem curItem in listView.SelectedItems)
257 | {
258 | int selectedChannel = Int32.Parse(curItem.SubItems[1].Text);
259 |
260 | // do not edit global items (this may happen at double click)
261 | if (channelList[selectedChannel].globalChannel)
262 | break;
263 |
264 | // diaplay edit box
265 | ChannelInfo channelInfo = new ChannelInfo(channelList[selectedChannel]);
266 | FormChannelSettingsEdit channelEdit = new FormChannelSettingsEdit(channelInfo, false);
267 | DialogResult dialogResult = channelEdit.ShowDialog(this);
268 |
269 | // update list view display in case of pressing OK
270 | if (dialogResult == DialogResult.OK)
271 | {
272 | // check for duplicate channel
273 | if (channelList.IsNewChannel(channelInfo, channelList[selectedChannel]))
274 | {
275 | // override the stored channel
276 | channelList[selectedChannel] = channelInfo;
277 | curItem.SubItems[2].Text = channelList[selectedChannel].link;
278 | curItem.SubItems[3].Text = channelList[selectedChannel].priority.ToString();
279 | }
280 | else
281 | {
282 | MessageBox.Show(
283 | Resources.str_channelSettingsDuplicateLink,
284 | Resources.str_settingsFormErrorHeader,
285 | MessageBoxButtons.OK,
286 | MessageBoxIcon.Error);
287 | }
288 | }
289 |
290 | // we just edit the first selection and skip the remaining ones
291 | break;
292 | }
293 |
294 | // we need to reselect an entry after this operation
295 | editButton.Enabled = false;
296 | deleteButton.Enabled = false;
297 | }
298 |
299 | private void OnDelete(object sender, EventArgs e)
300 | {
301 | bool deleteConfirmed = false;
302 |
303 | // just delete the first selected entry
304 | foreach (ListViewItem curItem in listView.SelectedItems)
305 | {
306 | int selectedChannel = Int32.Parse(curItem.SubItems[1].Text);
307 |
308 | // ask for confirmation just once
309 | if (!deleteConfirmed)
310 | {
311 | DialogResult dialogResult = MessageBox.Show(
312 | Properties.Resources.str_channelSettingsConfirmDeleteText + channelList[selectedChannel].link + "?",
313 | Properties.Resources.str_channelSettingsConfirmDeleteTitel,
314 | MessageBoxButtons.YesNo,
315 | MessageBoxIcon.Question);
316 |
317 | if (dialogResult == DialogResult.Yes)
318 | deleteConfirmed = true; // also for all succeeding entries
319 | else
320 | break; // also for all succeeding entries
321 | }
322 |
323 | if (deleteConfirmed)
324 | {
325 | // OK, we really want to delete it
326 | channelList.RemoveAt(selectedChannel);
327 | // rebuild list view
328 | FillChannelList();
329 | }
330 |
331 | // skip other selected entries
332 | break; // otherwise you need to take care on (*) index changes (*) confirm dialog text
333 | }
334 |
335 | // we need to reselect an entry after this operation
336 | editButton.Enabled = false;
337 | deleteButton.Enabled = false;
338 | }
339 |
340 |
341 | private void OnOK(object sender, EventArgs e)
342 | {
343 | // store data
344 | channelList.SaveToFile();
345 |
346 | // close window
347 | this.DialogResult = DialogResult.OK;
348 | Dispose();
349 | }
350 |
351 | private void OnCancel(object sender, EventArgs e)
352 | {
353 | // even if we press cancel we need to reload the channels if the user cleared the collected channel data
354 | this.DialogResult = DialogResult.Cancel;
355 |
356 | // close window
357 | Dispose();
358 | }
359 | }
360 | }
--------------------------------------------------------------------------------