Ignorelist settingspage
authorSebastian Goth <seezer@roath.org>
Sun, 16 Aug 2009 15:10:35 +0000 (17:10 +0200)
committerManuel Nickschas <sputnick@quassel-irc.org>
Mon, 24 Aug 2009 23:16:03 +0000 (01:16 +0200)
src/qtui/mainwin.cpp
src/qtui/settingspages/ignorelisteditdlg.ui [new file with mode: 0644]
src/qtui/settingspages/ignorelistmodel.cpp [new file with mode: 0644]
src/qtui/settingspages/ignorelistmodel.h [new file with mode: 0644]
src/qtui/settingspages/ignorelistsettingspage.cpp [new file with mode: 0644]
src/qtui/settingspages/ignorelistsettingspage.h [new file with mode: 0644]
src/qtui/settingspages/ignorelistsettingspage.ui [new file with mode: 0644]
src/qtui/settingspages/settingspages.inc

index b56c794..ee33952 100644 (file)
 #include "settingspages/generalsettingspage.h"
 #include "settingspages/highlightsettingspage.h"
 #include "settingspages/identitiessettingspage.h"
+#include "settingspages/ignorelistsettingspage.h"
 #include "settingspages/inputwidgetsettingspage.h"
 #include "settingspages/itemviewsettingspage.h"
 #include "settingspages/networkssettingspage.h"
@@ -825,6 +826,7 @@ void MainWin::showSettingsDlg() {
   dlg->registerSettingsPage(new IdentitiesSettingsPage(dlg));
   dlg->registerSettingsPage(new NetworksSettingsPage(dlg));
   dlg->registerSettingsPage(new AliasesSettingsPage(dlg));
+  dlg->registerSettingsPage(new IgnoreListSettingsPage(dlg));
 
   dlg->show();
 }
diff --git a/src/qtui/settingspages/ignorelisteditdlg.ui b/src/qtui/settingspages/ignorelisteditdlg.ui
new file mode 100644 (file)
index 0000000..98cae6e
--- /dev/null
@@ -0,0 +1,320 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <author>Sebastian Goth &lt;seezer@roath.org&gt;</author>
+ <class>IgnoreListEditDlg</class>
+ <widget class="QDialog" name="IgnoreListEditDlg">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>389</width>
+    <height>368</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Configure ignore rule</string>
+  </property>
+  <property name="windowIcon">
+   <iconset resource="../../../icons/oxygen.qrc">
+    <normaloff>:/icons/oxygen/16x16/actions/configure.png</normaloff>:/icons/oxygen/16x16/actions/configure.png</iconset>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout_3">
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout_4">
+     <item>
+      <widget class="QGroupBox" name="strictnessGroupBox">
+       <property name="toolTip">
+        <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:10pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Strictness:&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600;&quot;&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; text-decoration: underline;&quot;&gt;Dynamic:&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Messages are filtered &quot;on the fly&quot;.&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Whenever you disable/delete the ignore rule,&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;the messages are shown again.&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; text-decoration: underline;&quot;&gt;Permanent:&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Messages are filtered before they get stored in the database.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+       </property>
+       <property name="title">
+        <string>Strictness</string>
+       </property>
+       <layout class="QHBoxLayout" name="horizontalLayout_2">
+        <item>
+         <widget class="QRadioButton" name="dynamicStrictnessButton">
+          <property name="text">
+           <string>Dynamic</string>
+          </property>
+          <attribute name="buttonGroup">
+           <string>strictnessButtonGroup</string>
+          </attribute>
+         </widget>
+        </item>
+        <item>
+         <widget class="QRadioButton" name="permanentStrictnessButton">
+          <property name="text">
+           <string>Permanent</string>
+          </property>
+          <attribute name="buttonGroup">
+           <string>strictnessButtonGroup</string>
+          </attribute>
+         </widget>
+        </item>
+       </layout>
+      </widget>
+     </item>
+     <item>
+      <widget class="QGroupBox" name="typeGroupBox">
+       <property name="toolTip">
+        <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:10pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Rule Type:&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600;&quot;&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; text-decoration: underline;&quot;&gt;By Sender:&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;The rule is matched against the sender string &lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&quot;nick!ident@host.name&quot;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; text-decoration: underline;&quot;&gt;By Message:&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;The rule is matched against the actual message content&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; text-decoration: underline;&quot;&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+       </property>
+       <property name="title">
+        <string>Rule Type</string>
+       </property>
+       <layout class="QHBoxLayout" name="horizontalLayout_3">
+        <item>
+         <widget class="QRadioButton" name="senderTypeButton">
+          <property name="text">
+           <string>Sender</string>
+          </property>
+          <attribute name="buttonGroup">
+           <string>typeButtonGroup</string>
+          </attribute>
+         </widget>
+        </item>
+        <item>
+         <widget class="QRadioButton" name="messageTypeButton">
+          <property name="text">
+           <string>Message</string>
+          </property>
+          <attribute name="buttonGroup">
+           <string>typeButtonGroup</string>
+          </attribute>
+         </widget>
+        </item>
+       </layout>
+      </widget>
+     </item>
+    </layout>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="ignoreRuleGroupBox">
+     <property name="toolTip">
+      <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:10pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Ignore rule:&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600;&quot;&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Depending on the type of the rule, the text is matched against either:&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;- &lt;span style=&quot; text-decoration: underline;&quot;&gt;the message content:&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; text-decoration: underline;&quot;&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;Example:&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;    &quot;*foobar*&quot; matches any text containing the word &quot;foobar&quot;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;- &lt;span style=&quot; text-decoration: underline;&quot;&gt;the sender string &lt;/span&gt;&lt;span style=&quot; font-style:italic; text-decoration: underline;&quot;&gt;nick!ident@host.name&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-style:italic; text-decoration: underline;&quot;&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;Examples:&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;    &quot;*@foobar.com&quot; matches any sender from host &quot;foobar.com&quot;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;    &quot;stupid!.+&quot; (RegEx) matches any sender with nickname &quot;stupid&quot; from any host&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+     </property>
+     <property name="title">
+      <string>Ignore rule</string>
+     </property>
+     <layout class="QVBoxLayout" name="verticalLayout">
+      <item>
+       <widget class="QLineEdit" name="ignoreRuleLineEdit"/>
+      </item>
+      <item>
+       <layout class="QHBoxLayout" name="horizontalLayout_5">
+        <item>
+         <widget class="QCheckBox" name="isRegExCheckBox">
+          <property name="toolTip">
+           <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:10pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Use RegularExpressions:&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600;&quot;&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;If enabled, rules follow regular expression syntax.&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Otherwise rules allow wildcard matching with &lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt; *: represents &quot;any amount of any character&quot;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt; ?: represents &quot;one or none character&quot;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+          </property>
+          <property name="text">
+           <string>Use Regular Expressions</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QCheckBox" name="isActiveCheckBox">
+          <property name="toolTip">
+           <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:10pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Enable / Disable:&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:768;&quot;&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;Only enabled rules are filtered.&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:768;&quot;&gt;For dynamic rules, disabling actually shows the filtered messages again.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+          </property>
+          <property name="text">
+           <string>Enabled</string>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="scopeGroupBox">
+     <property name="toolTip">
+      <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:10pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Scope:&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600;&quot;&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; text-decoration: underline;&quot;&gt;Global:&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;The rule is active for any channel on any network&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; text-decoration: underline;&quot;&gt;Network:&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;The list below is interpreted as a list of networks for which the rule should match&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; text-decoration: underline;&quot;&gt;Channel:&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;The list below is interpreted as a list of channels for which the rule should match&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+     </property>
+     <property name="title">
+      <string>Scope</string>
+     </property>
+     <layout class="QVBoxLayout" name="verticalLayout_2">
+      <item>
+       <layout class="QHBoxLayout" name="horizontalLayout">
+        <item>
+         <widget class="QRadioButton" name="globalScopeButton">
+          <property name="text">
+           <string>Global</string>
+          </property>
+          <attribute name="buttonGroup">
+           <string>scopeButtonGroup</string>
+          </attribute>
+         </widget>
+        </item>
+        <item>
+         <widget class="QRadioButton" name="networkScopeButton">
+          <property name="text">
+           <string>Network</string>
+          </property>
+          <attribute name="buttonGroup">
+           <string>scopeButtonGroup</string>
+          </attribute>
+         </widget>
+        </item>
+        <item>
+         <widget class="QRadioButton" name="channelScopeButton">
+          <property name="text">
+           <string>Channel</string>
+          </property>
+          <attribute name="buttonGroup">
+           <string>scopeButtonGroup</string>
+          </attribute>
+         </widget>
+        </item>
+       </layout>
+      </item>
+      <item>
+       <widget class="QPlainTextEdit" name="scopeRuleTextEdit">
+        <property name="toolTip">
+         <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
+&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
+p, li { white-space: pre-wrap; }
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Sans Serif'; font-size:10pt; font-weight:400; font-style:normal;&quot;&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-weight:600;&quot;&gt;Scope rule:&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600;&quot;&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;A scope rule is a semicolon separated list of either&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;network or channel names.&lt;/p&gt;
+&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;Example:&lt;/span&gt;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&quot;#quassel*; #foobar&quot;&lt;/p&gt;
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;would match on #foobar and on any channel starting with &quot;#quassel&quot;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QDialogButtonBox" name="buttonBox">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+     <property name="standardButtons">
+      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources>
+  <include location="../../../icons/oxygen.qrc"/>
+ </resources>
+ <connections>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>accepted()</signal>
+   <receiver>IgnoreListEditDlg</receiver>
+   <slot>accept()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>248</x>
+     <y>254</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>157</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+  <connection>
+   <sender>buttonBox</sender>
+   <signal>rejected()</signal>
+   <receiver>IgnoreListEditDlg</receiver>
+   <slot>reject()</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>316</x>
+     <y>260</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>286</x>
+     <y>274</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+ <buttongroups>
+  <buttongroup name="typeButtonGroup"/>
+  <buttongroup name="strictnessButtonGroup"/>
+  <buttongroup name="scopeButtonGroup"/>
+ </buttongroups>
+</ui>
diff --git a/src/qtui/settingspages/ignorelistmodel.cpp b/src/qtui/settingspages/ignorelistmodel.cpp
new file mode 100644 (file)
index 0000000..445201a
--- /dev/null
@@ -0,0 +1,279 @@
+/***************************************************************************
+ *   Copyright (C) 2005-09 by the Quassel Project                          *
+ *   devel@quassel-irc.org                                                 *
+ *                                                                         *
+ *   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) version 3.                                           *
+ *                                                                         *
+ *   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 Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#include "ignorelistmodel.h"
+
+#include <QDebug>
+#include <QStringList>
+#include <QPushButton>
+
+#include "client.h"
+#include "signalproxy.h"
+
+IgnoreListModel::IgnoreListModel(QObject *parent)
+  : QAbstractItemModel(parent),
+    _configChanged(false),
+    _modelReady(false)
+{
+  // we need this signal for future connects to reset the data;
+  connect(Client::instance(), SIGNAL(connected()), this, SLOT(clientConnected()));
+  connect(Client::instance(), SIGNAL(disconnected()), this, SLOT(clientDisconnected()));
+
+  if(Client::isConnected())
+    clientConnected();
+  else
+    emit modelReady(false);
+}
+
+QVariant IgnoreListModel::data(const QModelIndex &index, int role) const {
+  if(!_modelReady)
+    return QVariant();
+
+  if(!index.isValid() || index.row() >= rowCount() || index.column() >= columnCount())
+    return QVariant();
+
+  switch(role) {
+  case Qt::ToolTipRole:
+    switch(index.column()) {
+      /*
+    case 0: return "<b>Type:</b><br />"
+  "<i><u>BySender:</u></i><br />"
+    "The ignore rule is matched against the <i>nick!ident@host.mask</i> sender-string.<br />"
+  "<i><u>ByMessage:</u></i><br />"
+    "The ignore rule is matched against the message content.";
+    case 1:
+      return "<b>Strictness:</b><br />"
+  "<i><u>Dynamic:</u></i><br />"
+        "Messages are hidden but still get stored in the database.<br />Deactivate or delete an ignore rule to show the messages again<br />"
+  "<i><u>Permanent:</u></i><br />"
+         "Messages are never stored or shown anywhere.";
+  */
+    case 0:
+      return tr("<b>Enable / Disable:</b><br />"
+                "Only enabled rules are filtered.<br />"
+                "For dynamic rules, disabling actually shows the filtered messages again");
+    case 2:
+      return tr("<b>Ignore rule:</b><br />"
+                "Depending on the type of the rule, the text is matched against either:<br /><br />"
+                "- <u>the message content:</u><br />"
+                "<i>Example:<i><br />"
+                "    \"*foobar*\" matches any text containing the word \"foobar\"<br /><br />"
+                "- <u>the sender string <i>nick!ident@host.name<i></u><br />"
+                "<i>Example:</i><br />"
+                "    \"*@foobar.com\" matches any sender from host foobar.com<br />"
+                "    \"stupid!.+\" (RegEx) matches any sender with nickname \"stupid\" from any host<br />");
+    default:
+      return QVariant();
+    }
+  case Qt::DisplayRole:
+    switch(index.column()) {
+    case 1:
+      if(ignoreListManager()[index.row()].type == IgnoreListManager::SenderIgnore)
+        return tr("By Sender");
+      else
+        return tr("By Message");
+    }
+  case Qt::EditRole:
+    switch(index.column()) {
+    case 0:
+      return ignoreListManager()[index.row()].isActive;
+    case 1:
+      return ignoreListManager()[index.row()].type;
+    case 2:
+      return ignoreListManager()[index.row()].ignoreRule;
+    default:
+      return QVariant();
+    }
+  default:
+    return QVariant();
+  }
+}
+
+bool IgnoreListModel::setData(const QModelIndex &index, const QVariant &value, int role) {
+  if(!_modelReady)
+    return false;
+
+  if(!index.isValid() || index.row() >= rowCount() || index.column() >= columnCount() || role != Qt::EditRole)
+    return false;
+
+  QVariant newValue = value;
+  if(newValue.isNull())
+    return false;
+
+  switch(index.column()) {
+  case 0:
+    cloneIgnoreListManager()[index.row()].isActive = newValue.toBool();
+    return true;
+  case 1:
+    cloneIgnoreListManager()[index.row()].type = (IgnoreListManager::IgnoreType)newValue.toInt();
+    return true;
+  case 2:
+    if(ignoreListManager().contains(newValue.toString())) {
+      return false;
+    } else {
+      cloneIgnoreListManager()[index.row()].ignoreRule = newValue.toString();
+      return true;
+    }
+  default:
+    return false;
+  }
+}
+
+bool IgnoreListModel::newIgnoreRule(const IgnoreListManager::IgnoreListItem &item) {
+  IgnoreListManager &manager = cloneIgnoreListManager();
+  if(manager.contains(item.ignoreRule))
+    return false;
+  beginInsertRows(QModelIndex(), rowCount(), rowCount());
+  manager.addIgnoreListItem(item);
+  endInsertRows();
+  return true;
+}
+
+void IgnoreListModel::loadDefaults() {
+  /*if(!_modelReady)
+    return;
+
+  IgnoreListManager &manager = cloneIgnoreListManager();
+
+  if(!manager.isEmpty()) {
+    beginRemoveRows(QModelIndex(), 0, rowCount() - 1);
+    for(int i = rowCount() - 1; i >= 0; i--)
+      manager.removeAt(i);
+    endRemoveRows();
+  }
+
+  IgnoreListManager::IgnoreList defaults = IgnoreListModel::defaults();
+  beginInsertRows(QModelIndex(), 0, defaults.count() - 1);
+  foreach(IgnoreListManager::IgnoreListItem item, defaults) {
+    manager.addIgnoreListItem(item.ignoreRule, item.isRegEx, item.strictness, item.scope, item.scopeRule);
+  }
+  endInsertRows();*/
+}
+
+void IgnoreListModel::removeIgnoreRule(int index) {
+  if(index < 0 || index >= rowCount())
+    return;
+
+  IgnoreListManager &manager = cloneIgnoreListManager();
+  beginRemoveRows(QModelIndex(), index, index);
+  manager.removeAt(index);
+  endRemoveRows();
+}
+
+Qt::ItemFlags IgnoreListModel::flags(const QModelIndex &index) const {
+  if(!index.isValid()) {
+    return Qt::ItemIsDropEnabled;
+  } else {
+    return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable;
+  }
+}
+
+
+QVariant IgnoreListModel::headerData(int section, Qt::Orientation orientation, int role) const {
+  QStringList header;
+  header << tr("Enabled")
+         << tr("Type")
+         << tr("Ignore Rule");
+
+  if(orientation == Qt::Horizontal && role == Qt::DisplayRole)
+    return header[section];
+
+  return QVariant();
+}
+
+QModelIndex IgnoreListModel::index(int row, int column, const QModelIndex &parent) const {
+  Q_UNUSED(parent);
+  if(row >= rowCount() || column >= columnCount())
+    return QModelIndex();
+
+  return createIndex(row, column);
+}
+
+
+const IgnoreListManager &IgnoreListModel::ignoreListManager() const {
+  if(_configChanged)
+    return _clonedIgnoreListManager;
+  else
+    return *Client::ignoreListManager();
+}
+
+IgnoreListManager &IgnoreListModel::ignoreListManager() {
+  if(_configChanged)
+    return _clonedIgnoreListManager;
+  else
+    return *Client::ignoreListManager();
+}
+
+IgnoreListManager &IgnoreListModel::cloneIgnoreListManager() {
+  if(!_configChanged) {
+    _clonedIgnoreListManager = *Client::ignoreListManager();
+    _configChanged = true;
+    emit configChanged(true);
+  }
+  return _clonedIgnoreListManager;
+}
+
+void IgnoreListModel::revert() {
+  if(!_configChanged)
+    return;
+
+  _configChanged = false;
+  emit configChanged(false);
+  reset();
+}
+
+void IgnoreListModel::commit() {
+  if(!_configChanged)
+    return;
+
+  Client::ignoreListManager()->requestUpdate(_clonedIgnoreListManager.toVariantMap());
+  revert();
+}
+
+void IgnoreListModel::initDone() {
+  _modelReady = true;
+  reset();
+  emit modelReady(true);
+}
+
+void IgnoreListModel::clientConnected() {
+  connect(Client::ignoreListManager(), SIGNAL(updated(QVariantMap)), SLOT(revert()));
+  if(Client::ignoreListManager()->isInitialized())
+    initDone();
+  else
+    connect(Client::ignoreListManager(), SIGNAL(initDone()), SLOT(initDone()));
+}
+
+void IgnoreListModel::clientDisconnected() {
+  // clear
+  _clonedIgnoreListManager = ClientIgnoreListManager();
+  _modelReady = false;
+  reset();
+  emit modelReady(false);
+}
+
+const IgnoreListManager::IgnoreListItem &IgnoreListModel::ignoreListItemAt(int row) const {
+  return ignoreListManager()[row];
+}
+// FIXME use QModelIndex?
+void IgnoreListModel::setIgnoreListItemAt(int row, const IgnoreListManager::IgnoreListItem &item) {
+  cloneIgnoreListManager()[row] = item;
+  emit dataChanged(createIndex(row, 0), createIndex(row, 2));
+}
diff --git a/src/qtui/settingspages/ignorelistmodel.h b/src/qtui/settingspages/ignorelistmodel.h
new file mode 100644 (file)
index 0000000..87b242a
--- /dev/null
@@ -0,0 +1,93 @@
+/***************************************************************************
+ *   Copyright (C) 2005-09 by the Quassel Project                          *
+ *   devel@quassel-irc.org                                                 *
+ *                                                                         *
+ *   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) version 3.                                           *
+ *                                                                         *
+ *   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 Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#ifndef IGNORELISTMODEL_H
+#define IGNORELISTMODEL_H
+
+#include <QAbstractItemModel>
+#include <QPointer>
+
+#include "clientignorelistmanager.h"
+
+class IgnoreListModel : public QAbstractItemModel {
+  Q_OBJECT
+
+public:
+  IgnoreListModel(QObject *parent = 0);
+
+  virtual QVariant data(const QModelIndex &index, int role) const;
+  virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole);
+
+  virtual Qt::ItemFlags flags(const QModelIndex &index) const;
+
+  QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
+
+  QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
+
+  inline QModelIndex parent(const QModelIndex &) const { return QModelIndex(); }
+
+  inline int rowCount(const QModelIndex &parent = QModelIndex()) const;
+  inline int columnCount(const QModelIndex &parent = QModelIndex()) const;
+
+  inline bool configChanged() const { return _configChanged; }
+  inline bool isReady() const { return _modelReady; }
+
+  const IgnoreListManager::IgnoreListItem &ignoreListItemAt(int row) const;
+  void setIgnoreListItemAt(int row, const IgnoreListManager::IgnoreListItem &item);
+  bool newIgnoreRule(const IgnoreListManager::IgnoreListItem &item);
+
+public slots:
+  void loadDefaults();
+  void removeIgnoreRule(int index);
+  void revert();
+  void commit();
+
+signals:
+  void configChanged(bool);
+  void modelReady(bool);
+
+private:
+  ClientIgnoreListManager _clonedIgnoreListManager;
+  bool _configChanged;
+  bool _modelReady;
+
+  const IgnoreListManager &ignoreListManager() const;
+  IgnoreListManager &ignoreListManager();
+  IgnoreListManager &cloneIgnoreListManager();
+
+private slots:
+  void clientConnected();
+  void clientDisconnected();
+  void initDone();
+};
+
+// Inlines
+int IgnoreListModel::rowCount(const QModelIndex &parent) const {
+  Q_UNUSED(parent);
+  return isReady() ? ignoreListManager().count() : 0;
+}
+
+int IgnoreListModel::columnCount(const QModelIndex &parent) const {
+  Q_UNUSED(parent);
+  return isReady() ? 3 : 0;
+}
+    
+
+#endif //IGNORELISTMODEL_H
diff --git a/src/qtui/settingspages/ignorelistsettingspage.cpp b/src/qtui/settingspages/ignorelistsettingspage.cpp
new file mode 100644 (file)
index 0000000..62dfc88
--- /dev/null
@@ -0,0 +1,274 @@
+/***************************************************************************
+ *   Copyright (C) 2005-09 by the Quassel Project                          *
+ *   devel@quassel-irc.org                                                 *
+ *                                                                         *
+ *   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) version 3.                                           *
+ *                                                                         *
+ *   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 Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#include "ignorelistsettingspage.h"
+
+#include <QHeaderView>
+#include <QItemSelectionModel>
+#include <QModelIndex>
+#include <QPainter>
+#include <QMessageBox>
+#include <QString>
+#include <QEvent>
+
+#include "iconloader.h"
+
+IgnoreListSettingsPage::IgnoreListSettingsPage(QWidget *parent)
+  : SettingsPage(tr("Misc"), tr("Ignorelist"), parent)
+{
+  ui.setupUi(this);
+  _delegate = new IgnoreListDelegate(ui.ignoreListView);
+  ui.newIgnoreRuleButton->setIcon(SmallIcon("list-add"));
+  ui.deleteIgnoreRuleButton->setIcon(SmallIcon("edit-delete"));
+  ui.editIgnoreRuleButton->setIcon(SmallIcon("configure"));
+
+  ui.ignoreListView->setSelectionBehavior(QAbstractItemView::SelectRows);
+  ui.ignoreListView->setSelectionMode(QAbstractItemView::SingleSelection);
+  ui.ignoreListView->setAlternatingRowColors(true);
+  ui.ignoreListView->setTabKeyNavigation(false);
+  ui.ignoreListView->setModel(&_ignoreListModel);
+ // ui.ignoreListView->setEditTriggers(QAbstractItemView::NoEditTriggers);
+
+  // ui.ignoreListView->setSortingEnabled(true);
+  ui.ignoreListView->verticalHeader()->hide();
+  ui.ignoreListView->hideColumn(1);
+  ui.ignoreListView->resizeColumnToContents(0);
+  ui.ignoreListView->horizontalHeader()->setStretchLastSection(true);
+  ui.ignoreListView->setItemDelegateForColumn(0, _delegate);
+  ui.ignoreListView->viewport()->setAttribute(Qt::WA_Hover);
+  ui.ignoreListView->viewport()->setMouseTracking(true);
+
+  connect(ui.ignoreListView->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), this, SLOT(selectionChanged(const QItemSelection &, const QItemSelection &)));
+  connect(ui.newIgnoreRuleButton, SIGNAL(clicked()), this, SLOT(newIgnoreRule()));
+  connect(ui.deleteIgnoreRuleButton, SIGNAL(clicked()), this, SLOT(deleteSelectedIgnoreRule()));
+  connect(ui.editIgnoreRuleButton, SIGNAL(clicked()), this, SLOT(editSelectedIgnoreRule()));
+  connect(&_ignoreListModel, SIGNAL(configChanged(bool)), this, SLOT(setChangedState(bool)));
+  connect(&_ignoreListModel, SIGNAL(modelReady(bool)), this, SLOT(enableDialog(bool)));
+
+  enableDialog(_ignoreListModel.isReady());
+}
+
+IgnoreListSettingsPage::~IgnoreListSettingsPage() {
+  delete _delegate;
+}
+
+void IgnoreListSettingsPage::load() {
+  if(_ignoreListModel.configChanged())
+    _ignoreListModel.revert();
+}
+
+void IgnoreListSettingsPage::defaults() {
+  _ignoreListModel.loadDefaults();
+}
+
+void IgnoreListSettingsPage::save() {
+  if(_ignoreListModel.configChanged()) {
+    _ignoreListModel.commit();
+  }
+}
+
+void IgnoreListSettingsPage::enableDialog(bool enabled) {
+  ui.newIgnoreRuleButton->setEnabled(enabled);
+  setEnabled(enabled);
+}
+
+void IgnoreListSettingsPage::selectionChanged(const QItemSelection &selection, const QItemSelection &) {
+  bool state = !selection.isEmpty();
+  ui.deleteIgnoreRuleButton->setEnabled(state);
+  ui.editIgnoreRuleButton->setEnabled(state);
+}
+
+void IgnoreListSettingsPage::deleteSelectedIgnoreRule() {
+  if(!ui.ignoreListView->selectionModel()->hasSelection())
+    return;
+
+  _ignoreListModel.removeIgnoreRule(ui.ignoreListView->selectionModel()->selectedIndexes()[0].row());
+}
+
+void IgnoreListSettingsPage::newIgnoreRule() {
+  IgnoreListEditDlg *dlg = new IgnoreListEditDlg(-1, IgnoreListManager::IgnoreListItem(), this);
+
+  while(dlg->exec() == QDialog::Accepted) {
+    if(!_ignoreListModel.newIgnoreRule(dlg->ignoreListItem())) {
+      if(QMessageBox::warning(this,
+                         tr("Rule already exists"),
+                         tr("There is already a rule\n\"%1\"\nPlease choose another rule.")
+                         .arg(dlg->ignoreListItem().ignoreRule),
+                         QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok)
+          == QMessageBox::Cancel)
+        break;
+
+      IgnoreListManager::IgnoreListItem item = dlg->ignoreListItem();
+      delete dlg;
+      dlg = new IgnoreListEditDlg(-1, item, this);
+    }
+    else {
+      break;
+    }
+  }
+  dlg->deleteLater();
+}
+
+void IgnoreListSettingsPage::editSelectedIgnoreRule() {
+  if(!ui.ignoreListView->selectionModel()->hasSelection())
+    return;
+  int row = ui.ignoreListView->selectionModel()->selectedIndexes()[0].row();
+  IgnoreListEditDlg dlg(row, _ignoreListModel.ignoreListItemAt(row), this);
+  dlg.setAttribute(Qt::WA_DeleteOnClose, false);
+  if(dlg.exec() == QDialog::Accepted) {
+    _ignoreListModel.setIgnoreListItemAt(row, dlg.ignoreListItem());
+  }
+}
+
+void IgnoreListDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const {
+  if(index.column() == 0) {
+    QStyle *style = QApplication::style();
+    if(option.state & QStyle::State_Selected)
+      painter->fillRect(option.rect, option.palette.highlight());
+
+    QStyleOptionButton opts;
+    opts.direction = option.direction;
+    opts.rect = option.rect;
+    opts.rect.moveLeft(option.rect.center().rx()-10);
+    opts.state = option.state;
+    opts.state |= index.data().toBool() ? QStyle::State_On : QStyle::State_Off;
+    style->drawControl(QStyle::CE_CheckBox, &opts, painter);
+  }
+  else
+    QStyledItemDelegate::paint(painter, option, index);
+}
+
+IgnoreListEditDlg::IgnoreListEditDlg(int row, const IgnoreListManager::IgnoreListItem &item, QWidget *parent)
+    : QDialog(parent), _selectedRow(row), _ignoreListItem(item), _hasChanged(false) {
+  ui.setupUi(this);
+  setAttribute(Qt::WA_DeleteOnClose, false);
+  setModal(true);
+
+  ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
+
+  ui.ignoreRuleLineEdit->setText(item.ignoreRule);
+
+  if(item.type == IgnoreListManager::MessageIgnore)
+    ui.messageTypeButton->setChecked(true);
+  else
+    ui.senderTypeButton->setChecked(true);
+
+  ui.isRegExCheckBox->setChecked(item.isRegEx);
+  ui.isActiveCheckBox->setChecked(item.isActive);
+
+  if(item.strictness == IgnoreListManager::HardStrictness)
+    ui.permanentStrictnessButton->setChecked(true);
+  else
+    ui.dynamicStrictnessButton->setChecked(true);
+
+  switch(item.scope) {
+    case IgnoreListManager::NetworkScope:
+      ui.networkScopeButton->setChecked(true);
+      ui.scopeRuleTextEdit->setEnabled(true);
+      break;
+    case IgnoreListManager::ChannelScope:
+      ui.channelScopeButton->setChecked(true);
+      ui.scopeRuleTextEdit->setEnabled(true);
+      break;
+    default:
+      ui.globalScopeButton->setChecked(true);
+      ui.scopeRuleTextEdit->setEnabled(false);
+  }
+
+  if(item.scope == IgnoreListManager::GlobalScope)
+    ui.scopeRuleTextEdit->clear();
+  else
+    ui.scopeRuleTextEdit->setPlainText(item.scopeRule);
+
+  connect(ui.ignoreRuleLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(widgetHasChanged()));
+  connect(ui.scopeRuleTextEdit, SIGNAL(textChanged()), this, SLOT(widgetHasChanged()));
+  connect(ui.typeButtonGroup, SIGNAL(buttonClicked(int)), this, SLOT(widgetHasChanged()));
+  connect(ui.strictnessButtonGroup, SIGNAL(buttonClicked(int)), this, SLOT(widgetHasChanged()));
+  connect(ui.scopeButtonGroup, SIGNAL(buttonClicked(int)), this, SLOT(widgetHasChanged()));
+  connect(ui.typeButtonGroup, SIGNAL(buttonClicked(int)), this, SLOT(widgetHasChanged()));
+  connect(ui.isRegExCheckBox, SIGNAL(stateChanged(int)), this, SLOT(widgetHasChanged()));
+  connect(ui.isRegExCheckBox, SIGNAL(stateChanged(int)), this, SLOT(widgetHasChanged()));
+  connect(ui.isActiveCheckBox, SIGNAL(stateChanged(int)), this, SLOT(widgetHasChanged()));
+
+  connect(ui.buttonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked()), this, SLOT(aboutToAccept()));
+}
+
+void IgnoreListEditDlg::widgetHasChanged() {
+  if(ui.messageTypeButton->isChecked())
+    _clonedIgnoreListItem.type = IgnoreListManager::MessageIgnore;
+  else
+    _clonedIgnoreListItem.type = IgnoreListManager::SenderIgnore;
+
+  if(ui.permanentStrictnessButton->isChecked())
+    _clonedIgnoreListItem.strictness = IgnoreListManager::HardStrictness;
+  else
+    _clonedIgnoreListItem.strictness = IgnoreListManager::SoftStrictness;
+
+  if(ui.networkScopeButton->isChecked()) {
+    _clonedIgnoreListItem.scope = IgnoreListManager::NetworkScope;
+    ui.scopeRuleTextEdit->setEnabled(true);
+  }
+  else if(ui.channelScopeButton->isChecked()) {
+    _clonedIgnoreListItem.scope = IgnoreListManager::ChannelScope;
+    ui.scopeRuleTextEdit->setEnabled(true);
+  }
+  else {
+    _clonedIgnoreListItem.scope = IgnoreListManager::GlobalScope;
+    ui.scopeRuleTextEdit->setEnabled(false);
+  }
+
+  if(_clonedIgnoreListItem.scope == IgnoreListManager::GlobalScope) {
+    _clonedIgnoreListItem.scopeRule = QString();
+  }
+  else {
+    QStringList text = ui.scopeRuleTextEdit->toPlainText().split(";", QString::SkipEmptyParts);
+    QStringList::iterator it = text.begin();
+    while(it != text.end())
+      (*it++).trimmed();
+
+    _clonedIgnoreListItem.scopeRule = text.join("; ");
+  }
+
+  _clonedIgnoreListItem.ignoreRule = ui.ignoreRuleLineEdit->text();
+  _clonedIgnoreListItem.isRegEx = ui.isRegExCheckBox->isChecked();
+  _clonedIgnoreListItem.isActive = ui.isActiveCheckBox->isChecked();
+
+  if(!_clonedIgnoreListItem.ignoreRule.isEmpty() && _clonedIgnoreListItem != _ignoreListItem)
+    _hasChanged = true;
+  else
+    _hasChanged = false;
+  ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(_hasChanged);
+}
+
+// provide interactivity for the checkboxes
+bool IgnoreListDelegate::editorEvent(QEvent *event, QAbstractItemModel *model,
+                                     const QStyleOptionViewItem &option, const QModelIndex &index) {
+  Q_UNUSED(option)
+  switch(event->type()) {
+    case QEvent::MouseButtonRelease:
+      model->setData(index, !index.data().toBool());
+      return true;
+      // don't show the default editor for the column
+    case QEvent::MouseButtonDblClick:
+      return true;
+    default:
+      return false;
+  }
+}
diff --git a/src/qtui/settingspages/ignorelistsettingspage.h b/src/qtui/settingspages/ignorelistsettingspage.h
new file mode 100644 (file)
index 0000000..646b95b
--- /dev/null
@@ -0,0 +1,93 @@
+/***************************************************************************
+ *   Copyright (C) 2005-09 by the Quassel Project                          *
+ *   devel@quassel-irc.org                                                 *
+ *                                                                         *
+ *   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) version 3.                                           *
+ *                                                                         *
+ *   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 Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#ifndef IGNORELISTSETTINGSPAGE_H
+#define IGNORELISTSETTINGSPAGE_H
+
+#include <QStyledItemDelegate>
+
+#include "settingspage.h"
+#include "ui_ignorelistsettingspage.h"
+#include "ui_ignorelisteditdlg.h"
+#include "ignorelistmodel.h"
+#include "clientignorelistmanager.h"
+
+class QEvent;
+class QPainter;
+class QAbstractItemModel;
+
+// the delegate is used to draw the checkbox in column 0
+class IgnoreListDelegate : public QStyledItemDelegate {
+  Q_OBJECT
+
+public:
+  IgnoreListDelegate(QWidget *parent = 0) : QStyledItemDelegate(parent) {}
+  void paint(QPainter *painter, const QStyleOptionViewItem &option,
+             const QModelIndex &index) const;
+  bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option,
+                   const QModelIndex &index);
+};
+
+class IgnoreListEditDlg : public QDialog {
+  Q_OBJECT
+
+public:
+  IgnoreListEditDlg(int row, const IgnoreListManager::IgnoreListItem &item, QWidget *parent = 0);
+  inline IgnoreListManager::IgnoreListItem ignoreListItem() { return _ignoreListItem; }
+
+private slots:
+  void widgetHasChanged();
+  void aboutToAccept() { _ignoreListItem = _clonedIgnoreListItem; }
+private:
+  int _selectedRow;
+  IgnoreListManager::IgnoreListItem _ignoreListItem;
+  IgnoreListManager::IgnoreListItem _clonedIgnoreListItem;
+  bool _hasChanged;
+  Ui::IgnoreListEditDlg ui;
+};
+
+class IgnoreListSettingsPage : public SettingsPage {
+  Q_OBJECT
+
+public:
+  IgnoreListSettingsPage(QWidget *parent = 0);
+  ~IgnoreListSettingsPage();
+  virtual inline bool hasDefaults() const { return true; }
+
+public slots:
+  void save();
+  void load();
+  void defaults();
+
+private slots:
+  void enableDialog(bool);
+  void deleteSelectedIgnoreRule();
+  void editSelectedIgnoreRule();
+  void newIgnoreRule();
+  void selectionChanged(const QItemSelection &selection, const QItemSelection &);
+
+private:
+  IgnoreListDelegate *_delegate;
+  Ui::IgnoreListSettingsPage ui;
+  IgnoreListModel _ignoreListModel;
+};
+
+
+#endif //IGNORELISTSETTINGSPAGE_H
diff --git a/src/qtui/settingspages/ignorelistsettingspage.ui b/src/qtui/settingspages/ignorelistsettingspage.ui
new file mode 100644 (file)
index 0000000..22c28b8
--- /dev/null
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>IgnoreListSettingsPage</class>
+ <widget class="QWidget" name="IgnoreListSettingsPage">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>291</width>
+    <height>229</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QTableView" name="ignoreListView"/>
+   </item>
+   <item>
+    <layout class="QHBoxLayout" name="horizontalLayout">
+     <item>
+      <widget class="QPushButton" name="newIgnoreRuleButton">
+       <property name="enabled">
+        <bool>false</bool>
+       </property>
+       <property name="text">
+        <string>New</string>
+       </property>
+       <property name="icon">
+        <iconset>
+         <normaloff>:/16x16/actions/oxygen/16x16/actions/list-add.png</normaloff>:/16x16/actions/oxygen/16x16/actions/list-add.png</iconset>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="deleteIgnoreRuleButton">
+       <property name="enabled">
+        <bool>false</bool>
+       </property>
+       <property name="text">
+        <string>Delete</string>
+       </property>
+       <property name="icon">
+        <iconset>
+         <normaloff>:/16x16/actions/oxygen/16x16/actions/edit-delete.png</normaloff>:/16x16/actions/oxygen/16x16/actions/edit-delete.png</iconset>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <widget class="QPushButton" name="editIgnoreRuleButton">
+       <property name="enabled">
+        <bool>false</bool>
+       </property>
+       <property name="text">
+        <string>&amp;Edit</string>
+       </property>
+       <property name="icon">
+        <iconset>
+         <normaloff>:/16x16/actions/oxygen/16x16/actions/edit-delete.png</normaloff>:/16x16/actions/oxygen/16x16/actions/edit-delete.png</iconset>
+       </property>
+      </widget>
+     </item>
+     <item>
+      <spacer name="horizontalSpacer">
+       <property name="orientation">
+        <enum>Qt::Horizontal</enum>
+       </property>
+       <property name="sizeHint" stdset="0">
+        <size>
+         <width>40</width>
+         <height>20</height>
+        </size>
+       </property>
+      </spacer>
+     </item>
+    </layout>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
index 66ca1f2..2f1df1c 100644 (file)
@@ -1,9 +1,9 @@
 # Putting $FOO in SETTINGSPAGES automatically includes
 # $FOOsettingspage.cpp, $FOOsettingspage.h and $FOOsettingspage.ui
 
-set(SETTINGSPAGES aliases appearance backlog bufferview chatview connection chatmonitor general highlight identities inputwidget itemview networks)
+set(SETTINGSPAGES aliases appearance backlog bufferview chatview connection chatmonitor general highlight identities ignorelist inputwidget itemview networks)
 
 # Specify additional files (e.g. for subdialogs) here!
-set(SP_SOURCES aliasesmodel.cpp identityeditwidget.cpp notificationssettingspage.cpp)
-set(SP_HEADERS aliasesmodel.h identityeditwidget.h notificationssettingspage.h previewbufferview.h)
-set(SP_FORMS buffervieweditdlg.ui createidentitydlg.ui identityeditwidget.ui saveidentitiesdlg.ui networkadddlg.ui networkeditdlg.ui nickeditdlg.ui servereditdlg.ui)
+set(SP_SOURCES aliasesmodel.cpp identityeditwidget.cpp ignorelistmodel.cpp notificationssettingspage.cpp)
+set(SP_HEADERS aliasesmodel.h identityeditwidget.h ignorelistmodel.h notificationssettingspage.h previewbufferview.h)
+set(SP_FORMS buffervieweditdlg.ui createidentitydlg.ui identityeditwidget.ui ignorelisteditdlg.ui saveidentitiesdlg.ui networkadddlg.ui networkeditdlg.ui nickeditdlg.ui servereditdlg.ui)